8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-23 07:23:46 +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)
* python3-django-macaddress (stretch)
* python3-dateutil (jessie-backports)
* texlive-latex-base
* texlive-fonts-recommended
Moteur de db conseillé (mysql), postgresql fonctionne également.
Pour mysql, il faut installer :

View file

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

View file

@ -3,8 +3,7 @@
<tr>
<th>Utilisateur</th>
<th>Designation</th>
<th>Nombre</th>
<th>Prix unitaire</th>
<th>Prix total</th>
<th>Moyen de paiement</th>
<th>Date</th>
<th></th>
@ -15,8 +14,7 @@
<tr>
<td>{{ facture.user }}</td>
<td>{{ facture.name }}</td>
<td>{{ facture.number }}</td>
<td>{{ facture.prix }}</td>
<td>{{ facture.prix_total }}</td>
<td>{{ facture.paiement }}</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>

View file

@ -9,6 +9,10 @@
<form class="form" method="post">
{% csrf_token %}
{% 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" %}
</form>
{% endblock %}

View file

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

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-banque" %}">Liste des banques</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 %}

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 import messages
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 .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, PaiementForm, DelPaiementForm, BanqueForm, DelBanqueForm, NewFactureFormPdf
from users.models import User
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 import settings
from dateutil.relativedelta import relativedelta
from django.utils import timezone
@ -44,15 +47,16 @@ def new_facture(request, userid):
return redirect("/cotisations/")
facture = Facture(user=user)
facture_form = NewFactureForm(request.POST or None, instance=facture)
ArticleFormSet = formset_factory(ArticleForm)
if facture_form.is_valid():
new_facture = facture_form.save(commit=False)
article = facture_form.cleaned_data['article']
new_facture.save()
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()
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)
messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name )
else:
@ -61,7 +65,7 @@ def new_facture(request, userid):
return form({'factureform': facture_form}, 'cotisations/facture.html', request)
@login_required
@permission_required('cableur')
@permission_required('trésorier')
def new_facture_pdf(request):
facture_form = NewFactureFormPdf(request.POST or None)
if facture_form.is_valid():
@ -70,12 +74,13 @@ def new_facture_pdf(request):
quantite = facture_form.cleaned_data['number']
paid = facture_form.cleaned_data['paid']
destinataire = facture_form.cleaned_data['dest']
objet = facture_form.cleaned_data['obj']
detail = facture_form.cleaned_data['detail']
chambre = facture_form.cleaned_data['chambre']
fid = facture_form.cleaned_data['fid']
for a in article:
tbl.append([a, quantite, a.prix * quantite])
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)
@login_required
@ -91,9 +96,10 @@ def facture_pdf(request, factureid):
vente = Vente.objects.all().filter(facture=facture)
ventes = []
for v in vente:
ventes.append([v, facture.number, v.prix * facture.number])
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})
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':os.path.join(settings.BASE_DIR, LOGO_PATH)})
@login_required
@permission_required('cableur')
def edit_facture(request, factureid):
try:
@ -102,11 +108,15 @@ def edit_facture(request, factureid):
messages.error(request, u"Facture inexistante" )
return redirect("/cotisations/")
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()
vente_form.save()
messages.success(request, "La facture a bien été modifiée")
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
@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, ...)
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__)))