8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-23 11:53:12 +00:00

subscripbtion voucher

This commit is contained in:
Hugo LEVY-FALK 2019-01-05 19:45:21 +01:00
parent 0a8335c375
commit 48d8d7921d
10 changed files with 217 additions and 29 deletions

View file

@ -30,8 +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, CostEstimate from .models import CustomInvoice, CostEstimate, DocumentTemplate
from .tex import DocumentTemplate
class FactureAdmin(VersionAdmin): class FactureAdmin(VersionAdmin):

View file

@ -48,9 +48,8 @@ from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin from re2o.mixins import FormRevMixin
from .models import ( from .models import (
Article, Paiement, Facture, Banque, Article, Paiement, Facture, Banque,
CustomInvoice, Vente, CostEstimate CustomInvoice, Vente, CostEstimate, DocumentTemplate
) )
from .tex import DocumentTemplate
from .payment_methods import balance from .payment_methods import balance

View file

@ -236,11 +236,23 @@ class Facture(BaseInvoice):
'control': self.can_change_control, 'control': self.can_change_control,
} }
self.__original_valid = self.valid self.__original_valid = self.valid
self.__original_control = self.control
def get_subscribtion(self):
return self.vent_set.filter(
Q(type_cotisation='All') |
Q(type_cotisation='Cotisation')
)
def is_subscribtion(self):
return bool(self.get_subscribtion())
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:
send_mail_voucher(self)
def __str__(self): def __str__(self):
return str(self.user) + ' ' + str(self.date) return str(self.user) + ' ' + str(self.date)
@ -255,6 +267,10 @@ 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)
@ -935,3 +951,39 @@ def cotisation_post_delete(**_kwargs):
""" """
regen('mac_ip_list') regen('mac_ip_list')
regen('mailing') regen('mailing')
class DocumentTemplate(RevMixin, AclMixin, models.Model):
"""Represent a template in order to create documents such as invoice or
subscribtion voucher.
"""
template = models.FileField(
upload_to='templates/',
verbose_name=_('template')
)
name = models.CharField(
max_length=255,
verbose_name=_('name')
)
class Meta:
verbose_name = _("document template")
verbose_name_plural = _("document templates")
def __str__(self):
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)

View file

@ -48,27 +48,6 @@ CACHE_PREFIX = getattr(settings, 'TEX_CACHE_PREFIX', 'render-tex')
CACHE_TIMEOUT = getattr(settings, 'TEX_CACHE_TIMEOUT', 86400) # 1 day CACHE_TIMEOUT = getattr(settings, 'TEX_CACHE_TIMEOUT', 86400) # 1 day
class DocumentTemplate(RevMixin, AclMixin, models.Model):
"""Represent a template in order to create documents such as invoice or
subscribtion voucher.
"""
template = models.FileField(
upload_to='templates/',
verbose_name=_('template')
)
name = models.CharField(
max_length=255,
verbose_name=_('name')
)
class Meta:
verbose_name = _("document template")
verbose_name_plural = _("document templates")
def __str__(self):
return str(self.name)
def render_invoice(_request, ctx={}): def render_invoice(_request, ctx={}):
""" """
Render an invoice using some available information such as the current Render an invoice using some available information such as the current
@ -92,6 +71,27 @@ def render_invoice(_request, ctx={}):
return r return r
def render_voucher(_request, ctx={}):
"""
Render a subscribtion voucher.
"""
options, _ = CotisationsOption.objects.get_or_create()
filename = '_'.join([
'voucher',
slugify(ctx.get('asso_name', "")),
slugify(ctx.get('recipient_name', "")),
str(ctx.get('DATE', datetime.now()).year),
str(ctx.get('DATE', datetime.now()).month),
str(ctx.get('DATE', datetime.now()).day),
])
templatename = options.voucher_template.template.name.split('/')[-1]
r = create_pdf(templatename, ctx)
r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format(
name=filename
)
return r
def create_pdf(template, ctx={}): def create_pdf(template, ctx={}):
"""Creates and returns a PDF from a LaTeX template using pdflatex. """Creates and returns a PDF from a LaTeX template using pdflatex.

View file

@ -93,3 +93,56 @@ def send_mail_invoice(invoice):
attachments=[('invoice.pdf', pdf, 'application/pdf')] attachments=[('invoice.pdf', pdf, 'application/pdf')]
) )
mail.send() mail.send()
def send_mail_voucher(invoice):
"""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 = {
'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'),
'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)
}
pdf = create_pdf('cotisations/factures.tex', ctx)
template = get_template('cotisations/email_invoice')
ctx = {
'name': "{} {}".format(
invoice.user.name,
invoice.user.surname
),
'contact_mail': AssoOption.get_cached_value('contact'),
'asso_name': AssoOption.get_cached_value('name')
}
mail = EmailMessage(
'Votre facture / Your invoice',
template.render(ctx),
GeneralOption.get_cached_value('email_from'),
[invoice.user.get_mail],
attachments=[('invoice.pdf', pdf, 'application/pdf')]
)
mail.send()

View file

@ -69,7 +69,8 @@ from .models import (
Banque, Banque,
CustomInvoice, CustomInvoice,
BaseInvoice, BaseInvoice,
CostEstimate CostEstimate,
DocumentTemplate
) )
from .forms import ( from .forms import (
FactureForm, FactureForm,
@ -87,7 +88,7 @@ from .forms import (
DocumentTemplateForm, DocumentTemplateForm,
DelDocumentTemplateForm DelDocumentTemplateForm
) )
from .tex import render_invoice, escape_chars, DocumentTemplate from .tex import render_invoice, 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

View file

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-01-03 19:56
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import re2o.mixins
def initialize_invoice_template(apps, schema_editor):
CotisationsOption = apps.get_model('preferences', 'CotisationsOption')
DocumentTemplate = apps.get_model('cotisations', 'DocumentTemplate')
CotisationsOption.objects.create(
invoice_template=DocumentTemplate.objects.first()
)
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0039_documenttemplate'),
('preferences', '0056_4_radiusoption'),
]
operations = [
migrations.CreateModel(
name='CotisationsOption',
fields=[
('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')),
],
options={
'verbose_name': 'cotisations options',
},
bases=(re2o.mixins.AclMixin, models.Model),
),
migrations.RunPython(initialize_invoice_template),
]

View file

@ -698,4 +698,9 @@ class CotisationsOption(AclMixin, PreferencesModel):
related_name="invoice_template", related_name="invoice_template",
on_delete=models.PROTECT, on_delete=models.PROTECT,
) )
voucher_template = models.OneToOneField(
'cotisations.DocumentTemplate',
verbose_name=_("Template for subscription voucher"),
related_name="voucher_template",
on_delete=models.PROTECT,
)

View file

@ -663,6 +663,25 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
) )
return return
def notif_subscription_accepted(self):
"""Send an email when the subscription has been accepted"""
template = loader.get_template('users/email_subscription_accepted')
mailmessageoptions, _created = MailMessageOption\
.objects.get_or_create()
context = Context({
'nom': self.get_full_name(),
'asso_name': AssoOption.get_cached_value('name'),
'asso_email': AssoOption.get_cached_value('contact'),
})
send_mail(
'Votre inscription a été validée / Your subscription has been accepted',
'',
GeneralOption.get_cached_value('email_from'),
[self.email],
html_message=template.render(context)
)
return
def reset_passwd_mail(self, request): def reset_passwd_mail(self, request):
""" Prend en argument un request, envoie un mail de """ Prend en argument un request, envoie un mail de
réinitialisation de mot de pass """ réinitialisation de mot de pass """

View file

@ -0,0 +1,22 @@
<p>Bonjour {{nom}} !</p>
<p>Nous vous informons que votre cotisation auprès de {{asso_name}} a été acceptée. Vous voilà donc membre de l'association.</p>
<p>Vous trouverez en pièce jointe un reçu.</p>
<p>Pour nous faire part de toute remarque, suggestion ou problème vous pouvez nous envoyer un mail à {{asso_email}}.</p>
<p>À bientôt,<br>
L'équipe de {{asso_name}}.</p>
<p>---</p>
<p>Your subscription to {{asso_name}} has just been accepted. You are now a full member of {{asso_name}}.
<p>You will find with this email a subscription voucher.</p>
<p>For any information, suggestion or problem, you can contact us via email at<br>
{{asso_email}}.</p>
<p>Regards,<br>
The {{asso_name}} team.</p>