fix sabtfactor

This commit is contained in:
javad committed 2026-06-24 00:44:50 +03:30
1 parent 339f909018
commit bf78bc2520
1 file changed
+16 -22
+16 -22
View File
@@ -951,7 +951,6 @@ def newFactor(request, c_id):
return redirect('/panel/customer/'+str(c_id)+'/factors/')
@login_required(login_url='/panel/p_login/')
def newFactor2(request, c_id):
if request.method != 'POST':
@@ -959,7 +958,6 @@ def newFactor2(request, c_id):
user_op = request.user
# ۱. پارس داده‌های JSON ارسال شده از فرم (پشتیبانی کامل از ساختار paylist و orderList جاوااسکریپت)
try:
prds_list = json.loads(request.POST.get('prdsList') or '[]')
json_pardakht_ha = json.loads(request.POST.get('PardakhtHa') or '{}')
@@ -970,15 +968,18 @@ def newFactor2(request, c_id):
factor_desc = request.POST.get('FactorDesc', '')
sar_resid_date = _parse_jalali_date(request.POST.get('sarResidDate'))
# ۲. واکشی اطلاعات پایه‌ای
customer_obj = get_object_or_404(Customer, id=c_id)
store_room = get_object_or_404(StoreRoom, user=user_op)
# ۳. واکشی دسته‌جمعی محصولات برای جلوگیری از فشار به دیتابیس
product_ids = [item.get('prd_id') for item in prds_list if item.get('prd_id') and item.get('prd_id') != 9999]
# رفع مشکل متنی/عددی در استخراج شناسه کالاها
product_ids = []
for item in prds_list:
p_id = item.get('prd_id')
if p_id and _safe_int(p_id) != 9999:
product_ids.append(_safe_int(p_id))
products_by_id = {p.id: p for p in Product.objects.filter(id__in=product_ids)}
# ۴. محاسبه مبلغ کل با نادیده گرفتن محصولاتی که گارانتی/اشانتیون هستند
sum_price = sum(
_safe_int(item.get('prd_count')) * _safe_int(item.get('price'))
for item in prds_list
@@ -986,10 +987,8 @@ def newFactor2(request, c_id):
)
try:
# ۵. باز کردن یک تراکنش امن دیتابیس
with transaction.atomic():
# ثبت آبجکت فاکتور
new_factor = Factor.objects.create(
customer=customer_obj,
amount=sum_price,
@@ -999,7 +998,6 @@ def newFactor2(request, c_id):
user=user_op
)
# ثبت بدهکاری کلی در سند حسابداری
Article.objects.create(
debit=sum_price,
credit=0,
@@ -1009,7 +1007,6 @@ def newFactor2(request, c_id):
user=user_op
)
# ثبت ریزپرداختی‌ها بر اساس دیکشنری paylist جاوااسکریپت
payment_map = {
'l_naghd': 'نقد',
'l_kartbekart': 'کارت به کارت',
@@ -1035,7 +1032,6 @@ def newFactor2(request, c_id):
user=user_op
)
# ثبت اسناد چک و نسیه
elif key in ['l_nesiye', 'l_checkPrice']:
is_nesiye = (key == 'l_nesiye')
type_str = 'nesiye' if is_nesiye else 'check'
@@ -1053,12 +1049,12 @@ def newFactor2(request, c_id):
sarresidDT=sar_resid_dt
)
# ثبت آیتم‌های فاکتور با کارایی بالا (املای کلاس FactorIteam دقیقا منطبق بر models.py)
factor_items_pool = []
user_fullname = f"{user_op.first_name} {user_op.last_name}".strip() or user_op.username
for item in prds_list:
prd_id = item.get('prd_id')
# تبدیل امن شناسه به عدد در همینجا برای جلوگیری از خطای یافت نشدن دیکشنری
prd_id = _safe_int(item.get('prd_id'))
prd_count = _safe_int(item.get('prd_count'))
garanty_esh = item.get('garanty_Esh', '')
@@ -1073,8 +1069,10 @@ def newFactor2(request, c_id):
))
else:
product_obj = products_by_id.get(prd_id)
# خطای کاربرپسند در صورت نبود محصول
if not product_obj:
raise ValidationError(f"محصولی با شناسه {prd_id} یافت نشد.")
raise InventoryException(f"خطا در دریافت محصول: محصولی با شناسه {prd_id} در سیستم وجود ندارد.")
factor_items_pool.append(FactorIteam(
factor=new_factor,
@@ -1085,12 +1083,10 @@ def newFactor2(request, c_id):
garantyEsh=garanty_esh
))
# ثبت یکباره تمام آیتم‌ها
FactorIteam.objects.bulk_create(factor_items_pool, batch_size=500)
# چک کردن موجودی انبار و ثبت کسر کالا
for item in prds_list:
prd_id = item.get('prd_id')
prd_id = _safe_int(item.get('prd_id'))
if prd_id == 9999:
continue
@@ -1098,7 +1094,9 @@ def newFactor2(request, c_id):
garanty_esh = item.get('garanty_Esh', '')
product_obj = products_by_id.get(prd_id)
# قفل کردن ردیف برای اطمینان ۱۰۰ درصدی از عدم تداخل پیش از متد Save مدل
if not product_obj:
continue
stock_records = ProductInStore.objects.select_for_update().filter(
Product=product_obj,
StoreRoom=store_room,
@@ -1119,8 +1117,6 @@ def newFactor2(request, c_id):
else:
desc_text = f"خروج: {prd_count}#فروش#{customer_obj.name_family} * {user_fullname}"
# این خط به‌طور خودکار متد حرفه‌ای Save شما در models.py را فراخوانی می‌کند
# و جداول تاریخچه انبارداری را نیز بروزرسانی می‌نماید
ProductInStore.objects.create(
StoreRoom=store_room,
Product=product_obj,
@@ -1131,13 +1127,11 @@ def newFactor2(request, c_id):
)
except InventoryException as e:
# اگر خطا دهد دیتابیس Rollback می‌شود و فرم در قالب همان پیغام HTML به کاربر برمی‌گردد
return HttpResponse(str(e), status=400)
except Exception as e:
logger.error(f"Error creating factor for customer {c_id}: {str(e)}", exc_info=True)
return HttpResponse("خطایی غیرمنتظره در سرور رخ داد. اطلاعات ذخیره نشد.", status=500)
# بازگشت موفقیت‌آمیز دقیقاً به همان آدرس فایل urls.py
return redirect(f'/panel/customer/{c_id}/factors/')
@login_required(login_url='/panel/p_login/')