Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
re2o
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nounous
re2o
Commits
cc0e1cb3
Commit
cc0e1cb3
authored
Jul 09, 2016
by
Dalahro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Création basique de facture
parent
8833f5fe
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
78 additions
and
198 deletions
+78
-198
cotisations/forms.py
cotisations/forms.py
+9
-1
cotisations/templates/cotisations/factures.tex
cotisations/templates/cotisations/factures.tex
+24
-25
cotisations/templates/cotisations/factures_old.tex
cotisations/templates/cotisations/factures_old.tex
+0
-116
cotisations/tex.py
cotisations/tex.py
+21
-54
cotisations/views.py
cotisations/views.py
+16
-2
re2o/settings.py
re2o/settings.py
+8
-0
No files found.
cotisations/forms.py
View file @
cc0e1cb3
from
django
import
forms
from
django.forms
import
ModelForm
from
django.forms
import
ModelForm
,
Form
from
.models
import
Article
,
Paiement
,
Facture
,
Banque
class
NewFactureForm
(
ModelForm
):
...
...
@@ -27,6 +27,14 @@ class NewFactureForm(ModelForm):
raise
forms
.
ValidationError
(
"Le numero de chèque et la banque sont obligatoires"
)
return
cleaned_data
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"
)
class
EditFactureForm
(
NewFactureForm
):
class
Meta
(
NewFactureForm
.
Meta
):
fields
=
'__all__'
...
...
cotisations/templates/cotisations/factures.tex
View file @
cc0e1cb3
{
% load i18n %}
{
% language 'fr' %}
\nonstopmode
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Invoice Template
% LaTeX Template
...
...
@@ -29,19 +28,19 @@
\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
}
\usepackage
{
tabularx
}
\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
\setlength
{
\parindent
}{
0cm
}
...
...
@@ -49,43 +48,43 @@
%\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)
%\begin{textblock
}{4cm}(20mm,5mm)
%\includegraphics[scale=0.3]{% templatetag openbrace %}{{tpl_path}}/logo.png}
\end{textblock*
}
%\end{textblock
}
\end{titlepage}
\hfil
{
\Huge\bf
ReZo Metz
}
\hfil
% Company providing the invoice
\hfil
{
\Huge\bf
{{
asso
_
name
}}
}
\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 :
\hrule
% Horizontal line \\
\vspace
{
0.5cm
}
{{
line1
}}
\hfill
{{
phone
}}
\\
% Your address and contact information
{{
line2
}}
\hfill
{{
email
}}
\\
Siret :
{{
siret
}}
\\
\\
{
\bf
À :
}
\tab
{{
f.user.name
}}
{{
f.user.surname
}}
\\
% Invoice recipient
{
\bf
À :
}
\tab
{{
dest
}}
\\
% Invoice recipient
{
\bf
Date:
}
\tab
{{
DATE
}}
\\
% Invoice date
{
\bf
Facture
\no
:
}
\tab
{{
fid
}}
\\
% Invoice number
{
\bf
Objet:
}
\tab
{{
obj
}}
\\
% Objet
\tab
\tab
{{
detail
}}
\\
% Details
%----------------------------------------------------------------------------------------
% TABLE OF EXPENSES
%----------------------------------------------------------------------------------------
\begin{tabularx}
{
\textwidth
}{
|
l|
X|r|r|r|
}
\begin{tabularx}
{
\textwidth
}{
|X|r|r|r|
}
\hline
\textbf
{
Code
}
&
\textbf
{
Désignation
}
&
\textbf
{
Qté.
}
&
\textbf
{
Prix Unit.
}
\euro
&
\textbf
{
Prix Tot.
}
\euro
\\
\textbf
{
Désignation
}
&
\textbf
{
Prix Unit.
}
&
\textbf
{
Quantité
}
&
\textbf
{
Prix total
}
\\
\hline
{
% for a in f.article %}
\product
[{{a.code}}][{{a.designation}}][{{a.nombre}}][{{a.pu|floatformat:2}}][{{a.ptotal|floatformat:2}}]
{
% for a in article %}
\hline
{{
a.0.name
}}
&
{{
a.0.prix
}}
&
{{
a.1
}}
&
{{
a.2
}}
\\
\hline
{
% endfor %}
\hline
...
...
@@ -93,14 +92,14 @@ Siret :
%\setcounter{paid}{0}
%\setcounter{topay}{\real{\value{total}}-\value{paid}}
\vspace
{
1cm
}
\hfill
\begin{tabular}
{
|l|r|
}
\hline
\textbf
{
Total
}
&
{{
total|floatformat:2
}}
\euro
\\
\textbf
{
Votre règlement
}
&
{
{
paid|floatformat:2
}}
\euro
\\
\textbf
{
Total
}
&
{{
total|floatformat:2
}}
\\
\textbf
{
Votre règlement
}
&
{
% if paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %}
\\
\hline
\textbf
{
À PAYER
}
&
{
{
topay|floatformat:2
}}
\euro
\\
\textbf
{
À PAYER
}
&
{
% if not paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %}
\\
\hline
\hline
...
...
cotisations/templates/cotisations/factures_old.tex
deleted
100644 → 0
View file @
8833f5fe
{
% 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}
cotisations/tex.py
View file @
cc0e1cb3
...
...
@@ -5,8 +5,8 @@ from django.core.cache import cache
from
django.conf
import
settings
from
django.shortcuts
import
redirect
from
tempfile
import
mkdtemp
import
subprocess
import
tempfile
from
subprocess
import
Popen
,
PIPE
import
os
import
shutil
from
hashlib
import
md5
...
...
@@ -17,55 +17,22 @@ 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
def
render_tex
(
request
,
tmp
,
ctx
=
{}):
context
=
Context
(
ctx
)
template
=
get_template
(
'cotisations/factures.tex'
)
rendered_tpl
=
template
.
render
(
context
).
encode
(
'utf-8'
)
with
tempfile
.
TemporaryDirectory
()
as
tempdir
:
for
i
in
range
(
2
):
process
=
Popen
(
[
'pdflatex'
,
'-output-directory'
,
tempdir
],
stdin
=
PIPE
,
stdout
=
PIPE
,
)
process
.
communicate
(
rendered_tpl
)
with
open
(
os
.
path
.
join
(
tempdir
,
'texput.pdf'
),
'rb'
)
as
f
:
pdf
=
f
.
read
()
r
=
HttpResponse
(
content_type
=
'application/pdf'
)
#r['Content-Disposition'] = 'attachement; filename=texput.pdf'
r
.
write
(
pdf
)
return
r
cotisations/views.py
View file @
cc0e1cb3
...
...
@@ -10,9 +10,10 @@ from django.contrib import messages
from
django.db.models
import
Max
,
ProtectedError
from
.models
import
Facture
,
Article
,
Cotisation
,
Paiement
,
Banque
from
.forms
import
NewFactureForm
,
EditFactureForm
,
ArticleForm
,
DelArticleForm
,
PaiementForm
,
DelPaiementForm
,
BanqueForm
,
DelBanqueForm
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
import
ASSO_NAME
,
ASSO_ADDRESS_LINE1
,
ASSO_ADDRESS_LINE2
,
ASSO_SIRET
,
ASSO_EMAIL
,
ASSO_PHONE
from
dateutil.relativedelta
import
relativedelta
from
django.utils
import
timezone
...
...
@@ -75,7 +76,20 @@ def new_facture(request, userid):
@
login_required
def
new_facture_pdf
(
request
):
return
render_tex
(
request
,
'cotisations/factures.tex'
,
{
'DATE'
:
None
})
facture_form
=
NewFactureFormPdf
(
request
.
POST
or
None
)
if
facture_form
.
is_valid
():
tbl
=
[]
article
=
facture_form
.
cleaned_data
[
'article'
]
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'
]
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
})
return
form
({
'factureform'
:
facture_form
},
'cotisations/facture.html'
,
request
)
@
login_required
@
permission_required
(
'cableur'
)
...
...
re2o/settings.py
View file @
cc0e1cb3
...
...
@@ -20,6 +20,14 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# Association information
ASSO_NAME
=
"ReZo Metz"
ASSO_ADDRESS_LINE1
=
"2, rue Edouard Belin"
ASSO_ADDRESS_LINE2
=
"57070 Metz"
ASSO_SIRET
=
""
ASSO_EMAIL
=
"tresorier@ecole.fr"
ASSO_PHONE
=
"01 02 03 04 05"
# Auth definition
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment