add: akharin mojodi

This commit is contained in:
javad committed 2026-06-10 21:16:30 +03:30
1 parent 3b26ee3f93
commit 9eb1a9ef9b
2 files changed
+129 -102

No files matched your search

+81 -87
View File
@@ -3,46 +3,45 @@
{% load static %}
{% block storeBody %}
<p class="has-text-centered mt-2 mb-2 is-size-5 ">{{ storeO.store_name }}</p>
<p class="has-text-centered mt-2 mb-2 is-size-5">{{ storeO.store_name }}</p>
<form class="columns m-0 is-multiline is-mobile" method="post">
{% csrf_token %}
<div class="field column is-6-desktop is-6-mobile">
<div class="control ">
<input id="searchQS" value="{{ djsearchQS }}" name="searchQS" class="input is-fullwidth" type="text" placeholder="نام محصول">
</div>
</div>
<div class="field column is-3-desktop is-6-mobile">
<div class="control ">
<div class="select is-fullwidth">
<select id="mojodi" name="mojodi">
<option value="">وضعیت موجودی</option>
<option value="0">عدم موجودی</option>
<option value="1">نقطه سفارش</option>
</select>
<div class="field column is-6-desktop is-6-mobile">
<div class="control">
<input id="searchQS" value="{{ djsearchQS }}" name="searchQS" class="input is-fullwidth" type="text" placeholder="نام محصول">
</div>
</div>
</div>
<div class="field column is-3-desktop is-12-mobile">
<div class="control ">
<input type="submit" class="button is-link is-fullwidth" value="جستجو"/>
<div class="field column is-3-desktop is-6-mobile">
<div class="control">
<div class="select is-fullwidth">
<select id="mojodi" name="mojodi">
<option value="">وضعیت موجودی</option>
<option value="0">عدم موجودی</option>
<option value="1">نقطه سفارش</option>
</select>
</div>
</div>
</div>
</div>
</form>
<div class="field column is-3-desktop is-12-mobile">
<div class="control">
<input type="submit" class="button is-link is-fullwidth" value="جستجو"/>
</div>
</div>
</form>
<a class="button is-info mb-3 {% if searchStatus %} {% else %} is-hidden {% endif %}" href="{% url 'admin_panel:store' s_id %}">لغو جستجو و مشاهده همه</a>
<a class="button is-info mb-3 {% if not searchStatus %}is-hidden{% endif %}" href="{% url 'admin_panel:store' s_id %}">لغو جستجو و مشاهده همه</a>
<div class="table-container">
<table class="table m-auto has-text-centered table is-bordered is-striped is-narrow is-fullwidth mojodiTB ">
<table class="table m-auto has-text-centered table is-bordered is-striped is-narrow is-fullwidth mojodiTB">
<thead>
<tr>
<th style="min-width: 200px;">نام محصول</th>
<th>قیمت</th>
<th>موجودی</th>
<th style="min-width: 100px;">عملیات</th>
<th style="min-width: 100px;">عملیات</th>
</tr>
</thead>
<tfoot>
@@ -56,33 +55,28 @@
<tbody>
{% for prd in productSum %}
<tr prd_id="{{ prd.id }}" class="openPrdEdit" p_cat="{{ prd.ProductCategory.id }}">
<td >
<td>
<a {% if perms.admin_panel.ViewStore %}href="{% url 'admin_panel:operationProduct' s_id prd.id %}"{% endif %}>
<span class="product_name">{{ prd.product_name }}</span>
</a>
</a>
</td>
<td class="product_price">{{ prd.product_price }}</td>
<td class="product_mojodi">{{ prd.mojodi }}</td>
<td>
{% if perms.admin_panel.ViewStore %}
<span class="Oedit_prd" style="cursor: pointer; margin-left: 5px;">
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/edit.png' %}" alt="ویرایش">
</span>
<span class="delet_prd" style="cursor: pointer; margin-left: 5px;">
<img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/delet.png' %}" alt="حذف">
</span>
<a href="{% url 'admin_panel:newOperation' s_id prd.id %}">
<span><img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/add.png' %}" alt="تراکنش جدید"></span>
</a>
{% endif %}
</td>
<td class="product_price">{{ prd.product_price }} </td>
<td class="product_mojodi" >{{ prd.mojodi }}</td>
<td>
{% if perms.admin_panel.ViewStore %}
<span class="Oedit_prd"><img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/edit.png' %}"></span>
<span class="delet_prd"><img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/delet.png' %}"></span>
<a href="{% url 'admin_panel:newOperation' s_id prd.id %}">
<span><img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/add.png' %}"></span>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
@@ -97,25 +91,21 @@
<button class="delete close_edit" aria-label="close"></button>
</header>
<form action="{% url 'admin_panel:productEdit' %}" id="formcsEdit" class="has-background-white brad5" method="post">
<section class="modal-card-body">
{% csrf_token %}
{% csrf_token %}
<section class="modal-card-body">
<input id="i_pcode" type="hidden" name="prd_code" value="">
<div id="userDT" class="is-hidden-mobile">
<div id="userDT">
<div class="field column is-12-desktop is-12-mobile m-0">
<label class="label">نام کالا</label>
<div class="control">
<input id="EditnamePrd" required value="" name="namePrd" class="input an_name" type="text" placeholder="نام محصول">
<input id="EditnamePrd" required name="namePrd" class="input an_name" type="text" placeholder="نام محصول">
</div>
</div>
<div class="field column is-12-desktop is-12-mobile m-0">
<label class="label">دسته کالا</label>
<div class="control">
<div class="select is-fullwidth">
<select id="Editcategory" name="category" required>
<option value=""></option>
@@ -124,61 +114,65 @@
{% endfor %}
</select>
</div>
</div>
</div>
<div class="field column is-12-desktop is-12-mobile m-0">
<label class="label">قیمت کالا</label>
<div class="control">
<input id="Editproduct_price" required value="" name="price" class="input an_name" type="text" placeholder="قیمت">
<input id="Editproduct_price" required name="price" class="input an_name" type="text" placeholder="قیمت">
</div>
</div>
</div>
</section>
<footer class="modal-card-foot">
<input value="ذخیره" type="submit" class="button is-success">
<button class="button close_edit">لغو</button>
</footer>
</section>
<footer class="modal-card-foot">
<input value="ذخیره" type="submit" class="button is-success">
<button type="button" class="button close_edit">لغو</button>
</footer>
</form>
</div>
</div>
<script>
// مقداردهی اولیه به وضعیت فیلتر موجودی با امنیت بیشتر
var mojodiVar = "{{ mojodi }}";
if (mojodiVar !== '') {
$('#mojodi').val(mojodiVar);
}
{% if not mojodi %}
var mojodiVar = '';
{% else %}
var mojodiVar = {{ mojodi }};
{% endif %}
var objpname = null;
var objpname = null;
$('#mojodi').val( mojodiVar );
// عملیات حذف کالا
$(".delet_prd").click(function(){
var prd_id = $(this).parent().parent().attr('prd_id');
if ( confirm("از حذف مطمئن هستید؟") ){
window.location.href = '/panel/product/del/'+prd_id+"/"+"{{ s_id }}";
var prd_id = $(this).closest('tr').attr('prd_id');
if (confirm("از حذف مطمئن هستید؟")){
window.location.href = '/panel/product/del/' + prd_id + "/" + "{{ s_id }}";
}
});
$(".close_edit").click(function(){
// بستن مودال ویرایش
$(".close_edit").click(function(e){
e.preventDefault();
$("#edit_prd").removeClass('is-active');
});
// باز کردن مودال و مقداردهی فرم با داده‌های ردیف جاری
$(".Oedit_prd").click(function(){
$("#edit_prd").addClass('is-active');
prd_id = $(this).parent().parent().attr("prd_id");
p_cat = $(this).parent().parent().attr("p_cat");
objpname = $(this).parent().parent().find('.product_name')
//alert($(this).parent().parent().find('.product_name'))
var tr = $(this).closest('tr');
var prd_id = tr.attr("prd_id");
var p_cat = tr.attr("p_cat");
objpname = tr.find('.product_name');
// استفاده از .text().trim() جهت حذف فضاهای خالی احتمالی ایجاد شده توسط تگ‌های قالب‌بندی
var currentName = tr.find('.product_name').text().trim();
var currentPrice = tr.find('.product_price').text().trim();
$("#i_pcode").val(prd_id);
$("#EditnamePrd").val( $(this).parent().parent().find('.product_name').html() );
$("#Editproduct_price").val( $(this).parent().parent().find('.product_price').html() );
$("#Editcategory").val( p_cat );
$("#EditnamePrd").val(currentName);
$("#Editproduct_price").val(currentPrice);
$("#Editcategory").val(p_cat);
});
</script>
{% endblock %}
+48 -15
View File
@@ -1,4 +1,4 @@
from django.shortcuts import redirect, render
from django.shortcuts import redirect, render, get_object_or_404
from django.urls.base import reverse
from persiantools.jdatetime import JalaliDate
from persiantools import characters, digits
@@ -13,9 +13,8 @@ from django.db.models import Count, Sum
from django.contrib.auth.models import Permission, User
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404
from django.db.models import Q
from django.db.models.functions import Coalesce
from django.db.models import Q, OuterRef, Subquery, Exists
from .models import *
@@ -578,20 +577,54 @@ def store(request, s_id):
productCategory = ProductCategory.objects.all()
storeO = StoreRoom.objects.get(id=s_id)
searchStatus = False
searchQS = request.POST.get('searchQS', '')
# استفاده از .strip() برای پاک‌سازی فضاهای خالی احتمالی
searchQS = request.POST.get('searchQS', '').strip()
mojodi = request.POST.get('mojodi', '')
#return HttpResponse(mojodi)
if searchQS !='':
productSum = Product.objects.filter(productinstore__StoreRoom=storeO ,productinstore__year=1400,product_name__contains=searchQS).annotate(mojodi=( Sum('productinstore__s_in') - Sum('productinstore__s_out') ))
if mojodi == "0":
productSum = productSum.filter(mojodi__lte=0)
# ۱. ساب‌کوئری برای دریافت آخرین موجودی در لحظه تراکنش
# اضافه کردن '-id' به عنوان کلید دوم برای مواقعی که زمان‌ها دقیقاً برابرند
latest_stock_subquery = ProductInStore.objects.filter(
StoreRoom=storeO,
Product=OuterRef('pk'),
year=1400
).order_by('-createdDT', '-id').values('current_stock_at_time')[:1]
# ۲. کوئری اصلی بهینه‌سازی شده با Exists (بدون JOIN سنگین و بدون نیاز به distinct)
products_qs = Product.objects.filter(
Exists(
ProductInStore.objects.filter(
StoreRoom=storeO,
Product=OuterRef('pk'),
year=1400
)
)
).annotate(
# اگر ساب‌کوئری NULL بود، به صورت پیش‌فرض مقدار 0 قرار داده می‌شود
mojodi=Coalesce(Subquery(latest_stock_subquery), 0)
)
# ۳. اعمال فیلتر جستجوی نام محصول
if searchQS != '':
productSum = products_qs.filter(product_name__contains=searchQS)
searchStatus = True
else:
productSum = Product.objects.filter(productinstore__StoreRoom=storeO ,productinstore__year=1400).annotate(mojodi=( Sum('productinstore__s_in') - Sum('productinstore__s_out') ))
if mojodi == "0":
searchStatus = True
productSum = productSum.filter(mojodi__lte=0)
data = {'storeO': storeO,'productSum': productSum, 's_id': s_id, 'searchStatus': searchStatus, "mojodi": mojodi, 'djsearchQS':searchQS, 'productCategory': productCategory}
productSum = products_qs
# ۴. فیلتر وضعیت موجودی (حالا با خیال راحت روی عدد 0 فیلتر می‌شود)
if mojodi == "0":
productSum = productSum.filter(mojodi__lte=0)
searchStatus = True
data = {
'storeO': storeO,
'productSum': productSum,
's_id': s_id,
'searchStatus': searchStatus,
"mojodi": mojodi,
'djsearchQS': searchQS,
'productCategory': productCategory
}
return render(request, 'admin_panel/store.html', data)
@login_required(login_url='/panel/p_login/')