Browse Source

Minor invoice pdf generation improvments

Fabs 10 years ago
parent
commit
5cd41433c7
4 changed files with 24 additions and 18 deletions
  1. 3 3
      coin/billing/admin.py
  2. 14 14
      coin/billing/models.py
  3. 1 1
      coin/billing/urls.py
  4. 6 0
      coin/utils.py

+ 3 - 3
coin/billing/admin.py

@@ -42,15 +42,15 @@ class PaymentInline(admin.StackedInline):
 
 
 class InvoiceAdmin(admin.ModelAdmin):
-    list_display = ('number', 'date', 'status', 'amount', 'member', 'validated')
+    list_display = ('number', 'date', 'status', 'amount', 'member', 'is_validated')
     list_display_links = ('number', 'date')
     inlines = [InvoiceDetailInline, PaymentInline]
     fields = (('number', 'date', 'status'),
        ('date_due'),
        ('member'),
        ('amount','amount_paid'),
-       ('validated', 'pdf'))
-    readonly_fields = ('amount','amount_paid','validated','pdf')
+       ('is_validated', 'pdf'))
+    readonly_fields = ('amount','amount_paid','is_validated','pdf')
     form = autocomplete_light.modelform_factory(Invoice)
 
     def get_formsets(self, request, obj=None):

+ 14 - 14
coin/billing/models.py

@@ -8,17 +8,13 @@ from decimal import Decimal
 from django.db import models
 from django.db.models.signals import post_save
 from django.dispatch import receiver
-from django.core.files.storage import FileSystemStorage
-from django.conf import settings
 
 from coin.offers.models import OfferSubscription
 from coin.members.models import Member
 from coin.html2pdf import render_as_pdf
+from coin.utils import private_files_storage
 
 
-# Stockage des factures
-invoices_storage = FileSystemStorage(location=os.path.join(settings.PRIVATE_FILES_ROOT, 'invoices/'))
-
 def next_invoice_number():
     "Détermine un numéro de facture aléatoire"
     return u'%s%02i-%i-%i' % (datetime.date.today().year,
@@ -26,6 +22,10 @@ def next_invoice_number():
                               random.randrange(100, 999),
                               random.randrange(100, 999))
 
+def invoice_pdf_filename(instance, filename):
+    "Nom du fichier pdf à stocker pour les factures"
+    return u'%d_%s_%s.pdf' % (instance.member.id, instance.number, uuid.uuid4())
+
 class Invoice(models.Model):
 
     INVOICES_STATUS_CHOICES = (
@@ -34,7 +34,7 @@ class Invoice(models.Model):
         ('trouble', u'Litige')
     )
 
-    validated = models.BooleanField(default=False, verbose_name='Facture validée')
+    validated = models.BooleanField(default=False, verbose_name='Validée')
     number = models.CharField(max_length=25,
                               default=next_invoice_number,
                               unique=True,
@@ -53,9 +53,9 @@ class Invoice(models.Model):
                                related_name='invoices',
                                verbose_name='Membre',
                                on_delete=models.SET_NULL)
-    pdf = models.FileField(storage=invoices_storage,
+    pdf = models.FileField(storage=private_files_storage, upload_to=invoice_pdf_filename,
                            null=True, blank=True,
-                           verbose_name=u'Facture en PDF')
+                           verbose_name=u'PDF')
 
     def amount(self):
         "Calcul le montant de la facture en fonction des éléments de détails"
@@ -90,20 +90,20 @@ class Invoice(models.Model):
     def generate_pdf(self):
         "Make and store a pdf file for the invoice"
         pdf_file = render_as_pdf('billing/invoice_pdf.html', {"invoice": self})
-        self.pdf.save(u'%s_%s.pdf' % (self.number, uuid.uuid4()), pdf_file)
+        self.pdf.save(u'%s.pdf' % self.number, pdf_file)
 
     def validate(self):
         """
         Switch invoice to validate mode. This set to False the draft field
         and generate the pdf
         """
-        # if not self.is_validated():
-        self.validated = True
-        self.save()
-        self.generate_pdf()
+        if not self.is_validated():
+            self.validated = True
+            self.save()
+            self.generate_pdf()
 
     def is_validated(self):
-        return self.validated and bool(self.pdf)
+        return self.validated and bool(self.pdf) and private_files_storage.exists(self.pdf.name)
 
     def __unicode__(self):
         return u'#%s %0.2f€ %s' % (self.number, self.amount(), self.date_due)

+ 1 - 1
coin/billing/urls.py

@@ -4,7 +4,7 @@ from coin.billing import views
 
 urlpatterns = patterns(
     '',
-    url(r'^invoice/(?P<id>.+).pdf$', views.invoice_pdf, name="invoice_pdf"),
+    url(r'^invoice/(?P<id>.+)/pdf$', views.invoice_pdf, name="invoice_pdf"),
     url(r'^invoice/(?P<id>.+)$', views.invoice, name="invoice"),
     # url(r'^invoice/(?P<id>.+)/validate$', views.invoice_validate, name="invoice_validate"),
     

+ 6 - 0
coin/utils.py

@@ -6,6 +6,12 @@ import base64
 import html2text
 from django.core.mail import EmailMultiAlternatives
 from django.template import TemplateDoesNotExist
+from django.core.files.storage import FileSystemStorage
+from django.conf import settings
+
+
+# Stockage des fichiers privés (comme les factures par exemple)
+private_files_storage = FileSystemStorage(location=settings.PRIVATE_FILES_ROOT)
 
 
 def str_or_none(obj):