mirror of https://gitlab.federez.net/re2o/re2o
12 changed files with 302 additions and 88 deletions
@ -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} |
||||
@ -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 |
||||
|
|
||||
|
|
||||
Loading…
Reference in new issue