Foodops
All docs

Settings · Updated 2026-08-16 · v02215ba

PDF Templates & Transaction Series

Audio narration for this article is generated with the weekly docs refresh.

Plain-English summary

PDF Templates control how your receipts, invoices, POs, and credit notes look when printed or emailed — logo placement, footer text, colour scheme, which fields appear. Transaction Series control the numbering system — "SO-0001/2026" vs "INV-2026-001" — with support for annual resets so the counter restarts each financial year. Together they define the visual and structural identity of every document Foodops generates.

When you'd use this

  • Brand setup — upload logo, set header/footer, choose receipt layout
  • Compliance — ensure tax invoices include all legally-required fields (TIN, GST registration, etc.)
  • Financial year start — verify annual-reset series tick over correctly
  • Multi-brand — different PDF templates per outlet/brand

How to access

  • PDF Templates: /settings/customisation/pdf-templates (admin backoffice — admin.foodops.io)
  • Transaction Series: /settings/customisation/transaction-series
  • Sidebar: Settings → Customisation section (settingsNavConfig.ts group customisation)

The legacy app.foodops.io /settings/templates pages (Blazor Haafai.Layouts) are retired at the July-2026 launch. Both pages live in the admin backoffice; templates are stored/served by hubits-api-sales DocumentTemplatesController and rendered by its DocumentGenerationService (see below).

PDF Templates

PDF Templates showing Sales (Customer Statement, Credit Note, Payment) and Expenses (Purchase Order, Bill, Debit Note, Payments Made, Customer Statement) template categories with a New Template button

Templates are grouped by document type:

Sales templates: Customer Statement · Credit Note · Payment Expense templates: Purchase Order · Bill · Debit Note · Payments Made · Customer Statement

Each template type can have multiple versions. The active one is used for new documents; switch by clicking the template and marking it active.

Important: NEW (2026-05): visual block-builder editor replaces the HTML-textarea modal Clicking New Template or Edit on a template no longer opens a small HTML-textarea modal — it now navigates to a dedicated full-page document template editor (Zoho-Books-style) at /settings/customisation/pdf-templates/new (or /:id/edit) [code: foodops-admin-app/apps/admin/src/pages/settings/customisation/pdf-templates/TemplateEditorPage.tsx; commit f4cadc0 2026-05-26]. It's a three-column layout: a Palette of drag-and-drop blocks (Heading, Text, Image/Logo, Spacer, Divider, Row/Column, Company/Customer Address, Key-Value Table, Doc-Number Heading, Line-Items Table, Totals, Signature, Footer Text, Custom HTML — 15 block types), a paper-sized Canvas with margin guides and header/footer regions, and a context-aware Properties panel. Editing an existing template loads its saved layout (legacy raw-HTML templates open wrapped in a single Custom-HTML block, so nothing is silently discarded) [code: components/settings/customisation/template-editor/deserialize.ts; commit a69b09e 2026-05-26]. Editor capabilities: drag-to-reorder blocks within and across header/body/footer regions, a Visual | HTML toggle (Monaco-powered code mode), a live Preview pane (client-side instant render or server-side render), undo/redo (Cmd/Ctrl+Z / Shift+Z), Cmd/Ctrl+S to save, and an unsaved-changes guard on tab close [code: commits 5cfc40d, 0d4b53c 2026-05-26].

Customisation options per template (now surfaced through the visual editor + Properties panel):

  • Logo — Image/Logo block; upload company logo, position via the block
  • Header / Footer — header/footer regions with their own blocks (free-form text, addresses, etc.), toggleable and per-page-positionable
  • Block-level styling — heading/text styling per block; insertable {{token}} placeholders for document/line-item data
  • Field visibility — Line-Items Table block exposes per-column visibility (e.g., hide TIN on walk-in receipts, show it on tax invoices)
  • Paper size & orientation — A4 / Letter / Legal / A5, portrait/landscape, with margins, set at the template level

How templates are selected and rendered (new stack)

  • Storage / CRUD: templates are DocumentTemplate rows, keyed by entity type (entityTypeId — Invoice=2, Payment=3, CreditNote=4, Quote=13, SalesOrder=25, plus CustomerStatement). The admin editor saves via documentTemplateService. [code: foodops-admin-app/apps/admin/src/services/documentTemplateService.ts; hubits-api-sales/Hubits.Sales.Api/Controllers/DocumentTemplatesController.cs:GetTemplates(entityTypeId) @ main]
  • Selection: which template a document uses is resolved per org/entity by DocumentTemplateHelper.GetTemplateFor (auto-seeds a default if none), and an invoice's chosen template comes from the sales register's InvoiceTemplateId (the invoice's PrintTemplate). [code: hubits-api-sales/.../DocumentGenerationService.cs:276-312 (invoice.PrintTemplate / "Check that the sales register has InvoiceTemplateId configured"); haafai.domain DocumentTemplateHelper @ staging]
  • Rendering: DocumentGenerationService resolves the template HTML (DocumentTemplateHelper.ResolveContent), inlines private images, and converts to PDF via HtmlToPdfService.ConvertHtmlToPdf (an HTML→PDF service). [code: hubits-api-sales/.../Services/Counter/Documents/{DocumentGenerationService.cs,HtmlToPdfService.cs} @ main]

Note: Renderer re-pointed — NOT haafai.app.common Earlier versions of this entry cited haafai.app.common ReportService (wkhtmltox) as the renderer. That is the legacy monolith path. In the new stack the rendering pipeline is hubits-api-sales (DocumentGenerationService + HtmlToPdfService) using DocumentTemplateHelper from haafai.domain. (The print broker foodops.app.printing handles thermal/physical printing of receipts/KOTs — distinct from this A4 document-PDF pipeline.)

Transaction Series

Transaction Series showing 7 configured series: Sales Orders (SO-, next 3), Payment (PAY-, next 2), Credit Notes (CR-, next 1, annual reset YES), Expense (EX-, next 1), Purchase Orders (PO-, next 1), Purchase Invoices (BILL-, next 1, annual reset YES), Supplier Credits (SCR-, next 1, annual reset YES)

Seven built-in series:

Series Prefix Next Annual Reset
Sales Orders SO- 3 No
Payment PAY- 2 No
Credit Notes CR- 1 Yes
Expense EX- 1 No
Purchase Orders PO- 1 No
Purchase Invoices BILL- 1 Yes
Supplier Credits SCR- 1 Yes

Info: Annual Reset Series with Annual Reset = Yes reset their counter to 1 on January 1 each year. The year is appended (e.g., CR-0001/2026CR-0001/2027). Series without annual reset increment forever. Choose based on your accounting conventions.

Each series is editable:

Field Purpose
Prefix Text before the number (e.g., "SO-", "INV-")
Next Number The next number to be assigned. Manually adjustable if you need to skip or align
Annual Reset Whether the counter resets each January 1

Key concepts

  • PDF Template — the rendering blueprint for a document type. Controls visual layout, branding, field visibility. Multiple templates per type; one active at a time.
  • Transaction Series — the numbering convention for a document type. Prefix + auto-incrementing number + optional year reset.
  • Annual Reset — counter resets to 1 each year. Useful for fiscal-year-aligned numbering (tax authorities sometimes require sequential numbering per year).
  • Next Number — adjustable. Use with caution — skipping numbers can trigger audit questions. Backdating (setting a lower number) is allowed but creates non-sequential records.
  • Thermal receipt — 80mm-width template for POS thermal printers. Different from A4 templates used for emailed/printed invoices.

Common questions

Q: How do I add my logo to receipts? A: PDF Templates → pick the relevant template (e.g., "Payment" for POS receipts) → upload logo. It appears on every future print/email of that template type.

Q: Can I have a different receipt look per outlet? A: Templates are org-wide by default. Multi-brand setups on higher plans can assign different templates per brand. For single-brand multi-outlet, all outlets share the same template.

Q: What happens if I edit a Transaction Series prefix mid-year? A: New documents get the new prefix; past documents keep the old one. Both coexist in reports — not recommended mid-year for audit clarity.

Q: The "Next Number" shows 3 for Sales Orders but I've only created 1 order — why? A: Voided or draft orders may have consumed numbers without completing. Transaction series assign numbers at creation, not at completion — cancelled orders still "use up" a number for audit traceability.

Q: Can I create custom series (e.g., for delivery notes)? A: The 7 built-in series cover standard document types. Custom series for arbitrary documents aren't exposed in the UI — contact support if you need one.

Q: The template editor looks completely different now — where did the HTML box go? A: As of the 2026-05 release, editing a template opens a full-page visual block-builder (drag-and-drop blocks, live preview) instead of the old single HTML-textarea modal. The raw HTML is still there — flip the editor's Visual | HTML toggle to edit it directly. Existing templates that were authored as raw HTML open inside a single Custom-HTML block, so your old layout is preserved.

  • 2026-07-23 (codebase, foodops-admin-app 70e66bc..e188062): Two editor-facing additions to the block-builder, neither contradicting existing entry claims. (1) The Properties panel's per-block styling (currently described only generically as 'heading/text styling per block') gained concrete controls — Font size (px), Font family (a fixed PDF-safe font-stack list: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana, Tahoma, Trebuchet MS, or inherit-default), Style (Bold/Italic toggle buttons), and a Color picker — serialized into the block's inline CSS (font-size/-weight/-style/-family/color) confirmed by new serialize.test.ts cases. (2) A new org-level 'Table Properties' dialog (TablePropertiesDialog.tsx, ported from the legacy POS) lets admins configure the Line-Items Table block's shared settings across ALL templates at once: a Labels tab (per-column visibility/width/label for Line Item Number, Item, Quantity, Rate, Discount, Amount — Description/Warehouse/Tax columns round-trip but aren't surfaced in this tab) and a Layout tab (table border toggle/color, plus font-size/background/font-color styling for the header row, item row, and item-description row). This is a materially richer mechanism than the entry's current one-line 'Field visibility — Line-Items Table block exposes per-column visibility' bullet — worth expanding that bullet into its own subsection once a screenshot of the dialog is available. Both changes are additive; no evidence of changes to PdfTemplatesPage.tsx/TransactionSeriesPage.tsx behavior (diffs unavailable) or to Transaction Series. (auto-applied by the truth pipeline; adversarially gated)
  • 2026-07-14 (codebase, hubits-api-sales 6f242ad..e31810a): GenerateQuoteDocument now eager-loads BillingAddress/ShippingAddress (with Country) via new EF Include/ThenInclude calls — a bug fix so the Quote PDF's {{Billing Address}}/{{Shipping Address}} template tokens (which render Model.BillingAddress?.AddressLine1..Country.Name) no longer come out blank from a null navigation property. Scoped to GenerateQuoteDocument only; doesn't touch DocumentTemplatesController, HtmlToPdfService, or any other document type's generation path, so the entry's 'How templates are selected and rendered' subsection remains accurate as written. Worth a one-line mention if this entry's token/placeholder documentation is expanded to call out per-document-type address rendering. (auto-applied by the truth pipeline; adversarially gated)
  • 2026-07-11 (codebase, foodops-admin-app 5c36f1b..e6e2d0e): Two editor-facing changes worth folding in. (1) Template scoping: the editor Toolbar gained an OutletSelector wired to a new template.outletId/setOutletId — templates can now be scoped to a single outlet instead of only org-wide/per-brand, contradicting the 'all outlets share the same template' Q&A (edit above). (2) Visual↔HTML round-trip behavior changed: editing in the Monaco HTML view now collapses the entire block body into one custom-html block via a new SET_BODY_HTML action (previously it appended/updated a custom-html block alongside the existing visual blocks, which fought re-serialization and made the editor feel uneditable per the commit's own rationale). Switching back to Visual mode now calls a new PARSE_BODY_HTML action that re-expands that single block through htmlToBlocks, so hand-edited HTML becomes structured blocks again (best-effort; anything unrecognized stays as text/custom-html). Neither change affects Transaction Series or the block palette/Properties panel structure; the Common-Questions Q&A on raw-HTML editing remains directionally accurate but doesn't mention the collapse-on-edit / re-expand-on-return mechanic. (auto-applied by the truth pipeline; adversarially gated)
  • 2026-07-04 (codebase, hubits-api-sales 1bbfd90..35483db): DocumentTemplatesController gained a new GET /resolve-invoice endpoint that resolves which invoice PDF template a Quote→Invoice conversion would apply, so the Convert dialog can pre-select it. It confirms and fleshes out this entry's existing claim that 'an invoice's chosen template comes from the sales register's InvoiceTemplateId' — the full fallback chain is: active register's InvoiceTemplateId → outlet's default template → any outlet template → org default template → any org template. No change to the PDF Templates or Transaction Series settings-page behavior documented here; worth folding this precedence detail into the 'How templates are selected and rendered' subsection next time this entry is touched. (auto-applied by the truth pipeline; adversarially gated)

Success: Verified 2026-04-16 · playwright Status: stable · Review due: 2026-07-15 Both pages verified live. 7 transaction series confirmed with exact prefix/next-number/annual-reset values from the test org.

Note: Code-verified 2026-05-04 · codebase Verified_by: codebase · Last verified: 2026-05-04 · haafai.app.foodops:4fdfac7 Curated source_repos[] to Haafai.Layouts/Areas/Settings/{Controllers/{Templates,SequenceNumberTypes}Controller.cs,Views/{Templates,SequenceNumberTypes}/**} — PDF Templates live under Haafai.Layouts (not Haafai.Restaurant.App as the old glob assumed), and Transaction Series is SequenceNumberTypes in code. No commits to either curated path since 2026-04-15: TemplatesController last touched 4fdfac7 2026-03-24 (mappers refactor); SequenceNumberTypes inactive since 2025. HIGH-drift flag was a false positive from broken globs. UI labels and the 7 series unchanged from 2026-04-16 playwright pass.

Note: Re-pointed after backend microservice split 2026-06-03 · codebase Verified_by: codebase · Last verified: 2026-06-03 · haafai.app.foodops:bf7c9d2 + foodops-admin-app:f3ae3e9 + haafai.app.common:004e2d5 Two repos added:

  • haafai/foodops-admin-app (backoffice settings UI, prod main): glob apps/admin/src/{pages/settings/customisation/{PdfTemplatesPage.tsx,TransactionSeriesPage.tsx,pdf-templates/**},components/settings/customisation/**} — the React backoffice hosts the PDF Templates page, the template-editor (pdf-templates/TemplateEditorPage.tsx + components/settings/customisation/template-editor/**), the Transaction Series page, and the sequence-number / document-template form dialogs.
  • haafai/haafai.app.common (shared PDF/document rendering NuGet, prod branch master): glob Haafai.Admin.Common/Services/{BaseReport.cs,BaseReportService.cs,ReportService.cs,Interfaces/IReportService.cs} — the shared report/document rendering layer (HTML→PDF via the libwkhtmltox engine in Haafai.Admin.Common) that materializes the PDF documents these templates define. Note: actual rendering is the wkhtmltox-based ReportService, not QuestPDF as the split-domain note suggested. All paths verified via gh api ...?ref=main (admin-app) / ?ref=master (common). Monolith glob still resolves on main; re-pinned to prod HEAD bf7c9d2. Did NOT add foodops.api or hubits.microservices.

Important: Content update 2026-06-04 · codebase — PDF template editor rewritten (real user-facing change) Verified_by: codebase · foodops-admin-app:main The backoffice replaced the basic HTML-textarea modal with a full-page visual block-builder editor (Zoho-Books-style) on a dedicated route /settings/customisation/pdf-templates/{new,:id/edit}. Landed across f4cadc0 (scaffold, 2026-05-26), 5cfc40d (DnD reorder + Monaco HTML mode + preview pane, 2026-05-26), 0d4b53c (keyboard shortcuts + unsaved-changes guard, 2026-05-26), a69b09e (legacy-HTML preservation + ContentJson round-trip, 2026-05-26), and 3bf9174 (logo repair, 2026-06-01). Updated the "PDF Templates" section + added a Common-Question Q&A. Transaction Series section unchanged (no commits to TransactionSeriesPage.tsx or SequenceNumberTypes since cutoff). NOTE: the Import Wizard also became a real React page (ImportWizardPage.tsx, commit 06cf8aa 2026-06-03) but that page belongs to the Settings Overview entry, not this one. Driver commit 3a73eb6 ("creating new entities in comboboxes and enhance quote handling") was a red herring for this entry — its only customisation touch was CSS-only layout tweaks to template-editor/Toolbar.tsx. The shared PDF renderer (haafai.app.common ReportService, wkhtmltox) is unchanged — 004e2d5 still HEAD; re-verified, backend rendering pipeline unchanged.

Important: Re-verified 2026-06-29 · codebase — NEW-STACK re-point (legacy app.foodops retired) Verified_by: codebase · foodops-admin-app:f6ffd0b + hubits-api-sales:19190b9 + haafai.domain:e138944 Legacy haafai.app.foodops removed from source_repos. Renderer re-pointed: dropped haafai.app.common (legacy wkhtmltox ReportService) and pointed at the new-stack pipeline — hubits-api-sales DocumentGenerationService + HtmlToPdfService, template content via haafai.domain DocumentTemplateHelper, CRUD via DocumentTemplatesController. CHANGES: (1) URLs /settings/templates/settings/customisation/pdf-templates, /settings/templates/transactions/settings/customisation/transaction-series; (2) added a "selection & rendering" subsection (templates keyed by entityTypeId; invoice template via sales-register InvoiceTemplateId). The block-builder editor section (TemplateEditorPage + documentTemplateService) re-confirmed present on main. RESIDUAL: the Sales/Expenses template category list + 7 transaction-series values are screenshot-derived (legacy) and not re-read against PdfTemplatesPage.tsx/TransactionSeriesPage.tsx field-by-field this pass — flag for re-check.

Related

  • Settings Overview — Customisation section
  • POS Takeaway Order — where receipts are printed
  • Shops Bills — uses the Purchase Invoices series
  • Suppliers & POs — uses the Purchase Orders series

Go beyond POS.
Choose the total solution.

Focus on creating the best experience for your guests while we handle the rest.