Commit b83bfc0d authored by Hugo LEVY-FALK's avatar Hugo LEVY-FALK

Fix #123 Subscription voucher

parent 713b4b5c
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-01-03 16:48 # Generated by Django 1.10.7 on 2019-01-03 16:48
from __future__ import unicode_literals from __future__ import unicode_literals
import os
from django.db import migrations, models from django.db import migrations, models
from django.core.files import File
from django.conf import settings
import re2o.mixins import re2o.mixins
def create_default_templates(apps, schema_editor):
DocumentTemplate = apps.get_model('cotisations', 'DocumentTemplate')
invoice_path = os.path.join(
settings.BASE_DIR,
"cotisations",
"templates",
"cotisations",
"factures.tex"
)
with open(invoice_path) as f:
tpl, _ = DocumentTemplate.objects.get_or_create(
name="Re2o default invoice",
)
tpl.template.save('default_invoice.tex', File(f))
tpl.save()
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
...@@ -46,5 +26,4 @@ class Migration(migrations.Migration): ...@@ -46,5 +26,4 @@ class Migration(migrations.Migration):
}, },
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model),
), ),
migrations.RunPython(create_default_templates),
] ]
...@@ -50,7 +50,9 @@ from machines.models import regen ...@@ -50,7 +50,9 @@ from machines.models import regen
from re2o.field_permissions import FieldPermissionModelMixin from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin, RevMixin from re2o.mixins import AclMixin, RevMixin
from cotisations.utils import find_payment_method, send_mail_invoice from cotisations.utils import (
find_payment_method, send_mail_invoice, send_mail_voucher
)
from cotisations.validators import check_no_balance from cotisations.validators import check_no_balance
...@@ -238,20 +240,22 @@ class Facture(BaseInvoice): ...@@ -238,20 +240,22 @@ class Facture(BaseInvoice):
self.__original_valid = self.valid self.__original_valid = self.valid
self.__original_control = self.control self.__original_control = self.control
def get_subscribtion(self): def get_subscription(self):
return self.vent_set.filter( return Cotisation.objects.filter(
Q(type_cotisation='All') | vente__in=self.vente_set.filter(
Q(type_cotisation='Cotisation') Q(type_cotisation='All') |
Q(type_cotisation='Cotisation')
)
) )
def is_subscribtion(self): def is_subscription(self):
return bool(self.get_subscribtion()) return bool(self.get_subscription())
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(Facture, self).save(*args, **kwargs) super(Facture, self).save(*args, **kwargs)
if not self.__original_valid and self.valid: if not self.__original_valid and self.valid:
send_mail_invoice(self) send_mail_invoice(self)
if self.is_subscribtion() and not self.__original_control and self.control: if self.is_subscription() and not self.__original_control and self.control:
send_mail_voucher(self) send_mail_voucher(self)
def __str__(self): def __str__(self):
...@@ -267,10 +271,6 @@ def facture_post_save(**kwargs): ...@@ -267,10 +271,6 @@ def facture_post_save(**kwargs):
user = facture.user user = facture.user
user.set_active() user.set_active()
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False) user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
if facture.control:
user = facture.user
if user.is_adherent():
user.notif_subscription_accepted()
@receiver(post_delete, sender=Facture) @receiver(post_delete, sender=Facture)
...@@ -955,7 +955,7 @@ def cotisation_post_delete(**_kwargs): ...@@ -955,7 +955,7 @@ def cotisation_post_delete(**_kwargs):
class DocumentTemplate(RevMixin, AclMixin, models.Model): class DocumentTemplate(RevMixin, AclMixin, models.Model):
"""Represent a template in order to create documents such as invoice or """Represent a template in order to create documents such as invoice or
subscribtion voucher. subscription voucher.
""" """
template = models.FileField( template = models.FileField(
upload_to='templates/', upload_to='templates/',
...@@ -972,18 +972,3 @@ class DocumentTemplate(RevMixin, AclMixin, models.Model): ...@@ -972,18 +972,3 @@ class DocumentTemplate(RevMixin, AclMixin, models.Model):
def __str__(self): def __str__(self):
return str(self.name) return str(self.name)
class Voucher(RevMixin, AclMixin, models.Model):
"""A Subscription Voucher."""
user = models.ForeignKey(
'users.User',
on_delete=models.CASCADE,
verbose_name=_("user")
)
class Meta:
verbose_name = _("subscription voucher")
def __str__(self):
return "voucher {} {}".format(self.user, self.date)
...@@ -75,7 +75,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -75,7 +75,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% if estimate.final_invoice %} {% if estimate.final_invoice %}
<a href="{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"><i style="color: #1ECA18;" class="fa fa-check"></i></a> <a href="{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"><i style="color: #1ECA18;" class="fa fa-check"></i></a>
{% else %} {% else %}
<i style="color: #D10115;" class="fa fa-times"></i>' <i style="color: #D10115;" class="fa fa-times"></i>
{% endif %} {% endif %}
</td> </td>
<td> <td>
......
...@@ -48,7 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -48,7 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% trans "Date" as tr_date %} {% trans "Date" as tr_date %}
{% include 'buttons/sort.html' with prefix='cotis' col='date' text=tr_date %} {% include 'buttons/sort.html' with prefix='cotis' col='date' text=tr_date %}
</th> </th>
<th> <th>
{% trans "Invoice ID" as tr_invoice_id %} {% trans "Invoice ID" as tr_invoice_id %}
{% include 'buttons/sort.html' with prefix='cotis' col='id' text=tr_invoice_id %} {% include 'buttons/sort.html' with prefix='cotis' col='id' text=tr_invoice_id %}
</th> </th>
...@@ -63,17 +63,17 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -63,17 +63,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ facture.prix_total }}</td> <td>{{ facture.prix_total }}</td>
<td>{{ facture.paiement }}</td> <td>{{ facture.paiement }}</td>
<td>{{ facture.date }}</td> <td>{{ facture.date }}</td>
<td>{{ facture.id }}</td> <td>{{ facture.id }}</td>
<td> <td>
{% can_edit facture %} {% can_edit facture %}
{% include 'buttons/edit.html' with href='cotisations:edit-facture' id=facture.id %} {% include 'buttons/edit.html' with href='cotisations:edit-facture' id=facture.id %}
{% acl_else %} {% acl_else %}
{% trans "Controlled invoice" %} {% trans "Controlled invoice" %}
{% acl_end %} {% acl_end %}
{% can_delete facture %} {% can_delete facture %}
{% include 'buttons/suppr.html' with href='cotisations:del-facture' id=facture.id %} {% include 'buttons/suppr.html' with href='cotisations:del-facture' id=facture.id %}
{% acl_end %} {% acl_end %}
{% history_button facture %} {% history_button facture %}
</td> </td>
<td> <td>
{% if facture.valid %} {% if facture.valid %}
...@@ -83,13 +83,18 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -83,13 +83,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% else %} {% else %}
<i class="text-danger">{% trans "Invalidated invoice" %}</i> <i class="text-danger">{% trans "Invalidated invoice" %}</i>
{% endif %} {% endif %}
{% if facture.control and facture.is_subscription %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:voucher-pdf' facture.id %}">
<i class="fa fa-file-pdf-o"></i> {% trans "Voucher" %}
</a>
{% endif %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if facture_list.paginator %} {% if facture_list.paginator %}
{% include 'pagination.html' with list=facture_list %} {% include 'pagination.html' with list=facture_list %}
{% endif %} {% endif %}
</div> </div>
Bonjour {{name}} !
Nous vous informons que votre cotisation auprès de {{asso_name}} a été acceptée. Vous voilà donc membre de l'association.
Vous trouverez en pièce jointe un reçu.
Pour nous faire part de toute remarque, suggestion ou problème vous pouvez nous envoyer un mail à {{asso_email}}.
À bientôt,
L'équipe de {{asso_name}}.
---
Your subscription to {{asso_name}} has just been accepted. You are now a full member of {{asso_name}}.
You will find with this email a subscription voucher.
For any information, suggestion or problem, you can contact us via email at
{{asso_email}}.
Regards,
The {{asso_name}} team.
{% load i18n %}
{% language 'fr' %}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Invoice Template
% LaTeX Template
% Version 1.0 (3/11/12)
%% This template has been downloaded from:
% http://www.LaTeXTemplates.com
%
% Original author:
% Trey Hunner (http://www.treyhunner.com/)
%
% License:
% CC BY-NC-SA 3.0 (http://creativecommons.org/licenses/by-nc-sa/3.0/)
%
% Important note:
% This template requires the invoice.cls file to be in the same directory as
% the .tex file. The invoice.cls file provides the style used for structuring the
% document.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%----------------------------------------------------------------------------------------
% DOCUMENT CONFIGURATION
%----------------------------------------------------------------------------------------
\documentclass[12pt]{article} % Use the custom invoice class (invoice.cls)
\usepackage[utf8]{inputenc}
\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry}
\usepackage{longtable}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{eurosym}
\usepackage{multicol}
\pagestyle{empty} % No page numbers
\linespread{1.5}
\newcommand{\doublehline}{\noalign{\hrule height 1pt}}
\setlength{\parindent}{0cm}
\begin{document}
%----------------------------------------------------------------------------------------
% HEADING SECTION
%----------------------------------------------------------------------------------------
\begin{center}
{\Huge\bf Reçu d'adhésion \\ {{asso_name|safe}} } % Company providing the invoice
\end{center}
\bigskip
\hrule
\bigskip
\vfill
Je sousigné, {{pres_name|safe}}, déclare par la présente avoir reçu le bulletin d'adhésion de:
\begin{center}
\setlength{\tabcolsep}{10pt} % Make table columns tighter, usefull for postionning
\begin{tabular}{r l r l}
{\bf Prénom :}~ & {{firstname|safe}} & {% if phone %}{\bf Téléphone :}~ & {{phone}}{% else %} & {% endif %} \\
{\bf Nom :}~ & {{lastname|safe}} & {\bf Mail :}~ & {{email|safe}} \\
\end{tabular}
\end{center}
\bigskip
ainsi que sa cotisation.
Le postulant, déclare reconnaître l'objet de l'association, et en a accepté les statuts ainsi que le règlement intérieur qui sont mis à sa disposition dans les locaux de l'association. L'adhésion du membre sus-nommé est ainsi validée. Ce reçu confirme la qualité de membre du postulant, et ouvre droit à la participation à l'assemblée générale de l'association jusqu'au {{date_end|date:"d F Y"}}.
\bigskip
Validé électroniquement par {{pres_name|safe}}, le {{date_begin|date:"d/m/Y"}}.
\vfill
\hrule
\smallskip
\footnotesize
Les informations recueillies sont nécessaires pour votre adhésion. Conformément à la loi "Informatique et Libertés" du 6 janvier 1978, vous disposez d'un droit d'accès et de rectification aux données personnelles vous concernant. Pour l'exercer, adressez-vous au secrétariat de l'association.
\end{document}
{% endlanguage %}
...@@ -79,13 +79,14 @@ def render_voucher(_request, ctx={}): ...@@ -79,13 +79,14 @@ def render_voucher(_request, ctx={}):
filename = '_'.join([ filename = '_'.join([
'voucher', 'voucher',
slugify(ctx.get('asso_name', "")), slugify(ctx.get('asso_name', "")),
slugify(ctx.get('recipient_name', "")), slugify(ctx.get('firstname', "")),
str(ctx.get('DATE', datetime.now()).year), slugify(ctx.get('lastname', "")),
str(ctx.get('DATE', datetime.now()).month), str(ctx.get('date_begin', datetime.now()).year),
str(ctx.get('DATE', datetime.now()).day), str(ctx.get('date_begin', datetime.now()).month),
str(ctx.get('date_begin', datetime.now()).day),
]) ])
templatename = options.voucher_template.template.name.split('/')[-1] templatename = options.voucher_template.template.name.split('/')[-1]
r = create_pdf(templatename, ctx) r = render_tex(_request, templatename, ctx)
r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format( r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format(
name=filename name=filename
) )
...@@ -110,12 +111,13 @@ def create_pdf(template, ctx={}): ...@@ -110,12 +111,13 @@ def create_pdf(template, ctx={}):
with tempfile.TemporaryDirectory() as tempdir: with tempfile.TemporaryDirectory() as tempdir:
for _ in range(2): for _ in range(2):
process = Popen( with open("/var/www/re2o/out.log", "w") as f:
['pdflatex', '-output-directory', tempdir], process = Popen(
stdin=PIPE, ['pdflatex', '-output-directory', tempdir],
stdout=PIPE, stdin=PIPE,
) stdout=f,#PIPE,
process.communicate(rendered_tpl) )
process.communicate(rendered_tpl)
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f: with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f:
pdf = f.read() pdf = f.read()
......
...@@ -51,6 +51,11 @@ urlpatterns = [ ...@@ -51,6 +51,11 @@ urlpatterns = [
views.facture_pdf, views.facture_pdf,
name='facture-pdf' name='facture-pdf'
), ),
url(
r'^voucher_pdf/(?P<factureid>[0-9]+)$',
views.voucher_pdf,
name='voucher-pdf'
),
url( url(
r'^new_cost_estimate/$', r'^new_cost_estimate/$',
views.new_cost_estimate, views.new_cost_estimate,
......
...@@ -25,7 +25,7 @@ from django.template.loader import get_template ...@@ -25,7 +25,7 @@ from django.template.loader import get_template
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
from .tex import create_pdf from .tex import create_pdf
from preferences.models import AssoOption, GeneralOption from preferences.models import AssoOption, GeneralOption, CotisationsOption
from re2o.settings import LOGO_PATH from re2o.settings import LOGO_PATH
from re2o import settings from re2o import settings
...@@ -97,52 +97,34 @@ def send_mail_invoice(invoice): ...@@ -97,52 +97,34 @@ def send_mail_invoice(invoice):
def send_mail_voucher(invoice): def send_mail_voucher(invoice):
"""Creates a voucher from an invoice and sends it by email to the client""" """Creates a voucher from an invoice and sends it by email to the client"""
purchases_info = []
for purchase in invoice.vente_set.all():
purchases_info.append({
'name': purchase.name,
'price': purchase.prix,
'quantity': purchase.number,
'total_price': purchase.prix_total
})
ctx = { ctx = {
'paid': True,
'fid': invoice.id,
'DATE': invoice.date,
'recipient_name': "{} {}".format(
invoice.user.name,
invoice.user.surname
),
'address': invoice.user.room,
'article': purchases_info,
'total': invoice.prix_total(),
'asso_name': AssoOption.get_cached_value('name'), 'asso_name': AssoOption.get_cached_value('name'),
'line1': AssoOption.get_cached_value('adresse1'), 'pres_name': AssoOption.get_cached_value('pres_name'),
'line2': AssoOption.get_cached_value('adresse2'), 'firstname': invoice.user.name,
'siret': AssoOption.get_cached_value('siret'), 'lastname': invoice.user.surname,
'email': AssoOption.get_cached_value('contact'), 'email': invoice.user.email,
'phone': AssoOption.get_cached_value('telephone'), 'phone': invoice.user.telephone,
'tpl_path': os.path.join(settings.BASE_DIR, LOGO_PATH) 'date_end': invoice.get_subscription().latest('date_end').date_end,
'date_begin': invoice.get_subscription().earliest('date_start').date_start
} }
templatename = CotisationsOption.get_cached_value('voucher_template').template.name.split('/')[-1]
pdf = create_pdf('cotisations/factures.tex', ctx) pdf = create_pdf(templatename, ctx)
template = get_template('cotisations/email_invoice') template = get_template('cotisations/email_subscription_accepted')
ctx = { ctx = {
'name': "{} {}".format( 'name': "{} {}".format(
invoice.user.name, invoice.user.name,
invoice.user.surname invoice.user.surname
), ),
'contact_mail': AssoOption.get_cached_value('contact'), 'asso_email': AssoOption.get_cached_value('contact'),
'asso_name': AssoOption.get_cached_value('name') 'asso_name': AssoOption.get_cached_value('name')
} }
mail = EmailMessage( mail = EmailMessage(
'Votre facture / Your invoice', 'Votre reçu / Your voucher',
template.render(ctx), template.render(ctx),
GeneralOption.get_cached_value('email_from'), GeneralOption.get_cached_value('email_from'),
[invoice.user.get_mail], [invoice.user.get_mail],
attachments=[('invoice.pdf', pdf, 'application/pdf')] attachments=[('voucher.pdf', pdf, 'application/pdf')]
) )
mail.send() mail.send()
...@@ -88,7 +88,7 @@ from .forms import ( ...@@ -88,7 +88,7 @@ from .forms import (
DocumentTemplateForm, DocumentTemplateForm,
DelDocumentTemplateForm DelDocumentTemplateForm
) )
from .tex import render_invoice, escape_chars from .tex import render_invoice, render_voucher, escape_chars
from .payment_methods.forms import payment_method_factory from .payment_methods.forms import payment_method_factory
from .utils import find_payment_method from .utils import find_payment_method
...@@ -220,6 +220,7 @@ def new_cost_estimate(request): ...@@ -220,6 +220,7 @@ def new_cost_estimate(request):
number=quantity number=quantity
) )
discount_form.apply_to_invoice(cost_estimate_instance) discount_form.apply_to_invoice(cost_estimate_instance)
messages.success( messages.success(
request, request,
_("The cost estimate was created.") _("The cost estimate was created.")
...@@ -485,7 +486,6 @@ def cost_estimate_pdf(request, invoice, **_kwargs): ...@@ -485,7 +486,6 @@ def cost_estimate_pdf(request, invoice, **_kwargs):
invoice with the total price, the payment method, the address and the invoice with the total price, the payment method, the address and the
legal information for the user. legal information for the user.
""" """
# TODO : change vente to purchase
purchases_objects = Vente.objects.all().filter(facture=invoice) purchases_objects = Vente.objects.all().filter(facture=invoice)
# Get the article list and build an list out of it # Get the article list and build an list out of it
# contiaining (article_name, article_price, quantity, total_price) # contiaining (article_name, article_price, quantity, total_price)
...@@ -1145,3 +1145,30 @@ def index_document_template(request): ...@@ -1145,3 +1145,30 @@ def index_document_template(request):
return render(request, 'cotisations/index_document_template.html', { return render(request, 'cotisations/index_document_template.html', {
'document_template_list': document_template_list 'document_template_list': document_template_list
}) })
@login_required
@can_view(Facture)
def voucher_pdf(request, invoice, **_kwargs):
"""
View used to generate a PDF file from a controlled invoice
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.
"""
if not invoice.control:
messages.error(
request,
_("Could not find a voucher for that invoice.")
)
return redirect(reverse('cotisations:index'))
return render_voucher(request, {
'asso_name': AssoOption.get_cached_value('name'),
'pres_name': AssoOption.get_cached_value('pres_name'),
'firstname': invoice.user.name,
'lastname': invoice.user.surname,
'email': invoice.user.email,
'phone': invoice.user.telephone,
'date_end': invoice.get_subscription().latest('date_end').date_end,
'date_begin': invoice.get_subscription().earliest('date_start').date_start
})
...@@ -331,7 +331,8 @@ copy_templates_files() { ...@@ -331,7 +331,8 @@ copy_templates_files() {
echo "Copying LaTeX templates ..." echo "Copying LaTeX templates ..."
mkdir -p media/templates/ mkdir -p media/templates/
cp cotisations/templates/cotisations/factures.tex media/templates cp cotisations/templates/cotisations/factures.tex media/templates/default_invoice.tex
cp cotisations/templates/cotisations/voucher.tex media/templates/default_voucher.tex
echo "Copying LaTeX templates: Done" echo "Copying LaTeX templates: Done"
} }
......
...@@ -183,9 +183,6 @@ class EditAssoOptionForm(ModelForm): ...@@ -183,9 +183,6 @@ class EditAssoOptionForm(ModelForm):
self.fields['pseudo'].label = _("Usual name") self.fields['pseudo'].label = _("Usual name")
self.fields['utilisateur_asso'].label = _("Account used for editing" self.fields['utilisateur_asso'].label = _("Account used for editing"
" from /admin") " from /admin")
self.fields['payment'].label = _("Payment")
self.fields['payment_id'].label = _("Payment ID")
self.fields['payment_pass'].label = _("Payment password")
self.fields['description'].label = _("Description") self.fields['description'].label = _("Description")
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-01-03 19:56 # Generated by Django 1.10.7 on 2019-01-03 19:56
from __future__ import unicode_literals from __future__ import unicode_literals
import os
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.core.files import File
from django.conf import settings
import re2o.mixins import re2o.mixins
def initialize_invoice_template(apps, schema_editor): def initialize_invoice_template(apps, schema_editor):
CotisationsOption = apps.get_model('preferences', 'CotisationsOption') CotisationsOption = apps.get_model('preferences', 'CotisationsOption')
DocumentTemplate = apps.get_model('cotisations', 'DocumentTemplate') DocumentTemplate = apps.get_model('cotisations', 'DocumentTemplate')
invoice_path = os.path.join(
settings.BASE_DIR,
"cotisations",
"templates",
"cotisations",
"factures.tex"
)
voucher_path = os.path.join(
settings.BASE_DIR,
"cotisations",
"templates",
"cotisations",
"voucher.tex"
)
with open(invoice_path) as f:
tpl_invoice, _ = DocumentTemplate.objects.get_or_create(
name="Re2o default invoice",
)
tpl_invoice.template.save('default_invoice.tex', File(f))
tpl_invoice.save()
with open(voucher_path) as f:
tpl_voucher, _ = DocumentTemplate.objects.get_or_create(
name="Re2o default voucher",
)
tpl_voucher.template.save('default_voucher.tex', File(f))
tpl_voucher.save()
CotisationsOption.objects.create( CotisationsOption.objects.create(
invoice_template=DocumentTemplate.objects.first() invoice_template=tpl_invoice,
voucher_template=tpl_voucher,
) )
...@@ -28,6 +58,7 @@ class Migration(migrations.Migration): ...@@ -28,6 +58,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('invoice_template', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='invoice_template', to='cotisations.DocumentTemplate', verbose_name='Template for invoices')), ('invoice_template', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='invoice_template', to='cotisations.DocumentTemplate', verbose_name='Template for invoices')),
('voucher_template', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='voucher_template', to='cotisations.DocumentTemplate', verbose_name='Template for subscription voucher')),
], ],
options={ options={
'verbose_name': 'cotisations options', 'verbose_name': 'cotisations options',
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-01-10 22:13
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0057_cotisationsoption'),
]
operations = [
migrations.AddField(
model_name='assooption',
name='pres_name',
field=models.CharField(default='', help_text='Displayed on subscription vouchers', max_length=255, verbose_name='President of the association'),
),
]
...@@ -521,6 +521,12 @@ class AssoOption(AclMixin, PreferencesModel): ...@@ -521,6 +521,12 @@ class AssoOption(AclMixin, PreferencesModel):
null=True, null=True,
blank=True, blank=True,
) )
pres_name = models.CharField(
max_length=255,
default="",
verbose_name=_("President of the association"),
help_text=_("Displayed on subscription vouchers")
)
class Meta: class Meta:
permissions = (