add name kala anbar

This commit is contained in:
javad committed 2026-06-26 11:17:10 +03:30
1 parent 7a305b8e19
commit 767e84cbcf
2 files changed
+24 -16

No files matched your search

@@ -8,6 +8,13 @@
<form method="GET" class="columns is-multiline is-centered is-vcentered"> <form method="GET" class="columns is-multiline is-centered is-vcentered">
<div class="column is-2-desktop is-12-mobile">
<label class="label is-small">نام کالا (بخشی از نام)</label>
<div class="control">
<input type="text" name="product_name" class="input is-small" placeholder="مثلاً: لوله، فیلتر..." value="{{ filters.product_name }}">
</div>
</div>
<div class="column is-2-desktop is-12-mobile"> <div class="column is-2-desktop is-12-mobile">
<label class="label is-small">نوع تراکنش کالا</label> <label class="label is-small">نوع تراکنش کالا</label>
<div class="select is-fullwidth is-small"> <div class="select is-fullwidth is-small">
@@ -50,13 +57,13 @@
</div> </div>
</div> </div>
<div class="column is-2-desktop is-6-mobile"> <div class="column is-1-desktop is-6-mobile">
<label class="label is-small">از تاریخ</label> <label class="label is-small">از تاریخ</label>
<input type="text" class="input is-small date-picker-az pwt-datepicker-input-element" placeholder="انتخاب کنید"> <input type="text" class="input is-small date-picker-az pwt-datepicker-input-element" placeholder="انتخاب کنید">
<input type="hidden" name="azTarikh" id="azTarikhAlt" value="{{ filters.azTarikh }}"> <input type="hidden" name="azTarikh" id="azTarikhAlt" value="{{ filters.azTarikh }}">
</div> </div>
<div class="column is-2-desktop is-6-mobile"> <div class="column is-1-desktop is-6-mobile">
<label class="label is-small">تا تاریخ</label> <label class="label is-small">تا تاریخ</label>
<input type="text" class="input is-small date-picker-ta pwt-datepicker-input-element" placeholder="انتخاب کنید"> <input type="text" class="input is-small date-picker-ta pwt-datepicker-input-element" placeholder="انتخاب کنید">
<input type="hidden" name="taTarikh" id="taTarikhAlt" value="{{ filters.taTarikh }}"> <input type="hidden" name="taTarikh" id="taTarikhAlt" value="{{ filters.taTarikh }}">
@@ -153,11 +160,11 @@
{% if page_obj.has_other_pages %} {% if page_obj.has_other_pages %}
<nav class="pagination is-centered is-small my-4" role="navigation" aria-label="pagination"> <nav class="pagination is-centered is-small my-4" role="navigation" aria-label="pagination">
{% if page_obj.has_previous %} {% if page_obj.has_previous %}
<a class="pagination-previous" href="?page={{ page_obj.previous_page_number }}&movement_type={{ filters.movement_type }}&user_id={{ filters.user_id }}&store_id={{ filters.store_id }}&azTarikh={{ filters.azTarikh }}&taTarikh={{ filters.taTarikh }}">صفحه قبل</a> <a class="pagination-previous" href="?page={{ page_obj.previous_page_number }}&product_name={{ filters.product_name }}&movement_type={{ filters.movement_type }}&user_id={{ filters.user_id }}&store_id={{ filters.store_id }}&azTarikh={{ filters.azTarikh }}&taTarikh={{ filters.taTarikh }}">صفحه قبل</a>
{% endif %} {% endif %}
{% if page_obj.has_next %} {% if page_obj.has_next %}
<a class="pagination-next" href="?page={{ page_obj.next_page_number }}&movement_type={{ filters.movement_type }}&user_id={{ filters.user_id }}&store_id={{ filters.store_id }}&azTarikh={{ filters.azTarikh }}&taTarikh={{ filters.taTarikh }}">صفحه بعد</a> <a class="pagination-next" href="?page={{ page_obj.next_page_number }}&product_name={{ filters.product_name }}&movement_type={{ filters.movement_type }}&user_id={{ filters.user_id }}&store_id={{ filters.store_id }}&azTarikh={{ filters.azTarikh }}&taTarikh={{ filters.taTarikh }}">صفحه بعد</a>
{% endif %} {% endif %}
<ul class="pagination-list"> <ul class="pagination-list">
@@ -172,7 +179,6 @@
{% block jsEnd %} {% block jsEnd %}
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// تنظیم تقویم شمسی برای تاریخ شروع
var pickerAz = $(".date-picker-az").pDatepicker({ var pickerAz = $(".date-picker-az").pDatepicker({
altField: '#azTarikhAlt', altField: '#azTarikhAlt',
initialValue: false, initialValue: false,
@@ -181,7 +187,6 @@
calendar: { persian: { locale: 'fa' } } calendar: { persian: { locale: 'fa' } }
}); });
// تنظیم تقویم شمسی برای تاریخ پایان
var pickerTa = $(".date-picker-ta").pDatepicker({ var pickerTa = $(".date-picker-ta").pDatepicker({
altField: '#taTarikhAlt', altField: '#taTarikhAlt',
initialValue: false, initialValue: false,
@@ -190,7 +195,6 @@
calendar: { persian: { locale: 'fa' } } calendar: { persian: { locale: 'fa' } }
}); });
// لود کردن تاریخ‌های قبلی در صورت فیلتر بودن صفحه
{% if filters.azTarikh %} {% if filters.azTarikh %}
pickerAz.setDate({{ filters.azTarikh }}); pickerAz.setDate({{ filters.azTarikh }});
{% endif %} {% endif %}
+13 -9
View File
@@ -188,10 +188,9 @@ def report(request):
@permission_required('admin_panel.ViewReportMali', raise_exception=True) @permission_required('admin_panel.ViewReportMali', raise_exception=True)
def inventory_movements_report(request): def inventory_movements_report(request):
""" """
گزارش جامع گردش و خروج کالا از انبار به تفکیک نوع تراکنش (گارانتی، اشانتیون، فروش و...)، گزارش جامع گردش و خروج کالا از انبار به همراه فیلتر متنی نام کالا،
کاربر ثبت‌کننده، انبار و بازه زمانی شمسی. نوع تراکنش، کاربر، انبار و بازه زمانی شمسی.
""" """
# واکشی اطلاعات اولیه برای 드롭‌داون‌های فیلتر در قالب
all_users = User.objects.all().order_by('first_name') all_users = User.objects.all().order_by('first_name')
all_stores = StoreRoom.objects.all() all_stores = StoreRoom.objects.all()
movement_choices = ProductInStore.MovementType.choices movement_choices = ProductInStore.MovementType.choices
@@ -200,26 +199,30 @@ def inventory_movements_report(request):
selected_type = request.GET.get('movement_type', '') selected_type = request.GET.get('movement_type', '')
selected_user = request.GET.get('user_id', '') selected_user = request.GET.get('user_id', '')
selected_store = request.GET.get('store_id', '') selected_store = request.GET.get('store_id', '')
selected_product_name = request.GET.get('product_name', '').strip() # فیلد جدید جستجوی نام کالا
az_tarikh = request.GET.get('azTarikh', '') az_tarikh = request.GET.get('azTarikh', '')
ta_tarikh = request.GET.get('taTarikh', '') ta_tarikh = request.GET.get('taTarikh', '')
# ۱. کوئری پایه: اعمال select_related جهت جلوگیری از فاجعه N+1 در پایگاه داده # ۱. کوئری پایه بهینه
movements_list = ProductInStore.objects.select_related( movements_list = ProductInStore.objects.select_related(
'Product', 'StoreRoom', 'factor__customer', 'factor__user' 'Product', 'StoreRoom', 'factor__customer', 'factor__user'
).filter(year=1400).order_by('-createdDT') ).filter(year=1400).order_by('-createdDT')
# ۲. اعمال فیلترهای پویای کاربر # ۲. اعمال فیلترهای پویا
if selected_type: if selected_type:
movements_list = movements_list.filter(movement_type=selected_type) movements_list = movements_list.filter(movement_type=selected_type)
if selected_user: if selected_user:
# فیلتر بر اساس کاربری که فاکتور خروج کالا را در سیستم ثبت کرده است
movements_list = movements_list.filter(factor__user__id=_safe_int(selected_user)) movements_list = movements_list.filter(factor__user__id=_safe_int(selected_user))
if selected_store: if selected_store:
movements_list = movements_list.filter(StoreRoom__id=_safe_int(selected_store)) movements_list = movements_list.filter(StoreRoom__id=_safe_int(selected_store))
# ۳. پردازش بازه زمانی (تبدیل تایم‌استمپ جاوااسکریپت به تاریخ میلادی) if selected_product_name:
# فیلتر متنی حساس نبودن به حروف بزرگ و کوچک (Case-Insensitive Contains)
movements_list = movements_list.filter(Product__product_name__icontains=selected_product_name)
# ۳. پردازش بازه زمانی
if az_tarikh: if az_tarikh:
try: try:
az_dt = datetime.datetime.fromtimestamp(int(az_tarikh) / 1000.0) az_dt = datetime.datetime.fromtimestamp(int(az_tarikh) / 1000.0)
@@ -234,13 +237,13 @@ def inventory_movements_report(request):
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
# ۴. محاسبه آماری سریع روی نتایج فیلتر شده (بدون نیاز به پایش دستی در پایتون) # ۴. محاسبه آماری سریع دیتابیس روی نتایج فیلتر شده
summary_stats = movements_list.aggregate( summary_stats = movements_list.aggregate(
total_out_qty=Sum('s_out'), total_out_qty=Sum('s_out'),
total_in_qty=Sum('s_in') total_in_qty=Sum('s_in')
) )
# ۵. صفحه‌بندی نتایج (۵۰ رکورد در هر صفحه جهت حفظ سرعت لود مرورگر) # ۵. صفحه‌بندی نتایج
paginator = Paginator(movements_list, 50) paginator = Paginator(movements_list, 50)
page_number = request.GET.get('page') page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number) page_obj = paginator.get_page(page_number)
@@ -255,6 +258,7 @@ def inventory_movements_report(request):
'movement_type': selected_type, 'movement_type': selected_type,
'user_id': _safe_int(selected_user) if selected_user else '', 'user_id': _safe_int(selected_user) if selected_user else '',
'store_id': _safe_int(selected_store) if selected_store else '', 'store_id': _safe_int(selected_store) if selected_store else '',
'product_name': selected_product_name, # ارسال فیلد جدید به قالب برای حفظ مقدار ورودی
'azTarikh': az_tarikh, 'azTarikh': az_tarikh,
'taTarikh': ta_tarikh, 'taTarikh': ta_tarikh,
} }