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