Features: 1) Add support for shipping and billing addresses in serializers, mutations, and models; 2) Validate address inputs during order purchasing; 3) Auto-fill billing address if only shipping address is provided and vice-versa;
Fixes: 1) Correct redundant variable and file handling in geo management commands; 2) Fix formatting inconsistencies in tqdm loops across geo management commands; 3) Remove unnecessary decorator in token verification view; Extra: Clean up imports, line breaks, and redundant code for better readability and maintainability in multiple files;
This commit is contained in:
parent
11edfb9d4f
commit
43c8df0c05
6 changed files with 111 additions and 83 deletions
|
|
@ -172,26 +172,32 @@ class BuyOrder(BaseMutation):
|
|||
force_balance = Boolean(required=False)
|
||||
force_payment = Boolean(required=False)
|
||||
promocode_uuid = UUID(required=False)
|
||||
shipping_address = UUID(required=False)
|
||||
billing_address = UUID(required=False)
|
||||
|
||||
order = Field(OrderType, required=False)
|
||||
transaction = Field(TransactionType, required=False)
|
||||
|
||||
@staticmethod
|
||||
def mutate(_parent, info, order_uuid=None, order_hr_id=None, force_balance=False, force_payment=False,
|
||||
promocode_uuid=None):
|
||||
promocode_uuid=None, shipping_address=None, billing_address=None):
|
||||
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"))
|
||||
user = info.context.user
|
||||
try:
|
||||
|
||||
order = None
|
||||
|
||||
if order_uuid:
|
||||
order = Order.objects.get(user=user, uuid=order_uuid)
|
||||
if order_hr_id:
|
||||
elif order_hr_id:
|
||||
order = Order.objects.get(user=user, human_readable_id=order_hr_id)
|
||||
|
||||
instance = order.buy(
|
||||
force_balance=force_balance, force_payment=force_payment, promocode_uuid=promocode_uuid
|
||||
force_balance=force_balance, force_payment=force_payment, promocode_uuid=promocode_uuid,
|
||||
shipping_address=shipping_address, billing_address=billing_address
|
||||
)
|
||||
|
||||
match str(type(instance)):
|
||||
case "<class 'payments.models.Transaction'>":
|
||||
return BuyOrder(transaction=instance)
|
||||
|
|
@ -199,6 +205,7 @@ class BuyOrder(BaseMutation):
|
|||
return BuyOrder(order=instance)
|
||||
case _:
|
||||
raise TypeError(_(f"wrong type came from order.buy() method: {type(instance)!s}"))
|
||||
|
||||
except Order.DoesNotExist:
|
||||
raise Http404(_(f"order {order_uuid} not found"))
|
||||
|
||||
|
|
|
|||
|
|
@ -625,7 +625,8 @@ class Order(NiceModel):
|
|||
return promocode.use(self)
|
||||
|
||||
def buy(
|
||||
self, force_balance: bool = False, force_payment: bool = False, promocode_uuid: str | None = None
|
||||
self, force_balance: bool = False, force_payment: bool = False, promocode_uuid: str | None = None,
|
||||
billing_address: str | None = None, shipping_address: str | None = None, **kwargs
|
||||
) -> Self | Transaction | None:
|
||||
if config.DISABLED_COMMERCE:
|
||||
raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes"))
|
||||
|
|
@ -633,6 +634,25 @@ class Order(NiceModel):
|
|||
if (not force_balance and not force_payment) or (force_balance and force_payment):
|
||||
raise ValueError(_("invalid force value"))
|
||||
|
||||
if not self.is_whole_digital and not any([shipping_address, billing_address]):
|
||||
raise ValueError(_("you can only buy physical products with shipping address specified"))
|
||||
|
||||
if shipping_address and not billing_address:
|
||||
shipping_address = Address.objects.get(uuid=shipping_address)
|
||||
billing_address = shipping_address
|
||||
|
||||
elif billing_address and not shipping_address:
|
||||
billing_address = Address.objects.get(uuid=billing_address)
|
||||
shipping_address = billing_address
|
||||
|
||||
else:
|
||||
billing_address = Address.objects.get(uuid=billing_address)
|
||||
shipping_address = Address.objects.get(uuid=shipping_address)
|
||||
|
||||
self.billing_address = billing_address
|
||||
self.shipping_address = shipping_address
|
||||
self.save()
|
||||
|
||||
if self.total_quantity < 1:
|
||||
raise ValueError(_("you cannot purchase an empty order!"))
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ class BuyOrderSerializer(Serializer):
|
|||
force_balance = BooleanField(required=False, default=False)
|
||||
force_payment = BooleanField(required=False, default=False)
|
||||
promocode_uuid = CharField(required=False)
|
||||
shipping_address_uuid = CharField(required=False)
|
||||
billing_address_uuid = CharField(required=False)
|
||||
|
||||
|
||||
class BuyUnregisteredOrderSerializer(Serializer):
|
||||
|
|
|
|||
|
|
@ -243,6 +243,8 @@ class OrderViewSet(EvibesViewSet):
|
|||
force_balance=serializer.validated_data.get("force_balance"),
|
||||
force_payment=serializer.validated_data.get("force_payment"),
|
||||
promocode_uuid=serializer.validated_data.get("promocode_uuid"),
|
||||
shipping_address=serializer.validated_data.get("shipping_address"),
|
||||
billing_address=serializer.validated_data.get("billing_address"),
|
||||
)
|
||||
match str(type(instance)):
|
||||
case "<class 'payments.models.Transaction'>":
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ Continent = load_model("geo", "Continent")
|
|||
Country = load_model("geo", "Country")
|
||||
City = load_model("geo", "City")
|
||||
|
||||
|
||||
# Only log errors during Travis tests
|
||||
LOGGER_NAME = os.environ.get("TRAVIS_LOGGER_NAME", "geo")
|
||||
|
||||
|
|
@ -198,9 +197,8 @@ class Command(BaseCommand):
|
|||
if not os.path.exists(self.data_dir):
|
||||
os.makedirs(self.data_dir)
|
||||
with open(os.path.join(self.data_dir, filename), "wb") as f:
|
||||
file = f
|
||||
file.write(web_file.read())
|
||||
file.close()
|
||||
f.write(web_file.read())
|
||||
f.close()
|
||||
elif not os.path.exists(os.path.join(self.data_dir, filename)):
|
||||
raise Exception(f"File not found and download failed: {filename} [{url}]")
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ class TokenVerifyView(TokenViewBase):
|
|||
serializer_class = TokenVerifySerializer
|
||||
_serializer_class = TokenVerifySerializer
|
||||
|
||||
@method_decorator(ratelimit(key="ip", rate="10/h" if not DEBUG else "888/h"))
|
||||
def post(self, request, *args, **kwargs):
|
||||
try:
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
|
|
|
|||
Loading…
Reference in a new issue