From 78fe4e52cabea35f5a2b24b50acd6b43d01ac80a Mon Sep 17 00:00:00 2001 From: imperosol Date: Wed, 19 Nov 2025 19:56:21 +0100 Subject: [PATCH] make `Selling.payment_method` a SmallIntegerField --- ...35_remove_selling_is_validated_and_more.py | 26 +++++++++++++++++++ counter/models.py | 25 +++++++++++------- counter/tests/test_customer.py | 5 +--- counter/views/invoice.py | 2 +- eboutic/models.py | 6 +++-- eboutic/tests/test_payment.py | 8 +++--- eboutic/views.py | 2 +- rootplace/tests/test_merge_users.py | 4 --- 8 files changed, 53 insertions(+), 25 deletions(-) diff --git a/counter/migrations/0035_remove_selling_is_validated_and_more.py b/counter/migrations/0035_remove_selling_is_validated_and_more.py index 37d4997b..b5ecf0b6 100644 --- a/counter/migrations/0035_remove_selling_is_validated_and_more.py +++ b/counter/migrations/0035_remove_selling_is_validated_and_more.py @@ -4,9 +4,35 @@ from django.db import migrations, models from django.db.migrations.state import StateApps +def migrate_payment_method(apps: StateApps, schema_editor): + Selling = apps.get_model("counter", "Selling") + Selling.objects.filter(payment_method_str="CARD").update(payment_method=1) + + +def migrate_payment_method_reverse(apps: StateApps, schema_editor): + Selling = apps.get_model("counter", "Selling") + Selling.objects.filter(payment_method=1).update(payment_method_str="CARD") + + class Migration(migrations.Migration): dependencies = [("counter", "0034_alter_selling_date_selling_date_month_idx")] operations = [ migrations.RemoveField(model_name="selling", name="is_validated"), + migrations.RenameField( + model_name="selling", + old_name="payment_method", + new_name="payment_method_str", + ), + migrations.AddField( + model_name="selling", + name="payment_method", + field=models.PositiveSmallIntegerField( + choices=[(0, "Sith account"), (1, "Credit card")], + default=0, + verbose_name="payment method", + ), + ), + migrations.RunPython(migrate_payment_method, migrate_payment_method_reverse), + migrations.RemoveField(model_name="selling", name="payment_method_str"), ] diff --git a/counter/models.py b/counter/models.py index 1e07be3b..7324e0c2 100644 --- a/counter/models.py +++ b/counter/models.py @@ -80,7 +80,8 @@ class CustomerQuerySet(models.QuerySet): ) money_out = Subquery( Selling.objects.filter( - customer=OuterRef("pk"), payment_method="SITH_ACCOUNT" + customer=OuterRef("pk"), + payment_method=Selling.PaymentMethod.SITH_ACCOUNT, ) .values("customer_id") .annotate(res=Sum(F("unit_price") * F("quantity"), default=0)) @@ -814,6 +815,10 @@ class SellingQuerySet(models.QuerySet): class Selling(models.Model): """Handle the sellings.""" + class PaymentMethod(models.IntegerChoices): + SITH_ACCOUNT = 0, _("Sith account") + CARD = 1, _("Credit card") + # We make sure that sellings have a way begger label than any product name is allowed to label = models.CharField(_("label"), max_length=128) product = models.ForeignKey( @@ -850,11 +855,8 @@ class Selling(models.Model): on_delete=models.SET_NULL, ) date = models.DateTimeField(_("date"), db_index=True) - payment_method = models.CharField( - _("payment method"), - max_length=255, - choices=[("SITH_ACCOUNT", _("Sith account")), ("CARD", _("Credit card"))], - default="SITH_ACCOUNT", + payment_method = models.PositiveSmallIntegerField( + _("payment method"), choices=PaymentMethod, default=PaymentMethod.SITH_ACCOUNT ) objects = SellingQuerySet.as_manager() @@ -874,7 +876,10 @@ class Selling(models.Model): if not self.date: self.date = timezone.now() self.full_clean() - if self._state.adding and self.payment_method == "SITH_ACCOUNT": + if ( + self._state.adding + and self.payment_method == self.PaymentMethod.SITH_ACCOUNT + ): self.customer.amount -= self.quantity * self.unit_price self.customer.save(allow_negative=allow_negative) user = self.customer.user @@ -946,7 +951,9 @@ class Selling(models.Model): def is_owned_by(self, user: User) -> bool: if user.is_anonymous: return False - return self.payment_method != "CARD" and user.is_owner(self.counter) + return self.payment_method != self.PaymentMethod.CARD and user.is_owner( + self.counter + ) def can_be_viewed_by(self, user: User) -> bool: if ( @@ -956,7 +963,7 @@ class Selling(models.Model): return user == self.customer.user def delete(self, *args, **kwargs): - if self.payment_method == "SITH_ACCOUNT": + if self.payment_method == Selling.PaymentMethod.SITH_ACCOUNT: self.customer.amount += self.quantity * self.unit_price self.customer.save() super().delete(*args, **kwargs) diff --git a/counter/tests/test_customer.py b/counter/tests/test_customer.py index 3676a701..311e48ed 100644 --- a/counter/tests/test_customer.py +++ b/counter/tests/test_customer.py @@ -298,7 +298,6 @@ def test_update_balance(): _quantity=len(customers), unit_price=10, quantity=1, - payment_method="SITH_ACCOUNT", _save_related=True, ), *sale_recipe.prepare( @@ -306,14 +305,12 @@ def test_update_balance(): _quantity=3, unit_price=5, quantity=2, - payment_method="SITH_ACCOUNT", _save_related=True, ), sale_recipe.prepare( customer=customers[4], quantity=1, unit_price=50, - payment_method="SITH_ACCOUNT", _save_related=True, ), *sale_recipe.prepare( @@ -324,7 +321,7 @@ def test_update_balance(): _quantity=len(customers), unit_price=50, quantity=1, - payment_method="CARD", + payment_method=Selling.PaymentMethod.CARD, _save_related=True, ), ] diff --git a/counter/views/invoice.py b/counter/views/invoice.py index c42090d6..11702803 100644 --- a/counter/views/invoice.py +++ b/counter/views/invoice.py @@ -74,7 +74,7 @@ class InvoiceCallView( ).aggregate(res=Sum("amount", default=0))["res"] kwargs["sum_cb"] += ( Selling.objects.filter( - payment_method="CARD", + payment_method=Selling.PaymentMethod.CARD, date__gte=start_date, date__lte=end_date, ) diff --git a/eboutic/models.py b/eboutic/models.py index 6d71e025..a2054610 100644 --- a/eboutic/models.py +++ b/eboutic/models.py @@ -110,7 +110,9 @@ class Basket(models.Model): )["total"] ) - def generate_sales(self, counter, seller: User, payment_method: str): + def generate_sales( + self, counter, seller: User, payment_method: Selling.PaymentMethod + ): """Generate a list of sold items corresponding to the items of this basket WITHOUT saving them NOR deleting the basket. @@ -267,7 +269,7 @@ class Invoice(models.Model): customer=customer, unit_price=i.product_unit_price, quantity=i.quantity, - payment_method="CARD", + payment_method=Selling.PaymentMethod.CARD, date=self.date, ) new.save() diff --git a/eboutic/tests/test_payment.py b/eboutic/tests/test_payment.py index dd619169..813e82c8 100644 --- a/eboutic/tests/test_payment.py +++ b/eboutic/tests/test_payment.py @@ -114,13 +114,13 @@ class TestPaymentSith(TestPaymentBase): "quantity" ) assert len(sellings) == 2 - assert sellings[0].payment_method == "SITH_ACCOUNT" + assert sellings[0].payment_method == Selling.PaymentMethod.SITH_ACCOUNT assert sellings[0].quantity == 1 assert sellings[0].unit_price == self.snack.selling_price assert sellings[0].counter.type == "EBOUTIC" assert sellings[0].product == self.snack - assert sellings[1].payment_method == "SITH_ACCOUNT" + assert sellings[1].payment_method == Selling.PaymentMethod.SITH_ACCOUNT assert sellings[1].quantity == 2 assert sellings[1].unit_price == self.beer.selling_price assert sellings[1].counter.type == "EBOUTIC" @@ -198,13 +198,13 @@ class TestPaymentCard(TestPaymentBase): "quantity" ) assert len(sellings) == 2 - assert sellings[0].payment_method == "CARD" + assert sellings[0].payment_method == Selling.PaymentMethod.CARD assert sellings[0].quantity == 1 assert sellings[0].unit_price == self.snack.selling_price assert sellings[0].counter.type == "EBOUTIC" assert sellings[0].product == self.snack - assert sellings[1].payment_method == "CARD" + assert sellings[1].payment_method == Selling.PaymentMethod.CARD assert sellings[1].quantity == 2 assert sellings[1].unit_price == self.beer.selling_price assert sellings[1].counter.type == "EBOUTIC" diff --git a/eboutic/views.py b/eboutic/views.py index fa25df66..74cdc7ad 100644 --- a/eboutic/views.py +++ b/eboutic/views.py @@ -275,7 +275,7 @@ class EbouticPayWithSith(CanViewMixin, SingleObjectMixin, View): return redirect("eboutic:payment_result", "failure") eboutic = get_eboutic() - sales = basket.generate_sales(eboutic, basket.user, "SITH_ACCOUNT") + sales = basket.generate_sales(eboutic, basket.user, Selling.PaymentMethod.SITH_ACCOUNT) try: with transaction.atomic(): # Selling.save has some important business logic in it. diff --git a/rootplace/tests/test_merge_users.py b/rootplace/tests/test_merge_users.py index 294e2bae..63c406cd 100644 --- a/rootplace/tests/test_merge_users.py +++ b/rootplace/tests/test_merge_users.py @@ -114,7 +114,6 @@ class TestMergeUser(TestCase): seller=self.root, unit_price=2, quantity=2, - payment_method="SITH_ACCOUNT", ).save() Selling( label="barbar", @@ -125,7 +124,6 @@ class TestMergeUser(TestCase): seller=self.root, unit_price=2, quantity=4, - payment_method="SITH_ACCOUNT", ).save() today = localtime(now()).date() # both subscriptions began last month and shall end in 5 months @@ -197,7 +195,6 @@ class TestMergeUser(TestCase): seller=self.root, unit_price=2, quantity=4, - payment_method="SITH_ACCOUNT", ).save() data = {"user1": self.to_keep.id, "user2": self.to_delete.id} res = self.client.post(reverse("rootplace:merge"), data) @@ -225,7 +222,6 @@ class TestMergeUser(TestCase): seller=self.root, unit_price=2, quantity=4, - payment_method="SITH_ACCOUNT", ).save() data = {"user1": self.to_keep.id, "user2": self.to_delete.id} res = self.client.post(reverse("rootplace:merge"), data)