Compare commits

...

6 commits

4 changed files with 86 additions and 1 deletions

View file

@ -25,6 +25,21 @@
</a> </a>
</div> </div>
<aside>
<div class="heading">
<span>Export des ventes</span>
</div>
<div class="buttons">
<a class="btn btn-primary" href="{% url 'kfet.purchases' 6 %}">
6 derniers mois
</a>
<a class="btn btn-primary" href="{% url 'kfet.purchases' %}">
12 derniers mois
</a>
</div>
</aside>
{% endblock %} {% endblock %}
{% block main %} {% block main %}

View file

@ -88,6 +88,7 @@
<li><a href="{% url 'kfet.article' %}">Articles</a></li> <li><a href="{% url 'kfet.article' %}">Articles</a></li>
<li><a href="{% url 'kfet.inventory' %}">Inventaires</a></li> <li><a href="{% url 'kfet.inventory' %}">Inventaires</a></li>
<li><a href="{% url 'kfet.order' %}">Commandes</a></li> <li><a href="{% url 'kfet.order' %}">Commandes</a></li>
<li><a href="{% url 'kfet.purchases' %}">Export des ventes</a></li>
{% if user.username != 'kfet_genericteam' %} {% if user.username != 'kfet_genericteam' %}
<li class="divider"></li> <li class="divider"></li>
<li> <li>

View file

@ -236,6 +236,13 @@ urlpatterns = [
"k-psul/get_settings", views.kpsul_get_settings, name="kfet.kpsul.get_settings" "k-psul/get_settings", views.kpsul_get_settings, name="kfet.kpsul.get_settings"
), ),
# ----- # -----
# Sales history urls
# -----
path("purchases", views.SalesStatList.as_view(), name="kfet.purchases"),
path(
"purchases/<int:n_months>", views.SalesStatList.as_view(), name="kfet.purchases"
),
# -----
# JSON urls # JSON urls
# ----- # -----
path("history.json", views.history_json, name="kfet.history.json"), path("history.json", views.history_json, name="kfet.history.json"),

View file

@ -1,3 +1,4 @@
import csv
import heapq import heapq
import statistics import statistics
from collections import defaultdict from collections import defaultdict
@ -12,12 +13,13 @@ from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.models import Permission, User from django.contrib.auth.models import Permission, User
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import SuspiciousOperation, ValidationError from django.core.exceptions import SuspiciousOperation
from django.db import transaction from django.db import transaction
from django.db.models import Count, F, Max, OuterRef, Prefetch, Q, Subquery, Sum from django.db.models import Count, F, Max, OuterRef, Prefetch, Q, Subquery, Sum
from django.forms import ValidationError, formset_factory from django.forms import ValidationError, formset_factory
from django.http import ( from django.http import (
Http404, Http404,
HttpResponse,
HttpResponseBadRequest, HttpResponseBadRequest,
HttpResponseForbidden, HttpResponseForbidden,
JsonResponse, JsonResponse,
@ -29,6 +31,7 @@ from django.utils.decorators import method_decorator
from django.views.generic import DetailView, FormView, ListView, TemplateView from django.views.generic import DetailView, FormView, ListView, TemplateView
from django.views.generic.detail import BaseDetailView from django.views.generic.detail import BaseDetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.list import BaseListView
from gestioncof.models import CofProfile from gestioncof.models import CofProfile
from kfet import KFET_DELETED_TRIGRAMME, consumers from kfet import KFET_DELETED_TRIGRAMME, consumers
@ -2451,6 +2454,65 @@ class ScaleMixin(object):
return {"labels": self.scale.get_labels()} return {"labels": self.scale.get_labels()}
# ------------------------
# Export des ventes en CSV
# ------------------------
@method_decorator(teamkfet_required, name="dispatch")
class SalesStatList(BaseListView):
model = Operation
def get_queryset(self):
return (
super()
.get_queryset()
.filter(type=Operation.PURCHASE, canceled_at=None, article__isnull=False)
.values_list("article__name")
.annotate(Sum("article_nb"))
)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
scale = MonthScale(n_steps=self.kwargs.get("n_months", 12), last=True)
articles = list(Article.objects.order_by("name"))
indexes = {a.name: index for index, a in enumerate(articles)}
ventes = scale.chunkify_qs(self.get_queryset(), field="group__at")
ctx["header"] = ["Mois"] + [a.name for a in articles]
ctx["ventes"] = []
ctx["total"] = [0] * len(articles)
labels = scale.get_labels()
for v in ventes:
m_ventes = [0] * len(articles)
for (a_name, nb_ventes) in v:
index = indexes[a_name]
m_ventes[index] = nb_ventes
ctx["total"][index] += nb_ventes
ctx["ventes"].append([labels.pop(0)] + m_ventes)
return ctx
def render_to_response(self, context):
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="historique_ventes.csv"'
writer = csv.writer(response)
writer.writerow(context["header"])
# On écrit chaque mois
for line in context["ventes"]:
writer.writerow(line)
writer.writerow([])
writer.writerow(["Total"] + context["total"])
return response
# ----------------------- # -----------------------
# Evolution Balance perso # Evolution Balance perso
# ----------------------- # -----------------------