Aller au contenu

Schemas

SimpleUserSchema

Bases: ModelSchema

A schema with the minimum amount of information to represent a user.

Counter

Bases: Model

gen_token()

Generate a new token for this counter.

Source code in counter/models.py
def gen_token(self) -> None:
    """Generate a new token for this counter."""
    self.token = "".join(
        random.choice(string.ascii_letters + string.digits) for _ in range(30)
    )
    self.save()

get_barmen_list()

Returns the barman list as list of User.

Also handle the timeout of the barmen

Source code in counter/models.py
def get_barmen_list(self) -> list[User]:
    """Returns the barman list as list of User.

    Also handle the timeout of the barmen
    """
    perms = self.permanencies.filter(end=None)

    # disconnect barmen who are inactive
    timeout = timezone.now() - timedelta(minutes=settings.SITH_BARMAN_TIMEOUT)
    perms.filter(activity__lte=timeout).update(end=F("activity"))

    return [p.user for p in perms.select_related("user")]

get_random_barman()

Return a random user being currently a barman.

Source code in counter/models.py
def get_random_barman(self) -> User:
    """Return a random user being currently a barman."""
    return random.choice(self.barmen_list)

update_activity()

Update the barman activity to prevent timeout.

Source code in counter/models.py
def update_activity(self) -> None:
    """Update the barman activity to prevent timeout."""
    self.permanencies.filter(end=None).update(activity=timezone.now())

is_inactive()

Returns True if the counter self is inactive from SITH_COUNTER_MINUTE_INACTIVE's value minutes, else False.

Source code in counter/models.py
def is_inactive(self) -> bool:
    """Returns True if the counter self is inactive from SITH_COUNTER_MINUTE_INACTIVE's value minutes, else False."""
    return self.is_open and (
        (timezone.now() - self.permanencies.order_by("-activity").first().activity)
        > timedelta(minutes=settings.SITH_COUNTER_MINUTE_INACTIVE)
    )

barman_list()

Returns the barman id list.

Source code in counter/models.py
def barman_list(self) -> list[int]:
    """Returns the barman id list."""
    return [b.id for b in self.barmen_list]

can_refill()

Show if the counter authorize the refilling with physic money.

Source code in counter/models.py
def can_refill(self) -> bool:
    """Show if the counter authorize the refilling with physic money."""
    if self.type != "BAR":
        return False
    if self.id in SITH_COUNTER_OFFICES:
        # If the counter is either 'AE' or 'BdF', refills are authorized
        return True
    # at least one of the barmen is in the AE board
    ae = Club.objects.get(unix_name=SITH_MAIN_CLUB["unix_name"])
    return any(ae.get_membership_for(barman) for barman in self.barmen_list)

get_top_barmen()

Return a QuerySet querying the office hours stats of all the barmen of all time of this counter, ordered by descending number of hours.

Each element of the QuerySet corresponds to a barman and has the following data
  • the full name (first name + last name) of the barman
  • the nickname of the barman
  • the promo of the barman
  • the total number of office hours the barman did attend
Source code in counter/models.py
def get_top_barmen(self) -> QuerySet:
    """Return a QuerySet querying the office hours stats of all the barmen of all time
    of this counter, ordered by descending number of hours.

    Each element of the QuerySet corresponds to a barman and has the following data :
        - the full name (first name + last name) of the barman
        - the nickname of the barman
        - the promo of the barman
        - the total number of office hours the barman did attend
    """
    return (
        self.permanencies.exclude(end=None)
        .annotate(
            name=Concat(F("user__first_name"), Value(" "), F("user__last_name"))
        )
        .annotate(nickname=F("user__nick_name"))
        .annotate(promo=F("user__promo"))
        .values("user", "name", "nickname", "promo")
        .annotate(perm_sum=Sum(F("end") - F("start")))
        .exclude(perm_sum=None)
        .order_by("-perm_sum")
    )

get_top_customers(since=None)

Return a QuerySet querying the money spent by customers of this counter since the specified date, ordered by descending amount of money spent.

Each element of the QuerySet corresponds to a customer and has the following data :

  • the full name (first name + last name) of the customer
  • the nickname of the customer
  • the amount of money spent by the customer

Parameters:

Name Type Description Default
since datetime | date | None

timestamp from which to perform the calculation

None
Source code in counter/models.py
def get_top_customers(self, since: datetime | date | None = 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.

    Each element of the QuerySet corresponds to a customer and has the following data :

    - the full name (first name + last name) of the customer
    - the nickname of the customer
    - the amount of money spent by the customer

    Args:
        since: timestamp from which to perform the calculation
    """
    if since is None:
        since = get_start_of_semester()
    if isinstance(since, date):
        since = datetime(since.year, since.month, since.day, tzinfo=tz.utc)
    return (
        self.sellings.filter(date__gte=since)
        .annotate(
            name=Concat(
                F("customer__user__first_name"),
                Value(" "),
                F("customer__user__last_name"),
            )
        )
        .annotate(nickname=F("customer__user__nick_name"))
        .annotate(promo=F("customer__user__promo"))
        .annotate(user=F("customer__user"))
        .values("user", "promo", "name", "nickname")
        .annotate(
            selling_sum=Sum(
                F("unit_price") * F("quantity"), output_field=CurrencyField()
            )
        )
        .filter(selling_sum__gt=0)
        .order_by("-selling_sum")
    )

get_total_sales(since=None)

Compute and return the total turnover of this counter since the given date.

By default, the date is the start of the current semester.

Parameters:

Name Type Description Default
since datetime | date | None

timestamp from which to perform the calculation

None

Returns:

Type Description
CurrencyField

Total revenue earned at this counter.

Source code in counter/models.py
def get_total_sales(self, since: datetime | date | None = None) -> CurrencyField:
    """Compute and return the total turnover of this counter since the given date.

    By default, the date is the start of the current semester.

    Args:
        since: timestamp from which to perform the calculation

    Returns:
        Total revenue earned at this counter.
    """
    if since is None:
        since = get_start_of_semester()
    if isinstance(since, date):
        since = datetime(since.year, since.month, since.day, tzinfo=tz.utc)
    return self.sellings.filter(date__gte=since).aggregate(
        total=Sum(
            F("quantity") * F("unit_price"),
            default=0,
            output_field=CurrencyField(),
        )
    )["total"]

CounterSchema

Bases: ModelSchema