diff --git a/cotisations/templates/cotisations/aff_cotisations.html b/cotisations/templates/cotisations/aff_cotisations.html index c1a88139..c33063f7 100644 --- a/cotisations/templates/cotisations/aff_cotisations.html +++ b/cotisations/templates/cotisations/aff_cotisations.html @@ -18,7 +18,7 @@ {{ facture.prix }} {{ facture.paiement }} {{ facture.date }} - Editer + {% if is_cableur %} Editer{% endif %} {% endfor %} diff --git a/cotisations/templates/cotisations/factures.tex b/cotisations/templates/cotisations/factures.tex index d4fe7aee..690f9af9 100644 --- a/cotisations/templates/cotisations/factures.tex +++ b/cotisations/templates/cotisations/factures.tex @@ -1,12 +1,12 @@ {% load i18n %} {% language 'fr' %} + \nonstopmode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Invoice Template % LaTeX Template % Version 1.0 (3/11/12) -% -% This template has been downloaded from: +%% This template has been downloaded from: % http://www.LaTeXTemplates.com % % Original author: @@ -16,30 +16,25 @@ % 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 +% 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 +% DOCUMENT CONFIGURATION %---------------------------------------------------------------------------------------- \documentclass[12pt]{article} % Use the custom invoice class (invoice.cls) \usepackage[utf8]{inputenc} \usepackage[frenchb]{babel} -\usepackage{eurosym} \usepackage{tabularx} \usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry} -\usepackage[parfill]{parskip} % Do not indent paragraphs -\usepackage{fp} % Fixed-point arithmetic \usepackage{calc} % Counters for totaling hours and cost \usepackage{longtable} \usepackage{graphicx} -\usepackage[absolute]{textpos} \usepackage{calc} -\usepackage{xparse} \pagestyle{empty} % No page numbers \linespread{1.5} % Line spacing @@ -84,7 +79,6 @@ Siret : % TABLE OF EXPENSES %---------------------------------------------------------------------------------------- - \begin{tabularx}{\textwidth}{|l|X|r|r|r|} \hline \textbf{Code} & \textbf{Désignation} & \textbf{Qté.} & \textbf{Prix Unit.} \euro & \textbf{Prix Tot.} \euro\\ @@ -120,5 +114,3 @@ Siret : %---------------------------------------------------------------------------------------- \end{document} - - diff --git a/cotisations/templates/cotisations/factures_old.tex b/cotisations/templates/cotisations/factures_old.tex new file mode 100644 index 00000000..690f9af9 --- /dev/null +++ b/cotisations/templates/cotisations/factures_old.tex @@ -0,0 +1,116 @@ +{% load i18n %} +{% language 'fr' %} + +\nonstopmode +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% 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[frenchb]{babel} +\usepackage{tabularx} +\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry} +\usepackage{calc} % Counters for totaling hours and cost +\usepackage{longtable} +\usepackage{graphicx} +\usepackage{calc} + +\pagestyle{empty} % No page numbers +\linespread{1.5} % Line spacing + +\setlength{\doublerulesep}{\arrayrulewidth} % Double rules look like one thick one +\def \tab {\hspace*{3ex}} % Define \tab to create some horizontal white space + + + + +\begin{document} +%\newcommand{\product}[5][0][0][0][0][0]{ +%\setlength{ptotal}{#3*\real{#4}} +%\addtolength{total}{#3*\real{#4}} +\DeclareDocumentCommand{\product}{ O{0} O{0} O{0} O{0} O{0} }{ +#1 & #2 & #3 & #4 & #5 \\ +\hline +} + +%---------------------------------------------------------------------------------------- +% HEADING SECTION +%---------------------------------------------------------------------------------------- +\begin{titlepage} +\begin{textblock*}{4cm}(20mm,5mm) +%\includegraphics[scale=0.3]{% templatetag openbrace %}{{tpl_path}}/logo.png} +\end{textblock*} +\end{titlepage} +\hfil{\Huge\bf ReZo Metz}\hfil % Company providing the invoice +\bigskip\break % Whitespace +\hrule % Horizontal line +2 rue Edouard Belin \\ % Your address and contact information +57070 Metz \hfill augustin.lemesle@supelec.fr \\ +Siret : +\\ \\ +{\bf À :} \tab {{f.user.name}} {{f.user.surname}} \\ % Invoice recipient + +{\bf Date:} \tab {{DATE}} \\ % Invoice date + +{\bf Facture \no:} \tab {{fid}} \\ % Invoice number + +%---------------------------------------------------------------------------------------- +% TABLE OF EXPENSES +%---------------------------------------------------------------------------------------- + +\begin{tabularx}{\textwidth}{|l|X|r|r|r|} +\hline + \textbf{Code} & \textbf{Désignation} & \textbf{Qté.} & \textbf{Prix Unit.} \euro & \textbf{Prix Tot.} \euro\\ +\hline + +{% for a in f.article %} +\product[{{a.code}}][{{a.designation}}][{{a.nombre}}][{{a.pu|floatformat:2}}][{{a.ptotal|floatformat:2}}] +{% endfor %} + + \hline +\end{tabularx} + +%\setcounter{paid}{0} +%\setcounter{topay}{\real{\value{total}}-\value{paid}} + +\hfill +\begin{tabular}{|l|r|} +\hline +\textbf{Total} & {{total|floatformat:2}}\euro \\ +\textbf{Votre règlement} & {{paid|floatformat:2}}\euro \\ +\hline +\textbf{À PAYER} & {{topay|floatformat:2}}\euro \\ +\hline +\hline + +\end{tabular} + +\vspace{1.5cm} % Whitespace +\hrule % Horizontal line +\footnotesize{TVA non applicable, art. 293 B du CGI} + +{% endlanguage %} +%---------------------------------------------------------------------------------------- + +\end{document} diff --git a/cotisations/tex.py b/cotisations/tex.py new file mode 100644 index 00000000..a06b73ce --- /dev/null +++ b/cotisations/tex.py @@ -0,0 +1,71 @@ +from django.template.loader import get_template +from django.template import TemplateDoesNotExist, Context +from django.http import HttpResponse, Http404, HttpResponseNotModified +from django.core.cache import cache +from django.conf import settings +from django.shortcuts import redirect + +from tempfile import mkdtemp +import subprocess +import os +import shutil +from hashlib import md5 + + +TEMP_PREFIX = getattr(settings, 'TEX_TEMP_PREFIX', 'render_tex-') +CACHE_PREFIX = getattr(settings, 'TEX_CACHE_PREFIX', 'render-tex') +CACHE_TIMEOUT = getattr(settings, 'TEX_CACHE_TIMEOUT', 86400) # 1 day + + +def render_tex(request, template, ctx={}): + doc = template.rsplit('/', 1)[-1].rsplit('.', 1)[0] + + # Utile ? Parfois il faut le chemin absolu pour retrouver les images + #ctx.setdefault('tpl_path', os.path.join(settings.BASE_DIR, 'factures/templates/factures')) + + try: + body = get_template(template).render(Context(ctx)).encode('utf-8') + except TemplateDoesNotExist: + raise Http404() + + etag = md5(body).hexdigest() + if request.META.get('HTTP_IF_NONE_MATCH', '') == etag: + return HttpResponseNotModified() + + cache_key = "%s:%s:%s" % (CACHE_PREFIX, template, etag) + pdf = cache.get(cache_key) + if pdf is None: + if b'\\nonstopmode' not in body: + raise ValueError("\\nonstopmode not present in document, cowardly refusing to process.") + + tmp = mkdtemp(prefix=TEMP_PREFIX) + try: + with open("%s/%s.tex" % (tmp, doc), "w") as f: + f.write(str(body)) + del body + + error = subprocess.Popen( + ["pdflatex", "%s.tex" % doc], + cwd=tmp, + stdin=open(os.devnull, "r"), + stderr=open(os.devnull, "wb"), + stdout=open(os.devnull, "wb") + ).wait() + + if error: + log = open("%s/%s.log" % (tmp, doc)).read() + return HttpResponse(log, content_type="text/plain") + + pdf = open("%s/%s.pdf" % (tmp, doc)).read() + finally: + shutil.rmtree(tmp) + pass + + if pdf: + cache.set(cache_key, pdf, CACHE_TIMEOUT) + + res = HttpResponse(pdf, content_type="application/pdf") + res['ETag'] = etag + return res + + diff --git a/cotisations/views.py b/cotisations/views.py index 738a0c30..5371d8bc 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -49,6 +49,7 @@ def create_cotis(facture, user, duration): return @login_required +@permission_required('cableur') def new_facture(request, userid): try: user = User.objects.get(pk=userid) @@ -77,6 +78,7 @@ def new_facture_pdf(request): return render_tex(request, 'cotisations/factures.tex', {'DATE':None}) @login_required +@permission_required('cableur') def edit_facture(request, factureid): try: facture = Facture.objects.get(pk=factureid) @@ -167,6 +169,7 @@ def del_paiement(request): return form({'factureform': paiement}, 'cotisations/facture.html', request) @login_required +@permission_required('cableur') def add_banque(request): banque = BanqueForm(request.POST or None) if banque.is_valid(): @@ -206,24 +209,29 @@ def del_banque(request): return form({'factureform': banque}, 'cotisations/facture.html', request) @login_required +@permission_required('cableur') def index_article(request): is_trez = request.user.has_perms(('trésorier',)) article_list = Article.objects.order_by('name') return render(request, 'cotisations/index_article.html', {'article_list':article_list, 'is_trez':is_trez}) @login_required +@permission_required('cableur') def index_paiement(request): is_trez = request.user.has_perms(('trésorier',)) paiement_list = Paiement.objects.order_by('moyen') return render(request, 'cotisations/index_paiement.html', {'paiement_list':paiement_list, 'is_trez':is_trez}) @login_required +@permission_required('cableur') def index_banque(request): is_trez = request.user.has_perms(('trésorier',)) banque_list = Banque.objects.order_by('name') return render(request, 'cotisations/index_banque.html', {'banque_list':banque_list, 'is_trez':is_trez}) @login_required +@permission_required('cableur') def index(request): + is_cableur = request.user.has_perms(('cableur',)) facture_list = Facture.objects.order_by('date').reverse() - return render(request, 'cotisations/index.html', {'facture_list': facture_list}) + return render(request, 'cotisations/index.html', {'facture_list': facture_list, 'is_cableur': is_cableur}) diff --git a/machines/views.py b/machines/views.py index 5a849c7b..57d8ba5d 100644 --- a/machines/views.py +++ b/machines/views.py @@ -191,17 +191,20 @@ def del_extension(request): return form({'machineform': extension, 'interfaceform': None}, 'machines/machine.html', request) @login_required +@permission_required('cableur') def index(request): interfaces_list = Interface.objects.order_by('pk') return render(request, 'machines/index.html', {'interfaces_list': interfaces_list}) @login_required +@permission_required('cableur') def index_machinetype(request): is_infra = request.user.has_perms(('infra',)) machinetype_list = MachineType.objects.order_by('type') return render(request, 'machines/index_machinetype.html', {'machinetype_list':machinetype_list, 'is_infra':is_infra}) @login_required +@permission_required('cableur') def index_extension(request): is_infra = request.user.has_perms(('infra',)) extension_list = Extension.objects.order_by('name') diff --git a/templates/base.html b/templates/base.html index 75c56b1c..ccb25f27 100644 --- a/templates/base.html +++ b/templates/base.html @@ -15,84 +15,86 @@ - + -
-
-
- {% block sidebar %} -

Link

-

Link

-

Link

- {% endblock %} -
-
- {# Display django.contrib.messages as Bootstrap alerts #} - {% bootstrap_messages %} - -
- - {% block content %}{% endblock %} -
-
-
-

ADS

+
+
+
+ {% block sidebar %} +

Link

+

Link

+

Link

+ {% endblock %}
-
-

ADS

+
+ {# Display django.contrib.messages as Bootstrap alerts #} + {% bootstrap_messages %} + +
+ + {% block content %}{% endblock %} +
+
+
+

ADS

+
+
+

ADS

+
-