fix update bank status
This commit is contained in:
+41
-8
@@ -10,27 +10,40 @@ from account.models import PushSubscription
|
||||
import ghasedak_sms
|
||||
from product.models import ProductImageModel
|
||||
from celery import shared_task
|
||||
from django.db import transaction
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@shared_task
|
||||
def udpate_bank_status():
|
||||
factory = bankfactories.BankFactory()
|
||||
|
||||
# ۱. بروزرسانی رکوردهای منقضی در یک تراکنش جداگانه
|
||||
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():
|
||||
try:
|
||||
with transaction.atomic():
|
||||
bank = factory.create(
|
||||
bank_type=item.bank_type, identifier=item.bank_choose_identifier
|
||||
)
|
||||
bank.verify(item.tracking_code)
|
||||
bank_record = bank_models.Bank.objects.get(tracking_code=item.tracking_code)
|
||||
# استفاده از select_for_update برای جلوگیری از Race Condition
|
||||
bank_record = bank_models.Bank.objects.select_related('order').select_for_update().get(tracking_code=item.tracking_code)
|
||||
|
||||
if bank_record.is_success and bank_record.order:
|
||||
bank_record.order.cart.clear_cart()
|
||||
bank_record.order.is_paid = True
|
||||
bank_record.order.save()
|
||||
logging.debug("This record is verify now.", extra={"pk": bank_record.pk})
|
||||
bank_record.order.save(update_fields=['is_paid'])
|
||||
elif bank_record.order:
|
||||
order = bank_record.order
|
||||
order.rollback_stock()
|
||||
bank_record.order.rollback_stock()
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to verify bank record {item.tracking_code}: {e}")
|
||||
|
||||
failed_statuses = [
|
||||
PaymentStatus.CANCEL_BY_USER,
|
||||
@@ -38,17 +51,37 @@ def udpate_bank_status():
|
||||
PaymentStatus.EXPIRE_VERIFY_PAYMENT,
|
||||
PaymentStatus.ERROR,
|
||||
]
|
||||
|
||||
# 1. ابتدا رکوردهای بانکی را بدون select_related پیدا کنید
|
||||
# از select_for_update اینجا استفاده نکنید چون به Order وصل است
|
||||
failed_records = bank_models.Bank.objects.filter(
|
||||
status__in=failed_statuses,
|
||||
order__isnull=False,
|
||||
order__is_paid=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:
|
||||
bank_record.order.rollback_stock()
|
||||
try:
|
||||
# استفاده از تراکنش اتمیک برای هر رکورد
|
||||
with transaction.atomic():
|
||||
# 2. حالا خودِ Order مربوطه را با select_for_update قفل کنید
|
||||
# این کار مانع از تداخل با بقیه تسکها میشود
|
||||
order = bank_record.order
|
||||
|
||||
return 'update bank record is done'
|
||||
# بررسی مجدد شرط برای اطمینان در لحظه قفل شدن
|
||||
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"
|
||||
|
||||
|
||||
@shared_task
|
||||
|
||||
Reference in New Issue
Block a user