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
37dbfd2f
Commit
37dbfd2f
authored
Dec 31, 2018
by
Hugo LEVY-FALK
Committed by
chirac
Jan 01, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Cost Estimates
parent
b85384b2
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
511 additions
and
9 deletions
+511
-9
cotisations/admin.py
cotisations/admin.py
+7
-1
cotisations/forms.py
cotisations/forms.py
+13
-1
cotisations/migrations/0037_costestimate.py
cotisations/migrations/0037_costestimate.py
+28
-0
cotisations/migrations/0038_auto_20181231_1657.py
cotisations/migrations/0038_auto_20181231_1657.py
+31
-0
cotisations/models.py
cotisations/models.py
+53
-1
cotisations/templates/cotisations/aff_cost_estimate.html
cotisations/templates/cotisations/aff_cost_estimate.html
+101
-0
cotisations/templates/cotisations/edit_facture.html
cotisations/templates/cotisations/edit_facture.html
+4
-0
cotisations/templates/cotisations/factures.tex
cotisations/templates/cotisations/factures.tex
+10
-0
cotisations/templates/cotisations/index_cost_estimate.html
cotisations/templates/cotisations/index_cost_estimate.html
+36
-0
cotisations/templates/cotisations/sidebar.html
cotisations/templates/cotisations/sidebar.html
+5
-0
cotisations/tex.py
cotisations/tex.py
+2
-1
cotisations/urls.py
cotisations/urls.py
+30
-0
cotisations/views.py
cotisations/views.py
+191
-5
No files found.
cotisations/admin.py
View file @
37dbfd2f
...
...
@@ -30,7 +30,7 @@ from django.contrib import admin
from
reversion.admin
import
VersionAdmin
from
.models
import
Facture
,
Article
,
Banque
,
Paiement
,
Cotisation
,
Vente
from
.models
import
CustomInvoice
from
.models
import
CustomInvoice
,
CostEstimate
class
FactureAdmin
(
VersionAdmin
):
...
...
@@ -38,6 +38,11 @@ class FactureAdmin(VersionAdmin):
pass
class
CostEstimateAdmin
(
VersionAdmin
):
"""Admin class for cost estimates."""
pass
class
CustomInvoiceAdmin
(
VersionAdmin
):
"""Admin class for custom invoices."""
pass
...
...
@@ -76,3 +81,4 @@ admin.site.register(Paiement, PaiementAdmin)
admin
.
site
.
register
(
Vente
,
VenteAdmin
)
admin
.
site
.
register
(
Cotisation
,
CotisationAdmin
)
admin
.
site
.
register
(
CustomInvoice
,
CustomInvoiceAdmin
)
admin
.
site
.
register
(
CostEstimate
,
CostEstimateAdmin
)
cotisations/forms.py
View file @
37dbfd2f
...
...
@@ -46,7 +46,10 @@ from django.shortcuts import get_object_or_404
from
re2o.field_permissions
import
FieldPermissionFormMixin
from
re2o.mixins
import
FormRevMixin
from
.models
import
Article
,
Paiement
,
Facture
,
Banque
,
CustomInvoice
,
Vente
from
.models
import
(
Article
,
Paiement
,
Facture
,
Banque
,
CustomInvoice
,
Vente
,
CostEstimate
)
from
.payment_methods
import
balance
...
...
@@ -153,6 +156,15 @@ class CustomInvoiceForm(FormRevMixin, ModelForm):
fields
=
'__all__'
class
CostEstimateForm
(
FormRevMixin
,
ModelForm
):
"""
Form used to create a cost estimate.
"""
class
Meta
:
model
=
CostEstimate
exclude
=
[
'paid'
,
'final_invoice'
]
class
ArticleForm
(
FormRevMixin
,
ModelForm
):
"""
Form used to create an article.
...
...
cotisations/migrations/0037_costestimate.py
0 → 100644
View file @
37dbfd2f
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-12-29 21:03
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'cotisations'
,
'0036_custominvoice_remark'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'CostEstimate'
,
fields
=
[
(
'custominvoice_ptr'
,
models
.
OneToOneField
(
auto_created
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
parent_link
=
True
,
primary_key
=
True
,
serialize
=
False
,
to
=
'cotisations.CustomInvoice'
)),
(
'validity'
,
models
.
DurationField
(
verbose_name
=
'Period of validity'
)),
(
'final_invoice'
,
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
related_name
=
'origin_cost_estimate'
,
to
=
'cotisations.CustomInvoice'
)),
],
options
=
{
'permissions'
:
((
'view_costestimate'
,
'Can view a cost estimate object'
),),
},
bases
=
(
'cotisations.custominvoice'
,),
),
]
cotisations/migrations/0038_auto_20181231_1657.py
0 → 100644
View file @
37dbfd2f
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-12-31 22:57
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'cotisations'
,
'0037_costestimate'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'costestimate'
,
name
=
'final_invoice'
,
field
=
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
related_name
=
'origin_cost_estimate'
,
to
=
'cotisations.CustomInvoice'
),
),
migrations
.
AlterField
(
model_name
=
'costestimate'
,
name
=
'validity'
,
field
=
models
.
DurationField
(
help_text
=
'DD HH:MM:SS'
,
verbose_name
=
'Period of validity'
),
),
migrations
.
AlterField
(
model_name
=
'custominvoice'
,
name
=
'paid'
,
field
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'Paid'
),
),
]
cotisations/models.py
View file @
37dbfd2f
...
...
@@ -284,7 +284,8 @@ class CustomInvoice(BaseInvoice):
verbose_name
=
_
(
"Address"
)
)
paid
=
models
.
BooleanField
(
verbose_name
=
_
(
"Paid"
)
verbose_name
=
_
(
"Paid"
),
default
=
False
)
remark
=
models
.
TextField
(
verbose_name
=
_
(
"Remark"
),
...
...
@@ -293,6 +294,57 @@ class CustomInvoice(BaseInvoice):
)
class
CostEstimate
(
CustomInvoice
):
class
Meta
:
permissions
=
(
(
'view_costestimate'
,
_
(
"Can view a cost estimate object"
)),
)
validity
=
models
.
DurationField
(
verbose_name
=
_
(
"Period of validity"
),
help_text
=
"DD HH:MM:SS"
)
final_invoice
=
models
.
ForeignKey
(
CustomInvoice
,
on_delete
=
models
.
SET_NULL
,
null
=
True
,
blank
=
True
,
related_name
=
"origin_cost_estimate"
,
primary_key
=
False
)
def
create_invoice
(
self
):
"""Create a CustomInvoice from the CostEstimate."""
if
self
.
final_invoice
is
not
None
:
return
self
.
final_invoice
invoice
=
CustomInvoice
()
invoice
.
recipient
=
self
.
recipient
invoice
.
payment
=
self
.
payment
invoice
.
address
=
self
.
address
invoice
.
paid
=
False
invoice
.
remark
=
self
.
remark
invoice
.
date
=
timezone
.
now
()
invoice
.
save
()
self
.
final_invoice
=
invoice
self
.
save
()
for
sale
in
self
.
vente_set
.
all
():
Vente
.
objects
.
create
(
facture
=
invoice
,
name
=
sale
.
name
,
prix
=
sale
.
prix
,
number
=
sale
.
number
,
)
return
invoice
def
can_delete
(
self
,
user_request
,
*
args
,
**
kwargs
):
if
not
user_request
.
has_perm
(
'cotisations.delete_costestimate'
):
return
False
,
_
(
"You don't have the right "
"to delete a cost estimate."
)
if
self
.
final_invoice
is
not
None
:
return
False
,
_
(
"The cost estimate has an "
"invoice and cannot be deleted."
)
return
True
,
None
# TODO : change Vente to Purchase
class
Vente
(
RevMixin
,
AclMixin
,
models
.
Model
):
"""
...
...
cotisations/templates/cotisations/aff_cost_estimate.html
0 → 100644
View file @
37dbfd2f
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2018 Hugo Levy-Falk
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load i18n %}
{% load acl %}
{% load logs_extra %}
{% load design %}
<div
class=
"table-responsive"
>
{% if cost_estimate_list.paginator %}
{% include 'pagination.html' with list=cost_estimate_list%}
{% endif %}
<table
class=
"table table-striped"
>
<thead>
<tr>
<th>
{% trans "Recipient" as tr_recip %}
{% include 'buttons/sort.html' with prefix='invoice' col='user' text=tr_user %}
</th>
<th>
{% trans "Designation" %}
</th>
<th>
{% trans "Total price" %}
</th>
<th>
{% trans "Payment method" as tr_payment_method %}
{% include 'buttons/sort.html' with prefix='invoice' col='payement' text=tr_payment_method %}
</th>
<th>
{% trans "Date" as tr_date %}
{% include 'buttons/sort.html' with prefix='invoice' col='date' text=tr_date %}
</th>
<th>
{% trans "Validity" as tr_validity %}
{% include 'buttons/sort.html' with prefix='invoice' col='validity' text=tr_validity %}
</th>
<th>
{% trans "Cost estimate ID" as tr_estimate_id %}
{% include 'buttons/sort.html' with prefix='invoice' col='id' text=tr_estimate_id %}
</th>
<th>
{% trans "Invoice created" as tr_invoice_created%}
{% include 'buttons/sort.html' with prefix='invoice' col='paid' text=tr_invoice_created %}
</th>
<th></th>
<th></th>
</tr>
</thead>
{% for estimate in cost_estimate_list %}
<tr>
<td>
{{ estimate.recipient }}
</td>
<td>
{{ estimate.name }}
</td>
<td>
{{ estimate.prix_total }}
</td>
<td>
{{ estimate.payment }}
</td>
<td>
{{ estimate.date }}
</td>
<td>
{{ estimate.validity }}
</td>
<td>
{{ estimate.id }}
</td>
<td>
{% if estimate.final_invoice %}
<a
href=
"{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"
><i
style=
"color: #1ECA18;"
class=
"fa fa-check"
></i></a>
{% else %}
<i
style=
"color: #D10115;"
class=
"fa fa-times"
></i>
'
{% endif %}
</td>
<td>
{% can_edit estimate %}
{% include 'buttons/edit.html' with href='cotisations:edit-cost-estimate' id=estimate.id %}
{% acl_end %}
{% history_button estimate %}
{% include 'buttons/suppr.html' with href='cotisations:del-cost-estimate' id=estimate.id %}
<a
class=
"btn btn-primary btn-sm"
role=
"button"
href=
"{% url 'cotisations:cost-estimate-to-invoice' estimate.id %}"
>
<i
class=
"fa fa-file"
></i>
</a>
<a
class=
"btn btn-primary btn-sm"
role=
"button"
href=
"{% url 'cotisations:cost-estimate-pdf' estimate.id %}"
>
<i
class=
"fa fa-file-pdf-o"
></i>
{% trans "PDF" %}
</a>
</td>
</tr>
{% endfor %}
</table>
{% if custom_invoice_list.paginator %}
{% include 'pagination.html' with list=custom_invoice_list %}
{% endif %}
</div>
cotisations/templates/cotisations/edit_facture.html
View file @
37dbfd2f
...
...
@@ -35,7 +35,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<form
class=
"form"
method=
"post"
>
{% csrf_token %}
{% if title %}
<h3>
{{title}}
</h3>
{% else %}
<h3>
{% trans "Edit the invoice" %}
</h3>
{% endif %}
{% massive_bootstrap_form factureform 'user' %}
{{ venteform.management_form }}
<h3>
{% trans "Articles" %}
</h3>
...
...
cotisations/templates/cotisations/factures.tex
View file @
37dbfd2f
...
...
@@ -75,8 +75,12 @@
{
\bf
Pour :
}
{{
recipient
_
name|safe
}}
&
{
\bf
Date :
}
{{
DATE
}}
\\
{
\bf
Adresse :
}
{
% if address is None %}Aucune adresse renseignée{% else %}{{address}}{% endif %} & \\
{
% if fid is not None %}
{
% if is_estimate %}
{
\bf
Devis n
\textsuperscript
{
o
}
:
}
{{
fid
}}
&
\\
{
% else %}
{
\bf
Facture n
\textsuperscript
{
o
}
:
}
{{
fid
}}
&
\\
{
% endif %}
{
% endif %}
\end{tabular*}
\\
...
...
@@ -104,9 +108,11 @@
\begin{tabular}
{
|l|r|
}
\hline
\textbf
{
Total
}
&
{{
total|floatformat:2
}}
\euro
\\
{
% if not is_estimate %}
\textbf
{
Votre règlement
}
&
{
% if paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %} \euro \\
\doublehline
\textbf
{
À PAYER
}
&
{
% if not paid %}{{total|floatformat:2}}{% else %} 00,00 {% endif %} \euro\\
{
% endif %}
\hline
\end{tabular}
...
...
@@ -119,6 +125,10 @@
\textbf
{
Remarque
}
&
{{
remark|safe
}}
\\
\hline
{
% endif %}
{
% if end_validity %}
\textbf
{
Validité
}
&
Jusqu'au
{{
end
_
validity
}}
\\
\hline
{
% endif %}
\end{tabularx}
...
...
cotisations/templates/cotisations/index_cost_estimate.html
0 → 100644
View file @
37dbfd2f
{% extends "cotisations/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
{% load i18n %}
{% block title %}{% trans "Cost estimates" %}{% endblock %}
{% block content %}
<h2>
{% trans "Cost estimates list" %}
</h2>
{% can_create CostEstimate %}
{% include "buttons/add.html" with href='cotisations:new-cost-estimate'%}
{% acl_end %}
{% include 'cotisations/aff_cost_estimate.html' %}
{% endblock %}
cotisations/templates/cotisations/sidebar.html
View file @
37dbfd2f
...
...
@@ -45,6 +45,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<i
class=
"fa fa-list-ul"
></i>
{% trans "Custom invoices" %}
</a>
{% acl_end %}
{% can_view_all CostEstimate %}
<a
class=
"list-group-item list-group-item-info"
href=
"{% url "
cotisations:index-cost-estimate
"
%}"
>
<i
class=
"fa fa-list-ul"
></i>
{% trans "Cost estimate" %}
</a>
{% acl_end %}
{% can_view_all Article %}
<a
class=
"list-group-item list-group-item-info"
href=
"{% url "
cotisations:index-article
"
%}"
>
<i
class=
"fa fa-list-ul"
></i>
{% trans "Available articles" %}
...
...
cotisations/tex.py
View file @
37dbfd2f
...
...
@@ -49,8 +49,9 @@ def render_invoice(_request, ctx={}):
Render an invoice using some available information such as the current
date, the user, the articles, the prices, ...
"""
is_estimate
=
ctx
.
get
(
'is_estimate'
,
False
)
filename
=
'_'
.
join
([
'invoice'
,
'
cost_estimate'
if
is_estimate
else
'
invoice'
,
slugify
(
ctx
.
get
(
'asso_name'
,
""
)),
slugify
(
ctx
.
get
(
'recipient_name'
,
""
)),
str
(
ctx
.
get
(
'DATE'
,
datetime
.
now
()).
year
),
...
...
cotisations/urls.py
View file @
37dbfd2f
...
...
@@ -51,11 +51,41 @@ urlpatterns = [
views
.
facture_pdf
,
name
=
'facture-pdf'
),
url
(
r
'^new_cost_estimate/$'
,
views
.
new_cost_estimate
,
name
=
'new-cost-estimate'
),
url
(
r
'^index_cost_estimate/$'
,
views
.
index_cost_estimate
,
name
=
'index-cost-estimate'
),
url
(
r
'^cost_estimate_pdf/(?P<costestimateid>[0-9]+)$'
,
views
.
cost_estimate_pdf
,
name
=
'cost-estimate-pdf'
,
),
url
(
r
'^index_custom_invoice/$'
,
views
.
index_custom_invoice
,
name
=
'index-custom-invoice'
),
url
(
r
'^edit_cost_estimate/(?P<costestimateid>[0-9]+)$'
,
views
.
edit_cost_estimate
,
name
=
'edit-cost-estimate'
),
url
(
r
'^cost_estimate_to_invoice/(?P<costestimateid>[0-9]+)$'
,
views
.
cost_estimate_to_invoice
,
name
=
'cost-estimate-to-invoice'
),
url
(
r
'^del_cost_estimate/(?P<costestimateid>[0-9]+)$'
,
views
.
del_cost_estimate
,
name
=
'del-cost-estimate'
),
url
(
r
'^new_custom_invoice/$'
,
views
.
new_custom_invoice
,
...
...
cotisations/views.py
View file @
37dbfd2f
...
...
@@ -68,7 +68,8 @@ from .models import (
Paiement
,
Banque
,
CustomInvoice
,
BaseInvoice
BaseInvoice
,
CostEstimate
)
from
.forms
import
(
FactureForm
,
...
...
@@ -81,7 +82,8 @@ from .forms import (
SelectArticleForm
,
RechargeForm
,
CustomInvoiceForm
,
DiscountForm
DiscountForm
,
CostEstimateForm
,
)
from
.tex
import
render_invoice
,
escape_chars
from
.payment_methods.forms
import
payment_method_factory
...
...
@@ -179,7 +181,58 @@ def new_facture(request, user, userid):
)
# TODO : change facture to invoice
@
login_required
@
can_create
(
CostEstimate
)
def
new_cost_estimate
(
request
):
"""
View used to generate a custom invoice. It's mainly used to
get invoices that are not taken into account, for the administrative
point of view.
"""
# The template needs the list of articles (for the JS part)
articles
=
Article
.
objects
.
filter
(
Q
(
type_user
=
'All'
)
|
Q
(
type_user
=
request
.
user
.
class_name
)
)
# Building the invocie form and the article formset
cost_estimate_form
=
CostEstimateForm
(
request
.
POST
or
None
)
articles_formset
=
formset_factory
(
SelectArticleForm
)(
request
.
POST
or
None
,
form_kwargs
=
{
'user'
:
request
.
user
}
)
discount_form
=
DiscountForm
(
request
.
POST
or
None
)
if
cost_estimate_form
.
is_valid
()
and
articles_formset
.
is_valid
()
and
discount_form
.
is_valid
():
cost_estimate_instance
=
cost_estimate_form
.
save
()
for
art_item
in
articles_formset
:
if
art_item
.
cleaned_data
:
article
=
art_item
.
cleaned_data
[
'article'
]
quantity
=
art_item
.
cleaned_data
[
'quantity'
]
Vente
.
objects
.
create
(
facture
=
cost_estimate_instance
,
name
=
article
.
name
,
prix
=
article
.
prix
,
type_cotisation
=
article
.
type_cotisation
,
duration
=
article
.
duration
,
number
=
quantity
)
discount_form
.
apply_to_invoice
(
cost_estimate_instance
)
messages
.
success
(
request
,
_
(
"The cost estimate was created."
)
)
return
redirect
(
reverse
(
'cotisations:index-cost-estimate'
))
return
form
({
'factureform'
:
cost_estimate_form
,
'action_name'
:
_
(
"Confirm"
),
'articlesformset'
:
articles_formset
,
'articlelist'
:
articles
,
'discount_form'
:
discount_form
,
'title'
:
_
(
"Cost estimate"
),
},
'cotisations/facture.html'
,
request
)
@
login_required
@
can_create
(
CustomInvoice
)
def
new_custom_invoice
(
request
):
...
...
@@ -336,6 +389,55 @@ def del_facture(request, facture, **_kwargs):
},
'cotisations/delete.html'
,
request
)
@
login_required
@
can_edit
(
CostEstimate
)
def
edit_cost_estimate
(
request
,
invoice
,
**
kwargs
):
# Building the invocie form and the article formset
invoice_form
=
CostEstimateForm
(
request
.
POST
or
None
,
instance
=
invoice
)
purchases_objects
=
Vente
.
objects
.
filter
(
facture
=
invoice
)
purchase_form_set
=
modelformset_factory
(
Vente
,
fields
=
(
'name'
,
'number'
),
extra
=
0
,
max_num
=
len
(
purchases_objects
)
)
purchase_form
=
purchase_form_set
(
request
.
POST
or
None
,
queryset
=
purchases_objects
)
if
invoice_form
.
is_valid
()
and
purchase_form
.
is_valid
():
if
invoice_form
.
changed_data
:
invoice_form
.
save
()
purchase_form
.
save
()
messages
.
success
(
request
,
_
(
"The cost estimate was edited."
)
)
return
redirect
(
reverse
(
'cotisations:index-cost-estimate'
))
return
form
({
'factureform'
:
invoice_form
,
'venteform'
:
purchase_form
,
'title'
:
"Edit the cost estimate"
},
'cotisations/edit_facture.html'
,
request
)
@
login_required
@
can_edit
(
CostEstimate
)
@
can_create
(
CustomInvoice
)
def
cost_estimate_to_invoice
(
request
,
cost_estimate
,
**
_kwargs
):
"""Create a custom invoice from a cos estimate"""
cost_estimate
.
create_invoice
()
messages
.
success
(
request
,
_
(
"An invoice was successfully created from your cost estimate."
)
)
return
redirect
(
reverse
(
'cotisations:index-custom-invoice'
))
@
login_required
@
can_edit
(
CustomInvoice
)
def
edit_custom_invoice
(
request
,
invoice
,
**
kwargs
):
...
...
@@ -371,6 +473,68 @@ def edit_custom_invoice(request, invoice, **kwargs):
},
'cotisations/edit_facture.html'
,
request
)
@
login_required
@
can_view
(
CostEstimate
)
def
cost_estimate_pdf
(
request
,
invoice
,
**
_kwargs
):
"""
View used to generate a PDF file from an existing cost estimate in database
Creates a line for each Purchase (thus article sold) and generate the
invoice with the total price, the payment method, the address and the
legal information for the user.
"""
# TODO : change vente to purchase
purchases_objects
=
Vente
.
objects
.
all
().
filter
(
facture
=
invoice
)
# Get the article list and build an list out of it
# contiaining (article_name, article_price, quantity, total_price)
purchases_info
=
[]
for
purchase
in
purchases_objects
:
purchases_info
.
append
({
'name'
:
escape_chars
(
purchase
.
name
),
'price'
:
purchase
.
prix
,
'quantity'
:
purchase
.
number
,
'total_price'
:
purchase
.
prix_total
})
return
render_invoice
(
request
,
{
'paid'
:
invoice
.
paid
,
'fid'
:
invoice
.
id
,
'DATE'
:
invoice
.
date
,
'recipient_name'
:
invoice
.
recipient
,
'address'
:
invoice
.
address
,
'article'
:
purchases_info
,
'total'
:
invoice
.
prix_total
(),
'asso_name'
:
AssoOption
.
get_cached_value
(
'name'
),
'line1'
:
AssoOption
.
get_cached_value
(
'adresse1'
),
'line2'
:
AssoOption
.
get_cached_value
(
'adresse2'
),
'siret'
:
AssoOption
.
get_cached_value
(
'siret'
),
'email'
:
AssoOption
.
get_cached_value
(
'contact'
),
'phone'
:
AssoOption
.
get_cached_value
(
'telephone'
),
'tpl_path'
:
os
.
path
.
join
(
settings
.
BASE_DIR
,
LOGO_PATH
),
'payment_method'
:
invoice
.
payment
,
'remark'
:
invoice
.
remark
,
'end_validity'
:
invoice
.
date
+
invoice
.
validity
,
'is_estimate'
:
True
,
})
@
login_required
@
can_delete
(
CostEstimate
)
def
del_cost_estimate
(
request
,
estimate
,
**
_kwargs
):
"""
View used to delete an existing invocie.
"""
if
request
.
method
==
"POST"
:
estimate
.
delete
()
messages
.
success
(
request
,
_
(
"The cost estimate was deleted."
)
)
return
redirect
(
reverse
(
'cotisations:index-cost-estimate'
))
return
form
({
'objet'
:
estimate
,
'objet_name'
:
_
(
"Cost Estimate"
)
},
'cotisations/delete.html'
,
request
)
@
login_required
@
can_view
(
CustomInvoice
)