Reset the statement window positions to the app's proven #9 (9x4) double-window geometry, mirroring sales_invoice_ns.html — recipient window at top:1.5in/left:1.125in. It previously copied the dunning format's 1.9in, which sits too low for a #9. Tighten the body padding-top to keep clearance below the higher window, and correct the stale #10 references in the template comment and docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
98 lines
3.5 KiB
HTML
98 lines
3.5 KiB
HTML
{# One customer account statement = one printed page.
|
||
Envelope geometry (recipient window at top:1.5in / left:1.125in) mirrors the
|
||
app's proven #9 (9x4) double-window print format (sales_invoice_ns.html) so
|
||
the same #9 double-window envelopes work. Rendered via
|
||
frappe.render_template with context key `s`
|
||
(see ns_app.api.statements.get_statement_data). #}
|
||
{% set fmt = frappe.utils.fmt_money %}
|
||
<div class="statement-page">
|
||
|
||
<!-- Return address (top-left envelope window) -->
|
||
<div class="return-window">
|
||
<strong>{{ s.company_name }}</strong><br>
|
||
{{ s.return_address | safe }}
|
||
</div>
|
||
|
||
<!-- Document header (top-right) -->
|
||
<div class="doc-header">
|
||
<div class="doc-title">STATEMENT</div>
|
||
<div><strong>Date:</strong> {{ frappe.utils.formatdate(s.statement_date, "MM-dd-yyyy") }}</div>
|
||
<div><strong>Account:</strong> {{ s.customer }}</div>
|
||
</div>
|
||
|
||
<!-- Recipient address (lower envelope window) -->
|
||
<div class="recipient-window">
|
||
{{ s.customer_name }}<br>
|
||
{{ s.customer_address | safe }}
|
||
</div>
|
||
|
||
<!-- Statement body (starts below the address windows) -->
|
||
<div class="statement-body">
|
||
|
||
<div class="intro">
|
||
The following is a summary of your account as of
|
||
{{ frappe.utils.formatdate(s.statement_date, "MM-dd-yyyy") }}.
|
||
Please remit payment for any past-due balance at your earliest convenience.
|
||
</div>
|
||
|
||
<table class="items">
|
||
<thead>
|
||
<tr>
|
||
<th>Invoice</th>
|
||
<th class="c">Date</th>
|
||
<th class="c">Due Date</th>
|
||
<th class="c">Days Overdue</th>
|
||
<th class="c">Aging</th>
|
||
<th class="r">Outstanding</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for inv in s.invoices %}
|
||
<tr class="{{ 'overdue' if inv.is_overdue else '' }}">
|
||
<td>{{ inv.name }}{% if inv.is_late_fee %} <span class="tag">late fee</span>{% endif %}</td>
|
||
<td class="c">{{ frappe.utils.formatdate(inv.posting_date, "MM-dd-yyyy") }}</td>
|
||
<td class="c">{{ frappe.utils.formatdate(inv.due_date, "MM-dd-yyyy") }}</td>
|
||
<td class="c">{{ inv.days_overdue if inv.days_overdue else "—" }}</td>
|
||
<td class="c">{{ inv.aging_bucket }}</td>
|
||
<td class="r">{{ fmt(inv.outstanding_amount, currency=s.currency) }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- Totals -->
|
||
<div class="totals">
|
||
<p class="grand"><span>Total Due:</span><span>{{ fmt(s.total_due, currency=s.currency) }}</span></p>
|
||
</div>
|
||
|
||
<!-- Aging summary -->
|
||
<table class="aging">
|
||
<thead>
|
||
<tr>
|
||
<th class="c">Current</th>
|
||
<th class="c">1–30</th>
|
||
<th class="c">31–60</th>
|
||
<th class="c">61–90</th>
|
||
<th class="c">90+</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="c">{{ fmt(s.aging["Current"], currency=s.currency) }}</td>
|
||
<td class="c">{{ fmt(s.aging["1-30"], currency=s.currency) }}</td>
|
||
<td class="c">{{ fmt(s.aging["31-60"], currency=s.currency) }}</td>
|
||
<td class="c">{{ fmt(s.aging["61-90"], currency=s.currency) }}</td>
|
||
<td class="c">{{ fmt(s.aging["90+"], currency=s.currency) }}</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<div class="footer">
|
||
Prompt payment is always appreciated. We accept payments by check or over
|
||
the phone using a debit or credit card. Automatic payment setup is also
|
||
available upon request. Please contact us if payment has already been sent.
|
||
</div>
|
||
|
||
</div><!-- /statement-body -->
|
||
</div><!-- /statement-page -->
|