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

Custom invoices.

parent 0527206e
...@@ -46,7 +46,7 @@ from django.shortcuts import get_object_or_404 ...@@ -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): ...@@ -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):
......
# -*- 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
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()
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0030_custom_payment'),
]
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_custom_invoice', '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'),
)
]
...@@ -55,8 +55,52 @@ from cotisations.utils import find_payment_method ...@@ -55,8 +55,52 @@ from cotisations.utils import find_payment_method
from cotisations.validators import check_no_balance from cotisations.validators import check_no_balance
class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
date = models.DateTimeField(
auto_now_add=True,
verbose_name=_l("Date")
)
# TODO : change prix to price
def prix(self):
"""
Returns: the raw price without the quantities.
Deprecated, use :total_price instead.
"""
price = Vente.objects.filter(
facture=self
).aggregate(models.Sum('prix'))['prix__sum']
return price
# TODO : change prix to price
def prix_total(self):
"""
Returns: the total price for an invoice. Sum all the articles' prices
and take the quantities into account.
"""
# TODO : change Vente to somethingelse
return Vente.objects.filter(
facture=self
).aggregate(
total=models.Sum(
models.F('prix')*models.F('number'),
output_field=models.FloatField()
)
)['total'] or 0
def name(self):
"""
Returns : a string with the name of all the articles in the invoice.
Used for reprensenting the invoice with a string.
"""
name = ' - '.join(Vente.objects.filter(
facture=self
).values_list('name', flat=True))
return name
# TODO : change facture to invoice # TODO : change facture to invoice
class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): class Facture(BaseInvoice):
""" """
The model for an invoice. It reprensents the fact that a user paid for The model for an invoice. It reprensents the fact that a user paid for
something (it can be multiple article paid at once). something (it can be multiple article paid at once).
...@@ -92,10 +136,6 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): ...@@ -92,10 +136,6 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
blank=True, blank=True,
verbose_name=_l("Cheque number") verbose_name=_l("Cheque number")
) )
date = models.DateTimeField(
auto_now_add=True,
verbose_name=_l("Date")
)
# TODO : change name to validity for clarity # TODO : change name to validity for clarity
valid = models.BooleanField( valid = models.BooleanField(
default=True, default=True,
...@@ -130,43 +170,6 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): ...@@ -130,43 +170,6 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
Usefull in history display""" Usefull in history display"""
return self.vente_set.all() return self.vente_set.all()
# TODO : change prix to price
def prix(self):
"""
Returns: the raw price without the quantities.
Deprecated, use :total_price instead.
"""
price = Vente.objects.filter(
facture=self
).aggregate(models.Sum('prix'))['prix__sum']
return price
# TODO : change prix to price
def prix_total(self):
"""
Returns: the total price for an invoice. Sum all the articles' prices
and take the quantities into account.
"""
# TODO : change Vente to somethingelse
return Vente.objects.filter(
facture=self
).aggregate(
total=models.Sum(
models.F('prix')*models.F('number'),
output_field=models.FloatField()
)
)['total'] or 0
def name(self):
"""
Returns : a string with the name of all the articles in the invoice.
Used for reprensenting the invoice with a string.
"""
name = ' - '.join(Vente.objects.filter(
facture=self
).values_list('name', flat=True))
return name
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.")
...@@ -265,6 +268,28 @@ def facture_post_delete(**kwargs): ...@@ -265,6 +268,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_custom_invoice', _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 +313,7 @@ class Vente(RevMixin, AclMixin, models.Model): ...@@ -288,7 +313,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 +380,10 @@ class Vente(RevMixin, AclMixin, models.Model): ...@@ -355,6 +380,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 +391,7 @@ class Vente(RevMixin, AclMixin, models.Model): ...@@ -362,7 +391,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 +400,9 @@ class Vente(RevMixin, AclMixin, models.Model): ...@@ -371,9 +400,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 +474,10 @@ def vente_post_save(**kwargs): ...@@ -445,6 +474,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 +495,12 @@ def vente_post_delete(**kwargs): ...@@ -462,8 +495,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)
......
{% 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
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 %}
<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" %}</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 }}</td>
<td>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="editinvoice" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
{% trans "Edit" %}<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="editinvoice">
{% can_edit invoice %}
<li>
<a href="{% url 'cotisations:edit-custom-invoice' invoice.id %}">
<i class="fa fa-dollar-sign"></i> {% trans "Edit" %}
</a>
</li>
{% acl_end %}
{% can_delete invoice %}
<li>
<a href="{% url 'cotisations:del-custom-invoice' invoice.id %}">
<i class="fa fa-trash"></i> {% trans "Delete" %}
</a>
</li>
{% acl_end %}
<li>
<a href="{% url 'cotisations:history' 'custominvoice' invoice.id %}">
<i class="fa fa-history"></i> {% trans "Historique" %}
</a>
</li>
</ul>
</div>
</td>
<td>
<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>
{% 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 %}
...@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block sidebar %} {% block sidebar %}
{% can_change Facture pdf %} {% can_change Facture pdf %}
<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., ...@@ -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" %}
......
...@@ -52,9 +52,29 @@ urlpatterns = [ ...@@ -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 ( ...@@ -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 ( ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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.
"""