268 lines
12 KiB
HTML
268 lines
12 KiB
HTML
{% extends '_base.html' %}
|
|
{% load static %}
|
|
{% load processes_tags %}
|
|
{% load humanize %}
|
|
|
|
{% block sidebar %}
|
|
{% include 'sidebars/admin.html' %}
|
|
{% endblock sidebar %}
|
|
|
|
{% block navbar %}
|
|
{% include 'navbars/admin.html' %}
|
|
{% endblock navbar %}
|
|
|
|
{% block title %}{{ step.name }} - درخواست {{ instance.code }}{% endblock %}
|
|
|
|
{% block style %}
|
|
<link rel="stylesheet" href="{% static 'assets/vendor/libs/bs-stepper/bs-stepper.css' %}">
|
|
<style>
|
|
@media print {
|
|
.no-print { display: none !important; }
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include '_toasts.html' %}
|
|
{% csrf_token %}
|
|
<div class="container-xxl flex-grow-1 container-p-y">
|
|
<div class="row">
|
|
<div class="col-12 mb-4">
|
|
<div class="d-flex align-items-center justify-content-between mb-3 no-print">
|
|
<div>
|
|
<h4 class="mb-1">{{ step.name }}: {{ instance.process.name }}</h4>
|
|
<small class="text-muted d-block">
|
|
اشتراک آب: {{ instance.well.water_subscription_number|default:"-" }}
|
|
| نماینده: {{ instance.representative.profile.national_code|default:"-" }}
|
|
</small>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<a href="{% url 'invoices:final_invoice_print' instance.id %}" target="_blank" class="btn btn-outline-secondary"><i class="bx bx-printer"></i> پرینت</a>
|
|
|
|
<a href="{% url 'processes:request_list' %}" class="btn btn-outline-secondary">بازگشت</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bs-stepper wizard-vertical vertical mt-2 no-print">
|
|
{% stepper_header instance step %}
|
|
<div class="bs-stepper-content">
|
|
|
|
<div class="card border">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">فاکتور نهایی</h5>
|
|
{% if is_manager %}
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="openSpecialChargeModal()"><i class="bx bx-plus"></i> افزودن هزینه تعمیر/تعویض</button>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-6 col-md-3">
|
|
<div class="border rounded p-3 h-100">
|
|
<div class="small text-muted">مبلغ نهایی</div>
|
|
<div class="h5 mt-1">{{ invoice.final_amount|floatformat:0|intcomma:False }} تومان</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6 col-md-3">
|
|
<div class="border rounded p-3 h-100">
|
|
<div class="small text-muted">پرداختیها</div>
|
|
<div class="h5 mt-1 text-success">{{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6 col-md-3">
|
|
<div class="border rounded p-3 h-100">
|
|
<div class="small text-muted">مانده</div>
|
|
<div class="h5 mt-1 {% if invoice.remaining_amount <= 0 %}text-success{% else %}text-danger{% endif %}">{{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6 col-md-3 d-flex align-items-center">
|
|
{% if invoice.remaining_amount <= 0 %}
|
|
<span class="badge bg-success">تسویه کامل</span>
|
|
{% else %}
|
|
<span class="badge bg-warning text-dark">باقیمانده دارد</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>آیتم</th>
|
|
<th class="text-center">تعداد پایه</th>
|
|
<th class="text-center">افزوده</th>
|
|
<th class="text-center">حذف</th>
|
|
<th class="text-center">تعداد نهایی</th>
|
|
<th class="text-end">قیمت واحد (تومان)</th>
|
|
<th class="text-end">قیمت کل (تومان)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for r in rows %}
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex flex-column">
|
|
<span class="fw-semibold">{{ r.item.name }}</span>
|
|
{% if r.item.description %}<small class="text-muted">{{ r.item.description }}</small>{% endif %}
|
|
</div>
|
|
</td>
|
|
<td class="text-center">{{ r.base_qty }}</td>
|
|
<td class="text-center text-success">{{ r.added_qty }}</td>
|
|
<td class="text-center text-danger">{{ r.removed_qty }}</td>
|
|
<td class="text-center">{{ r.quantity }}</td>
|
|
<td class="text-end">{{ r.unit_price|floatformat:0|intcomma:False }}</td>
|
|
<td class="text-end">{{ r.total_price|floatformat:0|intcomma:False }}</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr><td colspan="7" class="text-center text-muted">آیتمی یافت نشد</td></tr>
|
|
{% endfor %}
|
|
{% for si in invoice_specials %}
|
|
<tr class="table-warning">
|
|
<td>
|
|
<div class="d-flex flex-column">
|
|
<span class="fw-semibold">{{ si.item.name }}<span class="badge bg-info mx-2">ویژه</span></span>
|
|
</div>
|
|
</td>
|
|
<td class="text-center">-</td>
|
|
<td class="text-center">-</td>
|
|
<td class="text-center">-</td>
|
|
<td class="text-center">{{ si.quantity }}</td>
|
|
<td class="text-end">{{ si.unit_price|floatformat:0|intcomma:False }}</td>
|
|
<td class="text-end">
|
|
{{ si.total_price|floatformat:0|intcomma:False }}
|
|
{% if is_manager %}
|
|
<button type="button" class="btn btn-sm btn-outline-danger ms-2" onclick="deleteSpecial('{{ si.id }}')" title="حذف"><i class="bx bx-trash"></i></button>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<th colspan="6" class="text-end">مبلغ کل</th>
|
|
<th class="text-end">{{ invoice.total_amount|floatformat:0|intcomma:False }} تومان</th>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="6" class="text-end">تخفیف</th>
|
|
<th class="text-end">{{ invoice.discount_amount|floatformat:0|intcomma:False }} تومان</th>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="6" class="text-end">مبلغ نهایی</th>
|
|
<th class="text-end">{{ invoice.final_amount|floatformat:0|intcomma:False }} تومان</th>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="6" class="text-end">پرداختیها</th>
|
|
<th class="text-end">{{ invoice.paid_amount|floatformat:0|intcomma:False }} تومان</th>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="6" class="text-end">مانده</th>
|
|
<th class="text-end {% if invoice.remaining_amount <= 0 %}text-success{% else %}text-danger{% endif %}">{{ invoice.remaining_amount|floatformat:0|intcomma:False }} تومان</th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer d-flex justify-content-between">
|
|
{% if previous_step %}
|
|
<a href="{% url 'processes:step_detail' instance.id previous_step.id %}" class="btn btn-label-secondary">قبلی</a>
|
|
{% else %}
|
|
<span></span>
|
|
{% endif %}
|
|
{% if next_step %}
|
|
{% if is_manager %}
|
|
<button type="button" class="btn btn-primary" id="btnApproveFinalInvoice">تایید و ادامه</button>
|
|
{% else %}
|
|
<a href="{% url 'processes:step_detail' instance.id next_step.id %}" class="btn btn-primary">بعدی</a>
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Special Charge Modal -->
|
|
<div class="modal fade" id="specialChargeModal" tabindex="-1" aria-labelledby="specialChargeModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="specialChargeModalLabel">افزودن هزینه تعمیر/تعویض</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="specialChargeForm" onsubmit="return false;">
|
|
{% csrf_token %}
|
|
<div class="mb-3">
|
|
<label class="form-label">انتخاب آیتم ویژه</label>
|
|
<select class="form-select" name="item_id" id="id_special_item" required>
|
|
<option value="">انتخاب کنید...</option>
|
|
{% for s in special_choices %}
|
|
<option value="{{ s.id }}">{{ s.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">مبلغ (تومان)</label>
|
|
<input type="number" class="form-control" name="amount" id="id_charge_amount" min="1" required>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">انصراف</button>
|
|
<button type="button" class="btn btn-primary" onclick="submitSpecialCharge()">افزودن</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block script %}
|
|
<script>
|
|
function openSpecialChargeModal(){
|
|
const el = document.getElementById('specialChargeModal');
|
|
if (window.$ && typeof $(el).modal === 'function') { $(el).modal('show'); }
|
|
else if (window.bootstrap && window.bootstrap.Modal) { new window.bootstrap.Modal(el).show(); }
|
|
else { el.classList.add('show'); el.style.display = 'block'; }
|
|
}
|
|
function submitSpecialCharge(){
|
|
const fd = new FormData(document.getElementById('specialChargeForm'));
|
|
fd.append('csrfmiddlewaretoken', document.querySelector('input[name=csrfmiddlewaretoken]').value);
|
|
fetch('{% url "invoices:add_special_charge" instance.id step.id %}', { method: 'POST', body: fd })
|
|
.then(r=>r.json()).then(resp=>{
|
|
if (resp.success){
|
|
showToast('هزینه ویژه اضافه شد', 'success');
|
|
if (resp.redirect) setTimeout(()=>{ window.location.href = resp.redirect; }, 600);
|
|
} else {
|
|
showToast(resp.message || 'خطا در افزودن هزینه', 'danger');
|
|
}
|
|
}).catch(()=> showToast('خطا در ارتباط با سرور', 'danger'));
|
|
}
|
|
// No filtering needed; show all special items
|
|
function deleteSpecial(id){
|
|
const fd = new FormData();
|
|
fd.append('csrfmiddlewaretoken', document.querySelector('input[name=csrfmiddlewaretoken]').value);
|
|
fetch(`{% url "invoices:delete_special_charge" instance.id step.id 0 %}`.replace('/0/', `/${id}/`), { method: 'POST', body: fd })
|
|
.then(r=>r.json()).then(resp=>{
|
|
if (resp.success){
|
|
showToast('حذف شد', 'success');
|
|
if (resp.redirect) setTimeout(()=>{ window.location.href = resp.redirect; }, 500);
|
|
} else {
|
|
showToast(resp.message || 'خطا در حذف', 'danger');
|
|
}
|
|
}).catch(()=> showToast('خطا در ارتباط با سرور', 'danger'));
|
|
}
|
|
document.getElementById('btnApproveFinalInvoice')?.addEventListener('click', function(){
|
|
const fd = new FormData();
|
|
fd.append('csrfmiddlewaretoken', document.querySelector('input[name=csrfmiddlewaretoken]').value);
|
|
fetch('{% url "invoices:approve_final_invoice" instance.id step.id %}', { method:'POST', body: fd })
|
|
.then(r=>r.json()).then(resp=>{
|
|
if (resp.success){
|
|
showToast(resp.message || 'تایید شد', 'success');
|
|
if (resp.redirect) setTimeout(()=>{ window.location.href = resp.redirect; }, 600);
|
|
} else {
|
|
showToast(resp.message || 'خطا در تایید', 'danger');
|
|
}
|
|
}).catch(()=> showToast('خطا در ارتباط با سرور', 'danger'));
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
|