# Sales Invoice — Print Scenarios, Sizes & Format What a printed / downloaded / shared sales invoice looks like, per paper size and per invoice state. Source of truth: - Layouts: `Frontend/erp-system/components/sales/SalesInvoicePrint.tsx` - Shared print shell (sizes, PDF, send): `Frontend/erp-system/components/print/DocumentPrint.tsx` - Print CSS: `Frontend/erp-system/app/globals.css` (`.invoice-sheet`, `.invoice-print-root`) - Totals / lifecycle: `Backend/ERPCore/Services/SalesInvoiceService.cs`, `SalesPostingService.cs`, `SalesInvoicePaymentService.cs` Where it opens: **Sales → Invoices** (row action) and **Invoice detail → Print** open the print dialog; `/dashboard/sales/invoices/[id]/print` shows the same preview as a full page. --- ## 1. Paper sizes | Size | Sheet width | Page rule (`@page`) | Base font | Use for | |---|---|---|---|---| | **A4** (default) | 210 mm (on screen 210 × 297 mm) | `size: A4; margin: 12mm` | 14px (`text-sm`) | Office printers, email / WhatsApp PDF, B2B / credit customers | | **80mm** | 80 mm, padding 4 mm × 5 mm | `size: 80mm auto; margin: 3mm` | 11px | Standard thermal POS printer | | **58mm** | 58 mm, padding 2.5 mm × 4 mm | `size: 58mm auto; margin: 2mm` | 9.5px | Small / mobile thermal printer | - The dialog always opens on **A4**; the user switches with the **Paper size** dropdown. - Receipt sizes have **auto height** — one continuous page as long as the content. - A4 content longer than one page flows onto further pages; table rows and the totals / payment blocks don't split across pages (`break-inside: avoid`). ## 2. Output actions | Action | What happens | File name | |---|---|---| | **Print** | Browser print dialog; only the invoice sheet prints (app UI hidden), page size set from the choice above | — | | **Download** | Renders the previewed sheet to PDF (2× resolution). A4 → multi-page A4 PDF; receipts → one page at roll width × content height | `INV-xxxx.pdf`, `INV-xxxx-80mm.pdf`, `INV-xxxx-58mm.pdf` | | **Send** | Builds the same PDF, then opens the device share sheet with the PDF attached. If the browser can't share files: downloads the PDF and opens WhatsApp to the customer's phone (`0XXXXXXXXX` → `94XXXXXXXXX`) with a pre-filled message; user attaches the PDF | same as Download | Send message text: `Invoice INV-xxxx from — total Rs. x,xxx.xx, balance due Rs. x,xxx.xx.` (the balance part is omitted when fully paid). ## 3. Formatting rules (all sizes) | Item | Format | Example | |---|---|---| | Money | `Rs.` + thousands separator + exactly 2 decimals | `Rs. 12,450.00` | | Quantity | up to 3 decimals, trailing zeros dropped | `2`, `1.5`, `0.125` | | Dates | `dd/MM/yyyy` | `29/09/2026` | | Discounts | shown as negative | `-Rs. 250.00` | | Zero discount / tax on a line (A4) | em dash | `—` | | Accent colour (A4 only) | deep red `#8b1c24` for section underlines, header rule and status text | | | Receipts | black only, no fills, logo in greyscale (thermal-safe) | | ## 4. What each layout includes ### A4 1. **Header** — large `INVOICE` title; Invoice No., Invoice Date, Due Date; **Status** row only when the invoice is not Posted. Company logo top-right (if enabled). 2. **From** — company trade name (or legal name), address, city/country, phone, email, Tax Reg No (if enabled in template). 3. **Bill To** — customer name (snapshot at invoice time), address, phone, email, customer Tax No. 4. **Item Details table** — Item · Qty · Unit Price · Discount · Tax · Amount. Free-issue lines tagged `(free issue)`; free qty shown under qty as `+ N free`. 5. **Notes / Terms** (left) — each line of the template's *Terms & Conditions* then *Footer note*. 6. **Totals box** (right) — Subtotal; Discount / Tax / Round off (only when non-zero); **Total** (net payable). If anything is paid: Paid + **Balance Due**. 7. **Payment Method** — each recorded payment: date · bank/cash account · ref · amount; otherwise "No payment recorded yet." Bank transfer details below (if enabled). ### 80mm / 58mm receipt Single centred column, sections separated by dashed rules: 1. Logo (greyscale), company name (uppercase), address, `Tel:`, `Tax Reg:` (if enabled) 2. `INVOICE`, plus `*** DRAFT ***` / `*** CANCELLED ***` when not Posted 3. Invoice No., Date, Due, Customer, Phone 4. Items — name on one line, `qty x unit price +N free line total` on the next, `Disc -x` if discounted 5. Subtotal, Discount, Tax, Round off (non-zero only), **TOTAL** between heavy rules, Paid / **Balance** if paid 6. Payment list (date + account + amount), if any 7. Notes / terms (centred) 8. `Thank you!` Not on receipts: customer address/email, per-line tax column, bank transfer details. ## 5. Where the data comes from | Field | Source | |---|---| | Invoice no., date, lines, totals, status | Sales invoice (`GET /sales-invoices/{id}`) | | Customer name / tax no. | **Snapshot** stored on the invoice — later customer edits don't change old invoices | | Customer address, phone, email | Live customer record | | Due date | Not stored — `invoice date + customer.creditDays` (0 credit days → due date = invoice date) | | Payments | `GET /sales-invoices/{id}/payments` | | Company name, address, logo, bank details | Settings → Company Profile | | Logo on/off, Tax Reg No on/off, bank details on/off, terms, footer | Settings → Invoice Template | Only the invoice itself is required. If customer, payments, company profile or template fail to load, that block is just left out. With no company profile, A4 shows a hint on screen only (hidden when printed). ## 6. Scenarios | # | Scenario | What prints | |---|---|---| | 1 | **Draft** invoice | Normal layout + `Status: DRAFT` (A4, red) / `*** DRAFT ***` (receipt). Totals shown, no payments. | | 2 | **Posted, unpaid** | No status row. Totals box ends at **Total**; "No payment recorded yet." | | 3 | **Posted, partly paid** (installments) | Paid + **Balance Due** shown; each payment listed. Send text includes balance due. | | 4 | **Posted, fully paid** | Paid = Total, Balance Due `Rs. 0.00`; Send text has no balance part. | | 5 | **Cancelled** | `Status: CANCELLED` / `*** CANCELLED ***`. Only Drafts can be cancelled, so no payments. | | 6 | Line with **discount** (% or amount) | Discount column `-Rs. x`; Discount row in totals. | | 7 | Line with **tax** | Tax column amount (A4); Tax row in totals. | | 8 | **Free qty** on a paid line | `+ N free` under qty. | | 9 | **Free-issue** line (whole line free) | `(free issue)` / `(free)` after item name. | | 10 | **Credit customer** (creditDays > 0) | Due date = invoice date + credit days. | | 11 | **Cash customer** (creditDays = 0) | Due date = invoice date. | | 12 | Template **logo = None**, or no logo uploaded | No logo. | | 13 | Template **Show bank details** on + company bank set | "Bank transfer" block on A4 (bank, branch, account name/no., SWIFT). | | 14 | Template **Show Tax Reg No** on | Company Tax Reg No under From / receipt header. | | 15 | Terms / footer note filled | Printed line by line (blank lines skipped). | | 16 | Customer with **no phone** | Send → WhatsApp opens contact picker instead of a chat. | | 17 | Logo on a host without CORS | Print shows it; PDF replaces it with a blank so download still works. | | 18 | Long invoice (many lines) | A4: continues on page 2+; receipt: longer strip. | ## 7. Totals calculation (for checking printouts) Per invoice (`SalesInvoiceService.Recalculate`): ``` Subtotal = Σ (qty × unitPrice) DiscountTotal= Σ line discount TaxTotal = Σ line tax GrandTotal = Σ lineTotal + TaxTotal RoundOff = 0 (currently always 0 → row never shows) NetPayable = GrandTotal + RoundOff ← printed as "Total" Balance = NetPayable − Σ payments ``` Payment rules: only **Posted** invoices accept payments; a payment can't exceed the remaining balance. Only **Draft** invoices can be edited or cancelled. ## 8. Other invoice print route (legacy) `/print/sales/invoices/[id]` is an older A4-only page that follows the **Invoice Template style** (Classic / Compact / Modern). It includes warehouse, SKU and UOM columns and plain 2-decimal numbers without `Rs.`. The print dialog above does **not** use the template style — only its logo / tax no. / bank / terms settings.