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

Pdf pour les factures

This commit is contained in:
Dalahro 2016-07-14 01:54:06 +02:00
parent 61733e991c
commit 527f1b9f04
8 changed files with 49 additions and 35 deletions

View file

@ -15,6 +15,8 @@ Dépendances :
* django-bootstrap3 (pip install) * django-bootstrap3 (pip install)
* python3-django-macaddress (stretch) * python3-django-macaddress (stretch)
* python3-dateutil (jessie-backports) * python3-dateutil (jessie-backports)
* texlive-latex-base
* texlive-fonts-recommended
Moteur de db conseillé (mysql), postgresql fonctionne également. Moteur de db conseillé (mysql), postgresql fonctionne également.
Pour mysql, il faut installer : Pour mysql, il faut installer :

View file

@ -1,13 +1,13 @@
from django import forms from django import forms
from django.forms import ModelForm, Form from django.forms import ModelForm, Form
from .models import Article, Paiement, Facture, Banque from django import forms
from .models import Article, Paiement, Facture, Banque, Vente
class NewFactureForm(ModelForm): class NewFactureForm(ModelForm):
article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article") article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article", widget=forms.CheckboxSelectMultiple())
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(NewFactureForm, self).__init__(*args, **kwargs) super(NewFactureForm, self).__init__(*args, **kwargs)
self.fields['number'].label = 'Quantité'
self.fields['cheque'].required = False self.fields['cheque'].required = False
self.fields['banque'].required = False self.fields['banque'].required = False
self.fields['cheque'].label = 'Numero de chèque' self.fields['cheque'].label = 'Numero de chèque'
@ -16,7 +16,7 @@ class NewFactureForm(ModelForm):
class Meta: class Meta:
model = Facture model = Facture
fields = ['paiement','banque','cheque','number'] fields = ['paiement','banque','cheque']
def clean(self): def clean(self):
cleaned_data=super(NewFactureForm, self).clean() cleaned_data=super(NewFactureForm, self).clean()
@ -27,13 +27,17 @@ class NewFactureForm(ModelForm):
raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires") raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires")
return cleaned_data return cleaned_data
class SelectArticleForm(Form):
article = forms.ModelChoiceField(queryset=Article.objects.all(), label="Article")
quantity = forms.IntegerField(label="Quantité")
class NewFactureFormPdf(Form): class NewFactureFormPdf(Form):
article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article") article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article")
number = forms.IntegerField(label="Quantité") number = forms.IntegerField(label="Quantité")
paid = forms.BooleanField(label="Payé", required=False) paid = forms.BooleanField(label="Payé", required=False)
dest = forms.CharField(required=True, max_length=255, label="Destinataire") dest = forms.CharField(required=True, max_length=255, label="Destinataire")
obj = forms.CharField(required=False, label="Objet") chambre = forms.CharField(required=False, max_length=10, label="Adresse")
detail = forms.CharField(required=False, max_length=255, label="Détails") fid = forms.CharField(required=True, max_length=10, label="Numéro de la facture")
class EditFactureForm(NewFactureForm): class EditFactureForm(NewFactureForm):
class Meta(NewFactureForm.Meta): class Meta(NewFactureForm.Meta):

View file

@ -3,8 +3,7 @@
<tr> <tr>
<th>Utilisateur</th> <th>Utilisateur</th>
<th>Designation</th> <th>Designation</th>
<th>Nombre</th> <th>Prix total</th>
<th>Prix unitaire</th>
<th>Moyen de paiement</th> <th>Moyen de paiement</th>
<th>Date</th> <th>Date</th>
<th></th> <th></th>
@ -15,8 +14,7 @@
<tr> <tr>
<td>{{ facture.user }}</td> <td>{{ facture.user }}</td>
<td>{{ facture.name }}</td> <td>{{ facture.name }}</td>
<td>{{ facture.number }}</td> <td>{{ facture.prix_total }}</td>
<td>{{ facture.prix }}</td>
<td>{{ facture.paiement }}</td> <td>{{ facture.paiement }}</td>
<td>{{ facture.date }}</td> <td>{{ facture.date }}</td>
<td>{% if is_cableur %}<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:edit-facture' facture.id %}"><i class="glyphicon glyphicon-bitcoin"></i> Editer</a>{% endif %}</td> <td>{% if is_cableur %}<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:edit-facture' facture.id %}"><i class="glyphicon glyphicon-bitcoin"></i> Editer</a>{% endif %}</td>

View file

@ -9,6 +9,10 @@
<form class="form" method="post"> <form class="form" method="post">
{% csrf_token %} {% csrf_token %}
{% bootstrap_form factureform %} {% bootstrap_form factureform %}
{% for vente in venteform %}
{% bootstrap_form vente %}
{% endfor %}
{{ venteform.management_form }}
{% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %} {% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %}
</form> </form>
{% endblock %} {% endblock %}

View file

@ -34,6 +34,7 @@
\usepackage{graphicx} \usepackage{graphicx}
\usepackage{calc} \usepackage{calc}
\usepackage{tabularx} \usepackage{tabularx}
\usepackage{eurosym}
\pagestyle{empty} % No page numbers \pagestyle{empty} % No page numbers
\linespread{1.5} % Line spacing \linespread{1.5} % Line spacing
@ -52,12 +53,8 @@
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
% HEADING SECTION % HEADING SECTION
%---------------------------------------------------------------------------------------- %----------------------------------------------------------------------------------------
\begin{titlepage} \includegraphics[width=3.5cm]{% templatetag openbrace %}{{ tpl_path }}}
%\begin{textblock}{4cm}(20mm,5mm) \tab \tab \tab \tab \tab {\Huge\bf {{asso_name}} }\hfil % Company providing the invoice
%\includegraphics[scale=0.3]{/static_files/rezo-logo.png}
%\end{textblock}
\end{titlepage}
\hfil{\Huge\bf {{asso_name}} }\hfil % Company providing the invoice
\bigskip\break % Whitespace \bigskip\break % Whitespace
\hrule % Horizontal line \\ \hrule % Horizontal line \\
\vspace{0.5cm} \vspace{0.5cm}
@ -66,7 +63,7 @@
Siret : {{siret}} Siret : {{siret}}
\\ \\ \\ \\
{\bf À :} \tab {{dest.name}} {{dest.surname}} \\ % Invoice recipient {\bf À :} \tab {{dest.name}} {{dest.surname}} \\ % Invoice recipient
{\bf Chambre :} \tab {% if dest.room = None %} Aucune chambre {% else %}{{dest.room}}{% endif %} \\ {\bf Adresse :} \tab {% if dest.room = None %} Aucune adresse renseignée {% else %}{{dest.room}}{% endif %} \\
{\bf Date:} \tab {{DATE}} \\ % Invoice date {\bf Date:} \tab {{DATE}} \\ % Invoice date
@ -77,29 +74,27 @@ Siret : {{siret}}
\begin{tabularx}{\textwidth}{|X|r|r|r|} \begin{tabularx}{\textwidth}{|X|r|r|r|}
\hline \hline
\textbf{Désignation} & \textbf{Prix Unit.} & \textbf{Quantité} & \textbf{Prix total} \\ \textbf{Désignation} & \textbf{Prix Unit.} \euro & \textbf{Quantité} & \textbf{Prix total} \euro\\
\hline \hline
{% for a in article %} {% for a in article %}
\hline \hline
{{a.0.name}} & {{a.0.prix}} & {{a.1}} & {{a.2}}\\ {{a.0.name}} & {{a.0.prix}} \euro & {{a.1}} & {{a.2}} \euro\\
\hline \hline
{% endfor %} {% endfor %}
\hline \hline
\end{tabularx} \end{tabularx}
%\setcounter{paid}{0}
%\setcounter{topay}{\real{\value{total}}-\value{paid}}
\vspace{1cm} \vspace{1cm}
\hfill \hfill
\begin{tabular}{|l|r|} \begin{tabular}{|l|r|}
\hline \hline
\textbf{Total} & {{total|floatformat:2}} \\ \textbf{Total} & {{total|floatformat:2}} \euro \\
\textbf{Votre règlement} & {% if paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %} \\ \textbf{Votre règlement} & {% if paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %} \euro \\
\hline \hline
\textbf{À PAYER} & {% if not paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %}\\ \textbf{À PAYER} & {% if not paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %} \euro\\
\hline \hline
\hline \hline

View file

@ -5,4 +5,5 @@
<p><a href="{% url "cotisations:index-article" %}">Liste des articles en vente</a></p> <p><a href="{% url "cotisations:index-article" %}">Liste des articles en vente</a></p>
<p><a href="{% url "cotisations:index-banque" %}">Liste des banques</a></p> <p><a href="{% url "cotisations:index-banque" %}">Liste des banques</a></p>
<p><a href="{% url "cotisations:index-paiement" %}">Liste des moyens de paiement</a></p> <p><a href="{% url "cotisations:index-paiement" %}">Liste des moyens de paiement</a></p>
{% if is_trez %}<p><a href="{% url "cotisations:new-facture-pdf" %}">Créer une nouvelle facture</a></p>{% endif %}
{% endblock %} {% endblock %}

View file

@ -8,12 +8,15 @@ from django.template import Context, RequestContext, loader
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.contrib import messages from django.contrib import messages
from django.db.models import Max, ProtectedError from django.db.models import Max, ProtectedError
from django.forms import modelformset_factory, formset_factory
import os
from .models import Facture, Article, Vente, Cotisation, Paiement, Banque from .models import Facture, Article, Vente, Cotisation, Paiement, Banque
from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, PaiementForm, DelPaiementForm, BanqueForm, DelBanqueForm, NewFactureFormPdf from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, PaiementForm, DelPaiementForm, BanqueForm, DelBanqueForm, NewFactureFormPdf
from users.models import User from users.models import User
from .tex import render_tex from .tex import render_tex
from re2o.settings_local import ASSO_NAME, ASSO_ADDRESS_LINE1, ASSO_ADDRESS_LINE2, ASSO_SIRET, ASSO_EMAIL, ASSO_PHONE, LOGO_PATH from re2o.settings_local import ASSO_NAME, ASSO_ADDRESS_LINE1, ASSO_ADDRESS_LINE2, ASSO_SIRET, ASSO_EMAIL, ASSO_PHONE, LOGO_PATH
from re2o import settings
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from django.utils import timezone from django.utils import timezone
@ -44,15 +47,16 @@ def new_facture(request, userid):
return redirect("/cotisations/") return redirect("/cotisations/")
facture = Facture(user=user) facture = Facture(user=user)
facture_form = NewFactureForm(request.POST or None, instance=facture) facture_form = NewFactureForm(request.POST or None, instance=facture)
ArticleFormSet = formset_factory(ArticleForm)
if facture_form.is_valid(): if facture_form.is_valid():
new_facture = facture_form.save(commit=False) new_facture = facture_form.save(commit=False)
article = facture_form.cleaned_data['article'] article = facture_form.cleaned_data['article']
new_facture.save() new_facture.save()
for art in article: for art in article:
new_vente = Vente.objects.create(facture=new_facture, name=art.name, prix=art.prix, cotisation=art.cotisation, duration=art.duration) new_vente = Vente.objects.create(facture=new_facture, name=art.name, prix=art.prix, cotisation=art.cotisation, duration=art.duration, number=1)
new_vente.save() new_vente.save()
if any(art.cotisation for art in article): if any(art.cotisation for art in article):
duration = sum(art.duration*facture.number for art in article if art.cotisation) duration = sum(art.duration for art in article if art.cotisation)
create_cotis(new_facture, user, duration) create_cotis(new_facture, user, duration)
messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name ) messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name )
else: else:
@ -61,7 +65,7 @@ def new_facture(request, userid):
return form({'factureform': facture_form}, 'cotisations/facture.html', request) return form({'factureform': facture_form}, 'cotisations/facture.html', request)
@login_required @login_required
@permission_required('cableur') @permission_required('trésorier')
def new_facture_pdf(request): def new_facture_pdf(request):
facture_form = NewFactureFormPdf(request.POST or None) facture_form = NewFactureFormPdf(request.POST or None)
if facture_form.is_valid(): if facture_form.is_valid():
@ -70,12 +74,13 @@ def new_facture_pdf(request):
quantite = facture_form.cleaned_data['number'] quantite = facture_form.cleaned_data['number']
paid = facture_form.cleaned_data['paid'] paid = facture_form.cleaned_data['paid']
destinataire = facture_form.cleaned_data['dest'] destinataire = facture_form.cleaned_data['dest']
objet = facture_form.cleaned_data['obj'] chambre = facture_form.cleaned_data['chambre']
detail = facture_form.cleaned_data['detail'] fid = facture_form.cleaned_data['fid']
for a in article: for a in article:
tbl.append([a, quantite, a.prix * quantite]) tbl.append([a, quantite, a.prix * quantite])
prix_total = sum(a[2] for a in tbl) prix_total = sum(a[2] for a in tbl)
return render_tex(request, 'cotisations/factures.tex', {'DATE' : timezone.now(),'dest':destinataire, 'obj':objet, 'detail':detail, 'article':tbl, 'total':prix_total, 'paid':paid, 'asso_name':ASSO_NAME, 'line1':ASSO_ADDRESS_LINE1, 'line2':ASSO_ADDRESS_LINE2, 'siret':ASSO_SIRET, 'email':ASSO_EMAIL, 'phone':ASSO_PHONE}) user = {'name':destinataire, 'room':chambre}
return render_tex(request, 'cotisations/factures.tex', {'DATE' : timezone.now(),'dest':user,'fid':fid, 'article':tbl, 'total':prix_total, 'paid':paid, 'asso_name':ASSO_NAME, 'line1':ASSO_ADDRESS_LINE1, 'line2':ASSO_ADDRESS_LINE2, 'siret':ASSO_SIRET, 'email':ASSO_EMAIL, 'phone':ASSO_PHONE, 'tpl_path': os.path.join(settings.BASE_DIR, LOGO_PATH)})
return form({'factureform': facture_form}, 'cotisations/facture.html', request) return form({'factureform': facture_form}, 'cotisations/facture.html', request)
@login_required @login_required
@ -91,9 +96,10 @@ def facture_pdf(request, factureid):
vente = Vente.objects.all().filter(facture=facture) vente = Vente.objects.all().filter(facture=facture)
ventes = [] ventes = []
for v in vente: for v in vente:
ventes.append([v, facture.number, v.prix * facture.number]) ventes.append([v, v.number, v.prix_total])
return render_tex(request, 'cotisations/factures.tex', {'paid':True, 'fid':facture.id, 'DATE':facture.date,'dest':facture.user, 'article':ventes, 'total': facture.prix_total(), 'asso_name':ASSO_NAME, 'line1': ASSO_ADDRESS_LINE1, 'line2':ASSO_ADDRESS_LINE2, 'siret':ASSO_SIRET, 'email':ASSO_EMAIL, 'phone':ASSO_PHONE, 'tpl_path':LOGO_PATH}) return render_tex(request, 'cotisations/factures.tex', {'paid':True, 'fid':facture.id, 'DATE':facture.date,'dest':facture.user, 'article':ventes, 'total': facture.prix_total(), 'asso_name':ASSO_NAME, 'line1': ASSO_ADDRESS_LINE1, 'line2':ASSO_ADDRESS_LINE2, 'siret':ASSO_SIRET, 'email':ASSO_EMAIL, 'phone':ASSO_PHONE, 'tpl_path':os.path.join(settings.BASE_DIR, LOGO_PATH)})
@login_required
@permission_required('cableur') @permission_required('cableur')
def edit_facture(request, factureid): def edit_facture(request, factureid):
try: try:
@ -102,11 +108,15 @@ def edit_facture(request, factureid):
messages.error(request, u"Facture inexistante" ) messages.error(request, u"Facture inexistante" )
return redirect("/cotisations/") return redirect("/cotisations/")
facture_form = EditFactureForm(request.POST or None, instance=facture) facture_form = EditFactureForm(request.POST or None, instance=facture)
if facture_form.is_valid(): ventes_objects = Vente.objects.filter(facture=facture)
vente_form_set = modelformset_factory(Vente, fields=('name','prix','number'), can_delete=True)
vente_form = vente_form_set(request.POST or None, queryset=ventes_objects)
if facture_form.is_valid() and vente_form.is_valid():
facture_form.save() facture_form.save()
vente_form.save()
messages.success(request, "La facture a bien été modifiée") messages.success(request, "La facture a bien été modifiée")
return redirect("/cotisations/") return redirect("/cotisations/")
return form({'factureform': facture_form}, 'cotisations/facture.html', request) return form({'factureform': facture_form, 'venteform': vente_form}, 'cotisations/facture.html', request)
@login_required @login_required
@permission_required('trésorier') @permission_required('trésorier')

View file

@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS, ASSO_NAME, ASSO_ADDRESS_LINE1, ASSO_ADDRESS_LINE2, ASSO_SIRET, ASSO_EMAIL, ASSO_PHONE from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS, ASSO_NAME, ASSO_ADDRESS_LINE1, ASSO_ADDRESS_LINE2, ASSO_SIRET, ASSO_EMAIL, ASSO_PHONE, LOGO_PATH
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))