Store invoice source code instead of generate it everytime

This commit is contained in:
Yohann D'ANELLO 2020-08-06 22:30:14 +02:00
parent e23eafd56c
commit 1fb14ea33d
8 changed files with 224 additions and 180 deletions

View File

@ -28,7 +28,7 @@ class InvoiceForm(forms.ModelForm):
class Meta:
model = Invoice
exclude = ('bde', )
exclude = ('bde', 'tex', )
class ProductForm(forms.ModelForm):

View File

@ -6,6 +6,7 @@ from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, SpecialTransaction, MembershipTransaction
@ -62,6 +63,34 @@ class Invoice(models.Model):
verbose_name=_("Acquitted"),
)
tex = models.TextField(
default="",
verbose_name=_("tex source"),
)
def save(self, *args, **kwargs):
"""
When an invoice is generated, we store the tex source.
The advantage is to never change the template.
Warning: editing this model regenerate the tex source, so be careful.
"""
products = self.products.all()
self.place = "Gif-sur-Yvette"
self.my_name = "BDE ENS Cachan"
self.my_address_street = "4 avenue des Sciences"
self.my_city = "91190 Gif-sur-Yvette"
self.bank_code = 30003
self.desk_code = 3894
self.account_number = 37280662
self.rib_key = 14
self.bic = "SOGEFRPP"
# Fill the template with the information
self.tex = render_to_string("treasury/invoice_sample.tex", dict(obj=self, products=products))
return super().save(*args, **kwargs)
class Meta:
verbose_name = _("invoice")
verbose_name_plural = _("invoices")
@ -75,6 +104,8 @@ class Product(models.Model):
invoice = models.ForeignKey(
Invoice,
on_delete=models.PROTECT,
related_name="products",
verbose_name=_("invoice"),
)
designation = models.CharField(

View File

@ -13,6 +13,8 @@ def do_latex_escape(value):
.replace("_", "\\_")
.replace("{", "\\{")
.replace("}", "\\}")
.replace("\n", "\\\\")
.replace("\r", "")
)

View File

@ -139,23 +139,7 @@ class InvoiceRenderView(LoginRequiredMixin, View):
def get(self, request, **kwargs):
pk = kwargs["pk"]
invoice = Invoice.objects.filter(PermissionBackend.filter_queryset(request.user, Invoice, "view")).get(pk=pk)
products = Product.objects.filter(invoice=invoice).all()
invoice.place = "Gif-sur-Yvette"
invoice.my_name = "BDE ENS Cachan"
invoice.my_address_street = "4 avenue des Sciences"
invoice.my_city = "91190 Gif-sur-Yvette"
invoice.bank_code = 30003
invoice.desk_code = 3894
invoice.account_number = 37280662
invoice.rib_key = 14
invoice.bic = "SOGEFRPP"
# Replace line breaks with the LaTeX equivalent
invoice.description = invoice.description.replace("\r", "").replace("\n", "\\\\ ")
invoice.address = invoice.address.replace("\r", "").replace("\n", "\\\\ ")
# Fill the template with the information
tex = render_to_string("treasury/invoice_sample.tex", dict(obj=invoice, products=products))
tex = invoice.tex
try:
os.mkdir(BASE_DIR + "/tmp")

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-06 19:55+0200\n"
"POT-Creation-Date: 2020-08-06 22:27+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -96,7 +96,7 @@ msgid "type"
msgstr ""
#: apps/activity/models.py:87 apps/logs/models.py:22 apps/member/models.py:280
#: apps/note/models/notes.py:126 apps/treasury/models.py:222
#: apps/note/models/notes.py:126 apps/treasury/models.py:253
#: apps/wei/models.py:160 templates/treasury/sogecredit_detail.html:14
#: templates/wei/survey.html:16
msgid "user"
@ -194,7 +194,7 @@ msgstr ""
msgid "remove"
msgstr ""
#: apps/activity/tables.py:79 apps/note/forms.py:76 apps/treasury/models.py:141
#: apps/activity/tables.py:79 apps/note/forms.py:76 apps/treasury/models.py:172
msgid "Type"
msgstr ""
@ -960,7 +960,7 @@ msgstr ""
msgid "membership transaction"
msgstr ""
#: apps/note/models/transactions.py:344 apps/treasury/models.py:228
#: apps/note/models/transactions.py:344 apps/treasury/models.py:259
msgid "membership transactions"
msgstr ""
@ -1203,7 +1203,7 @@ msgstr ""
#: templates/django_filters/rest_framework/form.html:5
#: templates/member/add_members.html:31 templates/member/club_form.html:9
#: templates/note/transactiontemplate_form.html:15
#: templates/treasury/invoice_form.html:46 templates/wei/bus_form.html:13
#: templates/treasury/invoice_form.html:56 templates/wei/bus_form.html:13
#: templates/wei/busteam_form.html:13 templates/wei/weiclub_form.html:15
#: templates/wei/weiregistration_form.html:14
msgid "Submit"
@ -1221,7 +1221,7 @@ msgstr ""
msgid "You can't change the type of the remittance."
msgstr ""
#: apps/treasury/forms.py:124 apps/treasury/models.py:207
#: apps/treasury/forms.py:124 apps/treasury/models.py:238
#: apps/treasury/tables.py:77 apps/treasury/tables.py:85
#: templates/treasury/invoice_list.html:13
#: templates/treasury/remittance_list.html:13
@ -1239,121 +1239,121 @@ msgstr ""
msgid "Amount"
msgstr ""
#: apps/treasury/models.py:21
#: apps/treasury/models.py:22
msgid "Invoice identifier"
msgstr ""
#: apps/treasury/models.py:35
#: apps/treasury/models.py:36
msgid "BDE"
msgstr ""
#: apps/treasury/models.py:40
#: apps/treasury/models.py:41
msgid "Object"
msgstr ""
#: apps/treasury/models.py:44
#: apps/treasury/models.py:45
msgid "Description"
msgstr ""
#: apps/treasury/models.py:49 templates/note/transaction_form.html:125
#: apps/treasury/models.py:50 templates/note/transaction_form.html:125
msgid "Name"
msgstr ""
#: apps/treasury/models.py:53
#: apps/treasury/models.py:54
msgid "Address"
msgstr ""
#: apps/treasury/models.py:58
msgid "Place"
msgstr ""
#: apps/treasury/models.py:62
msgid "Acquitted"
msgstr ""
#: apps/treasury/models.py:66
msgid "invoice"
msgstr ""
#: apps/treasury/models.py:67
msgid "invoices"
msgstr ""
#: apps/treasury/models.py:82
msgid "Designation"
msgstr ""
#: apps/treasury/models.py:86
msgid "Quantity"
msgstr ""
#: apps/treasury/models.py:90
msgid "Unit price"
msgstr ""
#: apps/treasury/models.py:106
msgid "product"
msgstr ""
#: apps/treasury/models.py:107
msgid "products"
msgstr ""
#: apps/treasury/models.py:124
msgid "remittance type"
msgstr ""
#: apps/treasury/models.py:125
msgid "remittance types"
msgstr ""
#: apps/treasury/models.py:135
#: apps/treasury/models.py:59 apps/treasury/models.py:166
msgid "Date"
msgstr ""
#: apps/treasury/models.py:146
msgid "Comment"
#: apps/treasury/models.py:63
msgid "Acquitted"
msgstr ""
#: apps/treasury/models.py:151
msgid "Closed"
#: apps/treasury/models.py:68
msgid "tex source"
msgstr ""
#: apps/treasury/models.py:95 apps/treasury/models.py:108
msgid "invoice"
msgstr ""
#: apps/treasury/models.py:96
msgid "invoices"
msgstr ""
#: apps/treasury/models.py:113
msgid "Designation"
msgstr ""
#: apps/treasury/models.py:117
msgid "Quantity"
msgstr ""
#: apps/treasury/models.py:121
msgid "Unit price"
msgstr ""
#: apps/treasury/models.py:137
msgid "product"
msgstr ""
#: apps/treasury/models.py:138
msgid "products"
msgstr ""
#: apps/treasury/models.py:155
msgid "remittance"
msgid "remittance type"
msgstr ""
#: apps/treasury/models.py:156
msgid "remittance types"
msgstr ""
#: apps/treasury/models.py:177
msgid "Comment"
msgstr ""
#: apps/treasury/models.py:182
msgid "Closed"
msgstr ""
#: apps/treasury/models.py:186
msgid "remittance"
msgstr ""
#: apps/treasury/models.py:187
msgid "remittances"
msgstr ""
#: apps/treasury/models.py:188
#: apps/treasury/models.py:219
msgid "Remittance #{:d}: {}"
msgstr ""
#: apps/treasury/models.py:211
#: apps/treasury/models.py:242
msgid "special transaction proxy"
msgstr ""
#: apps/treasury/models.py:212
#: apps/treasury/models.py:243
msgid "special transaction proxies"
msgstr ""
#: apps/treasury/models.py:234
#: apps/treasury/models.py:265
msgid "credit transaction"
msgstr ""
#: apps/treasury/models.py:297
#: apps/treasury/models.py:328
msgid ""
"This user doesn't have enough money to pay the memberships with its note. "
"Please ask her/him to credit the note before invalidating this credit."
msgstr ""
#: apps/treasury/models.py:309 templates/treasury/sogecredit_detail.html:10
#: apps/treasury/models.py:340 templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale"
msgstr ""
#: apps/treasury/models.py:310
#: apps/treasury/models.py:341
msgid "Credits from the Société générale"
msgstr ""
@ -1403,28 +1403,28 @@ msgstr ""
msgid "Update an invoice"
msgstr ""
#: apps/treasury/views.py:205
#: apps/treasury/views.py:188
msgid "Create a new remittance"
msgstr ""
#: apps/treasury/views.py:226 templates/treasury/remittance_form.html:9
#: apps/treasury/views.py:209 templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr ""
#: apps/treasury/views.py:276
#: apps/treasury/views.py:259
msgid "Update a remittance"
msgstr ""
#: apps/treasury/views.py:299
#: apps/treasury/views.py:282
msgid "Attach a transaction to a remittance"
msgstr ""
#: apps/treasury/views.py:343
#: apps/treasury/views.py:326
msgid "List of credits from the Société générale"
msgstr ""
#: apps/treasury/views.py:377
#: apps/treasury/views.py:360
msgid "Manage credits from the Société générale"
msgstr ""
@ -2365,11 +2365,17 @@ msgid ""
"by following the link you received."
msgstr ""
#: templates/treasury/invoice_form.html:41
#: templates/treasury/invoice_form.html:10
msgid ""
"Warning: the LaTeX template is saved with this object. Updating the invoice "
"implies regenerate it. Be careful if you manipulate old invoices."
msgstr ""
#: templates/treasury/invoice_form.html:51
msgid "Add product"
msgstr ""
#: templates/treasury/invoice_form.html:42
#: templates/treasury/invoice_form.html:52
msgid "Remove product"
msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-06 19:55+0200\n"
"POT-Creation-Date: 2020-08-06 22:27+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -97,7 +97,7 @@ msgid "type"
msgstr "type"
#: apps/activity/models.py:87 apps/logs/models.py:22 apps/member/models.py:280
#: apps/note/models/notes.py:126 apps/treasury/models.py:222
#: apps/note/models/notes.py:126 apps/treasury/models.py:253
#: apps/wei/models.py:160 templates/treasury/sogecredit_detail.html:14
#: templates/wei/survey.html:16
msgid "user"
@ -195,7 +195,7 @@ msgstr "Entré le "
msgid "remove"
msgstr "supprimer"
#: apps/activity/tables.py:79 apps/note/forms.py:76 apps/treasury/models.py:141
#: apps/activity/tables.py:79 apps/note/forms.py:76 apps/treasury/models.py:172
msgid "Type"
msgstr "Type"
@ -974,7 +974,7 @@ msgstr "Transactions de crédit/retrait"
msgid "membership transaction"
msgstr "Transaction d'adhésion"
#: apps/note/models/transactions.py:344 apps/treasury/models.py:228
#: apps/note/models/transactions.py:344 apps/treasury/models.py:259
msgid "membership transactions"
msgstr "Transactions d'adhésion"
@ -1232,7 +1232,7 @@ msgstr "Trésorerie"
#: templates/django_filters/rest_framework/form.html:5
#: templates/member/add_members.html:31 templates/member/club_form.html:9
#: templates/note/transactiontemplate_form.html:15
#: templates/treasury/invoice_form.html:46 templates/wei/bus_form.html:13
#: templates/treasury/invoice_form.html:56 templates/wei/bus_form.html:13
#: templates/wei/busteam_form.html:13 templates/wei/weiclub_form.html:15
#: templates/wei/weiregistration_form.html:14
msgid "Submit"
@ -1250,7 +1250,7 @@ msgstr "La remise est déjà fermée."
msgid "You can't change the type of the remittance."
msgstr "Vous ne pouvez pas changer le type de la remise."
#: apps/treasury/forms.py:124 apps/treasury/models.py:207
#: apps/treasury/forms.py:124 apps/treasury/models.py:238
#: apps/treasury/tables.py:77 apps/treasury/tables.py:85
#: templates/treasury/invoice_list.html:13
#: templates/treasury/remittance_list.html:13
@ -1268,111 +1268,113 @@ msgstr "Pas de remise associée"
msgid "Amount"
msgstr "Montant"
#: apps/treasury/models.py:21
#: apps/treasury/models.py:22
msgid "Invoice identifier"
msgstr "Numéro de facture"
#: apps/treasury/models.py:35
#: apps/treasury/models.py:36
msgid "BDE"
msgstr "BDE"
#: apps/treasury/models.py:40
#: apps/treasury/models.py:41
msgid "Object"
msgstr "Objet"
#: apps/treasury/models.py:44
#: apps/treasury/models.py:45
msgid "Description"
msgstr "Description"
#: apps/treasury/models.py:49 templates/note/transaction_form.html:125
#: apps/treasury/models.py:50 templates/note/transaction_form.html:125
msgid "Name"
msgstr "Nom"
#: apps/treasury/models.py:53
#: apps/treasury/models.py:54
msgid "Address"
msgstr "Adresse"
#: apps/treasury/models.py:58
msgid "Place"
msgstr "Lieu"
#: apps/treasury/models.py:62
msgid "Acquitted"
msgstr "Acquittée"
#: apps/treasury/models.py:66
msgid "invoice"
msgstr "facture"
#: apps/treasury/models.py:67
msgid "invoices"
msgstr "factures"
#: apps/treasury/models.py:82
msgid "Designation"
msgstr "Désignation"
#: apps/treasury/models.py:86
msgid "Quantity"
msgstr "Quantité"
#: apps/treasury/models.py:90
msgid "Unit price"
msgstr "Prix unitaire"
#: apps/treasury/models.py:106
msgid "product"
msgstr "produit"
#: apps/treasury/models.py:107
msgid "products"
msgstr "produits"
#: apps/treasury/models.py:124
msgid "remittance type"
msgstr "type de remise"
#: apps/treasury/models.py:125
msgid "remittance types"
msgstr "types de remises"
#: apps/treasury/models.py:135
#: apps/treasury/models.py:59 apps/treasury/models.py:166
msgid "Date"
msgstr "Date"
#: apps/treasury/models.py:146
#: apps/treasury/models.py:63
msgid "Acquitted"
msgstr "Acquittée"
#: apps/treasury/models.py:68
#, fuzzy
#| msgid "source"
msgid "tex source"
msgstr "source"
#: apps/treasury/models.py:95 apps/treasury/models.py:108
msgid "invoice"
msgstr "facture"
#: apps/treasury/models.py:96
msgid "invoices"
msgstr "factures"
#: apps/treasury/models.py:113
msgid "Designation"
msgstr "Désignation"
#: apps/treasury/models.py:117
msgid "Quantity"
msgstr "Quantité"
#: apps/treasury/models.py:121
msgid "Unit price"
msgstr "Prix unitaire"
#: apps/treasury/models.py:137
msgid "product"
msgstr "produit"
#: apps/treasury/models.py:138
msgid "products"
msgstr "produits"
#: apps/treasury/models.py:155
msgid "remittance type"
msgstr "type de remise"
#: apps/treasury/models.py:156
msgid "remittance types"
msgstr "types de remises"
#: apps/treasury/models.py:177
msgid "Comment"
msgstr "Commentaire"
#: apps/treasury/models.py:151
#: apps/treasury/models.py:182
msgid "Closed"
msgstr "Fermée"
#: apps/treasury/models.py:155
#: apps/treasury/models.py:186
msgid "remittance"
msgstr "remise"
#: apps/treasury/models.py:156
#: apps/treasury/models.py:187
msgid "remittances"
msgstr "remises"
#: apps/treasury/models.py:188
#: apps/treasury/models.py:219
msgid "Remittance #{:d}: {}"
msgstr "Remise n°{:d} : {}"
#: apps/treasury/models.py:211
#: apps/treasury/models.py:242
msgid "special transaction proxy"
msgstr "Proxy de transaction spéciale"
#: apps/treasury/models.py:212
#: apps/treasury/models.py:243
msgid "special transaction proxies"
msgstr "Proxys de transactions spéciales"
#: apps/treasury/models.py:234
#: apps/treasury/models.py:265
msgid "credit transaction"
msgstr "transaction de crédit"
#: apps/treasury/models.py:297
#: apps/treasury/models.py:328
msgid ""
"This user doesn't have enough money to pay the memberships with its note. "
"Please ask her/him to credit the note before invalidating this credit."
@ -1380,11 +1382,11 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour payer les adhésions avec sa "
"note. Merci de lui demander de recharger sa note avant d'invalider ce crédit."
#: apps/treasury/models.py:309 templates/treasury/sogecredit_detail.html:10
#: apps/treasury/models.py:340 templates/treasury/sogecredit_detail.html:10
msgid "Credit from the Société générale"
msgstr "Crédit de la Société générale"
#: apps/treasury/models.py:310
#: apps/treasury/models.py:341
msgid "Credits from the Société générale"
msgstr "Crédits de la Société générale"
@ -1434,28 +1436,28 @@ msgstr "Liste des factures"
msgid "Update an invoice"
msgstr "Modifier la facture"
#: apps/treasury/views.py:205
#: apps/treasury/views.py:188
msgid "Create a new remittance"
msgstr "Créer une nouvelle remise"
#: apps/treasury/views.py:226 templates/treasury/remittance_form.html:9
#: apps/treasury/views.py:209 templates/treasury/remittance_form.html:9
#: templates/treasury/specialtransactionproxy_form.html:7
msgid "Remittances list"
msgstr "Liste des remises"
#: apps/treasury/views.py:276
#: apps/treasury/views.py:259
msgid "Update a remittance"
msgstr "Modifier la remise"
#: apps/treasury/views.py:299
#: apps/treasury/views.py:282
msgid "Attach a transaction to a remittance"
msgstr "Joindre une transaction à une remise"
#: apps/treasury/views.py:343
#: apps/treasury/views.py:326
msgid "List of credits from the Société générale"
msgstr "Liste des crédits de la Société générale"
#: apps/treasury/views.py:377
#: apps/treasury/views.py:360
msgid "Manage credits from the Société générale"
msgstr "Gérer les crédits de la Société générale"
@ -2467,11 +2469,20 @@ msgstr ""
"d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu."
#: templates/treasury/invoice_form.html:41
#: templates/treasury/invoice_form.html:10
msgid ""
"Warning: the LaTeX template is saved with this object. Updating the invoice "
"implies regenerate it. Be careful if you manipulate old invoices."
msgstr ""
"Attention : le template LaTeX est enregistré avec cet objet. Modifier la "
"facture implique la regénérer. Faites attention si vous manipulez de "
"vieilles factures."
#: templates/treasury/invoice_form.html:51
msgid "Add product"
msgstr "Ajouter produit"
#: templates/treasury/invoice_form.html:42
#: templates/treasury/invoice_form.html:52
msgid "Remove product"
msgstr "Retirer produit"
@ -2808,3 +2819,6 @@ msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée."
#: templates/wei/weiregistration_list.html:24
msgid "View validated memberships..."
msgstr "Voir les adhésions validées ..."
#~ msgid "Place"
#~ msgstr "Lieu"

View File

@ -4,6 +4,16 @@
{% load crispy_forms_tags %}
{% block content %}
<p><a class="btn btn-default" href="{% url 'treasury:invoice_list' %}">{% trans "Invoices list" %}</a></p>
{% if not object.pk %}
<div class="alert alert-info">
{% blocktrans trimmed %}
Warning: the LaTeX template is saved with this object. Updating the invoice implies regenerate it.
Be careful if you manipulate old invoices.
{% endblocktrans %}
</div>
{% endif %}
<form method="post" action="">
{% csrf_token %}
{# Render the invoice form #}

View File

@ -1,5 +1,4 @@
{% load escape_tex %}
{% load l10n %}
\nonstopmode
\documentclass[11pt]{article}
@ -48,11 +47,9 @@
}
\newcommand {\ListeProduits}{
{% localize off %}
{% for product in products %}
{{ product.designation|safe|escape_tex }} & {{ product.amount_euros|safe|escape_tex|floatformat:2 }} & {{ product.quantity|safe|escape_tex|floatformat:2 }} & {{ product.total_euros|safe|escape_tex|floatformat:2 }} \cr
{% endfor %}
{% endlocalize %}
{% for product in products %}
{{ product.designation|safe|escape_tex }} & {{ product.amount_euros|safe|escape_tex|floatformat:2 }} & {{ product.quantity|safe|escape_tex|floatformat:2 }} & {{ product.total_euros|safe|escape_tex|floatformat:2 }} \cr
{% endfor %}
}
% Logo du BDE
@ -70,9 +67,9 @@
%%%%%%%%%%%%%%%%%%%%% A MODIFIER DANS LA FACTURE %%%%%%%%%%%%%%%%%%%%%
% Infos Association
\def\MonNom{{"{"}}{{ obj.my_name }}} % Nom de l'association
\def\MonAdresseRue{{"{"}}{{ obj.my_address_street }}} % Adresse de l'association
\def\MonAdresseVille{{"{"}}{{ obj.my_city }}}
\def\MonNom{{"{"}}{{ obj.my_name|safe|escape_tex }}} % Nom de l'association
\def\MonAdresseRue{{"{"}}{{ obj.my_address_street|safe|escape_tex }}} % Adresse de l'association
\def\MonAdresseVille{{"{"}}{{ obj.my_city|safe|escape_tex }}}
% Informations bancaires de l'association
\def\CodeBanque{{"{"}}{{ obj.bank_code|stringformat:".05d" }}}