mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-22 15:51:19 +00:00
Merge branch 'clubs' into 'master'
Improve Sellings view for clubs See merge request ae/Sith!262
This commit is contained in:
commit
40832bb3bf
@ -157,7 +157,7 @@ class MailingForm(forms.Form):
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class SellingsFormBase(forms.Form):
|
||||
class SellingsForm(forms.Form):
|
||||
begin_date = forms.DateTimeField(
|
||||
input_formats=["%Y-%m-%d %H:%M:%S"],
|
||||
label=_("Begin date"),
|
||||
@ -170,10 +170,24 @@ class SellingsFormBase(forms.Form):
|
||||
required=False,
|
||||
widget=SelectDateTime,
|
||||
)
|
||||
counter = forms.ModelChoiceField(
|
||||
counters = forms.ModelMultipleChoiceField(
|
||||
Counter.objects.order_by("name").all(), label=_("Counter"), required=False
|
||||
)
|
||||
|
||||
def __init__(self, club, *args, **kwargs):
|
||||
|
||||
super(SellingsForm, self).__init__(*args, **kwargs)
|
||||
self.fields["products"] = forms.ModelMultipleChoiceField(
|
||||
club.products.order_by("name").filter(archived=False).all(),
|
||||
label=_("Products"),
|
||||
required=False,
|
||||
)
|
||||
self.fields["archived_products"] = forms.ModelMultipleChoiceField(
|
||||
club.products.order_by("name").filter(archived=True).all(),
|
||||
label=_("Archived products"),
|
||||
required=False,
|
||||
)
|
||||
|
||||
|
||||
class ClubMemberForm(forms.Form):
|
||||
"""
|
||||
|
@ -1,9 +1,9 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from 'core/macros.jinja' import user_profile_link %}
|
||||
{% from 'core/macros.jinja' import user_profile_link, paginate %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans %}Sellings{% endtrans %}</h3>
|
||||
<form action="" method="get">
|
||||
<form id="form" action="?page=1" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<p><input type="submit" value="{% trans %}Show{% endtrans %}" /></p>
|
||||
@ -28,7 +28,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for s in result %}
|
||||
{% for s in paginated_result %}
|
||||
<tr>
|
||||
<td>{{ s.date|localtime|date(DATETIME_FORMAT) }} {{ s.date|localtime|time(DATETIME_FORMAT) }}</td>
|
||||
<td>{{ s.counter }}</td>
|
||||
@ -53,6 +53,14 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
function formPagination(link){
|
||||
$("form").attr("action", link.href);
|
||||
link.href = "javascript:void(0)"; // block link action
|
||||
$("form").submit();
|
||||
}
|
||||
</script>
|
||||
{{ paginate(paginated_result, paginator, "formPagination(this)") }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
164
club/views.py
164
club/views.py
@ -23,6 +23,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
import csv
|
||||
|
||||
from django.conf import settings
|
||||
from django import forms
|
||||
@ -30,13 +31,21 @@ from django.views.generic import ListView, DetailView, TemplateView, View
|
||||
from django.views.generic.edit import DeleteView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic.edit import UpdateView, CreateView
|
||||
from django.http import HttpResponseRedirect, HttpResponse, Http404
|
||||
from django.http import (
|
||||
HttpResponseRedirect,
|
||||
HttpResponse,
|
||||
Http404,
|
||||
StreamingHttpResponse,
|
||||
)
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext as _t
|
||||
from django.core.exceptions import PermissionDenied, ValidationError, NON_FIELD_ERRORS
|
||||
from django.core.paginator import Paginator, InvalidPage
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.db.models import Sum
|
||||
|
||||
|
||||
from core.views import (
|
||||
CanCreateMixin,
|
||||
@ -60,7 +69,7 @@ from com.views import (
|
||||
)
|
||||
|
||||
from club.models import Club, Membership, Mailing, MailingSubscription
|
||||
from club.forms import MailingForm, ClubEditForm, ClubMemberForm, SellingsFormBase
|
||||
from club.forms import MailingForm, ClubEditForm, ClubMemberForm, SellingsForm
|
||||
|
||||
|
||||
class ClubTabsMixin(TabedViewMixin):
|
||||
@ -319,7 +328,7 @@ class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):
|
||||
current_tab = "elderlies"
|
||||
|
||||
|
||||
class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailView):
|
||||
class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
|
||||
"""
|
||||
Sellings of a club
|
||||
"""
|
||||
@ -328,21 +337,35 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailView):
|
||||
pk_url_kwarg = "club_id"
|
||||
template_name = "club/club_sellings.jinja"
|
||||
current_tab = "sellings"
|
||||
form_class = SellingsForm
|
||||
paginate_by = 70
|
||||
|
||||
def get_form_class(self):
|
||||
kwargs = {
|
||||
"product": forms.ModelChoiceField(
|
||||
self.object.products.order_by("name").all(),
|
||||
label=_("Product"),
|
||||
required=False,
|
||||
)
|
||||
}
|
||||
return type("SellingsForm", (SellingsFormBase,), kwargs)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
self.asked_page = int(request.GET.get("page", 1))
|
||||
except ValueError:
|
||||
raise Http404
|
||||
return super(ClubSellingView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(ClubSellingView, self).get_form_kwargs()
|
||||
kwargs["club"] = self.object
|
||||
return kwargs
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs = super(ClubSellingView, self).get_context_data(**kwargs)
|
||||
form = self.get_form_class()(self.request.GET)
|
||||
qs = Selling.objects.filter(club=self.object)
|
||||
|
||||
kwargs["result"] = qs[:0]
|
||||
kwargs["paginated_result"] = kwargs["result"]
|
||||
kwargs["total"] = 0
|
||||
kwargs["total_quantity"] = 0
|
||||
kwargs["benefit"] = 0
|
||||
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
if not len([v for v in form.cleaned_data.values() if v is not None]):
|
||||
qs = Selling.objects.filter(id=-1)
|
||||
@ -350,19 +373,36 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailView):
|
||||
qs = qs.filter(date__gte=form.cleaned_data["begin_date"])
|
||||
if form.cleaned_data["end_date"]:
|
||||
qs = qs.filter(date__lte=form.cleaned_data["end_date"])
|
||||
if form.cleaned_data["counter"]:
|
||||
qs = qs.filter(counter=form.cleaned_data["counter"])
|
||||
if form.cleaned_data["product"]:
|
||||
qs = qs.filter(product__id=form.cleaned_data["product"].id)
|
||||
|
||||
if form.cleaned_data["counters"]:
|
||||
qs = qs.filter(counter__in=form.cleaned_data["counters"])
|
||||
|
||||
selected_products = []
|
||||
if form.cleaned_data["products"]:
|
||||
selected_products.extend(form.cleaned_data["products"])
|
||||
if form.cleaned_data["archived_products"]:
|
||||
selected_products.extend(form.cleaned_data["archived_products"])
|
||||
|
||||
if len(selected_products) > 0:
|
||||
qs = qs.filter(product__in=selected_products)
|
||||
|
||||
kwargs["result"] = qs.all().order_by("-id")
|
||||
kwargs["total"] = sum([s.quantity * s.unit_price for s in qs.all()])
|
||||
kwargs["total_quantity"] = sum([s.quantity for s in qs.all()])
|
||||
kwargs["benefit"] = kwargs["total"] - sum(
|
||||
[s.product.purchase_price for s in qs.exclude(product=None)]
|
||||
kwargs["total"] = sum([s.quantity * s.unit_price for s in kwargs["result"]])
|
||||
total_quantity = qs.all().aggregate(Sum("quantity"))
|
||||
if total_quantity["quantity__sum"]:
|
||||
kwargs["total_quantity"] = total_quantity["quantity__sum"]
|
||||
benefit = (
|
||||
qs.exclude(product=None).all().aggregate(Sum("product__purchase_price"))
|
||||
)
|
||||
else:
|
||||
kwargs["result"] = qs[:0]
|
||||
kwargs["form"] = form
|
||||
if benefit["product__purchase_price__sum"]:
|
||||
kwargs["benefit"] = benefit["product__purchase_price__sum"]
|
||||
|
||||
kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by)
|
||||
try:
|
||||
kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page)
|
||||
except InvalidPage:
|
||||
raise Http404
|
||||
|
||||
return kwargs
|
||||
|
||||
|
||||
@ -371,16 +411,46 @@ class ClubSellingCSVView(ClubSellingView):
|
||||
Generate sellings in csv for a given period
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
import csv
|
||||
class StreamWriter:
|
||||
"""Implements a file-like interface for streaming the CSV"""
|
||||
|
||||
def write(self, value):
|
||||
"""Write the value by returning it, instead of storing in a buffer."""
|
||||
return value
|
||||
|
||||
def write_selling(self, selling):
|
||||
row = [selling.date, selling.counter]
|
||||
if selling.seller:
|
||||
row.append(selling.seller.get_display_name())
|
||||
else:
|
||||
row.append("")
|
||||
if selling.customer:
|
||||
row.append(selling.customer.user.get_display_name())
|
||||
else:
|
||||
row.append("")
|
||||
row = row + [
|
||||
selling.label,
|
||||
selling.quantity,
|
||||
selling.quantity * selling.unit_price,
|
||||
selling.get_payment_method_display(),
|
||||
]
|
||||
if selling.product:
|
||||
row.append(selling.product.selling_price)
|
||||
row.append(selling.product.purchase_price)
|
||||
row.append(selling.product.selling_price - selling.product.purchase_price)
|
||||
else:
|
||||
row = row + ["", "", ""]
|
||||
return row
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
response = HttpResponse(content_type="text/csv")
|
||||
self.object = self.get_object()
|
||||
name = _("Sellings") + "_" + self.object.name + ".csv"
|
||||
response["Content-Disposition"] = "filename=" + name
|
||||
kwargs = self.get_context_data(**kwargs)
|
||||
|
||||
# Use the StreamWriter class instead of request for streaming
|
||||
pseudo_buffer = self.StreamWriter()
|
||||
writer = csv.writer(
|
||||
response, delimiter=";", lineterminator="\n", quoting=csv.QUOTE_ALL
|
||||
pseudo_buffer, delimiter=";", lineterminator="\n", quoting=csv.QUOTE_ALL
|
||||
)
|
||||
|
||||
writer.writerow([_t("Quantity"), kwargs["total_quantity"]])
|
||||
@ -401,29 +471,17 @@ class ClubSellingCSVView(ClubSellingView):
|
||||
_t("Benefit"),
|
||||
]
|
||||
)
|
||||
for o in kwargs["result"]:
|
||||
row = [o.date, o.counter]
|
||||
if o.seller:
|
||||
row.append(o.seller.get_display_name())
|
||||
else:
|
||||
row.append("")
|
||||
if o.customer:
|
||||
row.append(o.customer.user.get_display_name())
|
||||
else:
|
||||
row.append("")
|
||||
row = row + [
|
||||
o.label,
|
||||
o.quantity,
|
||||
o.quantity * o.unit_price,
|
||||
o.get_payment_method_display(),
|
||||
]
|
||||
if o.product:
|
||||
row.append(o.product.selling_price)
|
||||
row.append(o.product.purchase_price)
|
||||
row.append(o.product.selling_price - o.product.purchase_price)
|
||||
else:
|
||||
row = row + ["", "", ""]
|
||||
writer.writerow(row)
|
||||
|
||||
# Stream response
|
||||
response = StreamingHttpResponse(
|
||||
(
|
||||
writer.writerow(self.write_selling(selling))
|
||||
for selling in kwargs["result"]
|
||||
),
|
||||
content_type="text/csv",
|
||||
)
|
||||
name = _("Sellings") + "_" + self.object.name + ".csv"
|
||||
response["Content-Disposition"] = "filename=" + name
|
||||
|
||||
return response
|
||||
|
||||
|
@ -113,10 +113,11 @@
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro paginate(page_obj, paginator) %}
|
||||
{% macro paginate(page_obj, paginator, js_action) %}
|
||||
{% set js = js_action|default('') %}
|
||||
{% if page_obj.has_previous() or page_obj.has_next() %}
|
||||
{% if page_obj.has_previous() %}
|
||||
<a href="?page={{ page_obj.previous_page_number() }}">{% trans %}Previous{% endtrans %}</a>
|
||||
<a {% if js %} type="submit" onclick="{{ js }}" {% endif %} href="?page={{ page_obj.previous_page_number() }}">{% trans %}Previous{% endtrans %}</a>
|
||||
{% else %}
|
||||
<span class="disabled">{% trans %}Previous{% endtrans %}</span>
|
||||
{% endif %}
|
||||
@ -124,11 +125,11 @@
|
||||
{% if page_obj.number == i %}
|
||||
<span class="active">{{ i }} <span class="sr-only">({% trans %}current{% endtrans %})</span></span>
|
||||
{% else %}
|
||||
<a href="?page={{ i }}">{{ i }}</a>
|
||||
<a {% if js %} type="submit" onclick="{{ js }}" {% endif %} href="?page={{ i }}">{{ i }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page_obj.has_next() %}
|
||||
<a href="?page={{ page_obj.next_page_number() }}">{% trans %}Next{% endtrans %}</a>
|
||||
<a {% if js %} type="submit" onclick="{{ js }}" {% endif %} href="?page={{ page_obj.next_page_number() }}">{% trans %}Next{% endtrans %}</a>
|
||||
{% else %}
|
||||
<span class="disabled">{% trans %}Next{% endtrans %}</span>
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user