From 4f343fc99f688059758a6ddde3ef6e22fa01a726 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Sun, 22 Mar 2020 01:22:27 +0100
Subject: [PATCH] Billing -> Invoice

---
 apps/treasury/admin.py                        |   6 +-
 apps/treasury/forms.py                        |   8 +-
 apps/treasury/models.py                       |   8 +-
 apps/treasury/tables.py                       |  16 +-
 apps/treasury/urls.py                         |  10 +-
 apps/treasury/views.py                        |  60 ++---
 locale/de/LC_MESSAGES/django.po               | 203 +++++++-------
 locale/fr/LC_MESSAGES/django.po               | 255 ++++++++++++------
 templates/base.html                           |   4 +-
 .../{billing_form.html => invoice_form.html}  |   6 +-
 .../{billing_list.html => invoice_list.html}  |   2 +-
 ...{billing_sample.tex => invoice_sample.tex} |   0
 12 files changed, 330 insertions(+), 248 deletions(-)
 rename templates/treasury/{billing_form.html => invoice_form.html} (95%)
 rename templates/treasury/{billing_list.html => invoice_list.html} (59%)
 rename templates/treasury/{billing_sample.tex => invoice_sample.tex} (100%)

diff --git a/apps/treasury/admin.py b/apps/treasury/admin.py
index fe9d3725..74b52150 100644
--- a/apps/treasury/admin.py
+++ b/apps/treasury/admin.py
@@ -3,11 +3,11 @@
 
 from django.contrib import admin
 
-from .models import Billing, Product
+from .models import Invoice, Product
 
 
-@admin.register(Billing)
-class BillingAdmin(admin.ModelAdmin):
+@admin.register(Invoice)
+class InvoiceAdmin(admin.ModelAdmin):
     list_display = ('id', 'name', 'subject', 'acquitted', )
 
 
diff --git a/apps/treasury/forms.py b/apps/treasury/forms.py
index e8697fda..d4b763ea 100644
--- a/apps/treasury/forms.py
+++ b/apps/treasury/forms.py
@@ -4,17 +4,17 @@
 from crispy_forms.helper import FormHelper
 from django import forms
 
-from .models import Billing, Product
+from .models import Invoice, Product
 
 
-class BillingForm(forms.ModelForm):
+class InvoiceForm(forms.ModelForm):
     class Meta:
-        model = Billing
+        model = Invoice
         fields = '__all__'
 
 
 ProductFormSet = forms.inlineformset_factory(
-    Billing,
+    Invoice,
     Product,
     fields='__all__',
     extra=1,
diff --git a/apps/treasury/models.py b/apps/treasury/models.py
index 4da3aa8d..3d1d0c48 100644
--- a/apps/treasury/models.py
+++ b/apps/treasury/models.py
@@ -5,10 +5,10 @@ from django.db import models
 from django.utils.translation import gettext_lazy as _
 
 
-class Billing(models.Model):
+class Invoice(models.Model):
     id = models.PositiveIntegerField(
         primary_key=True,
-        verbose_name=_("Billing identifier"),
+        verbose_name=_("Invoice identifier"),
     )
 
     bde = models.CharField(
@@ -104,8 +104,8 @@ class Billing(models.Model):
 
 
 class Product(models.Model):
-    billing = models.ForeignKey(
-        Billing,
+    invoice = models.ForeignKey(
+        Invoice,
         on_delete=models.PROTECT,
     )
 
diff --git a/apps/treasury/tables.py b/apps/treasury/tables.py
index c651d7f5..156f6dcd 100644
--- a/apps/treasury/tables.py
+++ b/apps/treasury/tables.py
@@ -5,16 +5,16 @@ import django_tables2 as tables
 from django.utils.translation import gettext_lazy as _
 from django_tables2 import A
 
-from .models import Billing
+from .models import Invoice
 
 
-class BillingTable(tables.Table):
-    id = tables.LinkColumn("treasury:billing_update",
+class InvoiceTable(tables.Table):
+    id = tables.LinkColumn("treasury:invoice_update",
                            args=[A("pk")],
-                           text=lambda record: _("Billing #{:d}").format(record.id), )
+                           text=lambda record: _("Invoice #{:d}").format(record.id), )
 
-    billing = tables.LinkColumn("treasury:billing_render",
-                                verbose_name=_("Billing"),
+    invoice = tables.LinkColumn("treasury:invoice_render",
+                                verbose_name=_("Invoice"),
                                 args=[A("pk")],
                                 accessor="pk",
                                 text="",
@@ -27,6 +27,6 @@ class BillingTable(tables.Table):
         attrs = {
             'class': 'table table-condensed table-striped table-hover'
         }
-        model = Billing
+        model = Invoice
         template_name = 'django_tables2/bootstrap4.html'
-        fields = ('id', 'name', 'subject', 'acquitted', 'billing',)
+        fields = ('id', 'name', 'subject', 'acquitted', 'invoice',)
diff --git a/apps/treasury/urls.py b/apps/treasury/urls.py
index 3f28c0a0..1afccabb 100644
--- a/apps/treasury/urls.py
+++ b/apps/treasury/urls.py
@@ -3,12 +3,12 @@
 
 from django.urls import path
 
-from .views import BillingCreateView, BillingListView, BillingUpdateView, BillingRenderView
+from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceRenderView
 
 app_name = 'treasury'
 urlpatterns = [
-    path('billing/', BillingListView.as_view(), name='billing'),
-    path('billing/create/', BillingCreateView.as_view(), name='billing_create'),
-    path('billing/<int:pk>/', BillingUpdateView.as_view(), name='billing_update'),
-    path('billing/render/<int:pk>/', BillingRenderView.as_view(), name='billing_render'),
+    path('invoice/', InvoiceListView.as_view(), name='invoice'),
+    path('invoice/create/', InvoiceCreateView.as_view(), name='invoice_create'),
+    path('invoice/<int:pk>/', InvoiceUpdateView.as_view(), name='invoice_update'),
+    path('invoice/render/<int:pk>/', InvoiceRenderView.as_view(), name='invoice_render'),
 ]
diff --git a/apps/treasury/views.py b/apps/treasury/views.py
index a5d31d66..dcf4e913 100644
--- a/apps/treasury/views.py
+++ b/apps/treasury/views.py
@@ -17,17 +17,17 @@ from django.views.generic.base import View
 from django_tables2 import SingleTableView
 from note_kfet.settings.base import BASE_DIR
 
-from .forms import BillingForm, ProductFormSet, ProductFormSetHelper
-from .models import Billing, Product
-from .tables import BillingTable
+from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper
+from .models import Invoice, Product
+from .tables import InvoiceTable
 
 
-class BillingCreateView(LoginRequiredMixin, CreateView):
+class InvoiceCreateView(LoginRequiredMixin, CreateView):
     """
-    Create Billing
+    Create Invoice
     """
-    model = Billing
-    form_class = BillingForm
+    model = Invoice
+    form_class = InvoiceForm
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
@@ -64,23 +64,23 @@ class BillingCreateView(LoginRequiredMixin, CreateView):
         return ret
 
     def get_success_url(self):
-        return reverse_lazy('treasury:billing')
+        return reverse_lazy('treasury:invoice')
 
 
-class BillingListView(LoginRequiredMixin, SingleTableView):
+class InvoiceListView(LoginRequiredMixin, SingleTableView):
     """
-    List existing Billings
+    List existing Invoices
     """
-    model = Billing
-    table_class = BillingTable
+    model = Invoice
+    table_class = InvoiceTable
 
 
-class BillingUpdateView(LoginRequiredMixin, UpdateView):
+class InvoiceUpdateView(LoginRequiredMixin, UpdateView):
     """
-    Create Billing
+    Create Invoice
     """
-    model = Billing
-    form_class = BillingForm
+    model = Invoice
+    form_class = InvoiceForm
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
@@ -119,27 +119,27 @@ class BillingUpdateView(LoginRequiredMixin, UpdateView):
                 else:
                     f.instance = None
 
-        Product.objects.filter(~Q(pk__in=saved), billing=form.instance).delete()
+        Product.objects.filter(~Q(pk__in=saved), invoice=form.instance).delete()
 
         return ret
 
     def get_success_url(self):
-        return reverse_lazy('treasury:billing')
+        return reverse_lazy('treasury:invoice')
 
 
-class BillingRenderView(LoginRequiredMixin, View):
+class InvoiceRenderView(LoginRequiredMixin, View):
     """
-    Render Billing as generated PDF
+    Render Invoice as generated PDF
     """
 
     def get(self, request, **kwargs):
         pk = kwargs["pk"]
-        billing = Billing.objects.get(pk=pk)
-        products = Product.objects.filter(billing=billing).all()
+        invoice = Invoice.objects.get(pk=pk)
+        products = Product.objects.filter(invoice=invoice).all()
 
-        billing.description = billing.description.replace("\n", "\\newline\n")
-        billing.address = billing.address.replace("\n", "\\newline\n")
-        tex = render_to_string("treasury/billing_sample.tex", dict(obj=billing, products=products))
+        invoice.description = invoice.description.replace("\n", "\\newline\n")
+        invoice.address = invoice.address.replace("\n", "\\newline\n")
+        tex = render_to_string("treasury/invoice_sample.tex", dict(obj=invoice, products=products))
         try:
             os.mkdir(BASE_DIR + "/tmp")
         except FileExistsError:
@@ -147,13 +147,13 @@ class BillingRenderView(LoginRequiredMixin, View):
         tmp_dir = mkdtemp(prefix=BASE_DIR + "/tmp/")
 
         try:
-            with open("{}/billing-{:d}.tex".format(tmp_dir, pk), "wb") as f:
+            with open("{}/invoice-{:d}.tex".format(tmp_dir, pk), "wb") as f:
                 f.write(tex.encode("UTF-8"))
             del tex
 
             for _ in range(2):
                 error = subprocess.Popen(
-                    ["pdflatex", "billing-{}.tex".format(pk)],
+                    ["pdflatex", "invoice-{}.tex".format(pk)],
                     cwd=tmp_dir,
                     stdin=open(os.devnull, "r"),
                     stderr=open(os.devnull, "wb"),
@@ -161,11 +161,11 @@ class BillingRenderView(LoginRequiredMixin, View):
                 ).wait()
 
                 if error:
-                    raise IOError("An error attempted while generating a billing (code=" + str(error) + ")")
+                    raise IOError("An error attempted while generating a invoice (code=" + str(error) + ")")
 
-            pdf = open("{}/billing-{}.pdf".format(tmp_dir, pk), 'rb').read()
+            pdf = open("{}/invoice-{}.pdf".format(tmp_dir, pk), 'rb').read()
             response = HttpResponse(pdf, content_type="application/pdf")
-            response['Content-Disposition'] = "inline;filename=billing-{:d}.pdf".format(pk)
+            response['Content-Disposition'] = "inline;filename=invoice-{:d}.pdf".format(pk)
         except IOError as e:
             raise e
         finally:
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 69168864..29ec1bdc 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-03-21 17:00+0100\n"
+"POT-Creation-Date: 2020-03-22 01:15+0100\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"
@@ -23,9 +23,9 @@ msgid "activity"
 msgstr ""
 
 #: apps/activity/models.py:19 apps/activity/models.py:44
-#: apps/member/models.py:61 apps/member/models.py:112
+#: apps/member/models.py:63 apps/member/models.py:114
 #: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
-#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:202
+#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:198
 #: templates/member/profile_detail.html:15
 msgid "name"
 msgstr ""
@@ -52,7 +52,7 @@ msgid "description"
 msgstr ""
 
 #: apps/activity/models.py:54 apps/note/models/notes.py:164
-#: apps/note/models/transactions.py:62 apps/note/models/transactions.py:115
+#: apps/note/models/transactions.py:62
 msgid "type"
 msgstr ""
 
@@ -144,114 +144,114 @@ msgstr ""
 msgid "member"
 msgstr ""
 
-#: apps/member/models.py:23
+#: apps/member/models.py:25
 msgid "phone number"
 msgstr ""
 
-#: apps/member/models.py:29 templates/member/profile_detail.html:28
+#: apps/member/models.py:31 templates/member/profile_detail.html:28
 msgid "section"
 msgstr ""
 
-#: apps/member/models.py:30
+#: apps/member/models.py:32
 msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 msgstr ""
 
-#: apps/member/models.py:36 templates/member/profile_detail.html:31
+#: apps/member/models.py:38 templates/member/profile_detail.html:31
 msgid "address"
 msgstr ""
 
-#: apps/member/models.py:42
+#: apps/member/models.py:44
 msgid "paid"
 msgstr ""
 
-#: apps/member/models.py:47 apps/member/models.py:48
+#: apps/member/models.py:49 apps/member/models.py:50
 msgid "user profile"
 msgstr ""
 
-#: apps/member/models.py:66
+#: apps/member/models.py:68
 msgid "email"
 msgstr ""
 
-#: apps/member/models.py:71
+#: apps/member/models.py:73
 msgid "membership fee"
 msgstr ""
 
-#: apps/member/models.py:75
+#: apps/member/models.py:77
 msgid "membership duration"
 msgstr ""
 
-#: apps/member/models.py:76
+#: apps/member/models.py:78
 msgid "The longest time a membership can last (NULL = infinite)."
 msgstr ""
 
-#: apps/member/models.py:81
+#: apps/member/models.py:83
 msgid "membership start"
 msgstr ""
 
-#: apps/member/models.py:82
+#: apps/member/models.py:84
 msgid "How long after January 1st the members can renew their membership."
 msgstr ""
 
-#: apps/member/models.py:87
+#: apps/member/models.py:89
 msgid "membership end"
 msgstr ""
 
-#: apps/member/models.py:88
+#: apps/member/models.py:90
 msgid ""
 "How long the membership can last after January 1st of the next year after "
 "members can renew their membership."
 msgstr ""
 
-#: apps/member/models.py:94 apps/note/models/notes.py:139
+#: apps/member/models.py:96 apps/note/models/notes.py:139
 msgid "club"
 msgstr ""
 
-#: apps/member/models.py:95
+#: apps/member/models.py:97
 msgid "clubs"
 msgstr ""
 
-#: apps/member/models.py:118 apps/permission/models.py:276
+#: apps/member/models.py:120 apps/permission/models.py:276
 msgid "role"
 msgstr ""
 
-#: apps/member/models.py:119
+#: apps/member/models.py:121
 msgid "roles"
 msgstr ""
 
-#: apps/member/models.py:143
+#: apps/member/models.py:145
 msgid "membership starts on"
 msgstr ""
 
-#: apps/member/models.py:146
+#: apps/member/models.py:148
 msgid "membership ends on"
 msgstr ""
 
-#: apps/member/models.py:150
+#: apps/member/models.py:152
 msgid "fee"
 msgstr ""
 
-#: apps/member/models.py:154
+#: apps/member/models.py:162
 msgid "membership"
 msgstr ""
 
-#: apps/member/models.py:155
+#: apps/member/models.py:163
 msgid "memberships"
 msgstr ""
 
-#: apps/member/views.py:69 templates/member/profile_detail.html:46
+#: apps/member/views.py:80 templates/member/profile_detail.html:46
 msgid "Update Profile"
 msgstr ""
 
-#: apps/member/views.py:82
+#: apps/member/views.py:93
 msgid "An alias with a similar name already exists."
 msgstr ""
 
-#: apps/member/views.py:132
+#: apps/member/views.py:146
 #, python-format
 msgid "Account #%(id)s: %(username)s"
 msgstr ""
 
-#: apps/member/views.py:202
+#: apps/member/views.py:216
 msgid "Alias successfully deleted"
 msgstr ""
 
@@ -416,70 +416,61 @@ msgstr ""
 msgid "quantity"
 msgstr ""
 
-#: apps/note/models/transactions.py:117 templates/note/transaction_form.html:15
-msgid "Gift"
-msgstr ""
-
-#: apps/note/models/transactions.py:118 templates/base.html:90
-#: templates/note/transaction_form.html:19
-#: templates/note/transaction_form.html:126
-msgid "Transfer"
+#: apps/note/models/transactions.py:115
+msgid "reason"
 msgstr ""
 
 #: apps/note/models/transactions.py:119
-msgid "Template"
-msgstr ""
-
-#: apps/note/models/transactions.py:120 templates/note/transaction_form.html:23
-msgid "Credit"
+msgid "valid"
 msgstr ""
 
-#: apps/note/models/transactions.py:121 templates/note/transaction_form.html:27
-msgid "Debit"
+#: apps/note/models/transactions.py:124
+msgid "transaction"
 msgstr ""
 
-#: apps/note/models/transactions.py:122 apps/note/models/transactions.py:230
-msgid "membership transaction"
+#: apps/note/models/transactions.py:125
+msgid "transactions"
 msgstr ""
 
-#: apps/note/models/transactions.py:129
-msgid "reason"
+#: apps/note/models/transactions.py:168 templates/base.html:98
+#: templates/note/transaction_form.html:19
+#: templates/note/transaction_form.html:145
+msgid "Transfer"
 msgstr ""
 
-#: apps/note/models/transactions.py:133
-msgid "valid"
+#: apps/note/models/transactions.py:188
+msgid "Template"
 msgstr ""
 
-#: apps/note/models/transactions.py:138
-msgid "transaction"
+#: apps/note/models/transactions.py:203
+msgid "first_name"
 msgstr ""
 
-#: apps/note/models/transactions.py:139
-msgid "transactions"
+#: apps/note/models/transactions.py:208
+msgid "bank"
 msgstr ""
 
-#: apps/note/models/transactions.py:190
-msgid "membership transaction"
+#: apps/note/models/transactions.py:214 templates/note/transaction_form.html:24
+msgid "Credit"
 msgstr ""
 
-#: apps/note/models/transactions.py:207
-msgid "first_name"
+#: apps/note/models/transactions.py:214 templates/note/transaction_form.html:28
+msgid "Debit"
 msgstr ""
 
-#: apps/note/models/transactions.py:191
-#: apps/note/models/transactions.py:212
-msgid "bank"
+#: apps/note/models/transactions.py:230 apps/note/models/transactions.py:235
+msgid "membership transaction"
 msgstr ""
 
 #: apps/note/models/transactions.py:231
 msgid "membership transactions"
 msgstr ""
 
-#: apps/note/views.py:31
+#: apps/note/views.py:39
 msgid "Transfer money"
 msgstr ""
 
-#: apps/note/views.py:144 templates/base.html:70
+#: apps/note/views.py:145 templates/base.html:79
 msgid "Consumptions"
 msgstr ""
 
@@ -501,12 +492,12 @@ msgstr ""
 msgid "Specifying field applies only to view and change permission types."
 msgstr ""
 
-#: apps/treasury/apps.py:11 templates/base.html:85
+#: apps/treasury/apps.py:10 templates/base.html:102
 msgid "Treasury"
 msgstr ""
 
 #: apps/treasury/models.py:11
-msgid "Billing identifier"
+msgid "Invoice identifier"
 msgstr ""
 
 #: apps/treasury/models.py:25
@@ -521,7 +512,7 @@ msgstr ""
 msgid "Description"
 msgstr ""
 
-#: apps/treasury/models.py:39
+#: apps/treasury/models.py:39 templates/note/transaction_form.html:86
 msgid "Name"
 msgstr ""
 
@@ -581,30 +572,30 @@ msgstr ""
 msgid "Unit price"
 msgstr ""
 
-#: apps/note/views.py:132 templates/base.html:78
-msgid "Consumptions"
+#: apps/treasury/tables.py:14
+msgid "Invoice #{:d}"
 msgstr ""
 
 #: apps/treasury/tables.py:17
-msgid "Billing"
+msgid "Invoice"
 msgstr ""
 
-#: note_kfet/settings/__init__.py:61
+#: note_kfet/settings/__init__.py:63
 msgid ""
 "The Central Authentication Service grants you access to most of our websites "
 "by authenticating only once, so you don't need to type your credentials "
 "again unless your session expires or you logout."
 msgstr ""
 
-#: note_kfet/settings/base.py:157
+#: note_kfet/settings/base.py:153
 msgid "German"
 msgstr ""
 
-#: note_kfet/settings/base.py:158
+#: note_kfet/settings/base.py:154
 msgid "English"
 msgstr ""
 
-#: note_kfet/settings/base.py:159
+#: note_kfet/settings/base.py:155
 msgid "French"
 msgstr ""
 
@@ -612,22 +603,18 @@ msgstr ""
 msgid "The ENS Paris-Saclay BDE note."
 msgstr ""
 
-#: templates/base.html:81
+#: templates/base.html:84
 msgid "Clubs"
 msgstr ""
 
-#: templates/base.html:84
+#: templates/base.html:89
 msgid "Activities"
 msgstr ""
 
-#: templates/base.html:79
+#: templates/base.html:94
 msgid "Buttons"
 msgstr ""
 
-#: templates/base.html:82 templates/note/transaction_form.html:35
-msgid "Transfer"
-msgstr ""
-
 #: templates/cas_server/base.html:7
 msgid "Central Authentication Service"
 msgstr ""
@@ -684,8 +671,7 @@ msgid "Field filters"
 msgstr ""
 
 #: templates/django_filters/rest_framework/form.html:5
-#: templates/member/club_form.html:10 templates/treasury/billing_form.html:38
-#: templates/member/club_form.html:10
+#: templates/member/club_form.html:10 templates/treasury/invoice_form.html:47
 msgid "Submit"
 msgstr ""
 
@@ -770,7 +756,7 @@ msgstr ""
 msgid "Sign up"
 msgstr ""
 
-#: templates/note/conso_form.html:28 templates/note/transaction_form.html:38
+#: templates/note/conso_form.html:28 templates/note/transaction_form.html:40
 msgid "Select emitters"
 msgstr ""
 
@@ -798,55 +784,52 @@ msgstr ""
 msgid "Double consumptions"
 msgstr ""
 
-#: templates/note/conso_form.html:141
+#: templates/note/conso_form.html:141 templates/note/transaction_form.html:152
 msgid "Recent transactions history"
 msgstr ""
 
-#: templates/note/transaction_form.html:55
-msgid "External payment"
+#: templates/note/transaction_form.html:15
+msgid "Gift"
 msgstr ""
 
-#: templates/note/transaction_form.html:63
-msgid "Transfer type"
+#: templates/note/transaction_form.html:68
+msgid "External payment"
 msgstr ""
 
-#: templates/note/transaction_form.html:73
-msgid "Name"
+#: templates/note/transaction_form.html:76
+msgid "Transfer type"
 msgstr ""
 
-#: templates/note/transaction_form.html:79
+#: templates/note/transaction_form.html:92
 msgid "First name"
 msgstr ""
 
-#: templates/note/transaction_form.html:85
+#: templates/note/transaction_form.html:98
 msgid "Bank"
 msgstr ""
 
-#: templates/note/transaction_form.html:97
-#: templates/note/transaction_form.html:179
-#: templates/note/transaction_form.html:186
+#: templates/note/transaction_form.html:111
+#: templates/note/transaction_form.html:169
+#: templates/note/transaction_form.html:176
 msgid "Select receivers"
 msgstr ""
 
-#: templates/note/transaction_form.html:114
+#: templates/note/transaction_form.html:128
 msgid "Amount"
 msgstr ""
 
-#: templates/note/transaction_form.html:119
+#: templates/note/transaction_form.html:138
 msgid "Reason"
 msgstr ""
 
-#: templates/note/transaction_form.html:193
+#: templates/note/transaction_form.html:183
 msgid "Credit note"
 msgstr ""
 
-#: templates/note/transaction_form.html:200
+#: templates/note/transaction_form.html:190
 msgid "Debit note"
 msgstr ""
 
-msgid "Sign up"
-msgstr ""
-
 #: templates/note/transactiontemplate_form.html:6
 msgid "Buttons list"
 msgstr ""
@@ -929,18 +912,18 @@ msgstr ""
 msgid "Reset my password"
 msgstr ""
 
-#: templates/treasury/billing_form.html:6
-msgid "Billings list"
+#: templates/treasury/invoice_form.html:6
+msgid "Invoices list"
 msgstr ""
 
-#: templates/treasury/billing_form.html:33
+#: templates/treasury/invoice_form.html:42
 msgid "Add product"
 msgstr ""
 
-#: templates/treasury/billing_form.html:34
+#: templates/treasury/invoice_form.html:43
 msgid "Remove product"
 msgstr ""
 
-#: templates/treasury/billing_list.html:8
-msgid "New billing"
+#: templates/treasury/invoice_list.html:8
+msgid "New invoice"
 msgstr ""
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 479ff0ad..b137cc0e 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-03-21 17:00+0100\n"
+"POT-Creation-Date: 2020-03-22 01:15+0100\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"
@@ -18,9 +18,10 @@ msgid "activity"
 msgstr "activité"
 
 #: apps/activity/models.py:19 apps/activity/models.py:44
-#: apps/member/models.py:61 apps/member/models.py:112
+#: apps/member/models.py:63 apps/member/models.py:114
 #: apps/note/models/notes.py:188 apps/note/models/transactions.py:24
-#: apps/note/models/transactions.py:44 templates/member/profile_detail.html:15
+#: apps/note/models/transactions.py:44 apps/note/models/transactions.py:198
+#: templates/member/profile_detail.html:15
 msgid "name"
 msgstr "nom"
 
@@ -138,61 +139,61 @@ msgstr "Les logs ne peuvent pas être détruits."
 msgid "member"
 msgstr "adhérent"
 
-#: apps/member/models.py:23
+#: apps/member/models.py:25
 msgid "phone number"
 msgstr "numéro de téléphone"
 
-#: apps/member/models.py:29 templates/member/profile_detail.html:28
+#: apps/member/models.py:31 templates/member/profile_detail.html:28
 msgid "section"
 msgstr "section"
 
-#: apps/member/models.py:30
+#: apps/member/models.py:32
 msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
 
-#: apps/member/models.py:36 templates/member/profile_detail.html:31
+#: apps/member/models.py:38 templates/member/profile_detail.html:31
 msgid "address"
 msgstr "adresse"
 
-#: apps/member/models.py:42
+#: apps/member/models.py:44
 msgid "paid"
 msgstr "payé"
 
-#: apps/member/models.py:47 apps/member/models.py:48
+#: apps/member/models.py:49 apps/member/models.py:50
 msgid "user profile"
 msgstr "profil utilisateur"
 
-#: apps/member/models.py:66
+#: apps/member/models.py:68
 msgid "email"
 msgstr "courriel"
 
-#: apps/member/models.py:71
+#: apps/member/models.py:73
 msgid "membership fee"
 msgstr "cotisation pour adhérer"
 
-#: apps/member/models.py:75
+#: apps/member/models.py:77
 msgid "membership duration"
 msgstr "durée de l'adhésion"
 
-#: apps/member/models.py:76
+#: apps/member/models.py:78
 msgid "The longest time a membership can last (NULL = infinite)."
 msgstr "La durée maximale d'une adhésion (NULL = infinie)."
 
-#: apps/member/models.py:81
+#: apps/member/models.py:83
 msgid "membership start"
 msgstr "début de l'adhésion"
 
-#: apps/member/models.py:82
+#: apps/member/models.py:84
 msgid "How long after January 1st the members can renew their membership."
 msgstr ""
 "Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur "
 "adhésion."
 
-#: apps/member/models.py:87
+#: apps/member/models.py:89
 msgid "membership end"
 msgstr "fin de l'adhésion"
 
-#: apps/member/models.py:88
+#: apps/member/models.py:90
 msgid ""
 "How long the membership can last after January 1st of the next year after "
 "members can renew their membership."
@@ -200,65 +201,65 @@ msgstr ""
 "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année "
 "suivante avant que les adhérents peuvent renouveler leur adhésion."
 
-#: apps/member/models.py:94 apps/note/models/notes.py:139
+#: apps/member/models.py:96 apps/note/models/notes.py:139
 msgid "club"
 msgstr "club"
 
-#: apps/member/models.py:95
+#: apps/member/models.py:97
 msgid "clubs"
 msgstr "clubs"
 
-#: apps/member/models.py:118 apps/permission/models.py:276
+#: apps/member/models.py:120 apps/permission/models.py:276
 msgid "role"
 msgstr "rôle"
 
-#: apps/member/models.py:119
+#: apps/member/models.py:121
 msgid "roles"
 msgstr "rôles"
 
-#: apps/member/models.py:143
+#: apps/member/models.py:145
 msgid "membership starts on"
 msgstr "l'adhésion commence le"
 
-#: apps/member/models.py:146
+#: apps/member/models.py:148
 msgid "membership ends on"
 msgstr "l'adhésion finie le"
 
-#: apps/member/models.py:150
+#: apps/member/models.py:152
 msgid "fee"
 msgstr "cotisation"
 
-#: apps/member/models.py:154
+#: apps/member/models.py:162
 msgid "membership"
 msgstr "adhésion"
 
-#: apps/member/models.py:155
+#: apps/member/models.py:163
 msgid "memberships"
 msgstr "adhésions"
 
-#: apps/member/views.py:69 templates/member/profile_detail.html:46
+#: apps/member/views.py:80 templates/member/profile_detail.html:46
 msgid "Update Profile"
 msgstr "Modifier le profil"
 
-#: apps/member/views.py:82
+#: apps/member/views.py:93
 msgid "An alias with a similar name already exists."
 msgstr "Un alias avec un nom similaire existe déjà."
 
-#: apps/member/views.py:132
+#: apps/member/views.py:146
 #, python-format
 msgid "Account #%(id)s: %(username)s"
 msgstr "Compte n°%(id)s : %(username)s"
 
-#: apps/member/views.py:202
+#: apps/member/views.py:216
 msgid "Alias successfully deleted"
 msgstr "L'alias a bien été supprimé"
 
-#: apps/note/admin.py:120 apps/note/models/transactions.py:93
+#: apps/note/admin.py:120 apps/note/models/transactions.py:94
 msgid "source"
 msgstr "source"
 
 #: apps/note/admin.py:128 apps/note/admin.py:156
-#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:99
+#: apps/note/models/transactions.py:53 apps/note/models/transactions.py:100
 msgid "destination"
 msgstr "destination"
 
@@ -278,10 +279,6 @@ msgstr "Choisissez une image"
 msgid "Maximal size: 2MB"
 msgstr "Taille maximale : 2 Mo"
 
-#: apps/note/forms.py:70
-msgid "Source and destination must be different."
-msgstr "La source et la destination doivent être différentes."
-
 #: apps/note/models/notes.py:27
 msgid "account balance"
 msgstr "solde du compte"
@@ -313,7 +310,7 @@ msgstr ""
 msgid "display image"
 msgstr "image affichée"
 
-#: apps/note/models/notes.py:53 apps/note/models/transactions.py:102
+#: apps/note/models/notes.py:53 apps/note/models/transactions.py:103
 msgid "created at"
 msgstr "créée le"
 
@@ -399,7 +396,7 @@ msgstr "catégories de transaction"
 msgid "A template with this name already exist"
 msgstr "Un modèle de transaction avec un nom similaire existe déjà."
 
-#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:109
+#: apps/note/models/transactions.py:56 apps/note/models/transactions.py:111
 msgid "amount"
 msgstr "montant"
 
@@ -407,47 +404,73 @@ msgstr "montant"
 msgid "in centimes"
 msgstr "en centimes"
 
-#: apps/note/models/transactions.py:74
+#: apps/note/models/transactions.py:75
 msgid "transaction template"
 msgstr "modèle de transaction"
 
-#: apps/note/models/transactions.py:75
+#: apps/note/models/transactions.py:76
 msgid "transaction templates"
 msgstr "modèles de transaction"
 
-#: apps/note/models/transactions.py:106
+#: apps/note/models/transactions.py:107
 msgid "quantity"
 msgstr "quantité"
 
-#: apps/note/models/transactions.py:111
+#: apps/note/models/transactions.py:115
 msgid "reason"
 msgstr "raison"
 
-#: apps/note/models/transactions.py:115
+#: apps/note/models/transactions.py:119
 msgid "valid"
 msgstr "valide"
 
-#: apps/note/models/transactions.py:120
+#: apps/note/models/transactions.py:124
 msgid "transaction"
 msgstr "transaction"
 
-#: apps/note/models/transactions.py:121
+#: apps/note/models/transactions.py:125
 msgid "transactions"
 msgstr "transactions"
 
-#: apps/note/models/transactions.py:190
+#: apps/note/models/transactions.py:168 templates/base.html:98
+#: templates/note/transaction_form.html:19
+#: templates/note/transaction_form.html:145
+msgid "Transfer"
+msgstr "Virement"
+
+#: apps/note/models/transactions.py:188
+msgid "Template"
+msgstr "Bouton"
+
+#: apps/note/models/transactions.py:203
+msgid "first_name"
+msgstr "prénom"
+
+#: apps/note/models/transactions.py:208
+msgid "bank"
+msgstr "banque"
+
+#: apps/note/models/transactions.py:214 templates/note/transaction_form.html:24
+msgid "Credit"
+msgstr "Crédit"
+
+#: apps/note/models/transactions.py:214 templates/note/transaction_form.html:28
+msgid "Debit"
+msgstr "Débit"
+
+#: apps/note/models/transactions.py:230 apps/note/models/transactions.py:235
 msgid "membership transaction"
 msgstr "transaction d'adhésion"
 
-#: apps/note/models/transactions.py:191
+#: apps/note/models/transactions.py:231
 msgid "membership transactions"
 msgstr "transactions d'adhésion"
 
-#: apps/note/views.py:31
-msgid "Transfer money from your account to one or others"
-msgstr "Transfert d'argent de ton compte vers un ou plusieurs autres"
+#: apps/note/views.py:39
+msgid "Transfer money"
+msgstr "Transférer de l'argent"
 
-#: apps/note/views.py:144 templates/base.html:70
+#: apps/note/views.py:145 templates/base.html:79
 msgid "Consumptions"
 msgstr "Consommations"
 
@@ -469,12 +492,12 @@ msgstr "Rang"
 msgid "Specifying field applies only to view and change permission types."
 msgstr ""
 
-#: apps/treasury/apps.py:11 templates/base.html:85
+#: apps/treasury/apps.py:10 templates/base.html:102
 msgid "Treasury"
 msgstr "Trésorerie"
 
 #: apps/treasury/models.py:11
-msgid "Billing identifier"
+msgid "Invoice identifier"
 msgstr "Numéro de facture"
 
 #: apps/treasury/models.py:25
@@ -489,7 +512,7 @@ msgstr "Objet"
 msgid "Description"
 msgstr "Description"
 
-#: apps/treasury/models.py:39
+#: apps/treasury/models.py:39 templates/note/transaction_form.html:86
 msgid "Name"
 msgstr "Nom"
 
@@ -550,29 +573,29 @@ msgid "Unit price"
 msgstr "Prix unitaire"
 
 #: apps/treasury/tables.py:14
-msgid "Billing #{:d}"
+msgid "Invoice #{:d}"
 msgstr "Facture n°{:d}"
 
 #: apps/treasury/tables.py:17
-msgid "Billing"
+msgid "Invoice"
 msgstr "Facture"
 
-#: note_kfet/settings/__init__.py:61
+#: note_kfet/settings/__init__.py:63
 msgid ""
 "The Central Authentication Service grants you access to most of our websites "
 "by authenticating only once, so you don't need to type your credentials "
 "again unless your session expires or you logout."
 msgstr ""
 
-#: note_kfet/settings/base.py:157
+#: note_kfet/settings/base.py:153
 msgid "German"
 msgstr ""
 
-#: note_kfet/settings/base.py:158
+#: note_kfet/settings/base.py:154
 msgid "English"
 msgstr ""
 
-#: note_kfet/settings/base.py:159
+#: note_kfet/settings/base.py:155
 msgid "French"
 msgstr ""
 
@@ -580,22 +603,18 @@ msgstr ""
 msgid "The ENS Paris-Saclay BDE note."
 msgstr "La note du BDE de l'ENS Paris-Saclay."
 
-#: templates/base.html:73
+#: templates/base.html:84
 msgid "Clubs"
 msgstr "Clubs"
 
-#: templates/base.html:76
+#: templates/base.html:89
 msgid "Activities"
 msgstr "Activités"
 
-#: templates/base.html:79
+#: templates/base.html:94
 msgid "Buttons"
 msgstr "Boutons"
 
-#: templates/base.html:82 templates/note/transaction_form.html:35
-msgid "Transfer"
-msgstr "Virement"
-
 #: templates/cas_server/base.html:7
 msgid "Central Authentication Service"
 msgstr ""
@@ -654,9 +673,9 @@ msgid "Field filters"
 msgstr ""
 
 #: templates/django_filters/rest_framework/form.html:5
-#: templates/member/club_form.html:10 templates/treasury/billing_form.html:38
+#: templates/member/club_form.html:10 templates/treasury/invoice_form.html:47
 msgid "Submit"
-msgstr ""
+msgstr "Envoyer"
 
 #: templates/member/club_detail.html:10
 msgid "Membership starts on"
@@ -704,15 +723,15 @@ msgstr "Ajouter un alias"
 
 #: templates/member/profile_detail.html:15
 msgid "first name"
-msgstr ""
+msgstr "prénom"
 
 #: templates/member/profile_detail.html:18
 msgid "username"
-msgstr ""
+msgstr "pseudo"
 
 #: templates/member/profile_detail.html:21
 msgid "password"
-msgstr ""
+msgstr "mot de passe"
 
 #: templates/member/profile_detail.html:24
 msgid "Change password"
@@ -739,6 +758,80 @@ msgstr "Sauvegarder les changements"
 msgid "Sign up"
 msgstr "Inscription"
 
+#: templates/note/conso_form.html:28 templates/note/transaction_form.html:40
+msgid "Select emitters"
+msgstr "Sélection des émetteurs"
+
+#: templates/note/conso_form.html:45
+msgid "Select consumptions"
+msgstr "Sélection des consommations"
+
+#: templates/note/conso_form.html:51
+msgid "Consume!"
+msgstr "Consommer !"
+
+#: templates/note/conso_form.html:64
+msgid "Most used buttons"
+msgstr "Boutons les plus utilisés"
+
+#: templates/note/conso_form.html:121
+msgid "Edit"
+msgstr "Éditer"
+
+#: templates/note/conso_form.html:126
+msgid "Single consumptions"
+msgstr "Consommations simples"
+
+#: templates/note/conso_form.html:130
+msgid "Double consumptions"
+msgstr "Consommations doubles"
+
+#: templates/note/conso_form.html:141 templates/note/transaction_form.html:152
+msgid "Recent transactions history"
+msgstr "Historique des transactions récentes"
+
+#: templates/note/transaction_form.html:15
+msgid "Gift"
+msgstr "Don"
+
+#: templates/note/transaction_form.html:68
+msgid "External payment"
+msgstr "Paiement externe"
+
+#: templates/note/transaction_form.html:76
+msgid "Transfer type"
+msgstr "Type de transfert"
+
+#: templates/note/transaction_form.html:92
+msgid "First name"
+msgstr "Prénom"
+
+#: templates/note/transaction_form.html:98
+msgid "Bank"
+msgstr "Banque"
+
+#: templates/note/transaction_form.html:111
+#: templates/note/transaction_form.html:169
+#: templates/note/transaction_form.html:176
+msgid "Select receivers"
+msgstr "Sélection des destinataires"
+
+#: templates/note/transaction_form.html:128
+msgid "Amount"
+msgstr "Montant"
+
+#: templates/note/transaction_form.html:138
+msgid "Reason"
+msgstr "Raison"
+
+#: templates/note/transaction_form.html:183
+msgid "Credit note"
+msgstr "Note à recharger"
+
+#: templates/note/transaction_form.html:190
+msgid "Debit note"
+msgstr "Note à débiter"
+
 #: templates/note/transactiontemplate_form.html:6
 msgid "Buttons list"
 msgstr "Liste des boutons"
@@ -821,18 +914,24 @@ msgstr ""
 msgid "Reset my password"
 msgstr ""
 
-#: templates/treasury/billing_form.html:6
-msgid "Billings list"
+#: templates/treasury/invoice_form.html:6
+msgid "Invoices list"
 msgstr "Liste des factures"
 
-#: templates/treasury/billing_form.html:33
+#: templates/treasury/invoice_form.html:42
 msgid "Add product"
 msgstr "Ajouter produit"
 
-#: templates/treasury/billing_form.html:34
+#: templates/treasury/invoice_form.html:43
 msgid "Remove product"
 msgstr "Retirer produit"
 
-#: templates/treasury/billing_list.html:8
-msgid "New billing"
+#: templates/treasury/invoice_list.html:8
+msgid "New invoice"
 msgstr "Nouvelle facture"
+
+#~ msgid "Source and destination must be different."
+#~ msgstr "La source et la destination doivent être différentes."
+
+#~ msgid "Transfer money from your account to one or others"
+#~ msgstr "Transfert d'argent de ton compte vers un ou plusieurs autres"
diff --git a/templates/base.html b/templates/base.html
index f96a16dd..c6bb88b3 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -97,9 +97,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
                 <li class="nav-item active">
                     <a class="nav-link" href="{% url 'note:transfer' %}"><i class="fa fa-exchange"></i>{% trans 'Transfer' %} </a>
                 </li>
-                {% if "treasury.billing"|not_empty_model_change_list %}
+                {% if "treasury.invoice"|not_empty_model_change_list %}
                     <li class="nav-item active">
-                        <a class="nav-link" href="{% url 'treasury:billing' %}"><i class="fa fa-money"></i>{% trans 'Treasury' %} </a>
+                        <a class="nav-link" href="{% url 'treasury:invoice' %}"><i class="fa fa-money"></i>{% trans 'Treasury' %} </a>
                     </li>
                 {% endif %}
             </ul>
diff --git a/templates/treasury/billing_form.html b/templates/treasury/invoice_form.html
similarity index 95%
rename from templates/treasury/billing_form.html
rename to templates/treasury/invoice_form.html
index 9c1416ed..2177d0f7 100644
--- a/templates/treasury/billing_form.html
+++ b/templates/treasury/invoice_form.html
@@ -3,7 +3,7 @@
 {% load i18n %}
 {% load crispy_forms_tags pretty_money %}
 {% block content %}
-    <p><a class="btn btn-default" href="{% url 'treasury:billing' %}">{% trans "Billings list" %}</a></p>
+    <p><a class="btn btn-default" href="{% url 'treasury:invoice' %}">{% trans "Invoices list" %}</a></p>
     <form method="post" action="">
         {% csrf_token %}
         {% crispy form %}
@@ -31,7 +31,7 @@
                             </div>
                         </div>
                     </td>
-                    {{ form.billing }}
+                    {{ form.invoice }}
                     {{ form.id }}
                  </tr>
         {% endfor %}
@@ -63,7 +63,7 @@
                             </div>
                         </div>
                     </td>
-                    {{ formset.empty_form.billing }}
+                    {{ formset.empty_form.invoice }}
                     {{ formset.empty_form.id }}
                 </tr>
             </tbody>
diff --git a/templates/treasury/billing_list.html b/templates/treasury/invoice_list.html
similarity index 59%
rename from templates/treasury/billing_list.html
rename to templates/treasury/invoice_list.html
index 749c0767..f80e2342 100644
--- a/templates/treasury/billing_list.html
+++ b/templates/treasury/invoice_list.html
@@ -5,6 +5,6 @@
 
 {% render_table table %}
 
-<a class="btn btn-primary" href="{% url 'treasury:billing_create' %}">{% trans "New billing" %}</a>
+<a class="btn btn-primary" href="{% url 'treasury:invoice_create' %}">{% trans "New invoice" %}</a>
 
 {% endblock %}
diff --git a/templates/treasury/billing_sample.tex b/templates/treasury/invoice_sample.tex
similarity index 100%
rename from templates/treasury/billing_sample.tex
rename to templates/treasury/invoice_sample.tex
-- 
GitLab