mirror of
https://github.com/ae-utbm/sith.git
synced 2026-03-13 15:15:03 +00:00
unify eboutic and regular counter price selection
This commit is contained in:
@@ -119,4 +119,31 @@ class Migration(migrations.Migration):
|
||||
migrations.RunPython(migrate_prices, reverse_code=migrations.RunPython.noop),
|
||||
migrations.RemoveField(model_name="product", name="selling_price"),
|
||||
migrations.RemoveField(model_name="product", name="special_selling_price"),
|
||||
migrations.AlterField(
|
||||
model_name="product",
|
||||
name="description",
|
||||
field=models.TextField(blank=True, default="", verbose_name="description"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="product",
|
||||
name="product_type",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="products",
|
||||
to="counter.producttype",
|
||||
verbose_name="product type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="productformula",
|
||||
name="result",
|
||||
field=models.OneToOneField(
|
||||
help_text="The product got with the formula.",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="formula",
|
||||
to="counter.product",
|
||||
verbose_name="result product",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -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 Literal, Self
|
||||
from typing import TYPE_CHECKING, Literal, Self
|
||||
|
||||
from dict2xml import dict2xml
|
||||
from django.conf import settings
|
||||
@@ -47,6 +47,9 @@ 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()
|
||||
@@ -356,13 +359,13 @@ class Product(models.Model):
|
||||
QUANTITY_FOR_TRAY_PRICE = 6
|
||||
|
||||
name = models.CharField(_("name"), max_length=64)
|
||||
description = models.TextField(_("description"), default="")
|
||||
description = models.TextField(_("description"), blank=True, default="")
|
||||
product_type = models.ForeignKey(
|
||||
ProductType,
|
||||
related_name="products",
|
||||
verbose_name=_("product type"),
|
||||
null=True,
|
||||
blank=True,
|
||||
blank=False,
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
code = models.CharField(_("code"), max_length=16, blank=True)
|
||||
@@ -726,13 +729,20 @@ 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) -> list[Price]:
|
||||
return list(
|
||||
Price.objects.filter(product__counters=self)
|
||||
def get_prices_for(
|
||||
self, customer: Customer, *, order_by: Sequence[str] | None = None
|
||||
) -> list[Price]:
|
||||
qs = (
|
||||
Price.objects.filter(
|
||||
product__counters=self, product__product_type__isnull=False
|
||||
)
|
||||
.for_user(customer.user)
|
||||
.select_related("product", "product__product_type")
|
||||
.prefetch_related("groups")
|
||||
)
|
||||
if order_by:
|
||||
qs = qs.order_by(*order_by)
|
||||
return list(qs)
|
||||
|
||||
|
||||
class RefillingQuerySet(models.QuerySet):
|
||||
|
||||
@@ -16,7 +16,7 @@ from counter.forms import (
|
||||
ScheduledProductActionForm,
|
||||
ScheduledProductActionFormSet,
|
||||
)
|
||||
from counter.models import Product, ScheduledProductAction
|
||||
from counter.models import Product, ProductType, ScheduledProductAction
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -47,8 +47,7 @@ def test_create_actions_alongside_product():
|
||||
form = ProductForm(
|
||||
data={
|
||||
"name": "foo",
|
||||
"description": "bar",
|
||||
"product_type": product.product_type_id,
|
||||
"product_type": ProductType.objects.first(),
|
||||
"club": product.club_id,
|
||||
"code": "FOO",
|
||||
"purchase_price": 1.0,
|
||||
@@ -63,6 +62,7 @@ def test_create_actions_alongside_product():
|
||||
"action-0-trigger_at": trigger_at,
|
||||
},
|
||||
)
|
||||
form.is_valid()
|
||||
assert form.is_valid()
|
||||
product = form.save()
|
||||
action = ScheduledProductAction.objects.last()
|
||||
|
||||
@@ -39,6 +39,7 @@ from counter.models import (
|
||||
Counter,
|
||||
Customer,
|
||||
Permanency,
|
||||
ProductType,
|
||||
Refilling,
|
||||
ReturnableProduct,
|
||||
Selling,
|
||||
@@ -238,31 +239,38 @@ class TestCounterClick(TestFullClickBase):
|
||||
old_subscriber_group = Group.objects.get(
|
||||
id=settings.SITH_GROUP_OLD_SUBSCRIBERS_ID
|
||||
)
|
||||
_product_recipe = product_recipe.extend(product_type=baker.make(ProductType))
|
||||
|
||||
cls.gift = price_recipe.make(amount=-1.5, groups=[subscriber_group])
|
||||
cls.gift = price_recipe.make(
|
||||
amount=-1.5, groups=[subscriber_group], product=_product_recipe.make()
|
||||
)
|
||||
cls.beer = price_recipe.make(
|
||||
groups=[subscriber_group],
|
||||
amount=1.5,
|
||||
product=product_recipe.make(limit_age=18),
|
||||
product=_product_recipe.make(limit_age=18),
|
||||
)
|
||||
cls.beer_tap = price_recipe.make(
|
||||
groups=[subscriber_group],
|
||||
amount=1.5,
|
||||
product=product_recipe.make(limit_age=18, tray=True),
|
||||
product=_product_recipe.make(limit_age=18, tray=True),
|
||||
)
|
||||
cls.snack = price_recipe.make(
|
||||
groups=[subscriber_group, old_subscriber_group],
|
||||
amount=1.5,
|
||||
product=product_recipe.make(limit_age=0),
|
||||
product=_product_recipe.make(limit_age=0),
|
||||
)
|
||||
cls.stamps = price_recipe.make(
|
||||
groups=[subscriber_group],
|
||||
amount=1.5,
|
||||
product=product_recipe.make(limit_age=0),
|
||||
product=_product_recipe.make(limit_age=0),
|
||||
)
|
||||
ReturnableProduct.objects.all().delete()
|
||||
cls.cons = price_recipe.make(amount=1, groups=[subscriber_group])
|
||||
cls.dcons = price_recipe.make(amount=-1, groups=[subscriber_group])
|
||||
cls.cons = price_recipe.make(
|
||||
amount=1, groups=[subscriber_group], product=_product_recipe.make()
|
||||
)
|
||||
cls.dcons = price_recipe.make(
|
||||
amount=-1, groups=[subscriber_group], product=_product_recipe.make()
|
||||
)
|
||||
baker.make(
|
||||
ReturnableProduct,
|
||||
product=cls.cons.product,
|
||||
@@ -575,18 +583,17 @@ class TestCounterClick(TestFullClickBase):
|
||||
group = baker.make(Group)
|
||||
customer = baker.make(Customer)
|
||||
group.users.add(customer.user)
|
||||
_product_recipe = product_recipe.extend(
|
||||
counters=[counter], product_type=baker.make(ProductType)
|
||||
)
|
||||
price_recipe.make(
|
||||
_quantity=2,
|
||||
product=iter(
|
||||
product_recipe.make(archived=True, counters=[counter], _quantity=2)
|
||||
),
|
||||
product=iter(_product_recipe.make(archived=True, _quantity=2)),
|
||||
groups=[group],
|
||||
)
|
||||
unarchived_prices = price_recipe.make(
|
||||
_quantity=2,
|
||||
product=iter(
|
||||
product_recipe.make(archived=False, counters=[counter], _quantity=2)
|
||||
),
|
||||
product=iter(_product_recipe.make(archived=False, _quantity=2)),
|
||||
groups=[group],
|
||||
)
|
||||
customer_prices = counter.get_prices_for(customer)
|
||||
|
||||
Reference in New Issue
Block a user