Features: 1) Add support for optional billing_address_uuid and shipping_address_uuid in apply_addresses; 2) Introduce chosen_products parameter in the buy method for customized order creation;

Fixes: 1) Correct type annotations in `buy` and `bulk_add_products` methods for improved type safety;

Extra: 1) Refactor `buy` method for enhanced readability and maintainability; 2) Update usage of `self` to `order` for clarity in dynamic order creation scenarios.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-07-06 23:53:46 +03:00
parent 34f25052e0
commit 1ace97c233

View file

@ -1532,7 +1532,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
raise Http404(_("promocode does not exist")) from dne raise Http404(_("promocode does not exist")) from dne
return promocode.use(self) return promocode.use(self)
def apply_addresses(self, billing_address_uuid, shipping_address_uuid): def apply_addresses(self, billing_address_uuid: str | None = None, shipping_address_uuid: str | None = None):
try: try:
if not any([shipping_address_uuid, billing_address_uuid]): if not any([shipping_address_uuid, billing_address_uuid]):
if self.is_whole_digital: if self.is_whole_digital:
@ -1561,21 +1561,27 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
def buy( def buy(
self, self,
force_balance=False, force_balance: bool = False,
force_payment=False, force_payment: bool = False,
promocode_uuid=None, promocode_uuid: str | None = None,
billing_address=None, billing_address: str | None = None,
shipping_address=None, shipping_address: str | None = None,
chosen_products: list = None,
) -> Self | Transaction | None: ) -> Self | Transaction | None:
order = self
if chosen_products:
order = Order.objects.create(status="MOMENTAL", user=self.user)
order.bulk_add_products(chosen_products)
if config.DISABLED_COMMERCE: if config.DISABLED_COMMERCE:
raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes")) raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes"))
if (not force_balance and not force_payment) or (force_balance and force_payment): if (not force_balance and not force_payment) or (force_balance and force_payment):
raise ValueError(_("invalid force value")) raise ValueError(_("invalid force value"))
self.apply_addresses(billing_address, shipping_address) order.apply_addresses(billing_address, shipping_address)
if self.total_quantity < 1: if order.total_quantity < 1:
raise ValueError(_("you cannot purchase an empty order!")) raise ValueError(_("you cannot purchase an empty order!"))
force = None force = None
@ -1586,34 +1592,34 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
if force_payment: if force_payment:
force = "payment" force = "payment"
amount = self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price amount = order.apply_promocode(promocode_uuid) if promocode_uuid else order.total_price
if not self.user: if not order.user:
raise ValueError(_("you cannot buy an order without a user")) raise ValueError(_("you cannot buy an order without a user"))
if not self.user.payments_balance: if not order.user.payments_balance:
raise ValueError(_("a user without a balance cannot buy with balance")) raise ValueError(_("a user without a balance cannot buy with balance"))
match force: match force:
case "balance": case "balance":
if self.user.payments_balance.amount < amount: if order.user.payments_balance.amount < amount:
raise NotEnoughMoneyError(_("insufficient funds to complete the order")) raise NotEnoughMoneyError(_("insufficient funds to complete the order"))
self.status = "CREATED" order.status = "CREATED"
self.buy_time = timezone.now() order.buy_time = timezone.now()
self.order_products.all().update(status="DELIVERING") order.order_products.all().update(status="DELIVERING")
self.save() order.save()
return self return order
case "payment": case "payment":
self.status = "PAYMENT" order.status = "PAYMENT"
self.save() order.save()
return Transaction.objects.create( return Transaction.objects.create(
balance=self.user.payments_balance, balance=order.user.payments_balance,
amount=amount, amount=amount,
currency=CURRENCY_CODE, currency=CURRENCY_CODE,
order=self, order=order,
) )
return self return order
def buy_without_registration(self, products: list, promocode_uuid, **kwargs) -> Transaction | None: def buy_without_registration(self, products: list, promocode_uuid, **kwargs) -> Transaction | None:
if config.DISABLED_COMMERCE: if config.DISABLED_COMMERCE:
@ -1689,7 +1695,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
self.status = "FINISHED" self.status = "FINISHED"
self.save() self.save()
def bulk_add_products(self, products: list): def bulk_add_products(self, products: list[dict[str, Any]]):
for product in products: for product in products:
self.add_product( self.add_product(
product.get("uuid"), product.get("uuid"),