import os import csv import datetime # ============================================================================ # ۱. تنظیمات محیطی جنگو (بسیار مهم) # ============================================================================ # نام 'myproject' را با نام پوشه اصلی پروژه خود (که فایل settings.py در آنجاست) عوض کنید os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'khatibi.settings') import django django.setup() from django.db.models import Sum, Subquery, OuterRef, F, IntegerField from django.db.models.functions import Coalesce from admin_panel.models import Article, Sarresid, Customer # ============================================================================ # ۲. هسته اصلی محاسبات (الگوریتم پرسرعت با Subquery) # ============================================================================ def run_audit(): print("\n" + "="*65) print(" 🚀 در حال اسکن دیتابیس و اجرای عملیات مغایرت‌گیری هوشمند...") print("="*65 + "\n") # واکشی سریع مجموع بدهکاری مشتریان sq_debit = Article.objects.filter( customer=OuterRef('pk') ).values('customer').annotate(s=Sum('debit')).values('s') # واکشی سریع مجموع بستانکاری مشتریان sq_credit = Article.objects.filter( customer=OuterRef('pk') ).values('customer').annotate(s=Sum('credit')).values('s') # واکشی سریع مجموع اسناد (چک/نسیه) پرداخت‌نشده sq_sarresid = Sarresid.objects.filter( customer=OuterRef('pk'), payStatus="false" ).values('customer').annotate(s=Sum('price')).values('s') # پردازش نهایی در لایه دیتابیس (بدون نیاز به لود کردن دیتا در RAM سرور) base_customers = Customer.objects.filter(is_active=True).annotate( t_debit=Coalesce(Subquery(sq_debit, output_field=IntegerField()), 0), t_credit=Coalesce(Subquery(sq_credit, output_field=IntegerField()), 0), t_sarresid=Coalesce(Subquery(sq_sarresid, output_field=IntegerField()), 0), ).annotate( net_debt=F('t_debit') - F('t_credit') # تراز نهایی ).annotate( diff=F('net_debt') - F('t_sarresid') # اختلاف تراز و اسناد ) # استخراج گروه اول: بدهکاران مطلقاً بدون چک group1 = base_customers.filter(net_debt__gt=0, t_sarresid=0).order_by('-net_debt') # استخراج گروه دوم: دارای خطای چک اضافی در سیستم group2 = base_customers.filter(diff__lt=0, t_sarresid__gt=0).annotate( fake_amount=F('t_sarresid') - F('net_debt') ).order_by('-fake_amount') # ============================================================================ # ۳. نمایش گزارش در کنسول # ============================================================================ print(f"🔴 گروه اول: بدهکاران فاقد سند/چک (تعداد: {group1.count()})") print("-" * 65) for c in group1[:10]: # نمایش ۱۰ نفر اول در کنسول print(f"👤 {c.name_family} | موبایل: {c.phone1} | بدهی روی هوا: {c.net_debt:,} ریال") if group1.count() > 10: print(f" ... و {group1.count() - 10} نفر دیگر (لیست کامل در فایل خروجی)") print("\n" + f"🟡 گروه دوم: دارای خطای ثبت چک اضافه (تعداد: {group2.count()})") print("-" * 65) for c in group2[:10]: print(f"👤 {c.name_family} | تراز واقعی: {c.net_debt:,} | مبلغ چک تو سیستم: {c.t_sarresid:,} | ❌ چک اضافی: {c.fake_amount:,}") if group2.count() > 10: print(f" ... و {group2.count() - 10} نفر دیگر (لیست کامل در فایل خروجی)") # ============================================================================ # ۴. تولید فایل خروجی CSV برای حسابدار # ============================================================================ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"financial_audit_{timestamp}.csv" with open(filename, mode='w', newline='', encoding='utf-8-sig') as file: writer = csv.writer(file) # هدر فایل writer.writerow(["شناسه مشتری", "نام و نام خانوادگی", "شماره تماس", "گروه خطا", "شرح خطا", "تراز واقعی (Article)", "جمع اسناد در دست (Sarresid)", "مبلغ مغایرت"]) # نوشتن دیتای گروه اول for c in group1: writer.writerow([ c.id, c.name_family, c.phone1, "گروه 1 (خطرناک)", "بدهی دفتری باز - بدون چک یا موعد نسیه", c.net_debt, c.t_sarresid, c.diff ]) # نوشتن دیتای گروه دوم for c in group2: writer.writerow([ c.id, c.name_family, c.phone1, "گروه 2 (خطای ثبتی)", "چک پاس نشده در سیستم بیشتر از بدهی واقعی است", c.net_debt, c.t_sarresid, c.fake_amount ]) print("\n" + "="*65) print(f"✅ عملیات با موفقیت انجام شد. فایل گزارش تولید شد: {filename}") print("="*65 + "\n") if __name__ == '__main__': run_audit()