Features: 1) Ensure is_business flag is consistently updated for users and orders; 2) Refactor serializers to improve handling of business order data structures; 3) Add support for business-specific attributes in buy operations.

**Fixes**: 1) Correct handling of non-dict `attributes` for users and orders; 2) Resolve serializer field inconsistencies in `BuyUnregisteredOrderSerializer` and others.

Extra: 1) Clean up redundant error handling and unused local variables; 2) Rename and align method arguments for clarity.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-09-05 19:04:15 +03:00
parent efb9aaeeef
commit ac439d7ead
4 changed files with 32 additions and 16 deletions

View file

@ -1605,7 +1605,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
) -> Self | Transaction | None: ) -> Self | Transaction | None:
order = self order = self
if not self.attributes: if not self.attributes or type(self.attributes) is not dict:
self.attributes = {} self.attributes = {}
if chosen_products: if chosen_products:
@ -1643,10 +1643,16 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
if not order.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 order.user.attributes.get("is_business", False): if type(order.user.attributes) is dict:
if type(order.attributes) is not dict: if order.user.attributes.get("is_business", False) or order.user.attributes.get(
order.attributes = {} "business_identificator", ""
order.attributes.update({"is_business": True}) ):
if type(order.attributes) is not dict:
order.attributes = {}
order.attributes.update({"is_business": True})
else:
order.user.attributes = {}
order.user.save()
if not order.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"))
@ -1681,7 +1687,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
if len(products) < 1: if len(products) < 1:
raise ValueError(_("you cannot purchase an empty order!")) raise ValueError(_("you cannot purchase an empty order!"))
customer_name = kwargs.get("customer_name") customer_name = kwargs.get("customer_name") or kwargs.get("business_identificator")
customer_email = kwargs.get("customer_email") customer_email = kwargs.get("customer_email")
customer_phone_number = kwargs.get("customer_phone_number") customer_phone_number = kwargs.get("customer_phone_number")

View file

@ -160,11 +160,11 @@ class BuyOrderSerializer(Serializer):
promocode_uuid = CharField(required=False) promocode_uuid = CharField(required=False)
shipping_address_uuid = CharField(required=False) shipping_address_uuid = CharField(required=False)
billing_address_uuid = CharField(required=False) billing_address_uuid = CharField(required=False)
chosen_products = ListField(child=AddOrderProductSerializer(), required=False) chosen_products = AddOrderProductSerializer(many=True, required=False)
class BuyUnregisteredOrderSerializer(Serializer): class BuyUnregisteredOrderSerializer(Serializer):
products = ListField(child=AddOrderProductSerializer(), required=True) products = AddOrderProductSerializer(many=True, required=True)
promocode_uuid = UUIDField(required=False) promocode_uuid = UUIDField(required=False)
customer_name = CharField(required=True) customer_name = CharField(required=True)
customer_email = CharField(required=True) customer_email = CharField(required=True)
@ -175,7 +175,7 @@ class BuyUnregisteredOrderSerializer(Serializer):
class BuyAsBusinessOrderSerializer(Serializer): class BuyAsBusinessOrderSerializer(Serializer):
products = ListField(child=AddOrderProductSerializer(), required=True) products = AddOrderProductSerializer(many=True, required=True)
business_identificator = CharField(required=True) business_identificator = CharField(required=True)
business_email = CharField(required=True) business_email = CharField(required=True)
business_phone_number = CharField(required=True) business_phone_number = CharField(required=True)

View file

@ -436,11 +436,11 @@ class BuyAsBusinessView(APIView):
transaction = order.buy_without_registration( transaction = order.buy_without_registration(
products=products, products=products,
promocode_uuid=serializer.validated_data.get("promocode_uuid"), promocode_uuid=serializer.validated_data.get("promocode_uuid"),
customer_name=serializer.validated_data.get("customer_name"), customer_name=serializer.validated_data.get("business_identificator"),
customer_email=serializer.validated_data.get("customer_email"), customer_email=serializer.validated_data.get("business_email"),
customer_phone=serializer.validated_data.get("customer_phone"), customer_phone_number=serializer.validated_data.get("business_phone_number"),
customer_billing_address=serializer.validated_data.get("customer_billing_address_uuid"), billing_customer_address=serializer.validated_data.get("billing_business_address_uuid"),
customer_shipping_address=serializer.validated_data.get("customer_shipping_address_uuid"), shipping_customer_address=serializer.validated_data.get("shipping_business_address_uuid"),
payment_method=serializer.validated_data.get("payment_method"), payment_method=serializer.validated_data.get("payment_method"),
is_business=True, is_business=True,
) )

View file

@ -17,11 +17,16 @@ class UserManager(BaseUserManager):
def handle_unregistered_entities(user): def handle_unregistered_entities(user):
try: try:
orders = set() orders = set()
mark_business = False
for order in Order.objects.filter(attributes__icontains=user.email): for order in Order.objects.filter(attributes__icontains=user.email):
if not order.user: if not order.user:
order.user = user order.user = user
order.save() order.save()
orders.add(order.uuid) orders.add(order.uuid)
if type(order.attributes) is not dict:
order.attributes = {}
if order.attributes.get("is_business"):
mark_business = True
if user.phone_number: if user.phone_number:
for order in Order.objects.filter(attributes__icontains=user.phone_number): for order in Order.objects.filter(attributes__icontains=user.phone_number):
if not order.user: if not order.user:
@ -36,6 +41,12 @@ class UserManager(BaseUserManager):
if not address.user: if not address.user:
address.user = user address.user = user
address.save() address.save()
if type(user.attributes) is not dict:
user.attributes = {}
if mark_business:
user.attributes.update({"is_business": True})
user.save()
return user
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
@ -47,8 +58,7 @@ class UserManager(BaseUserManager):
user = self.model(email=email, **extra_fields) user = self.model(email=email, **extra_fields)
user.password = make_password(password) user.password = make_password(password)
user.save(using=self._db) user.save(using=self._db)
self.handle_unregistered_entities(user) return self.handle_unregistered_entities(user)
return user
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def create_user(self, email=None, password=None, **extra_fields): def create_user(self, email=None, password=None, **extra_fields):