Update project
This commit is contained in:
@@ -98,13 +98,24 @@ class RedeemDiscountView(APIView):
|
||||
if discount.redemptions.filter(user_id=request.user.id).exists():
|
||||
raise ValidationError({'code': 'شما قبلاً این کد را استفاده کردهاید.'})
|
||||
|
||||
# فقط سفارشهای در انتظار پرداخت میتونن تخفیف بگیرن؛ سفارش
|
||||
# پرداختشده/ناموفق نباید عقبگرد تغییر کنه.
|
||||
if order.status != 'pending':
|
||||
raise ValidationError({'code': 'این سفارش دیگر قابل اعمال تخفیف نیست.'})
|
||||
|
||||
# ⚛️🔒 اصلاح race condition: قبلاً چکِ «order.status != 'pending'»
|
||||
# روی همون آبجکتِ order ای انجام میشد که *قبل* از ورود به این
|
||||
# atomic block و *بدون* قفل خونده شده بود (چند خط بالاتر، برای
|
||||
# چکِ مالکیت). یعنی اگه بینِ اون خواندنِ اولیه و این چک، یک
|
||||
# webhookِ پرداختِ همزمان روی همون سفارش paid میشد (که خودش با
|
||||
# select_for_update قفل میگیره)، این ویو همچنان مقدارِ
|
||||
# cached/قدیمیِ status='pending' رو میدید و اجازه میداد مبلغِ
|
||||
# یک سفارشِ *پرداختشده* بعد از پرداخت واقعی کم بشه — دقیقاً
|
||||
# همون کلاسِ باگی که apply_order_payment_result در
|
||||
# payment/services.py با قفلگرفتن *قبل* از چکِ already_paid
|
||||
# حلش کرده. حالا سفارش اول قفل میشه (select_for_update) و
|
||||
# چکِ pending بودن *بعد* از قفل، روی خودِ ردیفِ قفلشده
|
||||
# (order_locked) انجام میشه.
|
||||
order_locked = Order.objects.select_for_update().get(pk=order.id)
|
||||
|
||||
if order_locked.status != 'pending':
|
||||
raise ValidationError({'code': 'این سفارش دیگر قابل اعمال تخفیف نیست.'})
|
||||
|
||||
if discount.type == 'percent':
|
||||
discount_amount = order_locked.amount * discount.value // 100
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user