Skip to content

feat(templates): layered invoice/v2 skeleton on the extracted core#257

Merged
DemchaAV merged 1 commit into
2.0-devfrom
feat/invoice-v2-skeleton
Jun 28, 2026
Merged

feat(templates): layered invoice/v2 skeleton on the extracted core#257
DemchaAV merged 1 commit into
2.0-devfrom
feat/invoice-v2-skeleton

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

Stage-1 extracted a neutral templates.core.* (theme / identity / text / widgets). The next step brings the invoice family onto it. This PR stands up an invoice/v2 layered family — the skeleton the cinematic pixel-port (2.1b) builds on — so an invoice renders on core + a BrandTheme the same way the cv.v2 presets do.

What

  • core.theme: additive invoiceModern() factories on BrandTheme / Palette / Typography / Spacing — new static factories only, zero existing-caller changes.
  • invoice/v2/presets/ModernInvoice (DocumentTemplate<InvoiceDocumentSpec>, create() / create(BrandTheme)): composes the hero panel, FROM / BILL TO parties, line-items table, and notes / payment-terms footer through the canonical DSL, reading every value from the theme.
  • examples: ModernInvoiceV2Example + a GenerateAllExamples row.
  • smoke test: identity, both factory variants, theme-independence (renders under a non-invoice theme), and an empty invoice.

Three deliberate choices (vs the original plan bullet):

  1. Reuse templates.data.invoice.* instead of duplicating into invoice/v2/data — that model is already render-neutral, builder-driven, and shared with the proven builtin; forking it would be the smell.
  2. Parties render inline, not through core.identity.PartyIdentityContact mandates a non-blank phone/email/address triple (a one-person CV masthead), but invoice party fields are optional and an invoice shows two side-by-side parties.
  3. The line-items table is built inline via the DSL (DocumentTableColumn.auto()/.fixed()) — core.widgets.TableWidget is equal-width only (no header/zebra/total row), so it can't express it.

Follow-up (2.1b): exact pixel-port of builtins.InvoiceTemplateV2's look (BusinessTheme.modern() colours), visual snapshots, and migrating the invoice examples off the builtin.

Tests

./mvnw verify javadoc:javadoc -pl . → BUILD SUCCESS, 1617 tests, 0 failures; javadoc clean. The example renders a clean one-page invoice at examples/target/generated-pdfs/templates/invoice/invoice-modern-v2.pdf.

Stand up an invoice/v2 family that renders on templates.core + a
BrandTheme, mirroring the cv.v2 layered shape. ModernInvoice
(DocumentTemplate<InvoiceDocumentSpec>) composes the hero panel, the
FROM / BILL TO parties, the line-items table, and the notes /
payment-terms footer through the canonical DSL.

- core.theme: add invoiceModern() factories to BrandTheme / Palette /
  Typography / Spacing (additive — no existing caller changes).
- invoice/v2/presets/ModernInvoice + package-info, reusing the existing
  templates.data.invoice model. Parties render inline (two-party layout
  with optional contact fields), not through the CV-shaped PartyIdentity.
- examples: ModernInvoiceV2Example + a GenerateAllExamples row.
- smoke test: identity, both factory variants, theme-independence, and
  an empty invoice.

The exact cinematic pixel-port (BusinessTheme.modern() colours, visual
snapshots, migrating the invoice examples off builtins.InvoiceTemplateV2)
is the follow-up.
@DemchaAV DemchaAV merged commit 90c9335 into 2.0-dev Jun 28, 2026
11 checks passed
@DemchaAV DemchaAV deleted the feat/invoice-v2-skeleton branch June 28, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant