store transfer and panel anbar

This commit is contained in:
javad committed 2026-07-03 16:52:04 +03:30
1 parent bd775d6249
commit c5e9b1d18a
13 files changed
+2968 -190

No files matched your search

+1 -2
View File
@@ -47,7 +47,7 @@
</a>
{% endif %}
{% if not perms.admin_panel.ViewStore %}
{% if not perms.admin_panel.ViewStore %}
<a href="{% url 'admin_panel:ActionListUserToday' request.user.id %}" class="navbar-item">
اصلی
</a>
@@ -63,7 +63,6 @@
</a>
{% endif %}
<a href="{% url 'admin_panel:stores' %}" class="navbar-item">
انبار
</a>
@@ -96,16 +96,28 @@
<div id="storeData" class="column is-vcentered is-centered pt-0 is-12-mobile is-12-desktop">
<div class="tabs is-centered m-0">
<ul>
{% with url_name=request.resolver_match.url_name %}
<li class="{% if url_name == 'store' %}is-active{% endif %}"><a href="{% url 'admin_panel:store' s_id %}">موجودی</a></li>
<li class="{% if url_name == 'operations' %}is-active{% endif %}"><a href="{% url 'admin_panel:operations' s_id %}">دفترعملیات</a></li>
{% endwith %}
</ul>
</div>
<div class="tabs is-centered m-0">
<ul>
{% with url_name=request.resolver_match.url_name %}
<li class="{% if url_name == 'store' %}is-active{% endif %}">
<a href="{% url 'admin_panel:store' s_id %}">موجودی</a>
</li>
<li class="{% if url_name == 'operations' %}is-active{% endif %}">
<a href="{% url 'admin_panel:operations' s_id %}">دفترعملیات</a>
</li>
<li class="{% if url_name == 'store_transfers' %}is-active{% endif %}">
<a href="{% url 'admin_panel:store_transfers' s_id %}">
انتقال‌های انبار
{% if storeO.incoming_transfers.all|length > 0 %}
<span class="tag is-danger is-rounded is-small ml-1">!</span>
{% endif %}
</a>
</li>
{% endwith %}
</ul>
</div>
{% block storeBody %}
+88 -80
View File
@@ -3,86 +3,103 @@
{% 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 searchStatus %}{% else %}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>موجودی فیزیکی</th>
<th>در انتظار خروج (رزرو)</th>
<th>در انتظار ورود (در راه)</th>
<th style="min-width: 100px;">عملیات</th>
</tr>
</thead>
<tfoot>
<tr>
<th>نام محصول</th>
<th>قیمت</th>
<th>موجودی</th>
<th>موجودی فیزیکی</th>
<th>در انتظار خروج (رزرو)</th>
<th>در انتظار ورود (در راه)</th>
<th>عملیات</th>
</tr>
</tfoot>
<tbody>
{% for prd in productSum %}
<tr prd_id="{{ prd.id }}" class="openPrdEdit" p_cat="{{ prd.ProductCategory.id }}">
<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>
<td>
<a {% if perms.admin_panel.OnlyAnbar %}href="{% url 'admin_panel:operationProduct' s_id prd.id %}"{% endif %}>
<span class="product_name font-weight-bold">{{ prd.product_name }}</span>
</a>
</td>
<td class="product_price">{{ prd.product_price }} </td>
<td class="product_mojodi" >{{ prd.mojodi }}</td>
<td>
<td class="product_price">{{ prd.product_price }}</td>
<td class="product_mojodi has-text-weight-bold is-size-6">
{{ prd.mojodi }}
</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>
<td>
{% if prd.pending_out > 0 %}
<span class="tag is-warning is-medium" title="ارسال شده به انبار دیگر و منتظر تایید">
{{ prd.pending_out }} -
</span>
{% else %}
<span class="has-text-grey-light">0</span>
{% endif %}
</td>
<td>
{% if prd.pending_in > 0 %}
<span class="tag is-info is-medium" title="ارسال شده به این انبار و منتظر تایید شما">
{{ prd.pending_in }} +
</span>
{% else %}
<span class="has-text-grey-light">0</span>
{% endif %}
</td>
<td>
{% if perms.admin_panel.ViewStore or perms.admin_panel.OnlyAnbar %}
<span class="Oedit_prd" style="cursor: pointer;"><img style="width: 20px; height: 20px;" src="{% static 'admin_panel/icons/edit.png' %}"></span>
<span class="delet_prd" style="cursor: pointer;"><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>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
@@ -97,10 +114,8 @@
<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">
<section class="modal-card-body">
{% csrf_token %}
<input id="i_pcode" type="hidden" name="prd_code" value="">
<div id="userDT" class="is-hidden-mobile">
@@ -111,11 +126,9 @@
</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,7 +137,6 @@
{% endfor %}
</select>
</div>
</div>
</div>
@@ -134,51 +146,47 @@
<input id="Editproduct_price" required value="" 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>
{% if not mojodi %}
var mojodiVar = '';
{% else %}
var mojodiVar = {{ mojodi }};
{% endif %}
var objpname = null;
{% if not mojodi %}
var mojodiVar = '';
{% else %}
var mojodiVar = {{ mojodi }};
{% endif %}
var objpname = null;
$('#mojodi').val(mojodiVar);
$('#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 }}";
if (confirm("از حذف مطمئن هستید؟")) {
window.location.href = '/panel/product/del/' + prd_id + "/" + "{{ s_id }}";
}
});
$(".close_edit").click(function(){
$("#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 prd_id = $(this).parent().parent().attr("prd_id");
var p_cat = $(this).parent().parent().attr("p_cat");
objpname = $(this).parent().parent().find('.product_name');
$("#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($(this).parent().parent().find('.product_name').text().trim());
$("#Editproduct_price").val($(this).parent().parent().find('.product_price').text().trim());
$("#Editcategory").val(p_cat);
});
</script>
{% endblock %}
@@ -0,0 +1,224 @@
{% extends "./baseStore.html" %}
{% load custom_tags %}
{% load static %}
{% block storeBody %}
<div class="container is-fluid pt-3">
{% if messages %}
<div class="mb-4">
{% for message in messages %}
<div class="notification {% if message.tags == 'success' %}is-success{% elif message.tags == 'error' %}is-danger{% elif message.tags == 'warning' %}is-warning{% else %}is-info{% endif %} is-light">
<button class="delete"></button>
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
<div class="box mb-5 border-top-primary">
<h3 class="title is-5 has-text-primary mb-3">
📥 بارهای ورودی در انتظار تایید شما
<span class="tag is-primary is-rounded ml-2">{{ incoming_pending.count }}</span>
</h3>
{% if incoming_pending %}
<div class="table-container">
<table class="table is-bordered is-striped is-narrow is-fullwidth has-text-centered">
<thead class="has-background-light">
<tr>
<th>کد درخواست</th>
<th>کالا</th>
<th>تعداد</th>
<th>ارسال کننده (انبار مبدا)</th>
<th>کاربر ثبت‌کننده</th>
<th>زمان ارسال</th>
<th style="min-width: 180px;">اقدام انباردار</th>
</tr>
</thead>
<tbody>
{% for item in incoming_pending %}
<tr>
<td class="has-text-weight-bold">#{{ item.id }}</td>
<td class="has-text-weight-bold has-text-link">{{ item.product.product_name }}</td>
<td class="is-size-5 has-text-weight-bold has-text-success">{{ item.quantity }}</td>
<td>{{ item.source_store.store_name }}</td>
<td>{{ item.requester.first_name }} {{ item.requester.last_name }}</td>
<td dir="ltr">{{ item.created_at|toJalali }}</td>
<td>
<div class="buttons is-centered m-0">
<form action="{% url 'admin_panel:process_transfer_action' item.id %}" method="post" class="m-0" onsubmit="return confirm('آیا از تایید و ورود این کالا به انبار خود اطمینان دارید؟');">
{% csrf_token %}
<input type="hidden" name="action" value="approve">
<button type="submit" class="button is-success is-small ml-1">✓ تایید و دریافت</button>
</form>
<button type="button" class="button is-danger is-small btn-reject" data-id="{{ item.id }}" data-name="{{ item.product.product_name }}" data-qty="{{ item.quantity }}">
✕ رد بار
</button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="has-text-grey has-text-centered py-4">هیچ بار ورودی جدیدی در انتظار تایید شما نیست.</p>
{% endif %}
</div>
<div class="box mb-5">
<h3 class="title is-5 has-text-info mb-3">
📤 بارهای ارسالی شما (در انتظار تایید انبار مقصد)
<span class="tag is-info is-rounded ml-2">{{ outgoing_pending.count }}</span>
</h3>
{% if outgoing_pending %}
<div class="table-container">
<table class="table is-bordered is-striped is-narrow is-fullwidth has-text-centered">
<thead class="has-background-light">
<tr>
<th>کد درخواست</th>
<th>کالا</th>
<th>تعداد</th>
<th>انبار مقصد</th>
<th>زمان ارسال</th>
<th>توضیحات شما</th>
<th>وضعیت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
{% for item in outgoing_pending %}
<tr>
<td>#{{ item.id }}</td>
<td class="has-text-weight-bold">{{ item.product.product_name }}</td>
<td class="has-text-weight-bold">{{ item.quantity }}</td>
<td class="has-text-info has-text-weight-bold">{{ item.target_store.store_name }}</td>
<td dir="ltr">{{ item.created_at|toJalali }}</td>
<td>{{ item.desc|default:"-" }}</td>
<td><span class="tag is-warning">منتظر تحویل</span></td>
<td>
<form action="{% url 'admin_panel:process_transfer_action' item.id %}" method="post" class="m-0" onsubmit="return confirm('آیا قصد انصراف و بازگرداندن بار از مسیر انتقال را دارید؟');">
{% csrf_token %}
<input type="hidden" name="action" value="cancel">
<button type="submit" class="button is-warning is-small">↩ انصراف از ارسال</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="has-text-grey has-text-centered py-4">هیچ بار ارسالی معلقی ندارید.</p>
{% endif %}
</div>
<div class="box">
<h3 class="title is-6 has-text-grey-dark mb-3">🕒 تاریخچه ۵۰ انتقال اخیر انبار</h3>
<div class="table-container">
<table class="table is-bordered is-narrow is-fullwidth has-text-centered is-size-7">
<thead>
<tr>
<th>کد</th>
<th>کالا</th>
<th>تعداد</th>
<th>مبدا</th>
<th>مقصد</th>
<th>وضعیت</th>
<th>تعیین‌تکلیف کننده</th>
<th>زمان اقدام</th>
<th>توضیحات / دلیل رد</th>
</tr>
</thead>
<tbody>
{% for item in history_list %}
<tr>
<td>#{{ item.id }}</td>
<td class="has-text-weight-bold">{{ item.product.product_name }}</td>
<td>{{ item.quantity }}</td>
<td>{% if item.source_store_id == storeO.id %}<span class="tag is-light">انبار شما</span>{% else %}{{ item.source_store.store_name }}{% endif %}</td>
<td>{% if item.target_store_id == storeO.id %}<span class="tag is-light">انبار شما</span>{% else %}{{ item.target_store.store_name }}{% endif %}</td>
<td>
{% if item.status == 'APPROVED' %}
<span class="tag is-success is-light">✓ تایید و تحویل شد</span>
{% elif item.status == 'REJECTED' %}
<span class="tag is-danger is-light">✕ رد شد</span>
{% elif item.status == 'CANCELED' %}
<span class="tag is-warning is-light">انصراف مبدا</span>
{% endif %}
</td>
<td>{{ item.approver.first_name }} {{ item.approver.last_name }}</td>
<td dir="ltr">{{ item.action_date|toJalali|default:"-" }}</td>
<td class="has-text-right">{{ item.rejection_reason|default:item.desc|default:"-" }}</td>
</tr>
{% empty %}
<tr><td colspan="9" class="has-text-grey">هیچ تاریخچه‌ای یافت نشد.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div id="modal-reject" class="modal">
<div class="modal-background close-modal"></div>
<div class="modal-card">
<header class="modal-card-head has-background-danger-light">
<p class="modal-card-title has-text-danger-dark is-size-5">⚠️ اعلام دلیل رد دریافت بار</p>
<button class="delete close-modal" aria-label="close"></button>
</header>
<form id="form-reject" action="" method="post">
{% csrf_token %}
<input type="hidden" name="action" value="reject">
<section class="modal-card-body">
<p class="mb-3">شما در حال رد کردن ورود <strong id="modal-qty"></strong> عدد <strong id="modal-prd-name"></strong> به انبار خود هستید.</p>
<div class="field">
<label class="label">علت رد بار (الزام جهت اطلاع انبار مبدا): <span class="has-text-danger">*</span></label>
<div class="control">
<textarea name="reason" class="textarea" required placeholder="مثال: مغایرت در تعداد ارسالی / خرابی فیزیکی کالا / ارسال اشتباهی به این انبار..." rows="3"></textarea>
</div>
</div>
</section>
<footer class="modal-card-foot">
<button type="submit" class="button is-danger">تایید و رد بار</button>
<button type="button" class="button close-modal">انصراف</button>
</footer>
</form>
</div>
</div>
<script>
$(document).ready(function() {
// بستن پیام‌های هشدار
$('.notification .delete').click(function() {
$(this).parent().fadeOut();
});
// باز کردن مودال رد بار و تنظیم اطلاعات
$('.btn-reject').click(function() {
var id = $(this).data('id');
var name = $(this).data('name');
var qty = $(this).data('qty');
$('#modal-prd-name').text(name);
$('#modal-qty').text(qty);
// تنظیم اکشن فرم به آدرس مخصوص همین تراکنش
$('#form-reject').attr('action', '/panel/transfer/' + id + '/action/');
$('#modal-reject').addClass('is-active');
});
// بستن مودال
$('.close-modal').click(function() {
$('#modal-reject').removeClass('is-active');
$('#form-reject').find('textarea').val('');
});
});
</script>
{% endblock %}