Features: 1) Add support for processing chosen_products in order creation and update mutations; 2) Introduce new field chosen_products to serializers and GraphQL inputs; 3) Enhance order model to allow bulk addition of products with quantity updates;
Fixes: 1) Correct avatar resolution in `resolve_avatar` method for cases where `url` or `name` attributes are missing; 2) Refresh user object from the database after avatar update to avoid stale data; Extra: 1) Rename `BulkActionOrderProductInput` to `BulkProductInput` for consistency; 2) Minor code refactorings and adjustments for clarity.
This commit is contained in:
parent
171f2cb20f
commit
89301d6432
7 changed files with 21 additions and 10 deletions
|
|
@ -13,7 +13,7 @@ from core.elasticsearch import process_query
|
||||||
from core.graphene import BaseMutation
|
from core.graphene import BaseMutation
|
||||||
from core.graphene.object_types import (
|
from core.graphene.object_types import (
|
||||||
AddressType,
|
AddressType,
|
||||||
BulkActionOrderProductInput,
|
BulkProductInput,
|
||||||
OrderType,
|
OrderType,
|
||||||
ProductType,
|
ProductType,
|
||||||
SearchResultsType,
|
SearchResultsType,
|
||||||
|
|
@ -182,6 +182,7 @@ class BuyOrder(BaseMutation):
|
||||||
promocode_uuid = String(required=False)
|
promocode_uuid = String(required=False)
|
||||||
shipping_address = String(required=False)
|
shipping_address = String(required=False)
|
||||||
billing_address = String(required=False)
|
billing_address = String(required=False)
|
||||||
|
chosen_products = List(BulkProductInput, required=False)
|
||||||
|
|
||||||
order = Field(OrderType, required=False)
|
order = Field(OrderType, required=False)
|
||||||
transaction = Field(TransactionType, required=False)
|
transaction = Field(TransactionType, required=False)
|
||||||
|
|
@ -197,6 +198,7 @@ class BuyOrder(BaseMutation):
|
||||||
promocode_uuid=None,
|
promocode_uuid=None,
|
||||||
shipping_address=None,
|
shipping_address=None,
|
||||||
billing_address=None,
|
billing_address=None,
|
||||||
|
chosen_products=None,
|
||||||
):
|
):
|
||||||
if not any([order_uuid, order_hr_id]) or all([order_uuid, order_hr_id]):
|
if not any([order_uuid, order_hr_id]) or all([order_uuid, order_hr_id]):
|
||||||
raise BadRequest(_("please provide either order_uuid or order_hr_id - mutually exclusive"))
|
raise BadRequest(_("please provide either order_uuid or order_hr_id - mutually exclusive"))
|
||||||
|
|
@ -215,6 +217,7 @@ class BuyOrder(BaseMutation):
|
||||||
promocode_uuid=promocode_uuid,
|
promocode_uuid=promocode_uuid,
|
||||||
shipping_address=shipping_address,
|
shipping_address=shipping_address,
|
||||||
billing_address=billing_address,
|
billing_address=billing_address,
|
||||||
|
chosen_products=chosen_products,
|
||||||
)
|
)
|
||||||
|
|
||||||
match str(type(instance)):
|
match str(type(instance)):
|
||||||
|
|
@ -237,7 +240,7 @@ class BulkOrderAction(BaseMutation):
|
||||||
order_uuid = UUID(required=False)
|
order_uuid = UUID(required=False)
|
||||||
order_hr_id = String(required=False)
|
order_hr_id = String(required=False)
|
||||||
action = String(required=True, description=_("remove/add"))
|
action = String(required=True, description=_("remove/add"))
|
||||||
products = List(BulkActionOrderProductInput, required=True)
|
products = List(BulkProductInput, required=True)
|
||||||
|
|
||||||
order = Field(OrderType, required=False)
|
order = Field(OrderType, required=False)
|
||||||
|
|
||||||
|
|
@ -283,7 +286,7 @@ class BulkWishlistAction(BaseMutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
wishlist_uuid = UUID(required=False)
|
wishlist_uuid = UUID(required=False)
|
||||||
action = String(required=True, description="remove/add")
|
action = String(required=True, description="remove/add")
|
||||||
products = List(BulkActionOrderProductInput, required=True)
|
products = List(BulkProductInput, required=True)
|
||||||
|
|
||||||
wishlist = Field(WishlistType, required=False)
|
wishlist = Field(WishlistType, required=False)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -566,6 +566,6 @@ class SearchResultsType(ObjectType):
|
||||||
posts = List(description=_("posts search results"), of_type=SearchPostsResultsType)
|
posts = List(description=_("posts search results"), of_type=SearchPostsResultsType)
|
||||||
|
|
||||||
|
|
||||||
class BulkActionOrderProductInput(InputObjectType):
|
class BulkProductInput(InputObjectType):
|
||||||
uuid = UUID(required=True)
|
uuid = UUID(required=True)
|
||||||
attributes = GenericScalar(required=False)
|
attributes = GenericScalar(required=False)
|
||||||
|
|
|
||||||
|
|
@ -1579,7 +1579,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
|
||||||
|
|
||||||
if chosen_products:
|
if chosen_products:
|
||||||
order = Order.objects.create(status="MOMENTAL", user=self.user)
|
order = Order.objects.create(status="MOMENTAL", user=self.user)
|
||||||
order.bulk_add_products(chosen_products)
|
order.bulk_add_products(chosen_products, update_quantity=True)
|
||||||
|
|
||||||
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"))
|
||||||
|
|
@ -1713,19 +1713,19 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [mi
|
||||||
def update_order_products_statuses(self, status: str = "PENDING"):
|
def update_order_products_statuses(self, status: str = "PENDING"):
|
||||||
self.order_products.update(status=status)
|
self.order_products.update(status=status)
|
||||||
|
|
||||||
def bulk_add_products(self, products: list[dict[str, Any]]):
|
def bulk_add_products(self, products: list[dict[str, Any]], update_quantity: bool = False):
|
||||||
for product in products:
|
for product in products:
|
||||||
self.add_product(
|
self.add_product(
|
||||||
product.get("uuid"),
|
product.get("uuid") or product.get("product_uuid"),
|
||||||
attributes=product.get("attributes"),
|
attributes=product.get("attributes"),
|
||||||
update_quantity=False,
|
update_quantity=update_quantity,
|
||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def bulk_remove_products(self, products: list):
|
def bulk_remove_products(self, products: list):
|
||||||
for product in products:
|
for product in products:
|
||||||
self.remove_product(
|
self.remove_product(
|
||||||
product.get("uuid"),
|
product.get("uuid") or product.get("product_uuid"),
|
||||||
attributes=product.get("attributes"),
|
attributes=product.get("attributes"),
|
||||||
zero_quantity=True,
|
zero_quantity=True,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
class BuyUnregisteredOrderSerializer(Serializer):
|
class BuyUnregisteredOrderSerializer(Serializer):
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,7 @@ class OrderViewSet(EvibesViewSet):
|
||||||
promocode_uuid=serializer.validated_data.get("promocode_uuid"),
|
promocode_uuid=serializer.validated_data.get("promocode_uuid"),
|
||||||
shipping_address=serializer.validated_data.get("shipping_address_uuid"),
|
shipping_address=serializer.validated_data.get("shipping_address_uuid"),
|
||||||
billing_address=serializer.validated_data.get("billing_address_uuid"),
|
billing_address=serializer.validated_data.get("billing_address_uuid"),
|
||||||
|
chosen_products=serializer.validated_data.get("chosen_products"),
|
||||||
)
|
)
|
||||||
match str(type(instance)):
|
match str(type(instance)):
|
||||||
case "<class 'payments.models.Transaction'>":
|
case "<class 'payments.models.Transaction'>":
|
||||||
|
|
|
||||||
|
|
@ -338,6 +338,7 @@ class UploadAvatar(BaseMutation):
|
||||||
try:
|
try:
|
||||||
info.context.user.avatar = avatar
|
info.context.user.avatar = avatar
|
||||||
info.context.user.save()
|
info.context.user.save()
|
||||||
|
info.context.user.refresh_from_db()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BadRequest(str(e)) from e
|
raise BadRequest(str(e)) from e
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,12 @@ class UserType(DjangoObjectType):
|
||||||
|
|
||||||
def resolve_avatar(self: User, info) -> str:
|
def resolve_avatar(self: User, info) -> str:
|
||||||
if self.avatar:
|
if self.avatar:
|
||||||
return info.context.build_absolute_uri(self.avatar.url)
|
if hasattr(self.avatar, "url"):
|
||||||
|
return info.context.build_absolute_uri(self.avatar.url)
|
||||||
|
elif hasattr(self.avatar, "name"):
|
||||||
|
return info.context.build_absolute_uri(f"/media/{self.avatar.name}")
|
||||||
|
else:
|
||||||
|
return info.context.build_absolute_uri(f"/media/{self.avatar}")
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue