Skip to content

Commit

Permalink
Merge pull request #720 from ae-utbm/counter-refactor
Browse files Browse the repository at this point in the history
Refactor on counters
  • Loading branch information
imperosol authored Jul 21, 2024
2 parents d953183 + 82d3791 commit 002d8f8
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 139 deletions.
2 changes: 1 addition & 1 deletion core/templates/core/base.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
{% endif %}
{% if bar.is_inactive() %}
<i class="fa fa-question" style="color: #f39c12"></i>
{% elif bar.is_open(): %}
{% elif bar.is_open %}
<i class="fa fa-check" style="color: #2ecc71"></i>
{% else %}
<i class="fa fa-times" style="color: #eb2f06"></i>
Expand Down
87 changes: 34 additions & 53 deletions counter/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,110 +383,88 @@ class Meta:
def __str__(self):
return self.name

def get_absolute_url(self):
def get_absolute_url(self) -> str:
if self.type == "EBOUTIC":
return reverse("eboutic:main")
return reverse("counter:details", kwargs={"counter_id": self.id})

def __getattribute__(self, name):
def __getattribute__(self, name: str):
if name == "edit_groups":
return Group.objects.filter(
name=self.club.unix_name + settings.SITH_BOARD_SUFFIX
).all()
return object.__getattribute__(self, name)

def is_owned_by(self, user):
def is_owned_by(self, user: User) -> bool:
if user.is_anonymous:
return False
mem = self.club.get_membership_for(user)
if mem and mem.role >= 7:
return True
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)

def can_be_viewed_by(self, user):
def can_be_viewed_by(self, user: User) -> bool:
if self.type == "BAR":
return True
return user.is_board_member or user in self.sellers.all()

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

def add_barman(self, user):
"""Logs a barman in to the given counter.
A user is stored as a tuple with its login time.
"""
Permanency(user=user, counter=self, start=timezone.now(), end=None).save()

def del_barman(self, user):
"""Logs a barman out and store its permanency."""
perm = Permanency.objects.filter(counter=self, user=user, end=None).all()
for p in perm:
p.end = p.activity
p.save()

@cached_property
def barmen_list(self):
def barmen_list(self) -> list[User]:
return self.get_barmen_list()

def get_barmen_list(self):
def get_barmen_list(self) -> list[User]:
"""Returns the barman list as list of User.
Also handle the timeout of the barmen
"""
pl = Permanency.objects.filter(counter=self, end=None).all()
bl = []
for p in pl:
if timezone.now() - p.activity < timedelta(
minutes=settings.SITH_BARMAN_TIMEOUT
):
bl.append(p.user)
else:
p.end = p.activity
p.save()
return bl
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"))

def get_random_barman(self):
return [p.user for p in perms.select_related("user")]

def get_random_barman(self) -> User:
"""Return a random user being currently a barman."""
bl = self.get_barmen_list()
return bl[random.randrange(0, len(bl))]
return random.choice(self.barmen_list)

def update_activity(self):
def update_activity(self) -> None:
"""Update the barman activity to prevent timeout."""
for p in Permanency.objects.filter(counter=self, end=None).all():
p.save() # Update activity
self.permanencies.filter(end=None).update(activity=timezone.now())

def is_open(self):
@property
def is_open(self) -> bool:
return len(self.barmen_list) > 0

def is_inactive(self):
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 (
return self.is_open and (
(timezone.now() - self.permanencies.order_by("-activity").first().activity)
> timedelta(minutes=settings.SITH_COUNTER_MINUTE_INACTIVE)
)

def barman_list(self):
def barman_list(self) -> list[int]:
"""Returns the barman id list."""
return [b.id for b in self.get_barmen_list()]
return [b.id for b in self.barmen_list]

def can_refill(self):
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
is_ae_member = False
# at least one of the barmen is in the AE board
ae = Club.objects.get(unix_name=SITH_MAIN_CLUB["unix_name"])
for barman in self.get_barmen_list():
if ae.get_membership_for(barman):
is_ae_member = True
return is_ae_member
return any(ae.get_membership_for(barman) for barman in self.barmen_list)

def get_top_barmen(self) -> QuerySet:
"""Return a QuerySet querying the office hours stats of all the barmen of all time
Expand Down Expand Up @@ -565,10 +543,13 @@ def get_total_sales(self, since: datetime | date | None = None) -> CurrencyField
since = get_start_of_semester()
if isinstance(since, date):
since = datetime(since.year, since.month, since.day, tzinfo=tz.utc)
total = self.sellings.filter(date__gte=since).aggregate(
total=Sum(F("quantity") * F("unit_price"), output_field=CurrencyField())
return self.sellings.filter(date__gte=since).aggregate(
total=Sum(
F("quantity") * F("unit_price"),
default=0,
output_field=CurrencyField(),
)
)["total"]
return total if total is not None else CurrencyField(0)


class Refilling(models.Model):
Expand Down
2 changes: 1 addition & 1 deletion counter/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def get_user():
session_token = session.get("counter_token", None)
if session_token:
counter = Counter.objects.filter(token=session_token).first()
if counter and len(counter.get_barmen_list()) > 0:
if counter and len(counter.barmen_list) > 0:
return counter.get_random_barman()

# Get the current logged user if not from a counter
Expand Down
5 changes: 2 additions & 3 deletions counter/templates/counter/activity.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
{% if counter.type == 'BAR' %}
<h4>{% trans %}Barmen list{% endtrans %}</h4>
<ul>
{% set barmans_list = counter.get_barmen_list() %}
{% if barmans_list | length > 0 %}
{% for b in barmans_list %}
{% if counter.barmen_list | length > 0 %}
{% for b in counter.barmen_list %}
<li>{{ user_profile_link(b) }}</li>
{% endfor %}
{% else %}
Expand Down
11 changes: 6 additions & 5 deletions counter/templates/counter/counter_click.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@
<input type="submit" value="{% trans %}Go{% endtrans %}"/>
</form>
<h6>{% trans %}Registered cards{% endtrans %}</h6>
{% if customer.student_cards.exists() %}
{% if student_cards %}
<p>{{ student_cards }}</p>
<ul>
{% for card in customer.student_cards.all() %}
{% for card in student_cards %}
<li>{{ card.uid }}</li>
{% endfor %}
</ul>
Expand All @@ -55,7 +56,7 @@
<div id="click_form">
<h5>{% trans %}Selling{% endtrans %}</h5>
<div>
{% set counter_click_url = url('counter:click', counter_id=counter.id, user_id=customer.user.id) %}
{% set counter_click_url = url('counter:click', counter_id=counter.id, user_id=customer.user_id) %}

{# Formulaire pour rechercher un produit en tapant son code dans une barre de recherche #}
<form method="post" action=""
Expand Down Expand Up @@ -166,7 +167,7 @@
{%- endfor %}
</div>
</div>
{% endblock %}
{% endblock content %}

{% block script %}
{{ super() }}
Expand All @@ -193,4 +194,4 @@
{%- endfor %}
];
</script>
{% endblock %}
{% endblock script %}
4 changes: 2 additions & 2 deletions counter/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
name="activity",
),
path("<int:counter_id>/stats/", CounterStatView.as_view(), name="stats"),
path("<int:counter_id>/login/", CounterLogin.as_view(), name="login"),
path("<int:counter_id>/logout/", CounterLogout.as_view(), name="logout"),
path("<int:counter_id>/login/", counter_login, name="login"),
path("<int:counter_id>/logout/", counter_logout, name="logout"),
path(
"eticket/<int:selling_id>/pdf/",
EticketPDFView.as_view(),
Expand Down
Loading

0 comments on commit 002d8f8

Please sign in to comment.