exclude products over clic limit from eboutic

This commit is contained in:
imperosol
2026-05-14 12:28:59 +02:00
parent 2d135cdf6b
commit 62900b8c2e
7 changed files with 29 additions and 21 deletions
+6 -1
View File
@@ -29,7 +29,12 @@
align-items: center;
gap: 20px;
&.clickable:hover {
&:disabled {
background-color: darken($primary-neutral-light-color, 5%);
opacity: 65%;
}
&.clickable:not(:disabled):hover {
background-color: darken($primary-neutral-light-color, 5%);
}
+1 -1
View File
@@ -23,7 +23,7 @@
border-radius: 5px;
color: black;
&:hover {
&:not(.link-like):not(:disabled):hover {
background: hsl(0, 0%, 83%);
}
}
+3 -11
View File
@@ -22,7 +22,7 @@ import string
from datetime import date, datetime, timedelta
from datetime import timezone as tz
from decimal import Decimal
from typing import TYPE_CHECKING, Literal, Self
from typing import Literal, Self
from dict2xml import dict2xml
from django.conf import settings
@@ -48,9 +48,6 @@ from core.utils import get_start_of_semester
from counter.fields import CurrencyField
from subscription.models import Subscription
if TYPE_CHECKING:
from collections.abc import Sequence
def get_eboutic() -> Counter:
return Counter.objects.filter(type="EBOUTIC").order_by("id").first()
@@ -773,10 +770,8 @@ class Counter(models.Model):
# but they share the same primary key
return self.type == "BAR" and any(b.pk == customer.pk for b in self.barmen_list)
def get_prices_for(
self, customer: Customer, *, order_by: Sequence[str] | None = None
) -> list[Price]:
qs = (
def get_prices_for(self, customer: Customer) -> PriceQuerySet:
return (
Price.objects.filter(
product__counters=self, product__product_type__isnull=False
)
@@ -784,9 +779,6 @@ class Counter(models.Model):
.select_related("product", "product__product_type")
.prefetch_related("groups")
)
if order_by:
qs = qs.order_by(*order_by)
return list(qs)
class CounterSellers(models.Model):
+1 -1
View File
@@ -596,7 +596,7 @@ class TestCounterClick(TestFullClickBase):
product=iter(_product_recipe.make(archived=False, _quantity=2)),
groups=[group],
)
customer_prices = counter.get_prices_for(customer)
customer_prices = list(counter.get_prices_for(customer))
assert unarchived_prices == customer_prices
+1 -1
View File
@@ -103,7 +103,7 @@ class CounterClick(
):
return redirect(obj) # Redirect to counter
self.prices = obj.get_prices_for(self.customer)
self.prices = list(obj.get_prices_for(self.customer))
return super().dispatch(request, *args, **kwargs)
+5 -1
View File
@@ -187,9 +187,10 @@
{% for price in prices %}
<button
id="{{ price.id }}"
class="card product-button clickable shadow"
class="card clickable shadow"
:class="{selected: basket.some((i) => i.priceId === {{ price.id }})}"
@click='addFromCatalog({{ price.id }}, {{ price.full_label|tojson }}, {{ price.amount }})'
{% if price.sold_out %}disabled{% endif %}
>
{% if price.product.icon %}
<img
@@ -202,6 +203,9 @@
{% endif %}
<div class="card-content">
<h4 class="card-title">{{ price.full_label }}</h4>
{% if price.sold_out -%}
<p><em>{% trans %}Product sold out{% endtrans %}</em></p>
{%- endif %}
<p>{{ price.amount }} €</p>
</div>
</button>
+12 -5
View File
@@ -33,7 +33,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import SuspiciousOperation, ValidationError
from django.db import DatabaseError, transaction
from django.db.models import Subquery
from django.db.models import Exists, OuterRef, Subquery
from django.db.models.fields import forms
from django.db.utils import cached_property
from django.http import HttpResponse
@@ -92,7 +92,9 @@ class EbouticMainView(LoginRequiredMixin, FormView):
kwargs["form_kwargs"] = {
"customer": self.customer,
"counter": get_eboutic(),
"allowed_prices": {price.id: price for price in self.prices},
"allowed_prices": {
price.id: price for price in self.prices if not price.sold_out
},
}
return kwargs
@@ -118,9 +120,14 @@ class EbouticMainView(LoginRequiredMixin, FormView):
@cached_property
def prices(self) -> list[Price]:
return get_eboutic().get_prices_for(
self.customer,
order_by=["product__product_type__order", "product_id", "amount"],
eboutic = get_eboutic()
sold_out_subquery = ~Exists(
eboutic.products.under_clic_limit().filter(id=OuterRef("product_id"))
)
return list(
eboutic.get_prices_for(self.customer)
.annotate(sold_out=sold_out_subquery)
.order_by("product__product_type__order", "product_id", "amount")
)
@cached_property