mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-25 22:22:26 +00:00
Added choice for multiple articles in new PDF invoice
This commit is contained in:
parent
11ed8b6afe
commit
1447d7b173
5 changed files with 141 additions and 25 deletions
|
@ -145,14 +145,6 @@ class NewFactureFormPdf(Form):
|
||||||
"""
|
"""
|
||||||
Form used to create a custom PDF invoice.
|
Form used to create a custom PDF invoice.
|
||||||
"""
|
"""
|
||||||
article = forms.ModelMultipleChoiceField(
|
|
||||||
queryset=Article.objects.all(),
|
|
||||||
label=_l("Article")
|
|
||||||
)
|
|
||||||
number = forms.IntegerField(
|
|
||||||
label=_l("Quantity"),
|
|
||||||
validators=[MinValueValidator(1)]
|
|
||||||
)
|
|
||||||
paid = forms.BooleanField(label=_l("Paid"), required=False)
|
paid = forms.BooleanField(label=_l("Paid"), required=False)
|
||||||
# TODO : change dest field to recipient
|
# TODO : change dest field to recipient
|
||||||
dest = forms.CharField(required=True, max_length=255, label=_l("Recipient"))
|
dest = forms.CharField(required=True, max_length=255, label=_l("Recipient"))
|
||||||
|
|
|
@ -65,12 +65,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
{% trans "Date" as tr_date %}
|
{% trans "Date" as tr_date %}
|
||||||
{% include 'buttons/sort.html' with prefix='control' col='date' text=tr_date %}<
|
{% include 'buttons/sort.html' with prefix='control' col='date' text=tr_date %}i
|
||||||
/th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
{% trans "Validated" as tr_validated %}
|
{% trans "Validated" as tr_validated %}
|
||||||
{% include 'buttons/sort.html' with prefix='control' col='valid' text=tr_validated %}<
|
{% include 'buttons/sort.html' with prefix='control' col='valid' text=tr_validated %}
|
||||||
/th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
{% trans "Controlled" as tr_controlled %}
|
{% trans "Controlled" as tr_controlled %}
|
||||||
{% include 'buttons/sort.html' with prefix='control' col='control' text=tr_controlled %}
|
{% include 'buttons/sort.html' with prefix='control' col='control' text=tr_controlled %}
|
||||||
|
|
|
@ -34,8 +34,105 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
<form class="form" method="post">
|
<form class="form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
<h3>{% trans "Invoice's articles" %}</h3>
|
||||||
|
<div id="form_set" class="form-group">
|
||||||
|
{{ articlesformset.management_form }}
|
||||||
|
{% for articlesform in articlesformset.forms %}
|
||||||
|
<div class='product_to_sell form-inline'>
|
||||||
|
{% trans "Article" %} :
|
||||||
|
{% bootstrap_form articlesform label_class='sr-only' %}
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm" id="id_form-0-article-remove" type="button">
|
||||||
|
<span class="fa fa-times"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<input class="btn btn-primary btn-sm" role="button" value="{% trans "Add an article"%}" id="add_one">
|
||||||
|
<p>
|
||||||
|
{% blocktrans %}
|
||||||
|
Total price : <span id="total_price">0,00</span> €
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
{% bootstrap_form factureform %}
|
{% bootstrap_form factureform %}
|
||||||
{% bootstrap_button action_name button_type='submit' icon='star' %}
|
{% bootstrap_button action_name button_type='submit' icon='star' %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var prices = {};
|
||||||
|
{% for article in articles %}
|
||||||
|
prices[{{ article.id|escapejs }}] = {{ article.prix }};
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
var template = `Article :
|
||||||
|
{% bootstrap_form articlesformset.empty_form label_class='sr-only' %}
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm"
|
||||||
|
id="id_form-__prefix__-article-remove" type="button">
|
||||||
|
<span class="fa fa-times"></span>
|
||||||
|
</button>`
|
||||||
|
|
||||||
|
function add_article(){
|
||||||
|
// Index start at 0 => new_index = number of items
|
||||||
|
var new_index =
|
||||||
|
document.getElementsByClassName('product_to_sell').length;
|
||||||
|
document.getElementById('id_form-TOTAL_FORMS').value ++;
|
||||||
|
var new_article = document.createElement('div');
|
||||||
|
new_article.className = 'product_to_sell form-inline';
|
||||||
|
new_article.innerHTML = template.replace(/__prefix__/g, new_index);
|
||||||
|
document.getElementById('form_set').appendChild(new_article);
|
||||||
|
add_listenner_for_id(new_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_price(){
|
||||||
|
var price = 0;
|
||||||
|
var product_count =
|
||||||
|
document.getElementsByClassName('product_to_sell').length;
|
||||||
|
var article, article_price, quantity;
|
||||||
|
for (i = 0; i < product_count; ++i){
|
||||||
|
article = document.getElementById(
|
||||||
|
'id_form-' + i.toString() + '-article').value;
|
||||||
|
if (article == '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
article_price = prices[article];
|
||||||
|
quantity = document.getElementById(
|
||||||
|
'id_form-' + i.toString() + '-quantity').value;
|
||||||
|
price += article_price * quantity;
|
||||||
|
}
|
||||||
|
document.getElementById('total_price').innerHTML =
|
||||||
|
price.toFixed(2).toString().replace('.', ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_listenner_for_id(i){
|
||||||
|
document.getElementById('id_form-' + i.toString() + '-article')
|
||||||
|
.addEventListener("change", update_price, true);
|
||||||
|
document.getElementById('id_form-' + i.toString() + '-article')
|
||||||
|
.addEventListener("onkeypress", update_price, true);
|
||||||
|
document.getElementById('id_form-' + i.toString() + '-quantity')
|
||||||
|
.addEventListener("change", update_price, true);
|
||||||
|
document.getElementById('id_form-' + i.toString() + '-article-remove')
|
||||||
|
.addEventListener("click", function(event) {
|
||||||
|
var article = event.target.parentNode;
|
||||||
|
article.parentNode.removeChild(article);
|
||||||
|
document.getElementById('id_form-TOTAL_FORMS').value --;
|
||||||
|
update_price();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add events manager when DOM is fully loaded
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
document.getElementById("add_one")
|
||||||
|
.addEventListener("click", add_article, true);
|
||||||
|
var product_count =
|
||||||
|
document.getElementsByClassName('product_to_sell').length;
|
||||||
|
for (i = 0; i < product_count; ++i){
|
||||||
|
add_listenner_for_id(i);
|
||||||
|
}
|
||||||
|
update_price();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
\doublehline
|
\doublehline
|
||||||
|
|
||||||
{% for a in article %}
|
{% for a in article %}
|
||||||
{{a.0.name}} & {{a.0.prix}} \euro & {{a.1}} & {{a.2}} \euro\\
|
{{a.name}} & {{a.price}} \euro & {{a.quantity}} & {{a.total_price}} \euro\\
|
||||||
\hline
|
\hline
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -198,22 +198,40 @@ def new_facture_pdf(request):
|
||||||
get invoices that are not taken into account, for the administrative
|
get invoices that are not taken into account, for the administrative
|
||||||
point of view.
|
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
|
||||||
invoice_form = NewFactureFormPdf(request.POST or None)
|
invoice_form = NewFactureFormPdf(request.POST or None)
|
||||||
if invoice_form.is_valid():
|
if request.user.is_class_club:
|
||||||
tbl = []
|
articles_formset = formset_factory(SelectClubArticleForm)(request.POST or None)
|
||||||
article = invoice_form.cleaned_data['article']
|
else:
|
||||||
quantity = invoice_form.cleaned_data['number']
|
articles_formset = formset_factory(SelectUserArticleForm)(request.POST or None)
|
||||||
|
if invoice_form.is_valid() and articles_formset.is_valid():
|
||||||
|
# Get the article list and build an list out of it
|
||||||
|
# contiaining (article_name, article_price, quantity, total_price)
|
||||||
|
articles_info = []
|
||||||
|
for articles_form in articles_formset:
|
||||||
|
if articles_form.cleaned_data:
|
||||||
|
article = articles_form.cleaned_data['article']
|
||||||
|
quantity = articles_form.cleaned_data['quantity']
|
||||||
|
articles_info.append({
|
||||||
|
'name': article.name,
|
||||||
|
'price': article.prix,
|
||||||
|
'quantity': quantity,
|
||||||
|
'total_price': article.prix * quantity
|
||||||
|
})
|
||||||
paid = invoice_form.cleaned_data['paid']
|
paid = invoice_form.cleaned_data['paid']
|
||||||
recipient = invoice_form.cleaned_data['dest']
|
recipient = invoice_form.cleaned_data['dest']
|
||||||
address = invoice_form.cleaned_data['chambre']
|
address = invoice_form.cleaned_data['chambre']
|
||||||
for art in article:
|
total_price = sum(a['total_price'] for a in articles_info)
|
||||||
tbl.append([art, quantity, art.prix * quantity])
|
|
||||||
total_price = sum(a[2] for a in tbl)
|
|
||||||
return render_invoice(request, {
|
return render_invoice(request, {
|
||||||
'DATE': timezone.now(),
|
'DATE': timezone.now(),
|
||||||
'recipient_name': recipient,
|
'recipient_name': recipient,
|
||||||
'address': address,
|
'address': address,
|
||||||
'article': tbl,
|
'article': articles_info,
|
||||||
'total': total_price,
|
'total': total_price,
|
||||||
'paid': paid,
|
'paid': paid,
|
||||||
'asso_name': AssoOption.get_cached_value('name'),
|
'asso_name': AssoOption.get_cached_value('name'),
|
||||||
|
@ -226,7 +244,9 @@ def new_facture_pdf(request):
|
||||||
})
|
})
|
||||||
return form({
|
return form({
|
||||||
'factureform': invoice_form,
|
'factureform': invoice_form,
|
||||||
'action_name': _("Edit")
|
'action_name': _("Create"),
|
||||||
|
'articlesformset': articles_formset,
|
||||||
|
'articles': articles
|
||||||
}, 'cotisations/facture.html', request)
|
}, 'cotisations/facture.html', request)
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,9 +262,16 @@ def facture_pdf(request, facture, factureid):
|
||||||
"""
|
"""
|
||||||
# TODO : change vente to purchase
|
# TODO : change vente to purchase
|
||||||
purchases_objects = Vente.objects.all().filter(facture=facture)
|
purchases_objects = Vente.objects.all().filter(facture=facture)
|
||||||
purchases = []
|
# 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:
|
for purchase in purchases_objects:
|
||||||
purchases.append([purchase, purchase.number, purchase.prix_total])
|
purchases_info.append({
|
||||||
|
'name': purchase.name,
|
||||||
|
'price': purchase.prix,
|
||||||
|
'quantity': purchase.number,
|
||||||
|
'total_price': purchase.prix_total
|
||||||
|
})
|
||||||
return render_invoice(request, {
|
return render_invoice(request, {
|
||||||
'paid': True,
|
'paid': True,
|
||||||
'fid': facture.id,
|
'fid': facture.id,
|
||||||
|
@ -254,7 +281,7 @@ def facture_pdf(request, facture, factureid):
|
||||||
facture.user.surname
|
facture.user.surname
|
||||||
),
|
),
|
||||||
'address': facture.user.room,
|
'address': facture.user.room,
|
||||||
'article': purchases,
|
'article': purchases_info,
|
||||||
'total': facture.prix_total(),
|
'total': facture.prix_total(),
|
||||||
'asso_name': AssoOption.get_cached_value('name'),
|
'asso_name': AssoOption.get_cached_value('name'),
|
||||||
'line1': AssoOption.get_cached_value('adresse1'),
|
'line1': AssoOption.get_cached_value('adresse1'),
|
||||||
|
|
Loading…
Reference in a new issue