mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-27 07:02:26 +00:00
Merge branch 'fix_93_store_custom_invoices' into 'dev'
Fix 93 store custom invoices See merge request federez/re2o!203
This commit is contained in:
commit
3cae0564ef
16 changed files with 891 additions and 447 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -136,3 +136,17 @@ Fix several issues with email accounts, you need to collect the static files.
|
||||||
```bash
|
```bash
|
||||||
./manage.py collectstatic
|
./manage.py collectstatic
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MR 203 Add custom invoices
|
||||||
|
|
||||||
|
The custom invoices are now stored in database. You need to migrate your database :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
On some database engines (postgreSQL) you also need to update the id sequences:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 manage.py sqlsequencereset cotisations | python3 manage.py dbshell
|
||||||
|
```
|
||||||
|
|
|
@ -30,6 +30,7 @@ from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
from .models import Facture, Article, Banque, Paiement, Cotisation, Vente
|
from .models import Facture, Article, Banque, Paiement, Cotisation, Vente
|
||||||
|
from .models import CustomInvoice
|
||||||
|
|
||||||
|
|
||||||
class FactureAdmin(VersionAdmin):
|
class FactureAdmin(VersionAdmin):
|
||||||
|
@ -37,6 +38,11 @@ class FactureAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CustomInvoiceAdmin(VersionAdmin):
|
||||||
|
"""Admin class for custom invoices."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class VenteAdmin(VersionAdmin):
|
class VenteAdmin(VersionAdmin):
|
||||||
"""Class admin d'une vente, tous les champs (facture related)"""
|
"""Class admin d'une vente, tous les champs (facture related)"""
|
||||||
pass
|
pass
|
||||||
|
@ -69,3 +75,4 @@ admin.site.register(Banque, BanqueAdmin)
|
||||||
admin.site.register(Paiement, PaiementAdmin)
|
admin.site.register(Paiement, PaiementAdmin)
|
||||||
admin.site.register(Vente, VenteAdmin)
|
admin.site.register(Vente, VenteAdmin)
|
||||||
admin.site.register(Cotisation, CotisationAdmin)
|
admin.site.register(Cotisation, CotisationAdmin)
|
||||||
|
admin.site.register(CustomInvoice, CustomInvoiceAdmin)
|
||||||
|
|
|
@ -46,7 +46,7 @@ from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from re2o.field_permissions import FieldPermissionFormMixin
|
from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
from re2o.mixins import FormRevMixin
|
from re2o.mixins import FormRevMixin
|
||||||
from .models import Article, Paiement, Facture, Banque
|
from .models import Article, Paiement, Facture, Banque, CustomInvoice
|
||||||
from .payment_methods import balance
|
from .payment_methods import balance
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,24 +131,13 @@ class SelectClubArticleForm(Form):
|
||||||
self.fields['article'].queryset = Article.find_allowed_articles(user)
|
self.fields['article'].queryset = Article.find_allowed_articles(user)
|
||||||
|
|
||||||
|
|
||||||
# TODO : change Facture to Invoice
|
class CustomInvoiceForm(FormRevMixin, ModelForm):
|
||||||
class NewFactureFormPdf(Form):
|
|
||||||
"""
|
"""
|
||||||
Form used to create a custom PDF invoice.
|
Form used to create a custom invoice.
|
||||||
"""
|
"""
|
||||||
paid = forms.BooleanField(label=_l("Paid"), required=False)
|
class Meta:
|
||||||
# TODO : change dest field to recipient
|
model = CustomInvoice
|
||||||
dest = forms.CharField(
|
fields = '__all__'
|
||||||
required=True,
|
|
||||||
max_length=255,
|
|
||||||
label=_l("Recipient")
|
|
||||||
)
|
|
||||||
# TODO : change chambre field to address
|
|
||||||
chambre = forms.CharField(
|
|
||||||
required=False,
|
|
||||||
max_length=10,
|
|
||||||
label=_l("Address")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ArticleForm(FormRevMixin, ModelForm):
|
class ArticleForm(FormRevMixin, ModelForm):
|
||||||
|
|
Binary file not shown.
|
@ -21,9 +21,9 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 2.5\n"
|
"Project-Id-Version: 2.5\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2018-05-10 15:21-0500\n"
|
"POT-Creation-Date: 2018-07-25 23:22+0200\n"
|
||||||
"PO-Revision-Date: 2018-03-31 16:09+0002\n"
|
"PO-Revision-Date: 2018-03-31 16:09+0002\n"
|
||||||
"Last-Translator: Maël Kervella <dev@maelkervella.eu>\n"
|
"Last-Translator: Hugo Levy-Falk <me@klafyvel.me>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: fr_FR\n"
|
"Language: fr_FR\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
@ -34,74 +34,39 @@ msgstr ""
|
||||||
msgid "You don't have the rights to see this application."
|
msgid "You don't have the rights to see this application."
|
||||||
msgstr "Vous n'avez pas les droits de voir cette application."
|
msgstr "Vous n'avez pas les droits de voir cette application."
|
||||||
|
|
||||||
#: forms.py:63 forms.py:321
|
#: forms.py:63 forms.py:274
|
||||||
msgid "Cheque number"
|
|
||||||
msgstr "Numéro de chèque"
|
|
||||||
|
|
||||||
#: forms.py:64 forms.py:322
|
|
||||||
msgid "Not specified"
|
|
||||||
msgstr "Non renseigné"
|
|
||||||
|
|
||||||
#: forms.py:66 forms.py:324
|
|
||||||
msgid "Select a payment method"
|
msgid "Select a payment method"
|
||||||
msgstr "Sélectionnez un moyen de paiement"
|
msgstr "Sélectionnez un moyen de paiement"
|
||||||
|
|
||||||
#: forms.py:83 forms.py:347
|
#: forms.py:66
|
||||||
msgid "A payment method must be specified."
|
|
||||||
msgstr "Un moyen de paiement doit être renseigné."
|
|
||||||
|
|
||||||
#: forms.py:87 forms.py:352
|
|
||||||
msgid "A cheque number and a bank must be specified."
|
|
||||||
msgstr "Un numéro de chèqe et une banque doivent être renseignés."
|
|
||||||
|
|
||||||
#: forms.py:184
|
|
||||||
msgid "Member"
|
msgid "Member"
|
||||||
msgstr "Adhérent"
|
msgstr "Adhérent"
|
||||||
|
|
||||||
#: forms.py:186
|
#: forms.py:68
|
||||||
msgid "Select the proprietary member"
|
msgid "Select the proprietary member"
|
||||||
msgstr "Sélectionnez l'adhérent propriétaire"
|
msgstr "Sélectionnez l'adhérent propriétaire"
|
||||||
|
|
||||||
#: forms.py:187
|
#: forms.py:69
|
||||||
msgid "Validated invoice"
|
msgid "Validated invoice"
|
||||||
msgstr "Facture validée"
|
msgstr "Facture validée"
|
||||||
|
|
||||||
#: forms.py:201
|
#: forms.py:82
|
||||||
|
msgid "A payment method must be specified."
|
||||||
|
msgstr "Un moyen de paiement doit être renseigné."
|
||||||
|
|
||||||
|
#: forms.py:154
|
||||||
msgid "Article name"
|
msgid "Article name"
|
||||||
msgstr "Nom de l'article"
|
msgstr "Nom de l'article"
|
||||||
|
|
||||||
#: forms.py:239
|
#: forms.py:192
|
||||||
msgid "Payment method name"
|
msgid "Payment method name"
|
||||||
msgstr "Nom du moyen de paiement"
|
msgstr "Nom du moyen de paiement"
|
||||||
|
|
||||||
#: forms.py:240
|
#: forms.py:230
|
||||||
msgid "Payment type"
|
|
||||||
msgstr "Type de paiement"
|
|
||||||
|
|
||||||
#: forms.py:242
|
|
||||||
msgid ""
|
|
||||||
"The payement type is used for specific behaviour. The \"cheque\" "
|
|
||||||
"type means a cheque number and a bank name may be added when "
|
|
||||||
"using this payment method."
|
|
||||||
msgstr ""
|
|
||||||
"Le type de paiement est utilisé pour des comportements spécifiques. Le type "
|
|
||||||
"\"chèque\" permet de spécifier un numéro de chèque et une banque lors de "
|
|
||||||
"l'utilisation de cette méthode."
|
|
||||||
|
|
||||||
#: forms.py:282
|
|
||||||
msgid "Bank name"
|
msgid "Bank name"
|
||||||
msgstr "Nom de la banque"
|
msgstr "Nom de la banque"
|
||||||
|
|
||||||
#: forms.py:380
|
#: forms.py:287
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Requested amount is too small. Minimum amount possible : "
|
|
||||||
"%(min_online_amount)s €."
|
|
||||||
msgstr ""
|
|
||||||
"Montant demandé est trop faible. Montant minimal possible : "
|
|
||||||
"%(min_online_amount)s €"
|
|
||||||
|
|
||||||
#: forms.py:390
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Requested amount is too high. Your balance can't exceed "
|
"Requested amount is too high. Your balance can't exceed "
|
||||||
|
@ -110,15 +75,15 @@ msgstr ""
|
||||||
"Montant demandé trop grand. Votre solde ne peut excéder "
|
"Montant demandé trop grand. Votre solde ne peut excéder "
|
||||||
"%(max_online_balance)s €"
|
"%(max_online_balance)s €"
|
||||||
|
|
||||||
#: models.py:165 models.py:213
|
#: models.py:175 models.py:223
|
||||||
msgid "You don't have the right to edit an invoice."
|
msgid "You don't have the right to edit an invoice."
|
||||||
msgstr "Vous n'avez pas le droit de modifier une facture."
|
msgstr "Vous n'avez pas le droit de modifier une facture."
|
||||||
|
|
||||||
#: models.py:168
|
#: models.py:178
|
||||||
msgid "You don't have the right to edit this user's invoices."
|
msgid "You don't have the right to edit this user's invoices."
|
||||||
msgstr "Vous n'avez pas le droit de modifier les facture de cette utilisateur."
|
msgstr "Vous n'avez pas le droit de modifier les facture de cette utilisateur."
|
||||||
|
|
||||||
#: models.py:172
|
#: models.py:182
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to edit an invoice already controlled or "
|
"You don't have the right to edit an invoice already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -126,15 +91,15 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de modifier une facture précedement controllée ou "
|
"Vous n'avez pas le droit de modifier une facture précedement controllée ou "
|
||||||
"invalidée."
|
"invalidée."
|
||||||
|
|
||||||
#: models.py:179
|
#: models.py:189
|
||||||
msgid "You don't have the right to delete an invoice."
|
msgid "You don't have the right to delete an invoice."
|
||||||
msgstr "Vous n'avez pas le droit de supprimer une facture."
|
msgstr "Vous n'avez pas le droit de supprimer une facture."
|
||||||
|
|
||||||
#: models.py:181
|
#: models.py:191
|
||||||
msgid "You don't have the right to delete this user's invoices."
|
msgid "You don't have the right to delete this user's invoices."
|
||||||
msgstr "Vous n'avez pas le droit de supprimer les factures de cet utilisateur."
|
msgstr "Vous n'avez pas le droit de supprimer les factures de cet utilisateur."
|
||||||
|
|
||||||
#: models.py:184
|
#: models.py:194
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to delete an invoice already controlled or "
|
"You don't have the right to delete an invoice already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -142,35 +107,41 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de supprimer une facture précedement controllée ou "
|
"Vous n'avez pas le droit de supprimer une facture précedement controllée ou "
|
||||||
"invalidée."
|
"invalidée."
|
||||||
|
|
||||||
#: models.py:192
|
#: models.py:202
|
||||||
msgid "You don't have the right to see someone else's invoices history."
|
msgid "You don't have the right to see someone else's invoices history."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous n'avez pas le droit de voir l'historique de la facture de quelqu'un "
|
"Vous n'avez pas le droit de voir l'historique de la facture de quelqu'un "
|
||||||
"d'autre."
|
"d'autre."
|
||||||
|
|
||||||
#: models.py:195
|
#: models.py:205
|
||||||
msgid "The invoice has been invalidated."
|
msgid "The invoice has been invalidated."
|
||||||
msgstr "La facture a été invalidée."
|
msgstr "La facture a été invalidée."
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:215
|
||||||
#, fuzzy
|
|
||||||
#| msgid "You don't have the right to edit the controlled state."
|
|
||||||
msgid "You don't have the right to edit the \"controlled\" state."
|
msgid "You don't have the right to edit the \"controlled\" state."
|
||||||
msgstr "Vous n'avez pas le droit de modifier l'état \"controllé\"."
|
msgstr "Vous n'avez pas le droit de modifier l'état \"controllé\"."
|
||||||
|
|
||||||
#: models.py:372
|
#: models.py:237
|
||||||
|
msgid "There are no payment types which you can use."
|
||||||
|
msgstr "Il n'y a pas de type de paiement que vous puissiez utiliser."
|
||||||
|
|
||||||
|
#: models.py:239
|
||||||
|
msgid "There are no article that you can buy."
|
||||||
|
msgstr "Il n'y a pas d'article qui vous soit autorisé."
|
||||||
|
|
||||||
|
#: models.py:424
|
||||||
msgid "A cotisation should always have a duration."
|
msgid "A cotisation should always have a duration."
|
||||||
msgstr "Une cotisation devrait toujours avoir une durée."
|
msgstr "Une cotisation devrait toujours avoir une durée."
|
||||||
|
|
||||||
#: models.py:379
|
#: models.py:431
|
||||||
msgid "You don't have the right to edit the purchases."
|
msgid "You don't have the right to edit the purchases."
|
||||||
msgstr "Vous n'avez pas le droit de modifier les achats."
|
msgstr "Vous n'avez pas le droit de modifier les achats."
|
||||||
|
|
||||||
#: models.py:384
|
#: models.py:436
|
||||||
msgid "You don't have the right to edit this user's purchases."
|
msgid "You don't have the right to edit this user's purchases."
|
||||||
msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur."
|
msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur."
|
||||||
|
|
||||||
#: models.py:388
|
#: models.py:440
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to edit a purchase already controlled or "
|
"You don't have the right to edit a purchase already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -178,15 +149,15 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de modifier un achat précédement controllé ou "
|
"Vous n'avez pas le droit de modifier un achat précédement controllé ou "
|
||||||
"invalidé."
|
"invalidé."
|
||||||
|
|
||||||
#: models.py:395
|
#: models.py:447
|
||||||
msgid "You don't have the right to delete a purchase."
|
msgid "You don't have the right to delete a purchase."
|
||||||
msgstr "Vous n'avez pas le droit de supprimer un achat."
|
msgstr "Vous n'avez pas le droit de supprimer un achat."
|
||||||
|
|
||||||
#: models.py:397
|
#: models.py:449
|
||||||
msgid "You don't have the right to delete this user's purchases."
|
msgid "You don't have the right to delete this user's purchases."
|
||||||
msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur."
|
msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur."
|
||||||
|
|
||||||
#: models.py:400
|
#: models.py:452
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to delete a purchase already controlled or "
|
"You don't have the right to delete a purchase already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -194,29 +165,46 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de supprimer un achat précédement controllé ou "
|
"Vous n'avez pas le droit de supprimer un achat précédement controllé ou "
|
||||||
"invalidé."
|
"invalidé."
|
||||||
|
|
||||||
#: models.py:408
|
#: models.py:460
|
||||||
msgid "You don't have the right to see someone else's purchase history."
|
msgid "You don't have the right to see someone else's purchase history."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous n'avez pas le droit de voir l'historique d'un achat de quelqu'un "
|
"Vous n'avez pas le droit de voir l'historique d'un achat de quelqu'un "
|
||||||
"d'autre."
|
"d'autre."
|
||||||
|
|
||||||
#: models.py:517
|
#: models.py:582
|
||||||
msgid "Solde is a reserved article name"
|
msgid "Solde is a reserved article name"
|
||||||
msgstr "Solde est un nom d'article réservé"
|
msgstr "Solde est un nom d'article réservé"
|
||||||
|
|
||||||
#: models.py:521
|
#: models.py:586
|
||||||
msgid "Duration must be specified for a cotisation"
|
msgid "Duration must be specified for a cotisation"
|
||||||
msgstr "La durée doit être spécifiée pour une cotisation"
|
msgstr "La durée doit être spécifiée pour une cotisation"
|
||||||
|
|
||||||
#: models.py:603
|
#: models.py:607
|
||||||
msgid "You cannot have multiple payment method of type cheque"
|
msgid "You cannot buy this Article."
|
||||||
msgstr "Vous ne pouvez avoir plusieurs moyens de paiement de type chèque"
|
msgstr "Vous ne pouvez pas acheter cet article."
|
||||||
|
|
||||||
#: models.py:654
|
#: models.py:713 payment_methods/comnpay/views.py:63
|
||||||
|
msgid ""
|
||||||
|
"The cotisation of %(member_name)s has been extended to %(end_date)s."
|
||||||
|
msgstr "La cotisation de %(member_name)s a été étendu jusqu'à %(end_date)s."
|
||||||
|
|
||||||
|
#: models.py:723
|
||||||
|
msgid "The invoice has been created."
|
||||||
|
msgstr "La facture a été créée."
|
||||||
|
|
||||||
|
#: models.py:744
|
||||||
|
msgid "You cannot use this Payment."
|
||||||
|
msgstr "Vous ne pouvez pas utiliser ce Paiement."
|
||||||
|
|
||||||
|
#: models.py:762
|
||||||
|
msgid "No custom payment method"
|
||||||
|
msgstr "Pas de méthode de paiement personnalisée"
|
||||||
|
|
||||||
|
#: models.py:811
|
||||||
msgid "You don't have the right to edit a cotisation."
|
msgid "You don't have the right to edit a cotisation."
|
||||||
msgstr "Vous n'avez pas le droit de modifier une cotisation."
|
msgstr "Vous n'avez pas le droit de modifier une cotisation."
|
||||||
|
|
||||||
#: models.py:658
|
#: models.py:815
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to edit a cotisation already controlled or "
|
"You don't have the right to edit a cotisation already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -224,11 +212,11 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de modifier une cotisaiton précédement controllée "
|
"Vous n'avez pas le droit de modifier une cotisaiton précédement controllée "
|
||||||
"ou invalidée."
|
"ou invalidée."
|
||||||
|
|
||||||
#: models.py:665
|
#: models.py:822
|
||||||
msgid "You don't have the right to delete a cotisation."
|
msgid "You don't have the right to delete a cotisation."
|
||||||
msgstr "Vous n'avez pas le droit de supprimer une cotisation."
|
msgstr "Vous n'avez pas le droit de supprimer une cotisation."
|
||||||
|
|
||||||
#: models.py:668
|
#: models.py:825
|
||||||
msgid ""
|
msgid ""
|
||||||
"You don't have the right to delete a cotisation already controlled or "
|
"You don't have the right to delete a cotisation already controlled or "
|
||||||
"invalidated."
|
"invalidated."
|
||||||
|
@ -236,113 +224,159 @@ msgstr ""
|
||||||
"Vous n'avez pas le droit de supprimer une cotisation précédement controllée "
|
"Vous n'avez pas le droit de supprimer une cotisation précédement controllée "
|
||||||
"ou invalidée."
|
"ou invalidée."
|
||||||
|
|
||||||
#: models.py:676
|
#: models.py:833
|
||||||
msgid "You don't have the right to see someone else's cotisation history."
|
msgid "You don't have the right to see someone else's cotisation history."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous n'avez pas le droit de voir l'historique d'une cotisation de quelqu'un "
|
"Vous n'avez pas le droit de voir l'historique d'une cotisation de quelqu'un "
|
||||||
"d'autre."
|
"d'autre."
|
||||||
|
|
||||||
#: payment.py:31
|
#: payment_methods/balance/models.py:82 payment_methods/balance/models.py:113
|
||||||
|
msgid "Your balance is too low for this operation."
|
||||||
|
msgstr "Votre solde est trop faible pour cette opération."
|
||||||
|
|
||||||
|
#: payment_methods/balance/models.py:100
|
||||||
|
msgid "There is already a payment type for user balance"
|
||||||
|
msgstr "Il y a déjà un type de paiement pour le solde utilisateur"
|
||||||
|
|
||||||
|
#: payment_methods/cheque/views.py:47
|
||||||
|
msgid "You cannot pay this invoice with a cheque."
|
||||||
|
msgstr "Vous ne pouvez pas payer cette facture avec un chèque."
|
||||||
|
|
||||||
|
#: payment_methods/comnpay/models.py:94
|
||||||
|
msgid "Pay invoice no : "
|
||||||
|
msgstr "Payer la facture numéro : "
|
||||||
|
|
||||||
|
#: payment_methods/comnpay/models.py:106
|
||||||
|
msgid ""
|
||||||
|
"In order to pay your invoice with ComNpay, the price must be grater than {} €"
|
||||||
|
msgstr ""
|
||||||
|
"Pour pouvoir payer votre facture avec ComNpay, le prix doit être plus grand "
|
||||||
|
"que {} €"
|
||||||
|
|
||||||
|
#: payment_methods/comnpay/views.py:53
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The payment of %(amount)s € has been accepted."
|
msgid "The payment of %(amount)s € has been accepted."
|
||||||
msgstr "Le paiement de %(amount)s € a été accepté."
|
msgstr "Le paiement de %(amount)s € a été accepté."
|
||||||
|
|
||||||
#: payment.py:49
|
#: payment_methods/comnpay/views.py:84
|
||||||
msgid "The payment has been refused."
|
msgid "The payment has been refused."
|
||||||
msgstr "Le paiment a été refusé."
|
msgstr "Le paiment a été refusé."
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:31
|
#: templates/cotisations/aff_article.html:33
|
||||||
#: templates/cotisations/facture.html:43
|
#: templates/cotisations/facture.html:60
|
||||||
#: templates/cotisations/new_facture.html:50
|
|
||||||
#: templates/cotisations/new_facture_solde.html:44
|
|
||||||
msgid "Article"
|
msgid "Article"
|
||||||
msgstr "Article"
|
msgstr "Article"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:32
|
#: templates/cotisations/aff_article.html:34
|
||||||
msgid "Price"
|
msgid "Price"
|
||||||
msgstr "Prix"
|
msgstr "Prix"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:33
|
#: templates/cotisations/aff_article.html:35
|
||||||
msgid "Cotisation type"
|
msgid "Cotisation type"
|
||||||
msgstr "Type de cotisation"
|
msgstr "Type de cotisation"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:34
|
#: templates/cotisations/aff_article.html:36
|
||||||
msgid "Duration (month)"
|
msgid "Duration (month)"
|
||||||
msgstr "Durée (mois)"
|
msgstr "Durée (mois)"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:35
|
#: templates/cotisations/aff_article.html:37
|
||||||
msgid "Concerned users"
|
msgid "Concerned users"
|
||||||
msgstr "Utilisateurs concernés"
|
msgstr "Utilisateurs concernés"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:48
|
#: templates/cotisations/aff_article.html:38
|
||||||
#: templates/cotisations/aff_banque.html:40
|
msgid "Available for everyone"
|
||||||
#: templates/cotisations/aff_cotisations.html:69
|
msgstr "Articles disponibles"
|
||||||
#: templates/cotisations/aff_cotisations.html:75
|
|
||||||
#: templates/cotisations/aff_paiement.html:40
|
#: templates/cotisations/aff_article.html:52
|
||||||
#: templates/cotisations/control.html:104 views.py:396 views.py:443
|
#: templates/cotisations/aff_banque.html:41
|
||||||
#: views.py:507 views.py:585
|
#: templates/cotisations/aff_cotisations.html:70
|
||||||
|
#: templates/cotisations/aff_cotisations.html:76
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:73
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:79
|
||||||
|
#: templates/cotisations/aff_paiement.html:48
|
||||||
|
#: templates/cotisations/control.html:104 views.py:480 views.py:568
|
||||||
|
#: views.py:649
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Modifier"
|
msgstr "Modifier"
|
||||||
|
|
||||||
#: templates/cotisations/aff_article.html:52
|
#: templates/cotisations/aff_banque.html:32
|
||||||
#: templates/cotisations/aff_banque.html:44
|
|
||||||
#: templates/cotisations/aff_cotisations.html:90
|
|
||||||
#: templates/cotisations/aff_paiement.html:44
|
|
||||||
msgid "Historique"
|
|
||||||
msgstr "Historique"
|
|
||||||
|
|
||||||
#: templates/cotisations/aff_banque.html:31
|
|
||||||
msgid "Bank"
|
msgid "Bank"
|
||||||
msgstr "Banque"
|
msgstr "Banque"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:37
|
#: templates/cotisations/aff_cotisations.html:38
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Utilisateur"
|
msgstr "Utilisateur"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:40
|
#: templates/cotisations/aff_cotisations.html:41
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:42
|
||||||
#: templates/cotisations/control.html:60
|
#: templates/cotisations/control.html:60
|
||||||
#: templates/cotisations/edit_facture.html:45
|
#: templates/cotisations/edit_facture.html:45
|
||||||
msgid "Designation"
|
msgid "Designation"
|
||||||
msgstr "Désignation"
|
msgstr "Désignation"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:41
|
#: templates/cotisations/aff_cotisations.html:42
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:43
|
||||||
#: templates/cotisations/control.html:61
|
#: templates/cotisations/control.html:61
|
||||||
msgid "Total price"
|
msgid "Total price"
|
||||||
msgstr "Prix total"
|
msgstr "Prix total"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:43
|
#: templates/cotisations/aff_cotisations.html:44
|
||||||
#: templates/cotisations/aff_paiement.html:31
|
#: templates/cotisations/aff_custom_invoice.html:45
|
||||||
#: templates/cotisations/control.html:63
|
#: templates/cotisations/control.html:63
|
||||||
msgid "Payment method"
|
msgid "Payment method"
|
||||||
msgstr "Moyen de paiement"
|
msgstr "Moyen de paiement"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:47
|
#: templates/cotisations/aff_cotisations.html:48
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:49
|
||||||
#: templates/cotisations/control.html:67
|
#: templates/cotisations/control.html:67
|
||||||
msgid "Date"
|
msgid "Date"
|
||||||
msgstr "Date"
|
msgstr "Date"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:51
|
#: templates/cotisations/aff_cotisations.html:52
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:53
|
||||||
#: templates/cotisations/control.html:53
|
#: templates/cotisations/control.html:53
|
||||||
msgid "Invoice id"
|
msgid "Invoice id"
|
||||||
msgstr "Id facture"
|
msgstr "Id facture"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:79
|
#: templates/cotisations/aff_cotisations.html:80
|
||||||
msgid "Controlled invoice"
|
msgid "Controlled invoice"
|
||||||
msgstr "Facture controllé"
|
msgstr "Facture controllé"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:84 views.py:464 views.py:542
|
#: templates/cotisations/aff_cotisations.html:85
|
||||||
#: views.py:620
|
#: templates/cotisations/aff_custom_invoice.html:86 views.py:502 views.py:604
|
||||||
|
#: views.py:685
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Supprimer"
|
msgstr "Supprimer"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:99
|
#: templates/cotisations/aff_cotisations.html:98
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:98
|
||||||
msgid "PDF"
|
msgid "PDF"
|
||||||
msgstr "PDF"
|
msgstr "PDF"
|
||||||
|
|
||||||
#: templates/cotisations/aff_cotisations.html:102
|
#: templates/cotisations/aff_cotisations.html:101
|
||||||
msgid "Invalidated invoice"
|
msgid "Invalidated invoice"
|
||||||
msgstr "Facture invalidée"
|
msgstr "Facture invalidée"
|
||||||
|
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:39
|
||||||
|
msgid "Recipient"
|
||||||
|
msgstr "Destinataire"
|
||||||
|
|
||||||
|
#: templates/cotisations/aff_custom_invoice.html:56
|
||||||
|
msgid "Paid"
|
||||||
|
msgstr "Payé"
|
||||||
|
|
||||||
|
#: templates/cotisations/aff_paiement.html:33
|
||||||
|
msgid "Payment type"
|
||||||
|
msgstr "Type de paiement"
|
||||||
|
|
||||||
|
#: templates/cotisations/aff_paiement.html:34
|
||||||
|
msgid "Is available for everyone"
|
||||||
|
msgstr "Est disponible pour tout le monde"
|
||||||
|
|
||||||
|
#: templates/cotisations/aff_paiement.html:35
|
||||||
|
msgid "Custom payment method"
|
||||||
|
msgstr "Méthode de paiement personnalisée"
|
||||||
|
|
||||||
#: templates/cotisations/control.html:30
|
#: templates/cotisations/control.html:30
|
||||||
msgid "Invoice control"
|
msgid "Invoice control"
|
||||||
msgstr "Contrôle des factures"
|
msgstr "Contrôle des factures"
|
||||||
|
@ -394,15 +428,11 @@ msgstr ""
|
||||||
|
|
||||||
#: templates/cotisations/delete.html:40
|
#: templates/cotisations/delete.html:40
|
||||||
#: templates/cotisations/edit_facture.html:60
|
#: templates/cotisations/edit_facture.html:60
|
||||||
#: templates/cotisations/new_facture_solde.html:59
|
|
||||||
#: templates/cotisations/recharge.html:42
|
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Confirmer"
|
msgstr "Confirmer"
|
||||||
|
|
||||||
#: templates/cotisations/edit_facture.html:31
|
#: templates/cotisations/edit_facture.html:31
|
||||||
#: templates/cotisations/facture.html:30
|
#: templates/cotisations/facture.html:30
|
||||||
#: templates/cotisations/new_facture.html:30
|
|
||||||
#: templates/cotisations/new_facture_solde.html:30
|
|
||||||
msgid "Invoices creation and edition"
|
msgid "Invoices creation and edition"
|
||||||
msgstr "Création et modification de factures"
|
msgstr "Création et modification de factures"
|
||||||
|
|
||||||
|
@ -411,9 +441,7 @@ msgid "Edit the invoice"
|
||||||
msgstr "Edition de factures"
|
msgstr "Edition de factures"
|
||||||
|
|
||||||
#: templates/cotisations/edit_facture.html:41
|
#: templates/cotisations/edit_facture.html:41
|
||||||
#: templates/cotisations/facture.html:38
|
#: templates/cotisations/facture.html:55
|
||||||
#: templates/cotisations/new_facture.html:46
|
|
||||||
#: templates/cotisations/new_facture_solde.html:40
|
|
||||||
msgid "Invoice's articles"
|
msgid "Invoice's articles"
|
||||||
msgstr "Articles de la facture"
|
msgstr "Articles de la facture"
|
||||||
|
|
||||||
|
@ -421,15 +449,23 @@ msgstr "Articles de la facture"
|
||||||
msgid "Quantity"
|
msgid "Quantity"
|
||||||
msgstr "Quantité"
|
msgstr "Quantité"
|
||||||
|
|
||||||
#: templates/cotisations/facture.html:52
|
#: templates/cotisations/facture.html:36
|
||||||
#: templates/cotisations/new_facture.html:59
|
msgid "New invoice"
|
||||||
#: templates/cotisations/new_facture_solde.html:53
|
msgstr "Nouvelle facture"
|
||||||
|
|
||||||
|
#: templates/cotisations/facture.html:39
|
||||||
|
msgid "Maximum allowed balance : "
|
||||||
|
msgstr "Solde maximum autorisé : "
|
||||||
|
|
||||||
|
#: templates/cotisations/facture.html:43
|
||||||
|
msgid "Current balance :"
|
||||||
|
msgstr "Solde actuel :"
|
||||||
|
|
||||||
|
#: templates/cotisations/facture.html:69
|
||||||
msgid "Add an article"
|
msgid "Add an article"
|
||||||
msgstr "Ajouter un article"
|
msgstr "Ajouter un article"
|
||||||
|
|
||||||
#: templates/cotisations/facture.html:54
|
#: templates/cotisations/facture.html:71
|
||||||
#: templates/cotisations/new_facture.html:61
|
|
||||||
#: templates/cotisations/new_facture_solde.html:55
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
" Total price : <span id=\"total_price\">0,00</span> €\n"
|
" Total price : <span id=\"total_price\">0,00</span> €\n"
|
||||||
|
@ -464,7 +500,7 @@ msgid "Delete article types"
|
||||||
msgstr "Supprimer des types d'articles"
|
msgstr "Supprimer des types d'articles"
|
||||||
|
|
||||||
#: templates/cotisations/index_banque.html:30
|
#: templates/cotisations/index_banque.html:30
|
||||||
#: templates/cotisations/sidebar.html:50
|
#: templates/cotisations/sidebar.html:55
|
||||||
msgid "Banks"
|
msgid "Banks"
|
||||||
msgstr "Banques"
|
msgstr "Banques"
|
||||||
|
|
||||||
|
@ -480,6 +516,15 @@ msgstr "Ajouter une banque"
|
||||||
msgid "Delete banks"
|
msgid "Delete banks"
|
||||||
msgstr "Supprimer des banques"
|
msgstr "Supprimer des banques"
|
||||||
|
|
||||||
|
#: templates/cotisations/index_custom_invoice.html:28
|
||||||
|
#: templates/cotisations/sidebar.html:45
|
||||||
|
msgid "Custom invoices"
|
||||||
|
msgstr "Factures personnalisées"
|
||||||
|
|
||||||
|
#: templates/cotisations/index_custom_invoice.html:31
|
||||||
|
msgid "Custom invoices list"
|
||||||
|
msgstr "Liste des factures personalisées"
|
||||||
|
|
||||||
#: templates/cotisations/index_paiement.html:30
|
#: templates/cotisations/index_paiement.html:30
|
||||||
msgid "Payments"
|
msgid "Payments"
|
||||||
msgstr "Paiement"
|
msgstr "Paiement"
|
||||||
|
@ -496,59 +541,24 @@ msgstr "Ajouter un type de paiement"
|
||||||
msgid "Delete payment types"
|
msgid "Delete payment types"
|
||||||
msgstr "Supprimer un type de paiement"
|
msgstr "Supprimer un type de paiement"
|
||||||
|
|
||||||
#: templates/cotisations/new_facture.html:37
|
#: templates/cotisations/payment.html:30
|
||||||
#: templates/cotisations/new_facture_solde.html:37
|
|
||||||
msgid "New invoice"
|
|
||||||
msgstr "Nouvelle facture"
|
|
||||||
|
|
||||||
#: templates/cotisations/new_facture.html:39
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" User's balance : %(user.solde)s €\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" Solde de l'utilisateur : %(user.solde)s €\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: templates/cotisations/new_facture.html:65 views.py:257
|
|
||||||
msgid "Create"
|
|
||||||
msgstr "Créer"
|
|
||||||
|
|
||||||
#: templates/cotisations/payment.html:30 templates/cotisations/recharge.html:30
|
|
||||||
#: templates/cotisations/recharge.html:33
|
|
||||||
msgid "Balance refill"
|
msgid "Balance refill"
|
||||||
msgstr "Rechargement de solde"
|
msgstr "Rechargement de solde"
|
||||||
|
|
||||||
#: templates/cotisations/payment.html:34
|
#: templates/cotisations/payment.html:34
|
||||||
#, python-format
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
" Refill of %(amount)s €\n"
|
" Pay %(amount)s €\n"
|
||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
" Recharger de %(amount)s €\n"
|
" Recharger de %(amount)s €\n"
|
||||||
" "
|
" "
|
||||||
|
|
||||||
#: templates/cotisations/payment.html:40
|
#: templates/cotisations/payment.html:44 views.py:867
|
||||||
msgid "Pay"
|
msgid "Pay"
|
||||||
msgstr "Payer"
|
msgstr "Payer"
|
||||||
|
|
||||||
#: templates/cotisations/recharge.html:35
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Balance : <span class=\"label label-default\">%(request.user.solde)s "
|
|
||||||
"€</span>\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" Solde : <span class=\"label label-default\">%(request.user.solde)s "
|
|
||||||
"€</span>\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: templates/cotisations/sidebar.html:32
|
#: templates/cotisations/sidebar.html:32
|
||||||
msgid "Create an invoice"
|
msgid "Create an invoice"
|
||||||
msgstr "Créer une facture"
|
msgstr "Créer une facture"
|
||||||
|
@ -557,83 +567,94 @@ msgstr "Créer une facture"
|
||||||
msgid "Control the invoices"
|
msgid "Control the invoices"
|
||||||
msgstr "Contrôler les factures"
|
msgstr "Contrôler les factures"
|
||||||
|
|
||||||
#: templates/cotisations/sidebar.html:45
|
#: templates/cotisations/sidebar.html:50
|
||||||
msgid "Available articles"
|
msgid "Available articles"
|
||||||
msgstr "Articles disponibles"
|
msgstr "Articles disponibles"
|
||||||
|
|
||||||
#: templates/cotisations/sidebar.html:55
|
#: templates/cotisations/sidebar.html:60
|
||||||
msgid "Payment methods"
|
msgid "Payment methods"
|
||||||
msgstr "Moyens de paiement"
|
msgstr "Moyens de paiement"
|
||||||
|
|
||||||
#: views.py:138
|
#: validators.py:20
|
||||||
msgid "Your balance is too low for this operation."
|
msgid "There are already payment method(s) for user balance"
|
||||||
msgstr "Votre solde est trop faible pour cette opération."
|
msgstr "Il y a déjà une méthode de paiement pour le solde utilisateur"
|
||||||
|
|
||||||
#: views.py:168
|
#: views.py:165
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"The cotisation of %(member_name)s has been extended to "
|
|
||||||
"%(end_date)s."
|
|
||||||
msgstr "La cotisation de %(member_name)s a été étendu jusqu'à %(end_date)s."
|
|
||||||
|
|
||||||
#: views.py:178
|
|
||||||
msgid "The invoice has been created."
|
|
||||||
msgstr "La facture a été créée."
|
|
||||||
|
|
||||||
#: views.py:186 views.py:824
|
|
||||||
msgid "You need to choose at least one article."
|
msgid "You need to choose at least one article."
|
||||||
msgstr "Vous devez choisir au moins un article."
|
msgstr "Vous devez choisir au moins un article."
|
||||||
|
|
||||||
#: views.py:338
|
#: views.py:178 views.py:232
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Créer"
|
||||||
|
|
||||||
|
#: views.py:225
|
||||||
|
msgid "The custom invoice was successfully created."
|
||||||
|
msgstr "La facture a été créée avec succès."
|
||||||
|
|
||||||
|
#: views.py:313 views.py:367
|
||||||
msgid "The invoice has been successfully edited."
|
msgid "The invoice has been successfully edited."
|
||||||
msgstr "La facture a été crée avec succès."
|
msgstr "La facture a été crée avec succès."
|
||||||
|
|
||||||
#: views.py:358
|
#: views.py:333 views.py:427
|
||||||
msgid "The invoice has been successfully deleted."
|
msgid "The invoice has been successfully deleted."
|
||||||
msgstr "La facture a été supprimée avec succès."
|
msgstr "La facture a été supprimée avec succès."
|
||||||
|
|
||||||
#: views.py:363
|
#: views.py:338 views.py:432
|
||||||
msgid "Invoice"
|
msgid "Invoice"
|
||||||
msgstr "Facture"
|
msgstr "Facture"
|
||||||
|
|
||||||
#: views.py:391
|
#: views.py:453
|
||||||
msgid "Balance successfully updated."
|
|
||||||
msgstr "Solde mis à jour avec succès."
|
|
||||||
|
|
||||||
#: views.py:417
|
|
||||||
msgid "The article has been successfully created."
|
msgid "The article has been successfully created."
|
||||||
msgstr "L'article a été créé avec succès."
|
msgstr "L'article a été créé avec succès."
|
||||||
|
|
||||||
#: views.py:422 views.py:485 views.py:563
|
#: views.py:458 views.py:531 views.py:626
|
||||||
#, fuzzy
|
msgid "Address"
|
||||||
#| msgid "Address"
|
|
||||||
msgid "Add"
|
|
||||||
msgstr "Adresse"
|
msgstr "Adresse"
|
||||||
|
|
||||||
#: views.py:438
|
#: views.py:459
|
||||||
|
msgid "New article"
|
||||||
|
msgstr "Nouvel article"
|
||||||
|
|
||||||
|
#: views.py:475
|
||||||
msgid "The article has been successfully edited."
|
msgid "The article has been successfully edited."
|
||||||
msgstr "L'article a été modifié avec succès."
|
msgstr "L'article a été modifié avec succès."
|
||||||
|
|
||||||
#: views.py:459
|
#: views.py:481
|
||||||
|
msgid "Edit article"
|
||||||
|
msgstr "Éditer l'article"
|
||||||
|
|
||||||
|
#: views.py:497
|
||||||
msgid "The article(s) have been successfully deleted."
|
msgid "The article(s) have been successfully deleted."
|
||||||
msgstr "L'(es) article(s) a(ont) été supprimé(s) avec succès. "
|
msgstr "L'(es) article(s) a(ont) été supprimé(s) avec succès. "
|
||||||
|
|
||||||
#: views.py:480
|
#: views.py:503
|
||||||
|
msgid "Delete article"
|
||||||
|
msgstr "Supprimer l'article"
|
||||||
|
|
||||||
|
#: views.py:525
|
||||||
msgid "The payment method has been successfully created."
|
msgid "The payment method has been successfully created."
|
||||||
msgstr "Le moyen de paiement a été créé avec succès."
|
msgstr "Le moyen de paiement a été créé avec succès."
|
||||||
|
|
||||||
#: views.py:502
|
#: views.py:532
|
||||||
|
msgid "New payment method"
|
||||||
|
msgstr "Nouveau moyen de paiement"
|
||||||
|
|
||||||
|
#: views.py:562
|
||||||
msgid "The payement method has been successfully edited."
|
msgid "The payement method has been successfully edited."
|
||||||
msgstr "Le moyen de paiement a été modifié avec succès."
|
msgstr "Le moyen de paiement a été modifié avec succès."
|
||||||
|
|
||||||
#: views.py:526
|
#: views.py:569
|
||||||
|
msgid "Edit payment method"
|
||||||
|
msgstr "Éditer le moyen de paiement"
|
||||||
|
|
||||||
|
#: views.py:588
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The payment method %(method_name)s has been successfully "
|
"The payment method %(method_name)s has been successfully "
|
||||||
"deleted."
|
"deleted."
|
||||||
msgstr "Le moyen de paiement %(method_name)s a été supprimé avec succès."
|
msgstr "Le moyen de paiement %(method_name)s a été supprimé avec succès."
|
||||||
|
|
||||||
#: views.py:534
|
#: views.py:596
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The payment method %(method_name)s can't be deleted "
|
"The payment method %(method_name)s can't be deleted "
|
||||||
|
@ -642,21 +663,33 @@ msgstr ""
|
||||||
"Le moyen de paiement %(method_name)s ne peut pas être mis à jour car il y a "
|
"Le moyen de paiement %(method_name)s ne peut pas être mis à jour car il y a "
|
||||||
"des factures l'utilisant."
|
"des factures l'utilisant."
|
||||||
|
|
||||||
#: views.py:558
|
#: views.py:605
|
||||||
|
msgid "Delete payment method"
|
||||||
|
msgstr "Supprimer le moyen de paiement"
|
||||||
|
|
||||||
|
#: views.py:621
|
||||||
msgid "The bank has been successfully created."
|
msgid "The bank has been successfully created."
|
||||||
msgstr "La banque a été crée avec succès."
|
msgstr "La banque a été crée avec succès."
|
||||||
|
|
||||||
#: views.py:580
|
#: views.py:627
|
||||||
|
msgid "New bank"
|
||||||
|
msgstr "Créer la banque"
|
||||||
|
|
||||||
|
#: views.py:644
|
||||||
msgid "The bank has been successfully edited"
|
msgid "The bank has been successfully edited"
|
||||||
msgstr "La banque a été modifée avec succès."
|
msgstr "La banque a été modifée avec succès."
|
||||||
|
|
||||||
#: views.py:604
|
#: views.py:650
|
||||||
|
msgid "Edit bank"
|
||||||
|
msgstr "Éditer la banque"
|
||||||
|
|
||||||
|
#: views.py:669
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The bank %(bank_name)s has been successfully deleted."
|
"The bank %(bank_name)s has been successfully deleted."
|
||||||
msgstr "La banque %(bank_name)s a été supprimée avec succès."
|
msgstr "La banque %(bank_name)s a été supprimée avec succès."
|
||||||
|
|
||||||
#: views.py:612
|
#: views.py:677
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The bank %(bank_name)s can't be deleted because there "
|
"The bank %(bank_name)s can't be deleted because there "
|
||||||
|
@ -665,127 +698,131 @@ msgstr ""
|
||||||
"La banque %(bank_name)s ne peut pas être supprimée car il y a des factures "
|
"La banque %(bank_name)s ne peut pas être supprimée car il y a des factures "
|
||||||
"qui l'utilisent."
|
"qui l'utilisent."
|
||||||
|
|
||||||
#: views.py:656
|
#: views.py:686
|
||||||
|
msgid "Delete bank"
|
||||||
|
msgstr "Supprimer la banque"
|
||||||
|
|
||||||
|
#: views.py:722
|
||||||
msgid "Your changes have been properly taken into account."
|
msgid "Your changes have been properly taken into account."
|
||||||
msgstr "Vos modifications ont correctement été prises en compte."
|
msgstr "Vos modifications ont correctement été prises en compte."
|
||||||
|
|
||||||
#: views.py:776
|
#: views.py:834
|
||||||
msgid "The balance is too low for this operation."
|
msgid "You are not allowed to credit your balance."
|
||||||
msgstr "Le solde est trop faible pour cette opération."
|
msgstr "Vous n'êtes pas autorisé à créditer votre solde."
|
||||||
|
|
||||||
#: views.py:806
|
#: views.py:866
|
||||||
#, python-format
|
msgid "Refill your balance"
|
||||||
msgid ""
|
msgstr "Créditer votre solde"
|
||||||
"The cotisation of %(member_name)s has been successfully "
|
|
||||||
"extended to %(end_date)s."
|
|
||||||
msgstr "La cotisation de %(member_name)s a été prolongée jusqu'à %(end_date)s."
|
|
||||||
|
|
||||||
#: views.py:816
|
#: models.py:137
|
||||||
msgid "The invoice has been successuflly created."
|
msgid "Cheque number"
|
||||||
msgstr "La facture a été créée avec succès."
|
msgstr "Numéro de chèque"
|
||||||
|
|
||||||
#: views.py:846
|
msgid "Not specified"
|
||||||
msgid "Online payment is disabled."
|
msgstr "Non renseigné"
|
||||||
msgstr "Le paiement en ligne est désactivé."
|
|
||||||
|
|
||||||
#~ msgid "Paid"
|
msgid "A cheque number and a bank must be specified."
|
||||||
#~ msgstr "Payé"
|
msgstr "Un numéro de chèqe et une banque doivent être renseignés."
|
||||||
|
|
||||||
#~ msgid "Recipient"
|
#: models.py:155
|
||||||
#~ msgstr "Destinataire"
|
msgid "Can change the \"controlled\" state"
|
||||||
|
msgstr "Peut modifier l'état \"controllé\""
|
||||||
|
|
||||||
#~ msgid "Invoice number"
|
#: models.py:157
|
||||||
#~ msgstr "Numéro de facture"
|
msgid "Can see an invoice's details"
|
||||||
|
msgstr "Peut voir les détails d'une facture"
|
||||||
|
|
||||||
#~ msgid "Existing articles"
|
#: models.py:159
|
||||||
#~ msgstr "Articles disponibles"
|
msgid "Can edit all the previous invoices"
|
||||||
|
msgstr "Peut modifier toutes les factures existantes"
|
||||||
|
|
||||||
#~ msgid "Existing payment method"
|
#: models.py:297
|
||||||
#~ msgstr "Moyen de paiements disponibles"
|
msgid "Connexion"
|
||||||
|
msgstr "Connexion"
|
||||||
|
|
||||||
#~ msgid "Existing banks"
|
#: models.py:336
|
||||||
#~ msgstr "Banques disponibles"
|
msgid "Membership"
|
||||||
|
msgstr "Adhésion"
|
||||||
|
|
||||||
#~ msgid "Amount"
|
#: models.py:299
|
||||||
#~ msgstr "Montant"
|
msgid "Both of them"
|
||||||
|
msgstr "Les deux"
|
||||||
|
|
||||||
#~ msgid "Can change the \"controlled\" state"
|
#: models.py:328
|
||||||
#~ msgstr "Peut modifier l'état \"controllé\""
|
msgid "Duration (in whole month)"
|
||||||
|
msgstr "Durée (en mois entiers)"
|
||||||
|
|
||||||
#~ msgid "Can create a custom PDF invoice"
|
#: models.py:336
|
||||||
#~ msgstr "Peut crée une facture PDF personnalisée"
|
msgid "Type of cotisation"
|
||||||
|
msgstr "Type de cotisation"
|
||||||
|
|
||||||
#~ msgid "Can see an invoice's details"
|
#: models.py:341
|
||||||
#~ msgstr "Peut voir les détails d'une facture"
|
msgid "Can see a purchase's details"
|
||||||
|
msgstr "Peut voir les détails d'un achat"
|
||||||
|
|
||||||
#~ msgid "Can edit all the previous invoices"
|
#: models.py:342
|
||||||
#~ msgstr "Peut modifier toutes les factures existantes"
|
msgid "Can edit all the previous purchases"
|
||||||
|
msgstr "Peut voir les achats existants"
|
||||||
|
|
||||||
#~ msgid "Connexion"
|
#: models.py:344
|
||||||
#~ msgstr "Connexion"
|
msgid "Purchase"
|
||||||
|
msgstr "Achat"
|
||||||
|
|
||||||
#~ msgid "Membership"
|
#: models.py:345
|
||||||
#~ msgstr "Adhésion"
|
msgid "Purchases"
|
||||||
|
msgstr "Achat"
|
||||||
|
|
||||||
#~ msgid "Both of them"
|
#: models.py:512
|
||||||
#~ msgstr "Les deux"
|
msgid "Club"
|
||||||
|
msgstr "Club"
|
||||||
|
|
||||||
#~ msgid "Duration (in whole month)"
|
#: models.py:530
|
||||||
#~ msgstr "Durée (en mois entiers)"
|
msgid "Unitary price"
|
||||||
|
msgstr "Prix unitaire"
|
||||||
|
|
||||||
#~ msgid "Type of cotisation"
|
#: models.py:538
|
||||||
#~ msgstr "Type de cotisation"
|
msgid "Type of users concerned"
|
||||||
|
msgstr "Type d'utilisateurs concernés"
|
||||||
|
|
||||||
#~ msgid "Can see a purchase's details"
|
#: models.py:561
|
||||||
#~ msgstr "Peut voir les détails d'un achat"
|
msgid "Can see an article's details"
|
||||||
|
msgstr "Peut voir les détails d'un article"
|
||||||
|
|
||||||
#~ msgid "Can edit all the previous purchases"
|
#: models.py:621
|
||||||
#~ msgstr "Peut voir les achats existants"
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
#~ msgid "Purchase"
|
#: models.py:626
|
||||||
#~ msgstr "Achat"
|
msgid "Can see a bank's details"
|
||||||
|
msgstr "Peut voir les détails d'une banque"
|
||||||
|
|
||||||
#~ msgid "Purchases"
|
#: models.py:344
|
||||||
#~ msgstr "Achat"
|
msgid "Standard"
|
||||||
|
msgstr "Standard"
|
||||||
|
|
||||||
#~ msgid "Club"
|
msgid "Cheque"
|
||||||
#~ msgstr "Club"
|
msgstr "Chèque"
|
||||||
|
|
||||||
#~ msgid "Unitary price"
|
#: models.py:647
|
||||||
#~ msgstr "Prix unitaire"
|
msgid "Method"
|
||||||
|
msgstr "Moyen"
|
||||||
|
|
||||||
#~ msgid "Type of users concerned"
|
#: models.py:663
|
||||||
#~ msgstr "Type d'utilisateurs concernés"
|
msgid "Can see a payement's details"
|
||||||
|
msgstr "Peut voir les détails d'un paiement"
|
||||||
|
|
||||||
#~ msgid "Can see an article's details"
|
#: models.py:785
|
||||||
#~ msgstr "Peut voir les détails d'un article"
|
msgid "Starting date"
|
||||||
|
msgstr "Date de début"
|
||||||
|
|
||||||
#~ msgid "Name"
|
#: models.py:788
|
||||||
#~ msgstr "Nom"
|
msgid "Ending date"
|
||||||
|
msgstr "Date de fin"
|
||||||
|
|
||||||
#~ msgid "Can see a bank's details"
|
#: models.py:793
|
||||||
#~ msgstr "Peut voir les détails d'une banque"
|
msgid "Can see a cotisation's details"
|
||||||
|
msgstr "Peut voir les détails d'une cotisation"
|
||||||
|
|
||||||
#~ msgid "Standard"
|
#: models.py:794
|
||||||
#~ msgstr "Standard"
|
msgid "Can edit the previous cotisations"
|
||||||
|
msgstr "Peut voir les cotisations existantes"
|
||||||
#~ msgid "Cheque"
|
|
||||||
#~ msgstr "Chèque"
|
|
||||||
|
|
||||||
#~ msgid "Method"
|
|
||||||
#~ msgstr "Moyen"
|
|
||||||
|
|
||||||
#~ msgid "Can see a payement's details"
|
|
||||||
#~ msgstr "Peut voir les détails d'un paiement"
|
|
||||||
|
|
||||||
#~ msgid "Starting date"
|
|
||||||
#~ msgstr "Date de début"
|
|
||||||
|
|
||||||
#~ msgid "Ending date"
|
|
||||||
#~ msgstr "Date de fin"
|
|
||||||
|
|
||||||
#~ msgid "Can see a cotisation's details"
|
|
||||||
#~ msgstr "Peut voir les détails d'une cotisation"
|
|
||||||
|
|
||||||
#~ msgid "Can edit the previous cotisations"
|
|
||||||
#~ msgstr "Peut voir les cotisations existantes"
|
|
||||||
|
|
102
cotisations/migrations/0032_custom_invoice.py
Normal file
102
cotisations/migrations/0032_custom_invoice.py
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2018-07-21 20:01
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.contrib.auth.management import create_permissions
|
||||||
|
import re2o.field_permissions
|
||||||
|
import re2o.mixins
|
||||||
|
|
||||||
|
|
||||||
|
def reattribute_ids(apps, schema_editor):
|
||||||
|
Facture = apps.get_model('cotisations', 'Facture')
|
||||||
|
BaseInvoice = apps.get_model('cotisations', 'BaseInvoice')
|
||||||
|
|
||||||
|
for f in Facture.objects.all():
|
||||||
|
base = BaseInvoice.objects.create(id=f.pk, date=f.date)
|
||||||
|
f.baseinvoice_ptr = base
|
||||||
|
f.save()
|
||||||
|
|
||||||
|
|
||||||
|
def update_rights(apps, schema_editor):
|
||||||
|
Permission = apps.get_model('auth', 'Permission')
|
||||||
|
|
||||||
|
# creates needed permissions
|
||||||
|
app = apps.get_app_config('cotisations')
|
||||||
|
app.models_module = True
|
||||||
|
create_permissions(app)
|
||||||
|
app.models_module = False
|
||||||
|
|
||||||
|
former = Permission.objects.get(codename='change_facture_pdf')
|
||||||
|
new_1 = Permission.objects.get(codename='add_custominvoice')
|
||||||
|
new_2 = Permission.objects.get(codename='change_custominvoice')
|
||||||
|
new_3 = Permission.objects.get(codename='view_custominvoice')
|
||||||
|
new_4 = Permission.objects.get(codename='delete_custominvoice')
|
||||||
|
for group in former.group_set.all():
|
||||||
|
group.permissions.remove(former)
|
||||||
|
group.permissions.add(new_1)
|
||||||
|
group.permissions.add(new_2)
|
||||||
|
group.permissions.add(new_3)
|
||||||
|
group.permissions.add(new_4)
|
||||||
|
group.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cotisations', '0031_comnpaypayment_production'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='BaseInvoice',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('date', models.DateTimeField(auto_now_add=True, verbose_name='Date')),
|
||||||
|
],
|
||||||
|
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, re2o.field_permissions.FieldPermissionModelMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CustomInvoice',
|
||||||
|
fields=[
|
||||||
|
('baseinvoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.BaseInvoice')),
|
||||||
|
('recipient', models.CharField(max_length=255, verbose_name='Recipient')),
|
||||||
|
('payment', models.CharField(max_length=255, verbose_name='Payment type')),
|
||||||
|
('address', models.CharField(max_length=255, verbose_name='Address')),
|
||||||
|
('paid', models.BooleanField(verbose_name='Paid')),
|
||||||
|
],
|
||||||
|
bases=('cotisations.baseinvoice',),
|
||||||
|
options={'permissions': (('view_custominvoice', 'Can view a custom invoice'),)},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='facture',
|
||||||
|
name='baseinvoice_ptr',
|
||||||
|
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='cotisations.BaseInvoice', null=True),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.RunPython(reattribute_ids),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='vente',
|
||||||
|
name='facture',
|
||||||
|
field=models.ForeignKey(on_delete=models.CASCADE, verbose_name='Invoice', to='cotisations.BaseInvoice')
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='facture',
|
||||||
|
name='id',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='facture',
|
||||||
|
name='date',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='facture',
|
||||||
|
name='baseinvoice_ptr',
|
||||||
|
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.BaseInvoice'),
|
||||||
|
),
|
||||||
|
migrations.RunPython(update_rights),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='facture',
|
||||||
|
options={'permissions': (('change_facture_control', 'Can change the "controlled" state'), ('view_facture', "Can see an invoice's details"), ('change_all_facture', 'Can edit all the previous invoices')), 'verbose_name': 'Invoice', 'verbose_name_plural': 'Invoices'},
|
||||||
|
),
|
||||||
|
]
|
|
@ -55,80 +55,11 @@ from cotisations.utils import find_payment_method
|
||||||
from cotisations.validators import check_no_balance
|
from cotisations.validators import check_no_balance
|
||||||
|
|
||||||
|
|
||||||
# TODO : change facture to invoice
|
class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
|
||||||
"""
|
|
||||||
The model for an invoice. It reprensents the fact that a user paid for
|
|
||||||
something (it can be multiple article paid at once).
|
|
||||||
|
|
||||||
An invoice is linked to :
|
|
||||||
* one or more purchases (one for each article sold that time)
|
|
||||||
* a user (the one who bought those articles)
|
|
||||||
* a payment method (the one used by the user)
|
|
||||||
* (if applicable) a bank
|
|
||||||
* (if applicable) a cheque number.
|
|
||||||
Every invoice is dated throught the 'date' value.
|
|
||||||
An invoice has a 'controlled' value (default : False) which means that
|
|
||||||
someone with high enough rights has controlled that invoice and taken it
|
|
||||||
into account. It also has a 'valid' value (default : True) which means
|
|
||||||
that someone with high enough rights has decided that this invoice was not
|
|
||||||
valid (thus it's like the user never paid for his articles). It may be
|
|
||||||
necessary in case of non-payment.
|
|
||||||
"""
|
|
||||||
|
|
||||||
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
|
||||||
# TODO : change paiement to payment
|
|
||||||
paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT)
|
|
||||||
# TODO : change banque to bank
|
|
||||||
banque = models.ForeignKey(
|
|
||||||
'Banque',
|
|
||||||
on_delete=models.PROTECT,
|
|
||||||
blank=True,
|
|
||||||
null=True
|
|
||||||
)
|
|
||||||
# TODO : maybe change to cheque nummber because not evident
|
|
||||||
cheque = models.CharField(
|
|
||||||
max_length=255,
|
|
||||||
blank=True,
|
|
||||||
verbose_name=_l("Cheque number")
|
|
||||||
)
|
|
||||||
date = models.DateTimeField(
|
date = models.DateTimeField(
|
||||||
auto_now_add=True,
|
auto_now_add=True,
|
||||||
verbose_name=_l("Date")
|
verbose_name=_l("Date")
|
||||||
)
|
)
|
||||||
# TODO : change name to validity for clarity
|
|
||||||
valid = models.BooleanField(
|
|
||||||
default=True,
|
|
||||||
verbose_name=_l("Validated")
|
|
||||||
)
|
|
||||||
# TODO : changed name to controlled for clarity
|
|
||||||
control = models.BooleanField(
|
|
||||||
default=False,
|
|
||||||
verbose_name=_l("Controlled")
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = False
|
|
||||||
permissions = (
|
|
||||||
# TODO : change facture to invoice
|
|
||||||
('change_facture_control',
|
|
||||||
_l("Can change the \"controlled\" state")),
|
|
||||||
# TODO : seems more likely to be call create_facture_pdf
|
|
||||||
# or create_invoice_pdf
|
|
||||||
('change_facture_pdf',
|
|
||||||
_l("Can create a custom PDF invoice")),
|
|
||||||
('view_facture',
|
|
||||||
_l("Can see an invoice's details")),
|
|
||||||
('change_all_facture',
|
|
||||||
_l("Can edit all the previous invoices")),
|
|
||||||
)
|
|
||||||
verbose_name = _l("Invoice")
|
|
||||||
verbose_name_plural = _l("Invoices")
|
|
||||||
|
|
||||||
def linked_objects(self):
|
|
||||||
"""Return linked objects : machine and domain.
|
|
||||||
Usefull in history display"""
|
|
||||||
return self.vente_set.all()
|
|
||||||
|
|
||||||
# TODO : change prix to price
|
# TODO : change prix to price
|
||||||
def prix(self):
|
def prix(self):
|
||||||
|
@ -167,6 +98,74 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
).values_list('name', flat=True))
|
).values_list('name', flat=True))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
|
class Facture(BaseInvoice):
|
||||||
|
"""
|
||||||
|
The model for an invoice. It reprensents the fact that a user paid for
|
||||||
|
something (it can be multiple article paid at once).
|
||||||
|
|
||||||
|
An invoice is linked to :
|
||||||
|
* one or more purchases (one for each article sold that time)
|
||||||
|
* a user (the one who bought those articles)
|
||||||
|
* a payment method (the one used by the user)
|
||||||
|
* (if applicable) a bank
|
||||||
|
* (if applicable) a cheque number.
|
||||||
|
Every invoice is dated throught the 'date' value.
|
||||||
|
An invoice has a 'controlled' value (default : False) which means that
|
||||||
|
someone with high enough rights has controlled that invoice and taken it
|
||||||
|
into account. It also has a 'valid' value (default : True) which means
|
||||||
|
that someone with high enough rights has decided that this invoice was not
|
||||||
|
valid (thus it's like the user never paid for his articles). It may be
|
||||||
|
necessary in case of non-payment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
||||||
|
# TODO : change paiement to payment
|
||||||
|
paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT)
|
||||||
|
# TODO : change banque to bank
|
||||||
|
banque = models.ForeignKey(
|
||||||
|
'Banque',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
# TODO : maybe change to cheque nummber because not evident
|
||||||
|
cheque = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_l("Cheque number")
|
||||||
|
)
|
||||||
|
# TODO : change name to validity for clarity
|
||||||
|
valid = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_l("Validated")
|
||||||
|
)
|
||||||
|
# TODO : changed name to controlled for clarity
|
||||||
|
control = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
verbose_name=_l("Controlled")
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = False
|
||||||
|
permissions = (
|
||||||
|
# TODO : change facture to invoice
|
||||||
|
('change_facture_control',
|
||||||
|
_l("Can change the \"controlled\" state")),
|
||||||
|
('view_facture',
|
||||||
|
_l("Can see an invoice's details")),
|
||||||
|
('change_all_facture',
|
||||||
|
_l("Can edit all the previous invoices")),
|
||||||
|
)
|
||||||
|
verbose_name = _l("Invoice")
|
||||||
|
verbose_name_plural = _l("Invoices")
|
||||||
|
|
||||||
|
def linked_objects(self):
|
||||||
|
"""Return linked objects : machine and domain.
|
||||||
|
Usefull in history display"""
|
||||||
|
return self.vente_set.all()
|
||||||
|
|
||||||
def can_edit(self, user_request, *args, **kwargs):
|
def can_edit(self, user_request, *args, **kwargs):
|
||||||
if not user_request.has_perm('cotisations.change_facture'):
|
if not user_request.has_perm('cotisations.change_facture'):
|
||||||
return False, _("You don't have the right to edit an invoice.")
|
return False, _("You don't have the right to edit an invoice.")
|
||||||
|
@ -212,14 +211,6 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
_("You don't have the right to edit the \"controlled\" state.")
|
_("You don't have the right to edit the \"controlled\" state.")
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_change_pdf(user_request, *_args, **_kwargs):
|
|
||||||
""" Returns True if the user can change this invoice """
|
|
||||||
return (
|
|
||||||
user_request.has_perm('cotisations.change_facture_pdf'),
|
|
||||||
_("You don't have the right to edit an invoice.")
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_create(user_request, *_args, **_kwargs):
|
def can_create(user_request, *_args, **_kwargs):
|
||||||
"""Check if a user can create an invoice.
|
"""Check if a user can create an invoice.
|
||||||
|
@ -265,6 +256,28 @@ def facture_post_delete(**kwargs):
|
||||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomInvoice(BaseInvoice):
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
('view_custominvoice', _l("Can view a custom invoice")),
|
||||||
|
)
|
||||||
|
recipient = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_l("Recipient")
|
||||||
|
)
|
||||||
|
payment = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_l("Payment type")
|
||||||
|
)
|
||||||
|
address = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_l("Address")
|
||||||
|
)
|
||||||
|
paid = models.BooleanField(
|
||||||
|
verbose_name="Paid"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO : change Vente to Purchase
|
# TODO : change Vente to Purchase
|
||||||
class Vente(RevMixin, AclMixin, models.Model):
|
class Vente(RevMixin, AclMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -288,7 +301,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
# TODO : change facture to invoice
|
# TODO : change facture to invoice
|
||||||
facture = models.ForeignKey(
|
facture = models.ForeignKey(
|
||||||
'Facture',
|
'BaseInvoice',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
verbose_name=_l("Invoice")
|
verbose_name=_l("Invoice")
|
||||||
)
|
)
|
||||||
|
@ -355,6 +368,10 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
cotisation_type defined (which means the article sold represents
|
cotisation_type defined (which means the article sold represents
|
||||||
a cotisation)
|
a cotisation)
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
|
invoice = self.facture.facture
|
||||||
|
except Facture.DoesNotExist:
|
||||||
|
return
|
||||||
if not hasattr(self, 'cotisation') and self.type_cotisation:
|
if not hasattr(self, 'cotisation') and self.type_cotisation:
|
||||||
cotisation = Cotisation(vente=self)
|
cotisation = Cotisation(vente=self)
|
||||||
cotisation.type_cotisation = self.type_cotisation
|
cotisation.type_cotisation = self.type_cotisation
|
||||||
|
@ -362,7 +379,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
end_cotisation = Cotisation.objects.filter(
|
end_cotisation = Cotisation.objects.filter(
|
||||||
vente__in=Vente.objects.filter(
|
vente__in=Vente.objects.filter(
|
||||||
facture__in=Facture.objects.filter(
|
facture__in=Facture.objects.filter(
|
||||||
user=self.facture.user
|
user=invoice.user
|
||||||
).exclude(valid=False))
|
).exclude(valid=False))
|
||||||
).filter(
|
).filter(
|
||||||
Q(type_cotisation='All') |
|
Q(type_cotisation='All') |
|
||||||
|
@ -371,9 +388,9 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
date_start__lt=date_start
|
date_start__lt=date_start
|
||||||
).aggregate(Max('date_end'))['date_end__max']
|
).aggregate(Max('date_end'))['date_end__max']
|
||||||
elif self.type_cotisation == "Adhesion":
|
elif self.type_cotisation == "Adhesion":
|
||||||
end_cotisation = self.facture.user.end_adhesion()
|
end_cotisation = invoice.user.end_adhesion()
|
||||||
else:
|
else:
|
||||||
end_cotisation = self.facture.user.end_connexion()
|
end_cotisation = invoice.user.end_connexion()
|
||||||
date_start = date_start or timezone.now()
|
date_start = date_start or timezone.now()
|
||||||
end_cotisation = end_cotisation or date_start
|
end_cotisation = end_cotisation or date_start
|
||||||
date_max = max(end_cotisation, date_start)
|
date_max = max(end_cotisation, date_start)
|
||||||
|
@ -445,6 +462,10 @@ def vente_post_save(**kwargs):
|
||||||
LDAP user when a purchase has been saved.
|
LDAP user when a purchase has been saved.
|
||||||
"""
|
"""
|
||||||
purchase = kwargs['instance']
|
purchase = kwargs['instance']
|
||||||
|
try:
|
||||||
|
purchase.facture.facture
|
||||||
|
except Facture.DoesNotExist:
|
||||||
|
return
|
||||||
if hasattr(purchase, 'cotisation'):
|
if hasattr(purchase, 'cotisation'):
|
||||||
purchase.cotisation.vente = purchase
|
purchase.cotisation.vente = purchase
|
||||||
purchase.cotisation.save()
|
purchase.cotisation.save()
|
||||||
|
@ -462,8 +483,12 @@ def vente_post_delete(**kwargs):
|
||||||
Synchronise the LDAP user after a purchase has been deleted.
|
Synchronise the LDAP user after a purchase has been deleted.
|
||||||
"""
|
"""
|
||||||
purchase = kwargs['instance']
|
purchase = kwargs['instance']
|
||||||
|
try:
|
||||||
|
invoice = purchase.facture.facture
|
||||||
|
except Facture.DoesNotExist:
|
||||||
|
return
|
||||||
if purchase.type_cotisation:
|
if purchase.type_cotisation:
|
||||||
user = purchase.facture.user
|
user = invoice.user
|
||||||
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<td>{{ article.type_cotisation }}</td>
|
<td>{{ article.type_cotisation }}</td>
|
||||||
<td>{{ article.duration }}</td>
|
<td>{{ article.duration }}</td>
|
||||||
<td>{{ article.type_user }}</td>
|
<td>{{ article.type_user }}</td>
|
||||||
<td>{{ article.available_for_everyone|tick }}</td>
|
<td>{{ article.available_for_everyone | tick }}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
{% can_edit article %}
|
{% can_edit article %}
|
||||||
<a class="btn btn-primary btn-sm" role="button" title="{% trans "Edit" %}" href="{% url 'cotisations:edit-article' article.id %}">
|
<a class="btn btn-primary btn-sm" role="button" title="{% trans "Edit" %}" href="{% url 'cotisations:edit-article' article.id %}">
|
||||||
|
|
89
cotisations/templates/cotisations/aff_custom_invoice.html
Normal file
89
cotisations/templates/cotisations/aff_custom_invoice.html
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2018 Hugo Levy-Falk
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load acl %}
|
||||||
|
{% load logs_extra %}
|
||||||
|
{% load design %}
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
{% if custom_invoice_list.paginator %}
|
||||||
|
{% include 'pagination.html' with list=custom_invoice_list %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{% trans "Recipient" as tr_recip %}
|
||||||
|
{% include 'buttons/sort.html' with prefix='invoice' col='user' text=tr_user %}
|
||||||
|
</th>
|
||||||
|
<th>{% trans "Designation" %}</th>
|
||||||
|
<th>{% trans "Total price" %}</th>
|
||||||
|
<th>
|
||||||
|
{% trans "Payment method" as tr_payment_method %}
|
||||||
|
{% include 'buttons/sort.html' with prefix='invoice' col='payement' text=tr_payment_method %}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{% trans "Date" as tr_date %}
|
||||||
|
{% include 'buttons/sort.html' with prefix='invoice' col='date' text=tr_date %}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{% trans "Invoice id" as tr_invoice_id %}
|
||||||
|
{% include 'buttons/sort.html' with prefix='invoice' col='id' text=tr_invoice_id %}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{% trans "Paid" as tr_invoice_paid%}
|
||||||
|
{% include 'buttons/sort.html' with prefix='invoice' col='paid' text=tr_invoice_paid %}
|
||||||
|
</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for invoice in custom_invoice_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ invoice.recipient }}</td>
|
||||||
|
<td>{{ invoice.name }}</td>
|
||||||
|
<td>{{ invoice.prix_total }}</td>
|
||||||
|
<td>{{ invoice.payment }}</td>
|
||||||
|
<td>{{ invoice.date }}</td>
|
||||||
|
<td>{{ invoice.id }}</td>
|
||||||
|
<td>{{ invoice.paid|tick }}</td>
|
||||||
|
<td>
|
||||||
|
{% can_edit invoice %}
|
||||||
|
{% include 'buttons/edit.html' with href='cotisations:edit-custom-invoice' id=invoice.id %}
|
||||||
|
{% acl_end %}
|
||||||
|
{% can_delete invoice %}
|
||||||
|
{% include 'buttons/suppr.html' with href='cotisations:del-custom-invoice' id=invoice.id %}
|
||||||
|
{% acl_end %}
|
||||||
|
{% history_button invoice %}
|
||||||
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:custom-invoice-pdf' invoice.id %}">
|
||||||
|
<i class="fa fa-file-pdf"></i> {% trans "PDF" %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% if custom_invoice_list.paginator %}
|
||||||
|
{% include 'pagination.html' with list=custom_invoice_list %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
36
cotisations/templates/cotisations/index_custom_invoice.html
Normal file
36
cotisations/templates/cotisations/index_custom_invoice.html
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{% extends "cotisations/sidebar.html" %}
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2017 Gabriel Détraz
|
||||||
|
Copyright © 2017 Goulven Kermarec
|
||||||
|
Copyright © 2017 Augustin Lemesle
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
{% load acl %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Custom invoices" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>{% trans "Custom invoices list" %}</h2>
|
||||||
|
{% can_create CustomInvoice %}
|
||||||
|
{% include "buttons/add.html" with href='cotisations:new-custom-invoice'%}
|
||||||
|
{% acl_end %}
|
||||||
|
{% include 'cotisations/aff_custom_invoice.html' with custom_invoice_list=custom_invoice_list %}
|
||||||
|
{% endblock %}
|
|
@ -27,8 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block sidebar %}
|
{% block sidebar %}
|
||||||
{% can_change Facture pdf %}
|
{% can_create CustomInvoice %}
|
||||||
<a class="list-group-item list-group-item-success" href="{% url "cotisations:new-facture-pdf" %}">
|
<a class="list-group-item list-group-item-success" href="{% url "cotisations:new-custom-invoice" %}">
|
||||||
<i class="fa fa-plus"></i> {% trans "Create an invoice" %}
|
<i class="fa fa-plus"></i> {% trans "Create an invoice" %}
|
||||||
</a>
|
</a>
|
||||||
<a class="list-group-item list-group-item-warning" href="{% url "cotisations:control" %}">
|
<a class="list-group-item list-group-item-warning" href="{% url "cotisations:control" %}">
|
||||||
|
@ -40,6 +40,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<i class="fa fa-list-ul"></i> {% trans "Invoices" %}
|
<i class="fa fa-list-ul"></i> {% trans "Invoices" %}
|
||||||
</a>
|
</a>
|
||||||
{% acl_end %}
|
{% acl_end %}
|
||||||
|
{% can_view_all CustomInvoice %}
|
||||||
|
<a class="list-group-item list-group-item-info" href="{% url "cotisations:index-custom-invoice" %}">
|
||||||
|
<i class="fa fa-list-ul"></i> {% trans "Custom invoices" %}
|
||||||
|
</a>
|
||||||
|
{% acl_end %}
|
||||||
{% can_view_all Article %}
|
{% can_view_all Article %}
|
||||||
<a class="list-group-item list-group-item-info" href="{% url "cotisations:index-article" %}">
|
<a class="list-group-item list-group-item-info" href="{% url "cotisations:index-article" %}">
|
||||||
<i class="fa fa-list-ul"></i> {% trans "Available articles" %}
|
<i class="fa fa-list-ul"></i> {% trans "Available articles" %}
|
||||||
|
|
|
@ -105,7 +105,7 @@ def render_tex(_request, template, ctx={}):
|
||||||
Returns:
|
Returns:
|
||||||
An HttpResponse with type `application/pdf` containing the PDF file.
|
An HttpResponse with type `application/pdf` containing the PDF file.
|
||||||
"""
|
"""
|
||||||
pdf = create_pdf(template, ctx={})
|
pdf = create_pdf(template, ctx)
|
||||||
r = HttpResponse(content_type='application/pdf')
|
r = HttpResponse(content_type='application/pdf')
|
||||||
r.write(pdf)
|
r.write(pdf)
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -52,9 +52,29 @@ urlpatterns = [
|
||||||
name='facture-pdf'
|
name='facture-pdf'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^new_facture_pdf/$',
|
r'^index_custom_invoice/$',
|
||||||
views.new_facture_pdf,
|
views.index_custom_invoice,
|
||||||
name='new-facture-pdf'
|
name='index-custom-invoice'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^new_custom_invoice/$',
|
||||||
|
views.new_custom_invoice,
|
||||||
|
name='new-custom-invoice'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^edit_custom_invoice/(?P<custominvoiceid>[0-9]+)$',
|
||||||
|
views.edit_custom_invoice,
|
||||||
|
name='edit-custom-invoice'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^custom_invoice_pdf/(?P<custominvoiceid>[0-9]+)$',
|
||||||
|
views.custom_invoice_pdf,
|
||||||
|
name='custom-invoice-pdf',
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'^del_custom_invoice/(?P<custominvoiceid>[0-9]+)$',
|
||||||
|
views.del_custom_invoice,
|
||||||
|
name='del-custom-invoice'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^credit_solde/(?P<userid>[0-9]+)$',
|
r'^credit_solde/(?P<userid>[0-9]+)$',
|
||||||
|
|
|
@ -58,7 +58,15 @@ from re2o.acl import (
|
||||||
can_change,
|
can_change,
|
||||||
)
|
)
|
||||||
from preferences.models import AssoOption, GeneralOption
|
from preferences.models import AssoOption, GeneralOption
|
||||||
from .models import Facture, Article, Vente, Paiement, Banque
|
from .models import (
|
||||||
|
Facture,
|
||||||
|
Article,
|
||||||
|
Vente,
|
||||||
|
Paiement,
|
||||||
|
Banque,
|
||||||
|
CustomInvoice,
|
||||||
|
BaseInvoice
|
||||||
|
)
|
||||||
from .forms import (
|
from .forms import (
|
||||||
FactureForm,
|
FactureForm,
|
||||||
ArticleForm,
|
ArticleForm,
|
||||||
|
@ -67,10 +75,10 @@ from .forms import (
|
||||||
DelPaiementForm,
|
DelPaiementForm,
|
||||||
BanqueForm,
|
BanqueForm,
|
||||||
DelBanqueForm,
|
DelBanqueForm,
|
||||||
NewFactureFormPdf,
|
|
||||||
SelectUserArticleForm,
|
SelectUserArticleForm,
|
||||||
SelectClubArticleForm,
|
SelectClubArticleForm,
|
||||||
RechargeForm
|
RechargeForm,
|
||||||
|
CustomInvoiceForm
|
||||||
)
|
)
|
||||||
from .tex import render_invoice
|
from .tex import render_invoice
|
||||||
from .payment_methods.forms import payment_method_factory
|
from .payment_methods.forms import payment_method_factory
|
||||||
|
@ -178,10 +186,10 @@ def new_facture(request, user, userid):
|
||||||
|
|
||||||
# TODO : change facture to invoice
|
# TODO : change facture to invoice
|
||||||
@login_required
|
@login_required
|
||||||
@can_change(Facture, 'pdf')
|
@can_create(CustomInvoice)
|
||||||
def new_facture_pdf(request):
|
def new_custom_invoice(request):
|
||||||
"""
|
"""
|
||||||
View used to generate a custom PDF invoice. It's mainly used to
|
View used to generate a custom invoice. It's mainly used to
|
||||||
get invoices that are not taken into account, for the administrative
|
get invoices that are not taken into account, for the administrative
|
||||||
point of view.
|
point of view.
|
||||||
"""
|
"""
|
||||||
|
@ -190,7 +198,7 @@ def new_facture_pdf(request):
|
||||||
Q(type_user='All') | Q(type_user=request.user.class_name)
|
Q(type_user='All') | Q(type_user=request.user.class_name)
|
||||||
)
|
)
|
||||||
# Building the invocie form and the article formset
|
# Building the invocie form and the article formset
|
||||||
invoice_form = NewFactureFormPdf(request.POST or None)
|
invoice_form = CustomInvoiceForm(request.POST or None)
|
||||||
if request.user.is_class_club:
|
if request.user.is_class_club:
|
||||||
articles_formset = formset_factory(SelectClubArticleForm)(
|
articles_formset = formset_factory(SelectClubArticleForm)(
|
||||||
request.POST or None,
|
request.POST or None,
|
||||||
|
@ -202,44 +210,31 @@ def new_facture_pdf(request):
|
||||||
form_kwargs={'user': request.user}
|
form_kwargs={'user': request.user}
|
||||||
)
|
)
|
||||||
if invoice_form.is_valid() and articles_formset.is_valid():
|
if invoice_form.is_valid() and articles_formset.is_valid():
|
||||||
# Get the article list and build an list out of it
|
new_invoice_instance = invoice_form.save()
|
||||||
# contiaining (article_name, article_price, quantity, total_price)
|
for art_item in articles_formset:
|
||||||
articles_info = []
|
if art_item.cleaned_data:
|
||||||
for articles_form in articles_formset:
|
article = art_item.cleaned_data['article']
|
||||||
if articles_form.cleaned_data:
|
quantity = art_item.cleaned_data['quantity']
|
||||||
article = articles_form.cleaned_data['article']
|
Vente.objects.create(
|
||||||
quantity = articles_form.cleaned_data['quantity']
|
facture=new_invoice_instance,
|
||||||
articles_info.append({
|
name=article.name,
|
||||||
'name': article.name,
|
prix=article.prix,
|
||||||
'price': article.prix,
|
type_cotisation=article.type_cotisation,
|
||||||
'quantity': quantity,
|
duration=article.duration,
|
||||||
'total_price': article.prix * quantity
|
number=quantity
|
||||||
})
|
)
|
||||||
paid = invoice_form.cleaned_data['paid']
|
messages.success(
|
||||||
recipient = invoice_form.cleaned_data['dest']
|
request,
|
||||||
address = invoice_form.cleaned_data['chambre']
|
_('The custom invoice was successfully created.')
|
||||||
total_price = sum(a['total_price'] for a in articles_info)
|
)
|
||||||
|
return redirect(reverse('cotisations:index-custom-invoice'))
|
||||||
|
|
||||||
|
|
||||||
return render_invoice(request, {
|
|
||||||
'DATE': timezone.now(),
|
|
||||||
'recipient_name': recipient,
|
|
||||||
'address': address,
|
|
||||||
'article': articles_info,
|
|
||||||
'total': total_price,
|
|
||||||
'paid': paid,
|
|
||||||
'asso_name': AssoOption.get_cached_value('name'),
|
|
||||||
'line1': AssoOption.get_cached_value('adresse1'),
|
|
||||||
'line2': AssoOption.get_cached_value('adresse2'),
|
|
||||||
'siret': AssoOption.get_cached_value('siret'),
|
|
||||||
'email': AssoOption.get_cached_value('contact'),
|
|
||||||
'phone': AssoOption.get_cached_value('telephone'),
|
|
||||||
'tpl_path': os.path.join(settings.BASE_DIR, LOGO_PATH)
|
|
||||||
})
|
|
||||||
return form({
|
return form({
|
||||||
'factureform': invoice_form,
|
'factureform': invoice_form,
|
||||||
'action_name': _("Create"),
|
'action_name': _("Create"),
|
||||||
'articlesformset': articles_formset,
|
'articlesformset': articles_formset,
|
||||||
'articles': articles
|
'articlelist': articles
|
||||||
}, 'cotisations/facture.html', request)
|
}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
@ -292,7 +287,7 @@ def facture_pdf(request, facture, **_kwargs):
|
||||||
def edit_facture(request, facture, **_kwargs):
|
def edit_facture(request, facture, **_kwargs):
|
||||||
"""
|
"""
|
||||||
View used to edit an existing invoice.
|
View used to edit an existing invoice.
|
||||||
Articles can be added or remove to the invoice and quantity
|
Articles can be added or removed to the invoice and quantity
|
||||||
can be set as desired. This is also the view used to invalidate
|
can be set as desired. This is also the view used to invalidate
|
||||||
an invoice.
|
an invoice.
|
||||||
"""
|
"""
|
||||||
|
@ -347,6 +342,100 @@ def del_facture(request, facture, **_kwargs):
|
||||||
}, 'cotisations/delete.html', request)
|
}, 'cotisations/delete.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_edit(CustomInvoice)
|
||||||
|
def edit_custom_invoice(request, invoice, **kwargs):
|
||||||
|
# Building the invocie form and the article formset
|
||||||
|
invoice_form = CustomInvoiceForm(
|
||||||
|
request.POST or None,
|
||||||
|
instance=invoice
|
||||||
|
)
|
||||||
|
purchases_objects = Vente.objects.filter(facture=invoice)
|
||||||
|
purchase_form_set = modelformset_factory(
|
||||||
|
Vente,
|
||||||
|
fields=('name', 'number'),
|
||||||
|
extra=0,
|
||||||
|
max_num=len(purchases_objects)
|
||||||
|
)
|
||||||
|
purchase_form = purchase_form_set(
|
||||||
|
request.POST or None,
|
||||||
|
queryset=purchases_objects
|
||||||
|
)
|
||||||
|
if invoice_form.is_valid() and purchase_form.is_valid():
|
||||||
|
if invoice_form.changed_data:
|
||||||
|
invoice_form.save()
|
||||||
|
purchase_form.save()
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been successfully edited.")
|
||||||
|
)
|
||||||
|
return redirect(reverse('cotisations:index-custom-invoice'))
|
||||||
|
|
||||||
|
return form({
|
||||||
|
'factureform': invoice_form,
|
||||||
|
'venteform': purchase_form
|
||||||
|
}, 'cotisations/edit_facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_view(CustomInvoice)
|
||||||
|
def custom_invoice_pdf(request, invoice, **_kwargs):
|
||||||
|
"""
|
||||||
|
View used to generate a PDF file from an existing invoice in database
|
||||||
|
Creates a line for each Purchase (thus article sold) and generate the
|
||||||
|
invoice with the total price, the payment method, the address and the
|
||||||
|
legal information for the user.
|
||||||
|
"""
|
||||||
|
# TODO : change vente to purchase
|
||||||
|
purchases_objects = Vente.objects.all().filter(facture=invoice)
|
||||||
|
# Get the article list and build an list out of it
|
||||||
|
# contiaining (article_name, article_price, quantity, total_price)
|
||||||
|
purchases_info = []
|
||||||
|
for purchase in purchases_objects:
|
||||||
|
purchases_info.append({
|
||||||
|
'name': purchase.name,
|
||||||
|
'price': purchase.prix,
|
||||||
|
'quantity': purchase.number,
|
||||||
|
'total_price': purchase.prix_total
|
||||||
|
})
|
||||||
|
return render_invoice(request, {
|
||||||
|
'paid': invoice.paid,
|
||||||
|
'fid': invoice.id,
|
||||||
|
'DATE': invoice.date,
|
||||||
|
'recipient_name': invoice.recipient,
|
||||||
|
'address': invoice.address,
|
||||||
|
'article': purchases_info,
|
||||||
|
'total': invoice.prix_total(),
|
||||||
|
'asso_name': AssoOption.get_cached_value('name'),
|
||||||
|
'line1': AssoOption.get_cached_value('adresse1'),
|
||||||
|
'line2': AssoOption.get_cached_value('adresse2'),
|
||||||
|
'siret': AssoOption.get_cached_value('siret'),
|
||||||
|
'email': AssoOption.get_cached_value('contact'),
|
||||||
|
'phone': AssoOption.get_cached_value('telephone'),
|
||||||
|
'tpl_path': os.path.join(settings.BASE_DIR, LOGO_PATH)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : change facture to invoice
|
||||||
|
@login_required
|
||||||
|
@can_delete(CustomInvoice)
|
||||||
|
def del_custom_invoice(request, invoice, **_kwargs):
|
||||||
|
"""
|
||||||
|
View used to delete an existing invocie.
|
||||||
|
"""
|
||||||
|
if request.method == "POST":
|
||||||
|
invoice.delete()
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("The invoice has been successfully deleted.")
|
||||||
|
)
|
||||||
|
return redirect(reverse('cotisations:index-custom-invoice'))
|
||||||
|
return form({
|
||||||
|
'objet': invoice,
|
||||||
|
'objet_name': _("Invoice")
|
||||||
|
}, 'cotisations/delete.html', request)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(Article)
|
@can_create(Article)
|
||||||
def add_article(request):
|
def add_article(request):
|
||||||
|
@ -681,8 +770,31 @@ def index_banque(request):
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_view_all(CustomInvoice)
|
||||||
|
def index_custom_invoice(request):
|
||||||
|
"""View used to display every custom invoice."""
|
||||||
|
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
||||||
|
custom_invoice_list = CustomInvoice.objects.prefetch_related('vente_set')
|
||||||
|
custom_invoice_list = SortTable.sort(
|
||||||
|
custom_invoice_list,
|
||||||
|
request.GET.get('col'),
|
||||||
|
request.GET.get('order'),
|
||||||
|
SortTable.COTISATIONS_CUSTOM
|
||||||
|
)
|
||||||
|
custom_invoice_list = re2o_paginator(
|
||||||
|
request,
|
||||||
|
custom_invoice_list,
|
||||||
|
pagination_number,
|
||||||
|
)
|
||||||
|
return render(request, 'cotisations/index_custom_invoice.html', {
|
||||||
|
'custom_invoice_list': custom_invoice_list
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(Facture)
|
@can_view_all(Facture)
|
||||||
|
@can_view_all(CustomInvoice)
|
||||||
def index(request):
|
def index(request):
|
||||||
"""
|
"""
|
||||||
View used to display the list of all exisitng invoices.
|
View used to display the list of all exisitng invoices.
|
||||||
|
@ -698,7 +810,7 @@ def index(request):
|
||||||
)
|
)
|
||||||
invoice_list = re2o_paginator(request, invoice_list, pagination_number)
|
invoice_list = re2o_paginator(request, invoice_list, pagination_number)
|
||||||
return render(request, 'cotisations/index.html', {
|
return render(request, 'cotisations/index.html', {
|
||||||
'facture_list': invoice_list
|
'facture_list': invoice_list,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,14 @@ class SortTable:
|
||||||
'cotis_id': ['id'],
|
'cotis_id': ['id'],
|
||||||
'default': ['-date']
|
'default': ['-date']
|
||||||
}
|
}
|
||||||
|
COTISATIONS_CUSTOM = {
|
||||||
|
'invoice_date': ['date'],
|
||||||
|
'invoice_id': ['id'],
|
||||||
|
'invoice_recipient': ['recipient'],
|
||||||
|
'invoice_address': ['address'],
|
||||||
|
'invoice_payment': ['payment'],
|
||||||
|
'default': ['-date']
|
||||||
|
}
|
||||||
COTISATIONS_CONTROL = {
|
COTISATIONS_CONTROL = {
|
||||||
'control_name': ['user__adherent__name'],
|
'control_name': ['user__adherent__name'],
|
||||||
'control_surname': ['user__surname'],
|
'control_surname': ['user__surname'],
|
||||||
|
|
|
@ -21,6 +21,6 @@ You should have received a copy of the GNU General Public License along
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
<a class="btn btn-primary btn-sm" role="button" href="{% url href id %}" title="{{ desc|default:"Ajouter" }}">
|
<a class="btn btn-primary btn-sm" role="button" href="{% if id %}{% url href id %}{% else %}{% url href %}{% endif %}" title="{{ desc|default:"Ajouter" }}">
|
||||||
<i class="fa fa-plus"></i>
|
<i class="fa fa-plus"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
Loading…
Reference in a new issue