How to save an invoice document with new record creation in the database

45 views
Skip to first unread message

Alexander Joseph

unread,
Aug 14, 2017, 7:48:12 PM8/14/17
to Django users
Hello, I have an app for creating invoices, but I'd like to be able to save a .docx of the invoice when the user creates the invoice (I'm using docx library). I'm very new to django so any direction you can give I appreciate. I'd like to know the proper way to go about doing this.

Right now I have it so that the 'invoice_number' is generated in the model in the save method and the 'created_by' user is assigned to the self.request.user in the view. Please let me know if there is a better way to do this also. Thanks for your help!

Here is my model ...


class Invoice(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    their_company = models.ForeignKey(Contact, on_delete=models.CASCADE,blank=True, null=True,)
    invoice_number = models.CharField(max_length=50, default='')
    bill_to = models.CharField(max_length=255, default='')
    in_trash = models.BooleanField(default=False)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL)
    
    def save(self, *args, **kwargs):
        
        if not self.id:
            today = datetime.date.today()
            date_str = datetime.datetime.strftime(today, '%y%m%d')
            doc_str = 'IN'
            last_invoice = Invoice.objects.filter(invoice_number__startswith=doc_str).order_by('invoice_number').last()
            if last_invoice:
                last_invoice_num = last_invoice.invoice_number[-2:]
                new_invoice_num = int(last_invoice_num) + 1
                new_invoice_num = "%02d" % new_invoice_num
            else:
                new_invoice_num = '01'
            self.invoice_number = doc_str + date_str + new_invoice_num
            
            
        super(Invoice, self).save(*args, **kwargs)
        
        
    class Meta:
        ordering = ['invoice_number', ]
        
    def __str__(self):
        return self.invoice_number
        
    def get_absolute_url(self):
        return reverse("accounting:invoices:detail", kwargs={"pk": self.pk})




and here is my InvoiceCreateView ...


class InvoiceCreateView(LoginRequiredMixin, CreateView):
    fields = ("their_company", "bill_to")
    model = Invoice
    form = forms.CreateInvoiceForm()
    
    def form_valid(self, form):
        object = form.save(commit=False)
        object.created_by = self.request.user
        object.save()
        
        
        document = Document()
        #use invoice data to create invoice
        
        #save the doc
        document.save('invoice.docx')
        
        return super(InvoiceCreateView, self).form_valid(form)



Derek

unread,
Aug 16, 2017, 4:56:33 AM8/16/17
to Django users
You may want to initiate  the .docx creation via a trigger in the post_save function; see:
https://docs.djangoproject.com/en/1.11/ref/signals/#post-save

Also, I would move the "utility" code for creating the invoice number into a separate function,
as its easier to test and (possibly) call from other parts of your app.

def create_invoice_number(doc_str):
    """Create a new invoice_number."""
    last_invoice = Invoice.objects.filter(invoice_number__startswith=doc_str).\

        order_by('invoice_number').last()
    if last_invoice:
        last_invoice_num = last_invoice.invoice_number[-2:]
        new_invoice_num = int(last_invoice_num) + 1
        new_invoice_num = "%02d" % new_invoice_num
    else:
        new_invoice_num = '01'
    return new_invoice_num


Then save becomes:


    def save(self, *args, **kwargs):
        if not self.id:
            today = datetime.date.today()
            date_str = datetime.datetime.strftime(today, '%y%m%d')
            doc_str = 'IN'
            self.invoice_number = doc_str + date_str + create_invoice_number(doc_str)

Alexander Joseph

unread,
Aug 16, 2017, 9:20:23 AM8/16/17
to django...@googlegroups.com
Thanks for the advice Derek. I actually had just moved the docx creation to the save method after I posted my question yesterday, and you're right, it works much better there

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/Tn00OT3b75E/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/e04ce903-156b-44bc-af39-9672ffbf9d9e%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Best Regards,

Alexander Joseph

Reply all
Reply to author
Forward
0 new messages