update: Major Overhaul to all subsystems
This commit is contained in:
708
backend/templates/quotation.html
Normal file
708
backend/templates/quotation.html
Normal file
@@ -0,0 +1,708 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ lang }}">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>{% if lang == 'gr' %}Προσφορά{% else %}Quotation{% endif %} {{ quotation.quotation_number }}</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,600;0,700;1,400&display=swap');
|
||||
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: 'Noto Sans', DejaVu Sans, Arial, sans-serif;
|
||||
font-size: 9.5pt;
|
||||
color: #1a1a2e;
|
||||
background: #fff;
|
||||
line-height: 1.45;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 36mm;
|
||||
}
|
||||
|
||||
/* pushes notes + validity down toward the fixed footer */
|
||||
.main-content-gap {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 15mm 15mm 15mm 15mm;
|
||||
}
|
||||
|
||||
/* ── HEADER ── */
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2.5px solid #5886c4;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.company-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.company-block img.logo {
|
||||
max-height: 70px;
|
||||
max-width: 250px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.company-block p {
|
||||
font-size: 10pt;
|
||||
color: #6b8fc4;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.quotation-meta-block {
|
||||
text-align: right;
|
||||
}
|
||||
.quotation-meta-block .doc-type {
|
||||
font-size: 14pt;
|
||||
font-weight: 700;
|
||||
color: #5886c4;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.quotation-meta-block .meta-line {
|
||||
font-size: 8.5pt;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.quotation-meta-block .meta-line .meta-label {
|
||||
color: #7a9cc8;
|
||||
}
|
||||
.quotation-meta-block .meta-line .meta-value {
|
||||
font-weight: 600;
|
||||
color: #1a1a2e;
|
||||
}
|
||||
|
||||
/* ── CLIENT + ORDER META ── */
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.client-block, .order-block {
|
||||
border: 1px solid #c2d4ec;
|
||||
border-radius: 5px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
.client-block { flex: 65; }
|
||||
.order-block { flex: 35; }
|
||||
|
||||
.block-title {
|
||||
font-size: 7.5pt;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #5886c4;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 3px;
|
||||
border-bottom: 1px solid #dce9f7;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.info-row table.fields {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
.info-row table.fields td {
|
||||
padding: 1px 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.info-row table.fields td.lbl {
|
||||
font-size: 8pt;
|
||||
color: #7a9cc8;
|
||||
white-space: nowrap;
|
||||
padding-right: 8px;
|
||||
}
|
||||
.info-row table.fields td.val {
|
||||
font-size: 8.5pt;
|
||||
font-weight: 500;
|
||||
color: #1a1a2e;
|
||||
}
|
||||
|
||||
/* ── TITLE / SUBTITLE ── */
|
||||
.quotation-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.quotation-title h2 {
|
||||
font-size: 13pt;
|
||||
font-weight: 700;
|
||||
color: #3a6aad;
|
||||
}
|
||||
.quotation-title p {
|
||||
font-size: 9pt;
|
||||
color: #555;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* ── ITEMS TABLE ── */
|
||||
.items-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 0;
|
||||
font-size: 8.5pt;
|
||||
}
|
||||
.items-table thead tr {
|
||||
background: #5886c4;
|
||||
color: #fff;
|
||||
}
|
||||
.items-table thead th {
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
.items-table thead th.right { text-align: right; }
|
||||
.items-table thead th.center { text-align: center; }
|
||||
|
||||
.items-table tbody tr:nth-child(even) { background: #eef4fc; }
|
||||
.items-table tbody tr:nth-child(odd) { background: #fff; }
|
||||
|
||||
.items-table tbody td {
|
||||
padding: 5px 8px;
|
||||
border-bottom: 1px solid #dce9f7;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.items-table tbody td.right { text-align: right; }
|
||||
.items-table tbody td.center { text-align: center; }
|
||||
.items-table tbody td.muted { color: #7a9cc8; font-size: 8pt; }
|
||||
|
||||
/* Special rows for shipping/install */
|
||||
.items-table tbody tr.special-row td {
|
||||
background: #edf3fb;
|
||||
border-top: 1px solid #c2d4ec;
|
||||
border-bottom: 1px solid #c2d4ec;
|
||||
font-style: italic;
|
||||
color: #3a6aad;
|
||||
}
|
||||
.items-table tbody tr.special-spacer td {
|
||||
height: 6px;
|
||||
background: #f4f8fd;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ── BELOW TABLE ROW: VAT notice + totals ── */
|
||||
.below-table {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-top: 0;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.vat-notice {
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
.vat-notice p {
|
||||
font-size: 8pt;
|
||||
font-weight: 700;
|
||||
color: #3a6aad;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.3px;
|
||||
border-left: 3px solid #5886c4;
|
||||
padding-left: 7px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
/* ── TOTALS ── */
|
||||
.totals-table {
|
||||
width: 280px;
|
||||
border-collapse: collapse;
|
||||
font-size: 8.5pt;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.totals-table td {
|
||||
padding: 4px 10px;
|
||||
border-bottom: 1px solid #dce9f7;
|
||||
}
|
||||
.totals-table .label { color: #555; text-align: right; }
|
||||
.totals-table .value { text-align: right; font-weight: 500; min-width: 90px; }
|
||||
.totals-table .discount-row { color: #c0392b; }
|
||||
.totals-table .new-subtotal-row td { font-size: 10pt; font-weight: 700; color: #1a1a2e; }
|
||||
.totals-table .vat-row td { color: #7a9cc8; font-style: italic; }
|
||||
.totals-table .final-row td {
|
||||
font-size: 11pt;
|
||||
font-weight: 700;
|
||||
color: #3a6aad;
|
||||
border-top: 2px solid #5886c4;
|
||||
border-bottom: none;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
/* ── COMMENTS ── */
|
||||
.comments-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.comments-section .section-title {
|
||||
font-size: 8pt;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #5886c4;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.comments-section ul {
|
||||
padding-left: 14px;
|
||||
}
|
||||
.comments-section li {
|
||||
font-size: 8.5pt;
|
||||
color: #333;
|
||||
margin-bottom: 3px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* ── FOOTER (validity line only) ── */
|
||||
.footer {
|
||||
border-top: 1px solid #c2d4ec;
|
||||
padding-top: 7px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.footer .validity {
|
||||
font-size: 7.5pt;
|
||||
font-style: italic;
|
||||
color: #7a9cc8;
|
||||
}
|
||||
|
||||
/* ── FIXED BOTTOM FOOTER (repeats on every page) ── */
|
||||
.fixed-footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 8px 0 0 0;
|
||||
border-top: 1.5px solid #5886c4;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 20px;
|
||||
background: #fff;
|
||||
}
|
||||
.footer-block {
|
||||
width: 30%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.footer-block-title {
|
||||
font-size: 7pt;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #5886c4;
|
||||
letter-spacing: 0.4px;
|
||||
margin-bottom: 4px;
|
||||
border-bottom: 1px solid #dce9f7;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
.footer-block dl {
|
||||
display: grid;
|
||||
grid-template-columns: max-content 1fr;
|
||||
gap: 2px 6px;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
.footer-block dt {
|
||||
font-size: 7pt;
|
||||
color: #7a9cc8;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.footer-block dd {
|
||||
font-size: 7pt;
|
||||
color: #1a1a2e;
|
||||
font-weight: 500;
|
||||
}
|
||||
.footer-ref {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.footer-ref .ref-quot {
|
||||
font-size: 7.5pt;
|
||||
font-weight: 700;
|
||||
color: #5886c4;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.footer-ref .ref-page {
|
||||
font-size: 7pt;
|
||||
color: #7a9cc8;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.footer-ref .ref-page::after {
|
||||
content: counter(page) " / " counter(pages);
|
||||
}
|
||||
|
||||
/* ── UTILS ── */
|
||||
.text-muted { color: #aaa; }
|
||||
.dash { color: #ccc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{# ── Bilingual labels ── #}
|
||||
{% if lang == 'gr' %}
|
||||
{% set L_QUOTATION = "ΠΡΟΣΦΟΡΑ" %}
|
||||
{% set L_NUMBER = "Αριθμός" %}
|
||||
{% set L_DATE = "Ημερομηνία" %}
|
||||
{% set L_CLIENT = "ΣΤΟΙΧΕΙΑ ΠΕΛΑΤΗ" %}
|
||||
{% set L_ORDER_META = "ΣΤΟΙΧΕΙΑ ΠΑΡΑΓΓΕΛΙΑΣ" %}
|
||||
{% set L_ORDER_TYPE = "Τύπος" %}
|
||||
{% set L_SHIP_METHOD = "Τρ. Αποστολής" %}
|
||||
{% set L_SHIP_DATE = "Εκτιμώμενη Παράδοση" %}
|
||||
{% set L_DESC = "Περιγραφή" %}
|
||||
{% set L_UNIT_COST = "Τιμή Μον." %}
|
||||
{% set L_DISC = "Έκπτ." %}
|
||||
{% set L_QTY = "Ποσ." %}
|
||||
{% set L_UNIT = "Μον." %}
|
||||
{% set L_VAT_COL = "Φ.Π.Α." %}
|
||||
{% set L_TOTAL = "Σύνολο" %}
|
||||
{% set L_SUBTOTAL = "Υποσύνολο" %}
|
||||
{% set L_GLOBAL_DISC = quotation.global_discount_label or "Έκπτωση" %}
|
||||
{% set L_NEW_SUBTOTAL = "Νέο Υποσύνολο" %}
|
||||
{% set L_VAT = "ΣΥΝΟΛΟ Φ.Π.Α." %}
|
||||
{% set L_SHIPPING_COST = "Μεταφορικά / Shipping" %}
|
||||
{% set L_INSTALL_COST = "Εγκατάσταση / Installation" %}
|
||||
{% set L_EXTRAS = quotation.extras_label or "Άλλα" %}
|
||||
{% set L_FINAL = "ΣΥΝΟΛΟ ΠΛΗΡΩΤΕΟ" %}
|
||||
{% set L_COMMENTS = "ΣΗΜΕΙΩΣΕΙΣ" %}
|
||||
{% set L_VALIDITY = "Η προσφορά ισχύει για 30 ημέρες από την ημερομηνία έκδοσής της." %}
|
||||
{% set L_ORG = "Φορέας" %}
|
||||
{% set L_CONTACT = "Επικοινωνία" %}
|
||||
{% set L_ADDRESS = "Διεύθυνση" %}
|
||||
{% set L_PHONE = "Τηλέφωνο" %}
|
||||
{% set L_COMPANY_ADDR = "Ε.Ο. Αντιρρίου Ιωαννίνων 23, Αγρίνιο, 30131" %}
|
||||
{% set L_CONTACT_INFO = "ΣΤΟΙΧΕΙΑ ΕΠΙΚΟΙΝΩΝΙΑΣ" %}
|
||||
{% set L_PAYMENT_INFO = "ΣΤΟΙΧΕΙΑ ΠΛΗΡΩΜΗΣ" %}
|
||||
{% else %}
|
||||
{% set L_QUOTATION = "QUOTATION" %}
|
||||
{% set L_NUMBER = "Number" %}
|
||||
{% set L_DATE = "Date" %}
|
||||
{% set L_CLIENT = "CLIENT DETAILS" %}
|
||||
{% set L_ORDER_META = "ORDER DETAILS" %}
|
||||
{% set L_ORDER_TYPE = "Order Type" %}
|
||||
{% set L_SHIP_METHOD = "Ship. Method" %}
|
||||
{% set L_SHIP_DATE = "Est. Delivery" %}
|
||||
{% set L_DESC = "Description" %}
|
||||
{% set L_UNIT_COST = "Unit Cost" %}
|
||||
{% set L_DISC = "Disc." %}
|
||||
{% set L_QTY = "Qty" %}
|
||||
{% set L_UNIT = "Unit" %}
|
||||
{% set L_VAT_COL = "VAT" %}
|
||||
{% set L_TOTAL = "Total" %}
|
||||
{% set L_SUBTOTAL = "Subtotal" %}
|
||||
{% set L_GLOBAL_DISC = quotation.global_discount_label or "Discount" %}
|
||||
{% set L_NEW_SUBTOTAL = "New Subtotal" %}
|
||||
{% set L_VAT = "Total VAT" %}
|
||||
{% set L_SHIPPING_COST = "Shipping / Transport" %}
|
||||
{% set L_INSTALL_COST = "Installation" %}
|
||||
{% set L_EXTRAS = quotation.extras_label or "Extras" %}
|
||||
{% set L_FINAL = "TOTAL DUE" %}
|
||||
{% set L_COMMENTS = "NOTES" %}
|
||||
{% set L_VALIDITY = "This quotation is valid for 30 days from the date of issue." %}
|
||||
{% set L_ORG = "Organization" %}
|
||||
{% set L_CONTACT = "Contact" %}
|
||||
{% set L_ADDRESS = "Location" %}
|
||||
{% set L_PHONE = "Phone" %}
|
||||
{% set L_COMPANY_ADDR = "E.O. Antirriou Ioanninon 23, Agrinio, 30131, Greece" %}
|
||||
{% set L_CONTACT_INFO = "CONTACT INFORMATION" %}
|
||||
{% set L_PAYMENT_INFO = "PAYMENT DETAILS" %}
|
||||
{% endif %}
|
||||
|
||||
{# ── Derived values ── #}
|
||||
{% set today = quotation.created_at[:10] %}
|
||||
|
||||
{# ── Find phone/email contacts + check if primary contact is already phone/email ── #}
|
||||
{% set ns = namespace(customer_phone='', customer_email='', primary_is_phone=false, primary_is_email=false) %}
|
||||
{% for contact in customer.contacts %}
|
||||
{% if contact.type == 'phone' and contact.value %}{% if contact.primary %}{% set ns.customer_phone = contact.value %}{% set ns.primary_is_phone = true %}{% elif not ns.customer_phone %}{% set ns.customer_phone = contact.value %}{% endif %}{% endif %}
|
||||
{% if contact.type == 'email' and contact.value %}{% if contact.primary %}{% set ns.customer_email = contact.value %}{% set ns.primary_is_email = true %}{% elif not ns.customer_email %}{% set ns.customer_email = contact.value %}{% endif %}{% endif %}
|
||||
{% endfor %}
|
||||
{% set customer_phone = ns.customer_phone %}
|
||||
{% set customer_email = ns.customer_email %}
|
||||
{% set primary_is_phone = ns.primary_is_phone %}
|
||||
{% set primary_is_email = ns.primary_is_email %}
|
||||
|
||||
<!-- HEADER -->
|
||||
<div class="header">
|
||||
<div class="company-block">
|
||||
<img class="logo" src="./logo.png" alt="BellSystems"/>
|
||||
<p>{{ L_COMPANY_ADDR }}</p>
|
||||
</div>
|
||||
<div class="quotation-meta-block">
|
||||
<div class="doc-type">{{ L_QUOTATION }}</div>
|
||||
<div class="meta-line"><span class="meta-label">{{ L_NUMBER }}: </span><span class="meta-value">{{ quotation.quotation_number }}</span></div>
|
||||
<div class="meta-line"><span class="meta-label">{{ L_DATE }}: </span><span class="meta-value">{{ today }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TITLE / SUBTITLE -->
|
||||
{% if quotation.title %}
|
||||
<div class="quotation-title">
|
||||
<h2>{{ quotation.title }}</h2>
|
||||
{% if quotation.subtitle %}<p>{{ quotation.subtitle }}</p>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- CLIENT + ORDER META -->
|
||||
<div class="info-row">
|
||||
|
||||
<div class="client-block">
|
||||
<div class="block-title">{{ L_CLIENT }}</div>
|
||||
<table class="fields"><tbody>{% if customer.organization %}<tr><td class="lbl">{{ L_ORG }}</td><td class="val">{{ customer.organization }}</td></tr>{% endif %}{% set name_parts = [customer.title, customer.name, customer.surname] | select | list %}{% if name_parts %}<tr><td class="lbl">{{ L_CONTACT }}</td><td class="val">{{ name_parts | join(' ') }}</td></tr>{% endif %}{% if customer.location %}{% set loc_parts = [customer.location.city, customer.location.region, customer.location.country] | select | list %}{% if loc_parts %}<tr><td class="lbl">{{ L_ADDRESS }}</td><td class="val">{{ loc_parts | join(', ') }}</td></tr>{% endif %}{% endif %}{% if customer_email %}<tr><td class="lbl">Email</td><td class="val">{{ customer_email }}</td></tr>{% endif %}{% if customer_phone %}<tr><td class="lbl">{{ L_PHONE }}</td><td class="val">{{ customer_phone }}</td></tr>{% endif %}</tbody></table>
|
||||
</div>
|
||||
|
||||
<div class="order-block">
|
||||
<div class="block-title">{{ L_ORDER_META }}</div>
|
||||
<table class="fields"><tbody>{% if quotation.order_type %}<tr><td class="lbl">{{ L_ORDER_TYPE }}</td><td class="val">{{ quotation.order_type }}</td></tr>{% endif %}{% if quotation.shipping_method %}<tr><td class="lbl">{{ L_SHIP_METHOD }}</td><td class="val">{{ quotation.shipping_method }}</td></tr>{% endif %}{% if quotation.estimated_shipping_date %}<tr><td class="lbl">{{ L_SHIP_DATE }}</td><td class="val">{{ quotation.estimated_shipping_date }}</td></tr>{% else %}<tr><td class="lbl">{{ L_SHIP_DATE }}</td><td class="val text-muted">—</td></tr>{% endif %}</tbody></table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ITEMS TABLE -->
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:38%">{{ L_DESC }}</th>
|
||||
<th class="right" style="width:11%">{{ L_UNIT_COST }}</th>
|
||||
<th class="center" style="width:7%">{{ L_DISC }}</th>
|
||||
<th class="center" style="width:7%">{{ L_QTY }}</th>
|
||||
<th class="center" style="width:7%">{{ L_UNIT }}</th>
|
||||
<th class="center" style="width:6%">{{ L_VAT_COL }}</th>
|
||||
<th class="right" style="width:12%">{{ L_TOTAL }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in quotation.items %}
|
||||
<tr>
|
||||
<td>{{ item.description or '' }}</td>
|
||||
<td class="right">{{ item.unit_cost | format_money }}</td>
|
||||
<td class="center">
|
||||
{% if item.discount_percent and item.discount_percent > 0 %}
|
||||
{{ item.discount_percent | int }}%
|
||||
{% else %}
|
||||
<span class="dash">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="center">{{ item.quantity | int if item.quantity == (item.quantity | int) else item.quantity }}</td>
|
||||
<td class="center muted">{{ item.unit_type }}</td>
|
||||
<td class="center">
|
||||
{% if item.vat_percent and item.vat_percent > 0 %}
|
||||
{{ item.vat_percent | int }}%
|
||||
{% else %}
|
||||
<span class="dash">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="right">{{ item.line_total | format_money }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if quotation.items | length == 0 %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-muted" style="text-align:center; padding: 12px;">—</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{# ── Shipping / Install as special rows ── #}
|
||||
{% set has_special = (quotation.shipping_cost and quotation.shipping_cost > 0) or (quotation.install_cost and quotation.install_cost > 0) %}
|
||||
{% if has_special %}
|
||||
<tr class="special-spacer"><td colspan="7"></td></tr>
|
||||
{% endif %}
|
||||
|
||||
{% if quotation.shipping_cost and quotation.shipping_cost > 0 %}
|
||||
{% set ship_net = quotation.shipping_cost * (1 - quotation.shipping_cost_discount / 100) %}
|
||||
<tr class="special-row">
|
||||
<td>{{ L_SHIPPING_COST }}{% if quotation.shipping_cost_discount and quotation.shipping_cost_discount > 0 %} <span style="font-size:7.5pt; color:#7a9cc8;">(-{{ quotation.shipping_cost_discount | int }}%)</span>{% endif %}</td>
|
||||
<td class="right">{{ quotation.shipping_cost | format_money }}</td>
|
||||
<td class="center"><span class="dash">—</span></td>
|
||||
<td class="center">1</td>
|
||||
<td class="center muted">—</td>
|
||||
<td class="center"><span class="dash">—</span></td>
|
||||
<td class="right">{{ ship_net | format_money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if quotation.install_cost and quotation.install_cost > 0 %}
|
||||
{% set install_net = quotation.install_cost * (1 - quotation.install_cost_discount / 100) %}
|
||||
<tr class="special-row">
|
||||
<td>{{ L_INSTALL_COST }}{% if quotation.install_cost_discount and quotation.install_cost_discount > 0 %} <span style="font-size:7.5pt; color:#7a9cc8;">(-{{ quotation.install_cost_discount | int }}%)</span>{% endif %}</td>
|
||||
<td class="right">{{ quotation.install_cost | format_money }}</td>
|
||||
<td class="center"><span class="dash">—</span></td>
|
||||
<td class="center">1</td>
|
||||
<td class="center muted">—</td>
|
||||
<td class="center"><span class="dash">—</span></td>
|
||||
<td class="right">{{ install_net | format_money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- TOTALS + VAT NOTICE -->
|
||||
<div class="below-table">
|
||||
|
||||
<div class="vat-notice">
|
||||
</div>
|
||||
|
||||
<table class="totals-table">
|
||||
<tr>
|
||||
<td class="label">{{ L_SUBTOTAL }}</td>
|
||||
<td class="value">{{ quotation.subtotal_before_discount | format_money }}</td>
|
||||
</tr>
|
||||
{% if quotation.global_discount_percent and quotation.global_discount_percent > 0 %}
|
||||
<tr class="discount-row">
|
||||
<td class="label">{{ L_GLOBAL_DISC }} ({{ quotation.global_discount_percent | int }}%)</td>
|
||||
<td class="value">- {{ quotation.global_discount_amount | format_money }}</td>
|
||||
</tr>
|
||||
<tr class="new-subtotal-row">
|
||||
<td class="label">{{ L_NEW_SUBTOTAL }}</td>
|
||||
<td class="value">{{ quotation.new_subtotal | format_money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr class="vat-row">
|
||||
<td class="label">{{ L_VAT }}</td>
|
||||
<td class="value">{{ quotation.vat_amount | format_money }}</td>
|
||||
</tr>
|
||||
{% if quotation.extras_cost and quotation.extras_cost > 0 %}
|
||||
<tr>
|
||||
<td class="label">{{ L_EXTRAS }}</td>
|
||||
<td class="value">{{ quotation.extras_cost | format_money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr class="final-row">
|
||||
<td class="label">{{ L_FINAL }}</td>
|
||||
<td class="value">{{ quotation.final_total | format_money }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- SPACER: flexible gap between totals and notes -->
|
||||
<div class="main-content-gap"></div>
|
||||
|
||||
<!-- COMMENTS / NOTES -->
|
||||
{% set qn = quotation.quick_notes or {} %}
|
||||
{% set has_quick = (qn.payment_advance and qn.payment_advance.enabled) or (qn.lead_time and qn.lead_time.enabled) or (qn.backup_relays and qn.backup_relays.enabled) %}
|
||||
{% set has_comments = quotation.comments and quotation.comments | length > 0 %}
|
||||
|
||||
{% if has_quick or has_comments %}
|
||||
<div class="comments-section">
|
||||
<div class="section-title">{{ L_COMMENTS }}</div>
|
||||
<ul>
|
||||
|
||||
{# ── Quick Notes ── #}
|
||||
|
||||
{# Payment Advance #}
|
||||
{% if qn.payment_advance and qn.payment_advance.enabled %}
|
||||
{% set pct = qn.payment_advance.percent | string %}
|
||||
{% if lang == 'gr' %}
|
||||
<li>Απαιτείται προκαταβολή <strong>{{ pct }}%</strong> με την επιβεβαίωση της παραγγελίας.</li>
|
||||
{% else %}
|
||||
<li><strong>{{ pct }}%</strong> advance payment is required upon order confirmation.</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# Lead Time #}
|
||||
{% if qn.lead_time and qn.lead_time.enabled %}
|
||||
{% set days = qn.lead_time.days | string %}
|
||||
{% if lang == 'gr' %}
|
||||
<li>Εκτιμώμενος χρόνος παράδοσης, <strong>{{ days }} εργάσιμες ημέρες</strong> από την επιβεβαίωση της παραγγελίας και παραλαβή της προκαταβολής.</li>
|
||||
{% else %}
|
||||
<li>Estimated delivery time is <strong>{{ days }} working days</strong> from order confirmation and receipt of advance payment.</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# Backup Relays #}
|
||||
{% if qn.backup_relays and qn.backup_relays.enabled %}
|
||||
{% set n = qn.backup_relays.count | int %}
|
||||
{% if lang == 'gr' %}
|
||||
{% if n == 1 %}
|
||||
<li>Συμπεριλαμβάνονται: <strong>{{ n }} έξτρα Εφεδρικό Ρελέ Ισχύος</strong></li>
|
||||
{% else %}
|
||||
<li>Συμπεριλαμβάνονται: <strong>{{ n }} έξτρα Εφεδρικά Ρελέ Ισχύος</strong></li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if n == 1 %}
|
||||
<li><strong>{{ n }} Extra Relay</strong> included as Backup, free of charge.</li>
|
||||
{% else %}
|
||||
<li><strong>{{ n }} Extra Relays</strong> included as Backups, free of charge.</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# ── Dynamic comments ── #}
|
||||
{% if has_comments %}
|
||||
{% for comment in quotation.comments %}
|
||||
{% if comment and comment.strip() %}
|
||||
<li>{{ comment }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- VALIDITY -->
|
||||
<div class="footer">
|
||||
<span class="validity">{{ L_VALIDITY }}</span>
|
||||
</div>
|
||||
|
||||
<!-- FIXED BOTTOM FOOTER: contact + payment (repeats every page) -->
|
||||
<div class="fixed-footer">
|
||||
|
||||
<div class="footer-block">
|
||||
<div class="footer-block-title">{{ L_CONTACT_INFO }}</div>
|
||||
<dl>
|
||||
<dt>{% if lang == 'gr' %}Εταιρεία{% else %}Company{% endif %}</dt>
|
||||
<dd>BellSystems</dd>
|
||||
<dt>{% if lang == 'gr' %}Τηλ.{% else %}Phone{% endif %}</dt>
|
||||
<dd>+(30) 26410 33344</dd>
|
||||
<dt>{% if lang == 'gr' %}Email{% else %}Email{% endif %}</dt>
|
||||
<dd>sales@bellsystems.gr</dd>
|
||||
<dt>Web</dt>
|
||||
<dd>www.bellsystems.gr</dd>
|
||||
<dt>Links</dt>
|
||||
<dd><img src="./linktree.png" alt="linktr.ee/bellsystems" style="height: 7pt; vertical-align: middle;"/></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="footer-block">
|
||||
<div class="footer-block-title">{{ L_PAYMENT_INFO }}</div>
|
||||
<dl>
|
||||
<dt>{% if lang == 'gr' %}Τράπεζα{% else %}Bank{% endif %}</dt>
|
||||
<dd>Piraeus Bank</dd>
|
||||
<dt>{% if lang == 'gr' %}Δικαιούχος{% else %}Holder{% endif %}</dt>
|
||||
<dd>Pontikas Georgios</dd>
|
||||
<dt>{% if lang == 'gr' %}Αριθμός{% else %}Account No.{% endif %}</dt>
|
||||
<dd>6264-1484-35226</dd>
|
||||
<dt>IBAN</dt>
|
||||
<dd>GR8101712640006264148435226</dd>
|
||||
<dt>BIC/SWIFT</dt>
|
||||
<dd>PIRBGRAA</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="footer-ref">
|
||||
<span class="ref-quot">{{ quotation.quotation_number }}</span>
|
||||
<span class="ref-page">{% if lang == 'gr' %}Σελίδα {% else %}Page {% endif %}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user