forked from DGNum/gestioCOF
Plein de nettoyage partout
This commit is contained in:
parent
46f447ec5d
commit
8f9c94fe10
2 changed files with 58 additions and 93 deletions
|
@ -1,6 +1,5 @@
|
||||||
from datetime import date, datetime, time, timedelta
|
from datetime import date, datetime, time, timedelta
|
||||||
|
|
||||||
from dateutil.parser import parse as dateutil_parse
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
@ -144,67 +143,24 @@ class MonthScale(Scale):
|
||||||
return to_kfet_day(dt).replace(day=1)
|
return to_kfet_day(dt).replace(day=1)
|
||||||
|
|
||||||
|
|
||||||
def scale_url_params(scales_def, **other_url_params):
|
SCALE_CLASS_CHOICES = ((cls.name, cls.name) for cls in Scale.__subclasses__())
|
||||||
|
SCALE_DICT = {cls.name: cls for cls in Scale.__subclasses__()}
|
||||||
|
|
||||||
|
|
||||||
|
def scale_url_params(scales_def):
|
||||||
"""
|
"""
|
||||||
Convertit une spécification de scales en arguments GET utilisables par ScaleMixin.
|
Convertit une spécification de scales en arguments GET utilisables par ScaleMixin.
|
||||||
La spécification est de la forme suivante :
|
La spécification est de la forme suivante :
|
||||||
- scales_def : liste de champs de la forme (label, scale)
|
- scales_def : liste de champs de la forme (label, scale, scale_args, default)
|
||||||
|
|
||||||
- scale_args : arguments à passer à Scale.__init__
|
- scale_args : arguments à passer à Scale.__init__
|
||||||
- other_url_params : paramètres GET supplémentaires
|
- default : le graphe à montrer par défaut
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params_list = []
|
params_list = []
|
||||||
for label, cls, params, default in scales_def:
|
for label, cls, params, default in scales_def:
|
||||||
url_params = {"scale_name": cls.name}
|
url_params = {"scale-name": cls.name}
|
||||||
url_params.update({"scale_" + key: value for key, value in params.items()})
|
url_params.update({"scale-" + key: value for key, value in params.items()})
|
||||||
url_params.update(other_url_params)
|
|
||||||
params_list.append(dict(label=label, url_params=url_params, default=default))
|
params_list.append(dict(label=label, url_params=url_params, default=default))
|
||||||
|
|
||||||
return params_list
|
return params_list
|
||||||
|
|
||||||
|
|
||||||
class ScaleMixin(object):
|
|
||||||
def parse_scale_args(self):
|
|
||||||
"""
|
|
||||||
Récupère les paramètres de subdivision encodés dans une requête GET.
|
|
||||||
"""
|
|
||||||
scale_args = {}
|
|
||||||
|
|
||||||
name = self.request.GET.get("scale_name", None)
|
|
||||||
if name is not None:
|
|
||||||
scale_args["name"] = name
|
|
||||||
|
|
||||||
n_steps = self.request.GET.get("scale_n_steps", None)
|
|
||||||
if n_steps is not None:
|
|
||||||
scale_args["n_steps"] = int(n_steps)
|
|
||||||
|
|
||||||
begin = self.request.GET.get("scale_begin", None)
|
|
||||||
if begin is not None:
|
|
||||||
scale_args["begin"] = dateutil_parse(begin)
|
|
||||||
|
|
||||||
end = self.request.GET.get("scale_send", None)
|
|
||||||
if end is not None:
|
|
||||||
scale_args["end"] = dateutil_parse(end)
|
|
||||||
|
|
||||||
last = self.request.GET.get("scale_last", None)
|
|
||||||
if last is not None:
|
|
||||||
scale_args["last"] = last in ["true", "True", "1"] and True or False
|
|
||||||
|
|
||||||
return scale_args
|
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
|
||||||
# On n'hérite pas
|
|
||||||
|
|
||||||
scale_args = self.parse_scale_args()
|
|
||||||
scale_name = scale_args.pop("name", None)
|
|
||||||
scale_cls = Scale.by_name(scale_name)
|
|
||||||
|
|
||||||
if scale_cls is None:
|
|
||||||
self.scale = self.get_default_scale()
|
|
||||||
else:
|
|
||||||
self.scale = scale_cls(**scale_args)
|
|
||||||
|
|
||||||
return {"labels": self.scale.get_labels()}
|
|
||||||
|
|
||||||
def get_default_scale(self):
|
|
||||||
return DayScale(n_steps=7, last=True)
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import ast
|
|
||||||
import heapq
|
import heapq
|
||||||
import statistics
|
import statistics
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
@ -12,6 +11,7 @@ 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
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Count, F, Prefetch, Q, Sum
|
from django.db.models import Count, F, Prefetch, Q, Sum
|
||||||
from django.forms import formset_factory
|
from django.forms import formset_factory
|
||||||
|
@ -36,6 +36,7 @@ from kfet.forms import (
|
||||||
AccountNoTriForm,
|
AccountNoTriForm,
|
||||||
AccountPwdForm,
|
AccountPwdForm,
|
||||||
AccountRestrictForm,
|
AccountRestrictForm,
|
||||||
|
AccountStatForm,
|
||||||
AccountTriForm,
|
AccountTriForm,
|
||||||
AddcostForm,
|
AddcostForm,
|
||||||
ArticleForm,
|
ArticleForm,
|
||||||
|
@ -55,6 +56,7 @@ from kfet.forms import (
|
||||||
KPsulOperationGroupForm,
|
KPsulOperationGroupForm,
|
||||||
OrderArticleForm,
|
OrderArticleForm,
|
||||||
OrderArticleToInventoryForm,
|
OrderArticleToInventoryForm,
|
||||||
|
StatScaleForm,
|
||||||
TransferFormSet,
|
TransferFormSet,
|
||||||
UserForm,
|
UserForm,
|
||||||
UserGroupForm,
|
UserGroupForm,
|
||||||
|
@ -78,7 +80,7 @@ from kfet.models import (
|
||||||
Transfer,
|
Transfer,
|
||||||
TransferGroup,
|
TransferGroup,
|
||||||
)
|
)
|
||||||
from kfet.statistic import DayScale, MonthScale, ScaleMixin, WeekScale, scale_url_params
|
from kfet.statistic import SCALE_DICT, DayScale, MonthScale, WeekScale, scale_url_params
|
||||||
from shared.views import AutocompleteView
|
from shared.views import AutocompleteView
|
||||||
|
|
||||||
from .auth import KFET_GENERIC_TRIGRAMME
|
from .auth import KFET_GENERIC_TRIGRAMME
|
||||||
|
@ -2295,6 +2297,26 @@ class UserAccountMixin:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class ScaleMixin(object):
|
||||||
|
"""Mixin pour utiliser les outils de `kfet.statistic`."""
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
# On n'hérite pas
|
||||||
|
form = StatScaleForm(self.request.GET, prefix="scale")
|
||||||
|
|
||||||
|
if not form.is_valid():
|
||||||
|
raise SuspiciousOperation(
|
||||||
|
"Invalid StatScaleForm. Did someone tamper with the GET parameters ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
scale_name = form.cleaned_data.pop("name")
|
||||||
|
scale_cls = SCALE_DICT.get(scale_name)
|
||||||
|
|
||||||
|
self.scale = scale_cls(**form.cleaned_data)
|
||||||
|
|
||||||
|
return {"labels": self.scale.get_labels()}
|
||||||
|
|
||||||
|
|
||||||
# -----------------------
|
# -----------------------
|
||||||
# Evolution Balance perso
|
# Evolution Balance perso
|
||||||
# -----------------------
|
# -----------------------
|
||||||
|
@ -2407,15 +2429,14 @@ class AccountStatBalance(UserAccountMixin, JSONDetailView):
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
last_days = self.request.GET.get("last_days", None)
|
form = AccountStatForm(self.request.GET)
|
||||||
if last_days is not None:
|
|
||||||
last_days = int(last_days)
|
|
||||||
begin_date = self.request.GET.get("begin_date", None)
|
|
||||||
end_date = self.request.GET.get("end_date", None)
|
|
||||||
|
|
||||||
changes = self.get_changes_list(
|
if not form.is_valid():
|
||||||
last_days=last_days, begin_date=begin_date, end_date=end_date
|
raise SuspiciousOperation(
|
||||||
)
|
"Invalid AccountStatForm. Did someone tamper with the GET parameters ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
changes = self.get_changes_list(**form.cleaned_data)
|
||||||
|
|
||||||
context["charts"] = [
|
context["charts"] = [
|
||||||
{"color": "rgb(200, 20, 60)", "label": "Balance", "values": changes}
|
{"color": "rgb(200, 20, 60)", "label": "Balance", "values": changes}
|
||||||
|
@ -2470,28 +2491,16 @@ class AccountStatOperation(UserAccountMixin, ScaleMixin, JSONDetailView):
|
||||||
slug_url_kwarg = "trigramme"
|
slug_url_kwarg = "trigramme"
|
||||||
slug_field = "trigramme"
|
slug_field = "trigramme"
|
||||||
|
|
||||||
def get_operations(self, types=None):
|
|
||||||
# On selectionne les opérations qui correspondent
|
|
||||||
# à l'article en question et qui ne sont pas annulées
|
|
||||||
# puis on choisi pour chaques intervalle les opérations
|
|
||||||
# effectuées dans ces intervalles de temps
|
|
||||||
all_operations = (
|
|
||||||
Operation.objects.filter(group__on_acc=self.object, canceled_at=None)
|
|
||||||
.values("article_nb", "group__at")
|
|
||||||
.order_by("group__at")
|
|
||||||
)
|
|
||||||
if types is not None:
|
|
||||||
all_operations = all_operations.filter(type__in=types)
|
|
||||||
return all_operations
|
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
|
|
||||||
types = self.request.GET.get("types", None)
|
operations = (
|
||||||
if types is not None:
|
Operation.objects.filter(
|
||||||
types = ast.literal_eval(types)
|
type=Operation.PURCHASE, group__on_acc=self.object, canceled_at=None
|
||||||
|
)
|
||||||
operations = self.get_operations(types=types)
|
.values("article_nb", "group__at")
|
||||||
|
.order_by("group__at")
|
||||||
|
)
|
||||||
# On compte les opérations
|
# On compte les opérations
|
||||||
nb_ventes = self.scale.chunkify_qs(
|
nb_ventes = self.scale.chunkify_qs(
|
||||||
operations, field="group__at", aggregate=Sum("article_nb")
|
operations, field="group__at", aggregate=Sum("article_nb")
|
||||||
|
@ -2508,7 +2517,7 @@ class AccountStatOperation(UserAccountMixin, ScaleMixin, JSONDetailView):
|
||||||
|
|
||||||
|
|
||||||
# ------------------------
|
# ------------------------
|
||||||
# Article Satistiques Last
|
# Article Statistiques Last
|
||||||
# ------------------------
|
# ------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -2563,16 +2572,16 @@ class ArticleStatSales(ScaleMixin, JSONDetailView):
|
||||||
.values("group__at", "article_nb")
|
.values("group__at", "article_nb")
|
||||||
.order_by("group__at")
|
.order_by("group__at")
|
||||||
)
|
)
|
||||||
liq_only = all_purchases.filter(group__on_acc__trigramme="LIQ")
|
cof_accts = all_purchases.filter(group__on_acc__profile__is_cof=True)
|
||||||
liq_exclude = all_purchases.exclude(group__on_acc__trigramme="LIQ")
|
noncof_accts = all_purchases.exclude(group__on_acc__profile__is_cof=True)
|
||||||
|
|
||||||
nb_liq = scale.chunkify_qs(
|
nb_cof = scale.chunkify_qs(
|
||||||
liq_only, field="group__at", aggregate=Sum("article_nb")
|
cof_accts, field="group__at", aggregate=Sum("article_nb")
|
||||||
)
|
)
|
||||||
nb_accounts = scale.chunkify_qs(
|
nb_noncof = scale.chunkify_qs(
|
||||||
liq_exclude, field="group__at", aggregate=Sum("article_nb")
|
noncof_accts, field="group__at", aggregate=Sum("article_nb")
|
||||||
)
|
)
|
||||||
nb_ventes = [n1 + n2 for n1, n2 in zip(nb_liq, nb_accounts)]
|
nb_ventes = [n1 + n2 for n1, n2 in zip(nb_cof, nb_noncof)]
|
||||||
|
|
||||||
context["charts"] = [
|
context["charts"] = [
|
||||||
{
|
{
|
||||||
|
@ -2580,11 +2589,11 @@ class ArticleStatSales(ScaleMixin, JSONDetailView):
|
||||||
"label": "Toutes consommations",
|
"label": "Toutes consommations",
|
||||||
"values": nb_ventes,
|
"values": nb_ventes,
|
||||||
},
|
},
|
||||||
{"color": "rgb(54, 162, 235)", "label": "LIQ", "values": nb_liq},
|
{"color": "rgb(54, 162, 235)", "label": "LIQ", "values": nb_cof},
|
||||||
{
|
{
|
||||||
"color": "rgb(255, 205, 86)",
|
"color": "rgb(255, 205, 86)",
|
||||||
"label": "Comptes K-Fêt",
|
"label": "Comptes K-Fêt",
|
||||||
"values": nb_accounts,
|
"values": nb_noncof,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return context
|
return context
|
||||||
|
|
Loading…
Reference in a new issue