fix update bank status
This commit is contained in:
+55
-22
@@ -10,45 +10,78 @@ from account.models import PushSubscription
|
|||||||
import ghasedak_sms
|
import ghasedak_sms
|
||||||
from product.models import ProductImageModel
|
from product.models import ProductImageModel
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def udpate_bank_status():
|
def udpate_bank_status():
|
||||||
factory = bankfactories.BankFactory()
|
factory = bankfactories.BankFactory()
|
||||||
|
|
||||||
bank_models.Bank.objects.update_expire_records()
|
# ۱. بروزرسانی رکوردهای منقضی در یک تراکنش جداگانه
|
||||||
|
try:
|
||||||
|
with transaction.atomic():
|
||||||
|
bank_models.Bank.objects.update_expire_records()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error in update_expire_records: {e}")
|
||||||
|
|
||||||
|
# ۲. پردازش رکوردهایی که از بانک برگشتهاند
|
||||||
for item in bank_models.Bank.objects.filter_return_from_bank():
|
for item in bank_models.Bank.objects.filter_return_from_bank():
|
||||||
bank = factory.create(
|
try:
|
||||||
bank_type=item.bank_type, identifier=item.bank_choose_identifier
|
with transaction.atomic():
|
||||||
)
|
bank = factory.create(
|
||||||
bank.verify(item.tracking_code)
|
bank_type=item.bank_type, identifier=item.bank_choose_identifier
|
||||||
bank_record = bank_models.Bank.objects.get(tracking_code=item.tracking_code)
|
)
|
||||||
if bank_record.is_success and bank_record.order:
|
bank.verify(item.tracking_code)
|
||||||
bank_record.order.cart.clear_cart()
|
# استفاده از select_for_update برای جلوگیری از Race Condition
|
||||||
bank_record.order.is_paid = True
|
bank_record = bank_models.Bank.objects.select_related('order').select_for_update().get(tracking_code=item.tracking_code)
|
||||||
bank_record.order.save()
|
|
||||||
logging.debug("This record is verify now.", extra={"pk": bank_record.pk})
|
if bank_record.is_success and bank_record.order:
|
||||||
elif bank_record.order:
|
bank_record.order.cart.clear_cart()
|
||||||
order = bank_record.order
|
bank_record.order.is_paid = True
|
||||||
order.rollback_stock()
|
bank_record.order.save(update_fields=['is_paid'])
|
||||||
|
elif bank_record.order:
|
||||||
|
bank_record.order.rollback_stock()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to verify bank record {item.tracking_code}: {e}")
|
||||||
|
|
||||||
failed_statuses = [
|
failed_statuses = [
|
||||||
PaymentStatus.CANCEL_BY_USER,
|
PaymentStatus.CANCEL_BY_USER,
|
||||||
PaymentStatus.EXPIRE_GATEWAY_TOKEN,
|
PaymentStatus.EXPIRE_GATEWAY_TOKEN,
|
||||||
PaymentStatus.EXPIRE_VERIFY_PAYMENT,
|
PaymentStatus.EXPIRE_VERIFY_PAYMENT,
|
||||||
PaymentStatus.ERROR,
|
PaymentStatus.ERROR,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# 1. ابتدا رکوردهای بانکی را بدون select_related پیدا کنید
|
||||||
|
# از select_for_update اینجا استفاده نکنید چون به Order وصل است
|
||||||
failed_records = bank_models.Bank.objects.filter(
|
failed_records = bank_models.Bank.objects.filter(
|
||||||
status__in=failed_statuses,
|
status__in=failed_statuses,
|
||||||
order__isnull=False,
|
order__isnull=False,
|
||||||
order__is_paid=False,
|
order__is_paid=False,
|
||||||
order__is_stock_rolled_back=False,
|
order__is_stock_rolled_back=False,
|
||||||
).select_related('order')
|
)
|
||||||
|
|
||||||
|
logger.info(f"Found {failed_records.count()} failed records for rollback.")
|
||||||
|
|
||||||
for bank_record in failed_records:
|
for bank_record in failed_records:
|
||||||
bank_record.order.rollback_stock()
|
try:
|
||||||
|
# استفاده از تراکنش اتمیک برای هر رکورد
|
||||||
|
with transaction.atomic():
|
||||||
|
# 2. حالا خودِ Order مربوطه را با select_for_update قفل کنید
|
||||||
|
# این کار مانع از تداخل با بقیه تسکها میشود
|
||||||
|
order = bank_record.order
|
||||||
|
|
||||||
|
# بررسی مجدد شرط برای اطمینان در لحظه قفل شدن
|
||||||
|
if order and not order.is_paid and not order.is_stock_rolled_back:
|
||||||
|
order.rollback_stock()
|
||||||
|
logger.info(f"Successfully rolled back stock for bank record {bank_record.id}")
|
||||||
|
else:
|
||||||
|
logger.info(f"Order {order.id} already processed or paid, skipping.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to rollback stock for bank record {bank_record.id}: {str(e)}")
|
||||||
|
|
||||||
return 'update bank record is done'
|
return "update bank record is done"
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
|
|||||||
Reference in New Issue
Block a user