Fix immutable default variable in get_start_of_semester (#656)

Le serveur ne percevait pas le changement de semestre, parce
que la valeur par défaut passée à la fonction `get_start_of_semester()` était une fonction appelée une seule fois, lors du lancement du serveur. Bref, c'était ça : https://beta.ruff.rs/docs/rules/function-call-in-default-argument/

---------

Co-authored-by: imperosol <thgirod@hotmail.com>
This commit is contained in:
Julien Constant
2023-09-07 23:11:58 +02:00
committed by GitHub
parent 544b0248b2
commit 38295e591d
12 changed files with 194 additions and 68 deletions

View File

@ -15,7 +15,7 @@
#
from __future__ import annotations
from typing import Tuple
from typing import Tuple, Optional
from django.db import models
from django.db.models import F, Value, Sum, QuerySet, OuterRef, Exists
@ -536,7 +536,7 @@ class Counter(models.Model):
.order_by("-perm_sum")
)
def get_top_customers(self, since=get_start_of_semester()) -> QuerySet:
def get_top_customers(self, since: Optional[date] = None) -> QuerySet:
"""
Return a QuerySet querying the money spent by customers of this counter
since the specified date, ordered by descending amount of money spent.
@ -546,6 +546,8 @@ class Counter(models.Model):
- the nickname of the customer
- the amount of money spent by the customer
"""
if since is None:
since = get_start_of_semester()
return (
self.sellings.filter(date__gte=since)
.annotate(
@ -557,7 +559,8 @@ class Counter(models.Model):
)
.annotate(nickname=F("customer__user__nick_name"))
.annotate(promo=F("customer__user__promo"))
.values("customer__user", "name", "nickname")
.annotate(user=F("customer__user"))
.values("user", "promo", "name", "nickname")
.annotate(
selling_sum=Sum(
F("unit_price") * F("quantity"), output_field=CurrencyField()
@ -567,15 +570,17 @@ class Counter(models.Model):
.order_by("-selling_sum")
)
def get_total_sales(self, since=get_start_of_semester()) -> CurrencyField:
def get_total_sales(self, since=None) -> CurrencyField:
"""
Compute and return the total turnover of this counter
since the date specified in parameter (by default, since the start of the current
semester)
:param since: timestamp from which to perform the calculation
:type since: datetime | date
:type since: datetime | date | None
:return: Total revenue earned at this counter
"""
if since is None:
since = get_start_of_semester()
if isinstance(since, date):
since = datetime.combine(since, datetime.min.time())
total = self.sellings.filter(date__gte=since).aggregate(

View File

@ -11,7 +11,9 @@
{% block content %}
<h3>{% trans counter_name=counter %}{{ counter_name }} stats{% endtrans %}</h3>
<h4>{% trans counter_name=counter.name %}Top 100 {{ counter_name }}{% endtrans %}</h4>
<h4>
{% trans counter_name=counter.name %}Top 100 {{ counter_name }}{% endtrans %} ({{ current_semester }})
</h4>
<table>
<thead>
<tr>
@ -35,7 +37,9 @@
</tbody>
</table>
<h4>{% trans counter_name=counter.name %}Top 100 barman {{ counter_name }}{% endtrans %}</h4>
<h4>
{% trans counter_name=counter.name %}Top 100 barman {{ counter_name }}{% endtrans %} ({{ current_semester }})
</h4>
<table>
<thead>
<tr>

View File

@ -13,6 +13,7 @@
# OR WITHIN THE LOCAL FILE "LICENSE"
#
#
from datetime import date, timedelta
import json
import re
import string
@ -322,42 +323,49 @@ class CounterStatsTest(TestCase):
Test the result of Counter.get_top_customers() is correct
"""
top = iter(self.counter.get_top_customers())
self.assertEqual(
next(top),
expected_results = [
{
"customer__user": self.sli.id,
"user": self.sli.id,
"name": f"{self.sli.first_name} {self.sli.last_name}",
"promo": self.sli.promo,
"nickname": self.sli.nick_name,
"selling_sum": 2000,
},
)
self.assertEqual(
next(top),
{
"customer__user": self.skia.id,
"user": self.skia.id,
"name": f"{self.skia.first_name} {self.skia.last_name}",
"promo": self.skia.promo,
"nickname": self.skia.nick_name,
"selling_sum": 1000,
},
)
self.assertEqual(
next(top),
{
"customer__user": self.krophil.id,
"user": self.krophil.id,
"name": f"{self.krophil.first_name} {self.krophil.last_name}",
"promo": self.krophil.promo,
"nickname": self.krophil.nick_name,
"selling_sum": 100,
},
)
self.assertEqual(
next(top),
{
"customer__user": self.root.id,
"user": self.root.id,
"name": f"{self.root.first_name} {self.root.last_name}",
"promo": self.root.promo,
"nickname": self.root.nick_name,
"selling_sum": 2,
},
)
]
for result in expected_results:
self.assertEqual(
next(top),
{
"user": result["user"],
"name": result["name"],
"promo": result["promo"],
"nickname": result["nickname"],
"selling_sum": result["selling_sum"],
},
)
self.assertIsNone(next(top, None))

View File

@ -48,7 +48,7 @@ import pytz
from datetime import timedelta, datetime
from http import HTTPStatus
from core.utils import get_start_of_semester
from core.utils import get_start_of_semester, get_semester_code
from core.views import CanViewMixin, TabedViewMixin, CanEditMixin
from core.views.forms import LoginForm
from core.models import User
@ -1354,13 +1354,14 @@ class CounterStatView(DetailView, CounterAdminMixin):
def get_context_data(self, **kwargs):
"""Add stats to the context"""
counter = self.object
counter: Counter = self.object
semester_start = get_start_of_semester()
office_hours = counter.get_top_barmen()
kwargs = super(CounterStatView, self).get_context_data(**kwargs)
kwargs.update(
{
"counter": counter,
"current_semester": get_semester_code(),
"total_sellings": counter.get_total_sales(since=semester_start),
"top_customers": counter.get_top_customers(since=semester_start)[:100],
"top_barman": office_hours[:100],