forked from hesabix/arc
1030 lines
40 KiB
HTML
Executable file
1030 lines
40 KiB
HTML
Executable file
{% extends "pdf/base.html" %}
|
||
{% block content %}
|
||
<style>
|
||
/* حاشیه کمتر از پیشفرض base (۱cm) فقط برای فاکتور؛ بقیهٔ @page از همان قالب */
|
||
@page {
|
||
margin: 8mm;
|
||
}
|
||
|
||
.invoice-layout {
|
||
font-size: 11px;
|
||
}
|
||
|
||
.invoice-layout .section-card {
|
||
border: 1px solid #000;
|
||
border-radius: 8px;
|
||
padding: 8px 10px;
|
||
margin-bottom: 8px;
|
||
background: #ffffff;
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
/* جدول کالا و جداول فرعی: اجازهٔ شکست صفحه برای استفاده بهتر از ارتفاع */
|
||
.invoice-layout .section-card.table-card {
|
||
page-break-inside: auto;
|
||
}
|
||
|
||
.invoice-layout table tbody tr {
|
||
page-break-inside: auto;
|
||
break-inside: auto;
|
||
}
|
||
|
||
.invoice-layout table td {
|
||
page-break-inside: auto;
|
||
}
|
||
|
||
.invoice-layout table {
|
||
font-size: 9px;
|
||
line-height: 1.25;
|
||
box-shadow: none;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.invoice-layout table th,
|
||
.invoice-layout table td {
|
||
padding: 3px 4px;
|
||
line-height: 1.25;
|
||
vertical-align: top;
|
||
}
|
||
|
||
.invoice-layout table thead th {
|
||
font-size: 8px;
|
||
padding: 4px 3px;
|
||
letter-spacing: 0;
|
||
white-space: normal;
|
||
}
|
||
|
||
html[dir="rtl"] .invoice-layout td.line-item-cell {
|
||
text-align: right;
|
||
}
|
||
|
||
html[dir="ltr"] .invoice-layout td.line-item-cell {
|
||
text-align: left;
|
||
}
|
||
|
||
.invoice-layout .line-item-name {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.invoice-layout .line-item-desc {
|
||
font-size: 8.5px;
|
||
font-weight: normal;
|
||
color: #333;
|
||
margin-top: 2px;
|
||
white-space: normal;
|
||
}
|
||
|
||
/* اعداد سطر کالا برای خوانایی بهتر چاپ */
|
||
.invoice-layout td.line-numeric-strong,
|
||
.invoice-layout th.line-numeric-strong {
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.invoice-layout .party-line {
|
||
font-size: 9.5px;
|
||
line-height: 1.4;
|
||
color: #222;
|
||
}
|
||
|
||
.invoice-layout .party-line + .party-line {
|
||
margin-top: 3px;
|
||
}
|
||
|
||
.invoice-layout .party-line .party-label {
|
||
font-weight: 700;
|
||
margin-inline-end: 4px;
|
||
color: #1e3a5f;
|
||
}
|
||
|
||
.invoice-layout .party-sep {
|
||
color: #aaa;
|
||
margin: 0 4px;
|
||
}
|
||
|
||
.invoice-layout .parties-desc-bottom {
|
||
margin-top: 5px;
|
||
padding-top: 5px;
|
||
border-top: 1px dashed #bbb;
|
||
font-size: 9.5px;
|
||
line-height: 1.4;
|
||
color: #222;
|
||
}
|
||
|
||
.invoice-layout .parties-desc-bottom .party-label {
|
||
font-weight: 700;
|
||
margin-inline-end: 4px;
|
||
color: #1e3a5f;
|
||
}
|
||
|
||
.invoice-layout .payments-list {
|
||
margin: 0;
|
||
padding-inline-start: 18px;
|
||
line-height: 1.45;
|
||
}
|
||
|
||
.invoice-layout .payments-list li {
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.invoice-layout .section-card h3 {
|
||
margin: 0 0 6px 0;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.invoice-layout .header {
|
||
margin-bottom: 0;
|
||
padding: 0;
|
||
background: none;
|
||
box-shadow: none;
|
||
border-bottom: none;
|
||
display: block;
|
||
}
|
||
|
||
/* ── هدر فاکتور: تکردیفه و فشرده (سازگار با WeasyPrint) ── */
|
||
.invoice-layout .inv-header-card {
|
||
padding: 5px 8px;
|
||
border-radius: 8px;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.invoice-layout .inv-header-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
table-layout: fixed;
|
||
}
|
||
|
||
.invoice-layout .inv-header-table td {
|
||
vertical-align: middle;
|
||
border: none;
|
||
padding: 0;
|
||
}
|
||
|
||
.invoice-layout .inv-header-logo-cell {
|
||
width: 14%;
|
||
padding-inline-end: 8px;
|
||
}
|
||
|
||
.invoice-layout .inv-header-logo-cell img {
|
||
display: block;
|
||
max-height: 36px;
|
||
max-width: 80px;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.invoice-layout .inv-header-main-cell {
|
||
width: auto;
|
||
padding-inline-end: 6px;
|
||
}
|
||
|
||
.invoice-layout .inv-header-qr-cell {
|
||
width: 46px;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.invoice-layout .inv-header-qr-box img {
|
||
display: block;
|
||
width: 42px;
|
||
height: 42px;
|
||
object-fit: contain;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px;
|
||
padding: 1px;
|
||
}
|
||
|
||
.invoice-layout .inv-header-title {
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
color: #1e3a5f;
|
||
margin: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.invoice-layout .inv-header-meta {
|
||
margin-top: 2px;
|
||
font-size: 9.5px;
|
||
color: #333;
|
||
line-height: 1.35;
|
||
}
|
||
|
||
.invoice-layout .inv-header-meta .sep {
|
||
color: #aaa;
|
||
margin: 0 5px;
|
||
}
|
||
|
||
.invoice-layout .inv-header-meta b {
|
||
font-weight: 700;
|
||
color: #555;
|
||
}
|
||
|
||
.invoice-layout .inv-header-meta .code-value {
|
||
font-weight: 700;
|
||
color: #000;
|
||
direction: ltr;
|
||
unicode-bidi: embed;
|
||
display: inline;
|
||
}
|
||
|
||
.invoice-layout .inv-header-badge {
|
||
display: inline;
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
color: #366092;
|
||
}
|
||
|
||
.invoice-layout .inv-header-badge.proforma {
|
||
color: #b45309;
|
||
}
|
||
|
||
.invoice-layout .footer-info-card {
|
||
padding: 6px 8px;
|
||
}
|
||
|
||
.invoice-layout .footer-info-section {
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.invoice-layout .footer-info-section + .footer-info-section {
|
||
margin-top: 6px;
|
||
padding-top: 6px;
|
||
border-top: 1px dashed #bbb;
|
||
}
|
||
|
||
.invoice-layout .footer-info-title {
|
||
margin-bottom: 3px;
|
||
font-weight: bold;
|
||
font-size: 10.5px;
|
||
}
|
||
|
||
.invoice-layout .footer-info-card .payments-list {
|
||
padding-inline-start: 14px;
|
||
font-size: 9.5px;
|
||
}
|
||
|
||
.invoice-layout .footer-info-card .payments-list li {
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.invoice-layout .header .title {
|
||
font-size: 16px;
|
||
color: #000;
|
||
margin-bottom: 3px;
|
||
}
|
||
|
||
.invoice-layout .header .meta {
|
||
color: #000;
|
||
}
|
||
|
||
.invoice-layout .table-card {
|
||
padding: 0;
|
||
overflow: visible;
|
||
border: none;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
}
|
||
|
||
.invoice-layout .table-card .table-inner {
|
||
padding: 4px 6px 2px 6px;
|
||
}
|
||
|
||
.invoice-layout .table-wrapper {
|
||
margin: 0;
|
||
border-radius: 8px;
|
||
border: 1px solid #000;
|
||
overflow: hidden;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.invoice-layout thead {
|
||
background: #f0f0f0;
|
||
color: #000;
|
||
}
|
||
|
||
.invoice-layout th,
|
||
.invoice-layout td {
|
||
border-color: #000;
|
||
text-align: center;
|
||
}
|
||
|
||
.invoice-layout .amount {
|
||
text-align: center;
|
||
}
|
||
|
||
.invoice-layout tbody tr:nth-child(even) {
|
||
background: #fafafa;
|
||
}
|
||
|
||
.invoice-layout .summary {
|
||
border: none;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
padding: 0;
|
||
margin-top: 0;
|
||
}
|
||
|
||
.invoice-layout .signatures-wrap {
|
||
margin-top: 6px;
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
.invoice-layout .signatures-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
table-layout: fixed;
|
||
}
|
||
|
||
.invoice-layout .signatures-table td {
|
||
border: none;
|
||
text-align: center;
|
||
}
|
||
|
||
.invoice-layout .sig-images-row td {
|
||
width: 50%;
|
||
padding: 0 10px;
|
||
vertical-align: bottom;
|
||
line-height: 0;
|
||
font-size: 0;
|
||
}
|
||
|
||
.invoice-layout .sig-labels-row td {
|
||
width: 50%;
|
||
padding: 0 10px 2px;
|
||
vertical-align: top;
|
||
line-height: 1.1;
|
||
font-size: 10px;
|
||
color: #333;
|
||
}
|
||
|
||
.invoice-layout .sig-stamp {
|
||
display: inline-block;
|
||
width: auto;
|
||
height: auto;
|
||
vertical-align: bottom;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.invoice-layout .sig-image {
|
||
display: inline-block;
|
||
width: auto;
|
||
height: auto;
|
||
vertical-align: bottom;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.invoice-layout .proforma-watermark {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%) rotate(-45deg);
|
||
font-size: 180px;
|
||
font-weight: bold;
|
||
color: rgba(0, 0, 0, 0.1);
|
||
z-index: 0;
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
width: 200%;
|
||
text-align: center;
|
||
user-select: none;
|
||
opacity: 0.15;
|
||
}
|
||
|
||
.invoice-layout {
|
||
position: relative;
|
||
}
|
||
|
||
.invoice-layout > * {
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* اضافات و کسورات فاکتور — جدول جمعوجور و ضمیمهشده در دل فاکتور */
|
||
.invoice-layout .adjustments-card {
|
||
margin-top: 4px;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.invoice-layout .adjustments-card .adj-table-wrapper {
|
||
border-radius: 6px;
|
||
border: 1px solid #000;
|
||
overflow: hidden;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.invoice-layout .adjustments-card table {
|
||
font-size: 9px;
|
||
line-height: 1.25;
|
||
}
|
||
|
||
.invoice-layout .adjustments-card thead {
|
||
background: #f0f0f0;
|
||
color: #000;
|
||
}
|
||
|
||
.invoice-layout .adjustments-card th,
|
||
.invoice-layout .adjustments-card td {
|
||
padding: 3px 4px;
|
||
vertical-align: middle;
|
||
border-color: #000;
|
||
text-align: center;
|
||
}
|
||
|
||
.invoice-layout .adjustments-card thead th {
|
||
font-size: 8.5px;
|
||
padding: 4px 3px;
|
||
letter-spacing: 0;
|
||
white-space: normal;
|
||
}
|
||
|
||
.invoice-layout tbody tr.adj-add { background: #f4faf4 !important; }
|
||
.invoice-layout tbody tr.adj-add:nth-child(even) { background: #ebf6ec !important; }
|
||
.invoice-layout tbody tr.adj-ded { background: #fdf5f3 !important; }
|
||
.invoice-layout tbody tr.adj-ded:nth-child(even) { background: #fbeae6 !important; }
|
||
|
||
.invoice-layout .adj-kind-tag {
|
||
display: inline-block;
|
||
padding: 1px 6px;
|
||
border-radius: 999px;
|
||
font-size: 8.5px;
|
||
font-weight: 700;
|
||
border: 1px solid #999;
|
||
white-space: nowrap;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.invoice-layout .adj-kind-tag.add {
|
||
color: #186a18;
|
||
border-color: #2f8a2f;
|
||
background: #e8f7e6;
|
||
}
|
||
|
||
.invoice-layout .adj-kind-tag.ded {
|
||
color: #8a2a2a;
|
||
border-color: #b54141;
|
||
background: #fbe5e0;
|
||
}
|
||
|
||
.invoice-layout .adj-tot-add { color: #186a18; }
|
||
.invoice-layout .adj-tot-ded { color: #8a2a2a; }
|
||
|
||
.invoice-layout .summary .adj-row {
|
||
font-size: 11px;
|
||
}
|
||
|
||
.invoice-layout .summary hr.summary-divider {
|
||
border: none;
|
||
border-top: 1px dashed #999;
|
||
margin: 4px 0;
|
||
}
|
||
</style>
|
||
|
||
<div class="invoice-layout">
|
||
{% if invoice.is_proforma %}
|
||
<div class="proforma-watermark">
|
||
{{ 'پیشفاکتور' if is_fa else 'PROFORMA' }}
|
||
</div>
|
||
{% endif %}
|
||
<div class="section-card inv-header-card">
|
||
<table class="inv-header-table" cellpadding="0" cellspacing="0">
|
||
<tr>
|
||
{% if business_logo_data_uri %}
|
||
<td class="inv-header-logo-cell">
|
||
<img src="{{ business_logo_data_uri }}" alt="Logo" />
|
||
</td>
|
||
{% endif %}
|
||
<td class="inv-header-main-cell">
|
||
<div class="inv-header-title">
|
||
{{ title_text or invoice.title or ('فاکتور' if is_fa else 'Invoice') }}
|
||
</div>
|
||
<div class="inv-header-meta">
|
||
{% if invoice.invoice_type_name %}
|
||
<span><b>{{ 'نوع فاکتور' if is_fa else 'Invoice type' }}:</b> {{ invoice.invoice_type_name }}</span>
|
||
{% endif %}
|
||
{% if invoice.is_proforma %}
|
||
{% if invoice.invoice_type_name %}<span class="sep">|</span>{% endif %}
|
||
<span class="inv-header-badge proforma">{{ 'پیشفاکتور' if is_fa else 'Proforma' }}</span>
|
||
{% endif %}
|
||
{% set _currency_display = invoice.currency_title or invoice.currency_name or invoice.currency_code %}
|
||
{% if _currency_display %}
|
||
{% if invoice.invoice_type_name or invoice.is_proforma %}<span class="sep">|</span>{% endif %}
|
||
<span><b>{{ 'واحد پول' if is_fa else 'Currency' }}:</b> {{ _currency_display }}</span>
|
||
{% endif %}
|
||
<span class="sep">|</span>
|
||
<b>{{ 'کد' if is_fa else 'Code' }}:</b>
|
||
<span class="code-value">{{ invoice.code or '-' }}</span>
|
||
<span class="sep">|</span>
|
||
<b>{{ 'تاریخ' if is_fa else 'Date' }}:</b>
|
||
{{ invoice.issue_date or '-' }}
|
||
</div>
|
||
</td>
|
||
{% if show_invoice_verify_qr and invoice_verify_qr_data_uri %}
|
||
<td class="inv-header-qr-cell">
|
||
<div class="inv-header-qr-box">
|
||
<img src="{{ invoice_verify_qr_data_uri }}" alt="QR" />
|
||
</div>
|
||
</td>
|
||
{% endif %}
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="section-card">
|
||
<div class="party-line">
|
||
<span class="party-label">{{ 'فروشنده' if is_fa else 'Seller' }}:</span>
|
||
{% if seller.get('name_prefix') %}
|
||
{{ ((seller.name_prefix ~ ' ' ~ (seller.name or '')) | trim) or '-' }}
|
||
{% else %}
|
||
{{ seller.name or '-' }}
|
||
{% endif %}
|
||
{% if seller.get('legal_entity_type') %}
|
||
<span class="party-sep">|</span>{{ seller.legal_entity_type_label or seller.legal_entity_type }}
|
||
{% endif %}
|
||
{% if seller.national_id or seller.national_code %}
|
||
<span class="party-sep">|</span><b>{{ 'کد ملی' if is_fa else 'National ID' }}:</b> {{ seller.national_id or seller.national_code }}
|
||
{% endif %}
|
||
{% if seller.economic_id or seller.economic_code %}
|
||
<span class="party-sep">|</span><b>{{ 'شناسه اقتصادی' if is_fa else 'Economic ID' }}:</b> {{ seller.economic_id or seller.economic_code }}
|
||
{% endif %}
|
||
{% if seller.registration_number %}
|
||
<span class="party-sep">|</span><b>{{ 'ثبت' if is_fa else 'Reg.' }}:</b> {{ seller.registration_number }}
|
||
{% endif %}
|
||
{% if seller.address %}
|
||
<span class="party-sep">|</span><b>{{ 'آدرس' if is_fa else 'Address' }}:</b> {{ seller.address }}
|
||
{% endif %}
|
||
{% if seller.postal_code %}
|
||
<span class="party-sep">|</span><b>{{ 'کدپستی' if is_fa else 'Postal' }}:</b> {{ seller.postal_code }}
|
||
{% endif %}
|
||
{% if seller.phone or seller.mobile %}
|
||
<span class="party-sep">|</span><b>{{ 'تلفن' if is_fa else 'Phone' }}:</b> {{ seller.phone or seller.mobile }}
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="party-line">
|
||
<span class="party-label">{{ 'خریدار' if is_fa else 'Buyer' }}:</span>
|
||
{% if buyer.get('name_prefix') %}
|
||
{{ ((buyer.name_prefix ~ ' ' ~ (buyer.name or '')) | trim) or '-' }}
|
||
{% else %}
|
||
{{ buyer.name or '-' }}
|
||
{% endif %}
|
||
{% if buyer.get('legal_entity_type') %}
|
||
<span class="party-sep">|</span>{{ buyer.legal_entity_type_label or buyer.legal_entity_type }}
|
||
{% endif %}
|
||
{% if buyer.economic_id or buyer.economic_code %}
|
||
<span class="party-sep">|</span><b>{{ 'شناسه اقتصادی' if is_fa else 'Economic ID' }}:</b> {{ buyer.economic_id or buyer.economic_code }}
|
||
{% elif buyer.national_id or buyer.national_code %}
|
||
<span class="party-sep">|</span><b>{{ 'کد ملی' if is_fa else 'National ID' }}:</b> {{ buyer.national_id or buyer.national_code }}
|
||
{% endif %}
|
||
{% if buyer.registration_number %}
|
||
<span class="party-sep">|</span><b>{{ 'ثبت' if is_fa else 'Reg.' }}:</b> {{ buyer.registration_number }}
|
||
{% endif %}
|
||
{% if buyer.address %}
|
||
<span class="party-sep">|</span><b>{{ 'آدرس' if is_fa else 'Address' }}:</b> {{ buyer.address }}
|
||
{% endif %}
|
||
{% if buyer.postal_code %}
|
||
<span class="party-sep">|</span><b>{{ 'کدپستی' if is_fa else 'Postal' }}:</b> {{ buyer.postal_code }}
|
||
{% endif %}
|
||
{% if buyer.mobile or buyer.phone %}
|
||
<span class="party-sep">|</span><b>{{ 'تلفن' if is_fa else 'Phone' }}:</b> {{ buyer.mobile or buyer.phone }}
|
||
{% endif %}
|
||
</div>
|
||
|
||
{% if invoice.description %}
|
||
<div class="parties-desc-bottom">
|
||
<span class="party-label">{{ 'توضیحات فاکتور' if is_fa else 'Invoice notes' }}:</span>
|
||
{{ invoice.description }}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="section-card table-card">
|
||
<div class="table-inner">
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>{{ 'ردیف' if is_fa else 'No.' }}</th>
|
||
<th>{{ 'کالا / خدمت و توضیحات' if is_fa else 'Item & description' }}</th>
|
||
<th class="line-numeric-strong">{{ 'تعداد' if is_fa else 'Qty' }}</th>
|
||
<th class="line-numeric-strong">{{ 'واحد' if is_fa else 'Unit' }}</th>
|
||
<th class="line-numeric-strong">{{ 'فی' if is_fa else 'Price' }}</th>
|
||
{% if show_line_discount_column | default(has_line_discount) %}
|
||
<th class="line-numeric-strong">{{ 'تخفیف' if is_fa else 'Discount' }}</th>
|
||
{% endif %}
|
||
{% if show_line_amount_before_discount_column | default(true) %}
|
||
<th class="line-numeric-strong">{{ 'جمع بدون تخفیف' if is_fa else 'Amount before discount' }}</th>
|
||
{% endif %}
|
||
{% if show_line_amount_before_tax_column | default(true) %}
|
||
<th class="line-numeric-strong">{{ 'جمع بدون مالیات' if is_fa else 'Amount before tax' }}</th>
|
||
{% endif %}
|
||
{% if show_line_tax_column | default(has_line_tax) %}
|
||
<th class="line-numeric-strong">{{ 'مالیات' if is_fa else 'Tax' }}</th>
|
||
{% endif %}
|
||
<th class="line-numeric-strong">{{ 'مبلغ' if is_fa else 'Amount' }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for line in lines or [] %}
|
||
<tr>
|
||
<td>{{ loop.index }}</td>
|
||
<td class="line-item-cell">
|
||
<div class="line-item-name">
|
||
{% if line.product_code %}
|
||
{{ line.product_code }} - {{ line.product_name or '-' }}
|
||
{% else %}
|
||
{{ line.product_name or '-' }}
|
||
{% endif %}
|
||
</div>
|
||
{% if line.description %}
|
||
<div class="line-item-desc">• {{ line.description }}</div>
|
||
{% endif %}
|
||
{% if line.attributes_display %}
|
||
<div class="line-item-desc">• {{ line.attributes_display }}</div>
|
||
{% endif %}
|
||
</td>
|
||
<td class="line-numeric-strong">{{ line.quantity_display | default('') | ltr | safe }}</td>
|
||
<td class="line-numeric-strong">{{ line.unit_display | default('-') }}</td>
|
||
<td class="amount line-numeric-strong">{{ (line.unit_price or 0) | format_amount(0) | ltr | safe }}</td>
|
||
{% if show_line_discount_column | default(has_line_discount) %}
|
||
<td class="amount line-numeric-strong">
|
||
{% if line.discount_display is defined and line.discount_display %}
|
||
{{ line.discount_display | ltr | safe }}
|
||
{% else %}
|
||
{{ (line.discount or 0) | format_amount(0) | ltr | safe }}
|
||
{% endif %}
|
||
</td>
|
||
{% endif %}
|
||
{% if show_line_amount_before_discount_column | default(true) %}
|
||
<td class="amount line-numeric-strong">
|
||
{{ (line.amount_before_discount if line.amount_before_discount is defined else ((line.line_total or 0) + (line.discount or 0) - (line.tax_amount or 0))) | format_amount(0) | ltr | safe }}
|
||
</td>
|
||
{% endif %}
|
||
{% if show_line_amount_before_tax_column | default(true) %}
|
||
<td class="amount line-numeric-strong">
|
||
{{ (line.amount_before_tax if line.amount_before_tax is defined else ((line.line_total or 0) - (line.tax_amount or 0))) | format_amount(0) | ltr | safe }}
|
||
</td>
|
||
{% endif %}
|
||
{% if show_line_tax_column | default(has_line_tax) %}
|
||
<td class="amount line-numeric-strong">{{ (line.tax_amount or 0) | format_amount(0) | ltr | safe }}</td>
|
||
{% endif %}
|
||
<td class="amount line-numeric-strong">{{ (line.line_total or 0) | format_amount(0) | ltr | safe }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{# اضافات و کسورات فاکتور — بهصورت ضمیمه و در دل فاکتور (نه صفحه جدا) #}
|
||
{% set _adj_rows = (invoice.invoice_adjustments | default([], true)) or [] %}
|
||
{% if _adj_rows|length > 0 %}
|
||
<div class="section-card adjustments-card">
|
||
<h3 style="margin-top: 0;">{{ 'اضافات و کسورات فاکتور' if is_fa else 'Invoice adjustments' }}</h3>
|
||
<div class="adj-table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>{{ 'ردیف' if is_fa else 'No.' }}</th>
|
||
<th>{{ 'نوع' if is_fa else 'Kind' }}</th>
|
||
<th>{{ 'حساب' if is_fa else 'Account' }}</th>
|
||
<th>{{ 'شرح' if is_fa else 'Description' }}</th>
|
||
<th class="line-numeric-strong">{{ 'مبلغ خالص' if is_fa else 'Net amount' }}</th>
|
||
<th class="line-numeric-strong">{{ 'نرخ مالیات' if is_fa else 'Tax rate' }}</th>
|
||
<th class="line-numeric-strong">{{ 'مالیات' if is_fa else 'Tax' }}</th>
|
||
<th class="line-numeric-strong">{{ 'جمع' if is_fa else 'Total' }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for r in _adj_rows %}
|
||
<tr class="{{ 'adj-add' if r.kind == 'addition' else 'adj-ded' }}">
|
||
<td>{{ loop.index }}</td>
|
||
<td>
|
||
<span class="adj-kind-tag {{ 'add' if r.kind == 'addition' else 'ded' }}">
|
||
{{ '+' if r.kind == 'addition' else '−' }} {{ r.kind_label }}
|
||
</span>
|
||
</td>
|
||
<td>
|
||
{% if r.account_code %}{{ r.account_code }} - {% endif %}{{ r.account_name or '-' }}
|
||
</td>
|
||
<td style="text-align: start;">{{ r.description or '-' }}</td>
|
||
<td class="amount line-numeric-strong">{{ (r.amount or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="line-numeric-strong">
|
||
{% if (r.tax_rate or 0) > 0 %}
|
||
<span class="amount" style="font-weight: 700;">{{ (r.tax_rate or 0) | smart_number | ltr | safe }}%</span>
|
||
{% else %}
|
||
-
|
||
{% endif %}
|
||
</td>
|
||
<td class="amount line-numeric-strong">{{ (r.tax_amount or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="amount line-numeric-strong">
|
||
<span class="{{ 'adj-tot-add' if r.kind == 'addition' else 'adj-tot-ded' }}">
|
||
{{ '+' if r.kind == 'addition' else '−' }}{{ (r.total or 0) | format_amount(0) | ltr | safe }}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{# توضیحات انتهایی، پرداختها و تراز مشتری در یک باکس؛ خلاصه مالی کنار آن #}
|
||
<div style="display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap;">
|
||
{% set _has_notes_block = invoice_footer_note %}
|
||
{% set _has_pay_block = payments and payments|length > 0 %}
|
||
{% set _has_balance_block = customer_balance_info %}
|
||
|
||
{% if _has_notes_block or _has_pay_block or _has_balance_block %}
|
||
<div class="section-card footer-info-card" style="flex: 1; min-width: 200px;">
|
||
{% if invoice_footer_note %}
|
||
<div class="footer-info-section">
|
||
<div class="footer-info-title meta">
|
||
{{ 'توضیحات / متن انتهای فاکتور' if is_fa else 'Footer notes' }}
|
||
</div>
|
||
<div class="meta">{{ invoice_footer_note }}</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if payments and payments|length > 0 %}
|
||
<div class="footer-info-section">
|
||
<div class="footer-info-title meta">
|
||
{{ 'اطلاعات پرداختها و اسناد مرتبط' if is_fa else 'Payment details & linked documents' }}
|
||
</div>
|
||
<ul class="payments-list meta">
|
||
{% for p in payments %}
|
||
<li>
|
||
<strong>{{ p.date or '-' }}</strong>
|
||
—
|
||
{{ p.document_type_name or '-' }}
|
||
—
|
||
<span>{{ p.code or '-' }}</span>
|
||
—
|
||
<span class="amount" style="font-weight: 700;">{{ (p.total_amount or 0) | format_amount(0) | ltr | safe }}</span>
|
||
{% if p.fx_display %}
|
||
<div style="margin-top: 3px; font-size: 9.5px; color: #1a1a1a; font-weight: 600;">
|
||
{% set fx = p.fx_display %}
|
||
{{ (fx.settles_amount or 0) | format_amount(2) | ltr | safe }}{{ fx.settles_unit or '' }}
|
||
({{ (fx.payment_amount or 0) | format_amount(0) | ltr | safe }}{{ fx.payment_unit or '' }}
|
||
{% if fx.rate %}
|
||
{{ 'با نرخ' if is_fa else 'at rate' }} {{ fx.rate | format_amount(0) | ltr | safe }}
|
||
{% endif %})
|
||
</div>
|
||
{% endif %}
|
||
{% if p.account_details and p.account_details|length > 0 %}
|
||
<div style="margin-top: 2px; font-size: 9px; color: #333;">
|
||
{% for acc in p.account_details %}
|
||
<span>• {{ acc.method_label or '-' }}</span>
|
||
{% if acc.display_name %}
|
||
<span> {{ acc.display_name }}</span>
|
||
{% endif %}
|
||
<span class="amount" style="font-weight: 700;"> {{ (acc.amount or 0) | format_amount(0) | ltr | safe }}</span>
|
||
{% if acc.description %}
|
||
<span style="color: #555;"> — {{ acc.description }}</span>
|
||
{% endif %}
|
||
{% if not loop.last %}<br />{% endif %}
|
||
{% endfor %}
|
||
</div>
|
||
{% endif %}
|
||
{% if p.description %}
|
||
<div style="margin-top: 2px; font-size: 9px; color: #555;">
|
||
{{ 'توضیح سند:' if is_fa else 'Doc. note:' }} {{ p.description }}
|
||
</div>
|
||
{% endif %}
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if customer_balance_info %}
|
||
<div class="footer-info-section">
|
||
<div class="footer-info-title meta">
|
||
{{ 'وضعیت حساب مشتری' if is_fa else 'Customer account status' }}
|
||
</div>
|
||
<div class="meta" style="line-height: 1.45;">
|
||
{% if invoice.is_proforma %}
|
||
<div style="margin-bottom: 4px;">
|
||
<strong>{{ 'تراز فعلی' if is_fa else 'Current balance' }}:</strong>
|
||
<span class="amount" style="margin-inline-start: 4px; font-weight: 700;">{{ customer_balance_info.current_balance | format_amount(0) | ltr | safe }}</span>
|
||
<span style="margin-inline-start: 6px; color: #555;">({{ customer_balance_info.current_status }})</span>
|
||
</div>
|
||
<div>
|
||
<strong>{{ 'تراز احتمالی پس از قطعی شدن' if is_fa else 'Potential balance after finalization' }}:</strong>
|
||
<span class="amount" style="margin-inline-start: 4px; font-weight: 700;">{{ customer_balance_info.potential_balance | format_amount(0) | ltr | safe }}</span>
|
||
<span style="margin-inline-start: 6px; color: #555;">({{ customer_balance_info.potential_status }})</span>
|
||
</div>
|
||
{% else %}
|
||
<div>
|
||
<strong>{{ 'تراز حساب' if is_fa else 'Account balance' }}:</strong>
|
||
<span class="amount" style="margin-inline-start: 4px; font-weight: 700;">{{ customer_balance_info.current_balance | format_amount(0) | ltr | safe }}</span>
|
||
<span style="margin-inline-start: 6px; color: #555;">({{ customer_balance_info.current_status }})</span>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
{# خلاصه مالی فاکتور #}
|
||
<div class="section-card" style="flex: 0 0 auto; min-width: 260px;">
|
||
<div class="summary">
|
||
<div class="meta" style="margin-bottom: 6px; font-size: 12px; font-weight: bold;">
|
||
{{ 'خلاصه مالی فاکتور' if is_fa else 'Invoice summary' }}
|
||
</div>
|
||
<div>
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ 'مبلغ قبل از تخفیف و مالیات' if is_fa else 'Amount before discount & tax' }}:</span>
|
||
<span class="amount">{{ (invoice.amount_before_discount_and_tax or invoice.subtotal or 0) | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
{% if show_summary_discount | default(invoice.discount_total) %}
|
||
{% if invoice.show_discount_breakdown %}
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ invoice.discount_line_label | default(('تخفیف سطری' if is_fa else 'Line discount')) }}:</span>
|
||
<span class="amount">{{ (invoice.line_discount_total or 0) | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ invoice.discount_global_label | default(('تخفیف کلی' if is_fa else 'Invoice discount')) }}:</span>
|
||
<span class="amount">
|
||
{% if invoice.global_discount_display %}
|
||
{{ invoice.global_discount_display | ltr | safe }}
|
||
{% else %}
|
||
{{ (invoice.global_discount_amount or 0) | format_amount(0) | ltr | safe }}
|
||
{% endif %}
|
||
</span>
|
||
</div>
|
||
{% else %}
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ invoice.discount_summary_label | default(('تخفیف' if is_fa else 'Discount')) }}:</span>
|
||
<span class="amount">
|
||
{% if invoice.discount_summary_display %}
|
||
{{ invoice.discount_summary_display | ltr | safe }}
|
||
{% else %}
|
||
{{ (invoice.discount_total or 0) | format_amount(0) | ltr | safe }}
|
||
{% endif %}
|
||
</span>
|
||
</div>
|
||
{% endif %}
|
||
{% endif %}
|
||
{% if show_summary_amount_without_tax | default(invoice.amount_without_tax is not none) %}
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ 'مبلغ بدون مالیات' if is_fa else 'Amount without tax' }}:</span>
|
||
<span class="amount">{{ (invoice.amount_without_tax or 0) | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
{% endif %}
|
||
{% if show_summary_tax | default(invoice.tax_total) %}
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">{{ 'مالیات' if is_fa else 'Tax' }}:</span>
|
||
<span class="amount">{{ (invoice.tax_total or 0) | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% set _adj_add_total = (invoice.adjustments_additions_total | default(0, true)) or 0 %}
|
||
{% set _adj_ded_total = (invoice.adjustments_deductions_total | default(0, true)) or 0 %}
|
||
{% set _adj_net = (invoice.adjustments_net | default(0, true)) or 0 %}
|
||
{% set _adj_tax = (invoice.adjustments_tax | default(0, true)) or 0 %}
|
||
{% if _adj_add_total or _adj_ded_total or _adj_net or _adj_tax %}
|
||
<hr class="summary-divider" />
|
||
{% if _adj_add_total %}
|
||
<div class="adj-row" style="display:flex; justify-content: space-between;">
|
||
<span class="meta adj-tot-add">{{ 'اضافات (با مالیات)' if is_fa else 'Additions (incl. tax)' }}:</span>
|
||
<span class="amount adj-tot-add">+{{ _adj_add_total | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
{% endif %}
|
||
{% if _adj_ded_total %}
|
||
<div class="adj-row" style="display:flex; justify-content: space-between;">
|
||
<span class="meta adj-tot-ded">{{ 'کسورات (با مالیات)' if is_fa else 'Deductions (incl. tax)' }}:</span>
|
||
<span class="amount adj-tot-ded">−{{ _adj_ded_total | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
{% endif %}
|
||
<hr class="summary-divider" />
|
||
{% endif %}
|
||
|
||
{% set _final_payable = (invoice.final_payable_total | default(invoice.payable_total, true)) | default(0, true) %}
|
||
<div style="display:flex; justify-content: space-between; font-weight: bold; margin-top: 6px;">
|
||
<span>{{ 'قابل پرداخت' if is_fa else 'Payable' }}:</span>
|
||
<span class="amount">{{ _final_payable | format_amount(0) | ltr | safe }}</span>
|
||
</div>
|
||
|
||
{% set _fx = invoice.fx_totals if invoice.fx_totals is mapping else none %}
|
||
{% set _show_dual = _fx and (_fx.show_dual | default(false)) %}
|
||
{% if is_multi_currency | default(false) and _show_dual %}
|
||
{% set _fx_foreign = _fx.foreign if _fx.foreign is mapping else {} %}
|
||
{% set _fx_base = _fx.base if _fx.base is mapping else {} %}
|
||
{% set _base_cur = base_currency if base_currency is mapping else {} %}
|
||
<div style="margin-top: 8px; padding-top: 8px; border-top: 1px dashed #ccc; font-size: 11px;">
|
||
<div class="meta" style="margin-bottom: 4px;">{{ 'معادل ارز پایه' if is_fa else 'Base currency equivalent' }}</div>
|
||
<div style="display:flex; justify-content: space-between;">
|
||
<span class="meta">
|
||
{{ (_fx_foreign.payable | default(_fx_foreign.net, true)) | default(0, true) | format_amount(0) | ltr | safe }}
|
||
{{ invoice.currency.code if invoice.currency and invoice.currency.code else '' }}
|
||
</span>
|
||
<span class="amount">
|
||
≈
|
||
{{ (_fx_base.payable | default(_fx_base.net, true)) | default(0, true) | format_amount(0) | ltr | safe }}
|
||
{{ _base_cur.code | default('', true) }}
|
||
</span>
|
||
</div>
|
||
{% if _fx_base.rate %}
|
||
<div class="meta" style="margin-top: 2px;">
|
||
{{ 'نرخ' if is_fa else 'Rate' }}:
|
||
{{ _fx_base.rate | format_amount(4) | ltr | safe }}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="clear: both;"></div>
|
||
|
||
{% set _show_sig_seller = show_seller_signature_area | default(true) %}
|
||
{% set _show_sig_buyer = show_buyer_signature_area | default(true) %}
|
||
{% if _show_sig_seller or _show_sig_buyer %}
|
||
<div class="signatures-wrap">
|
||
<table class="signatures-table" cellpadding="0" cellspacing="0">
|
||
<tr class="sig-images-row">
|
||
{% if _show_sig_seller %}
|
||
<td>
|
||
{% set _stamp_mw = stamp_max_width_px | default(160) %}
|
||
{% set _sig_mw = signature_max_width_px | default(140) %}
|
||
{% if business_stamp_data_uri %}
|
||
<img class="sig-stamp" src="{{ business_stamp_data_uri }}" alt="Stamp" style="max-width: {{ _stamp_mw }}px;" />
|
||
{% endif %}
|
||
{% if owner_signature_data_uri %}
|
||
<img class="sig-image" src="{{ owner_signature_data_uri }}" alt="Owner signature" style="max-width: {{ _sig_mw }}px;" />
|
||
{% endif %}
|
||
</td>
|
||
{% endif %}
|
||
{% if _show_sig_buyer %}
|
||
<td> </td>
|
||
{% endif %}
|
||
</tr>
|
||
<tr class="sig-labels-row">
|
||
{% if _show_sig_seller %}
|
||
<td>
|
||
{{ 'امضای فروشنده / مهر شرکت' if is_fa else 'Seller signature / Company stamp' }}
|
||
</td>
|
||
{% endif %}
|
||
{% if _show_sig_buyer %}
|
||
<td>
|
||
{{ 'امضای خریدار' if is_fa else 'Buyer signature' }}
|
||
</td>
|
||
{% endif %}
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if installment_plan and installment_plan.data and installment_plan.data.schedule %}
|
||
<div class="section-card table-card" style="page-break-before: always; margin-top: 16px;">
|
||
<div class="table-inner">
|
||
<div class="meta" style="font-weight:bold; margin-bottom:6px; font-size: 12px;">
|
||
{{ 'برنامه اقساط فاکتور' if is_fa else 'Invoice installment plan' }}
|
||
{% if installment_plan.meta.invoice_code %}
|
||
({{ installment_plan.meta.invoice_code }})
|
||
{% endif %}
|
||
</div>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>{{ 'قسط' if is_fa else 'Inst.' }}</th>
|
||
<th>{{ 'تاریخ سررسید' if is_fa else 'Due date' }}</th>
|
||
<th>{{ 'اصل' if is_fa else 'Principal' }}</th>
|
||
<th>{{ 'سود' if is_fa else 'Interest' }}</th>
|
||
<th>{{ 'مبلغ قسط' if is_fa else 'Installment' }}</th>
|
||
<th>{{ 'پرداخت شده' if is_fa else 'Paid' }}</th>
|
||
<th>{{ 'مانده' if is_fa else 'Remaining' }}</th>
|
||
<th>{{ 'وضعیت' if is_fa else 'Status' }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for it in installment_plan.data.schedule %}
|
||
<tr>
|
||
<td>{{ it.seq }}</td>
|
||
<td>{{ it.due_date_display or it.due_date or '-' }}</td>
|
||
<td class="amount">{{ (it.principal or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="amount">{{ (it.interest or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="amount">{{ (it.total or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="amount">{{ (it.paid_amount or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td class="amount">{{ (it.remaining or 0) | format_amount(0) | ltr | safe }}</td>
|
||
<td>{{ it.status or '-' }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endblock %}
|
||
|
||
|