Skip to content

feat(templates): promote the Luma Studio invoice onto the structured model - #623

Merged
DemchaAV merged 1 commit into
feature/template-promotionfrom
feat/luma-studio-invoice-preset
Aug 31, 2026
Merged

DemchaAV merged 1 commit into
feature/template-promotionfrom
feat/luma-studio-invoice-preset

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

The structured invoice model landed with one consumer. #622 fitted a second published
invoice to it and added the six things it could not say; this is that invoice —
luma-co-studio-invoice, a studio sheet built around a cream sidebar — brought into
the templates/ module so it ships with the library instead of living as a standalone
bundle.

It is also the first promoted preset that has to paginate. The CV presets before it
reproduce one sheet and refuse anything longer; an invoice's length belongs to the
document, so the line-items table has to flow and every page has to keep the same
frame.

What

invoice.presets.LumaStudioInvoice on StructuredInvoiceDocumentSpec, composed from
seven package-private files — the measured geometry and type scale, the icon loader,
the idioms the sheet repeats, and one file per region.

The sheet: the brand lockup on a terracotta block at the head of the sidebar with the
ornament running down the rest of it; the sender over the document title and its
metadata; the billed-to and shipped-to pair across a rule; the priced service lines
with a VAT column; the totals stack closing on a filled total-due band; the notes and
bank details side by side; the sign-off band.

Long invoices flow. The table repeats its dark header, the totals stack and each
closing block stay whole, and the paper tint, the sidebar column and the dark foot
band are page backgrounds, so every page carries the same frame and the folio always
has a dark ground.

One deliberate departure from the sheet it ports. On the published template the
sign-off relies on that background band, which is pinned to the paper's edge — right
on a one-page invoice, and white-on-cream in the middle of the last page of a longer
one, where the flow ends well above the paper's foot. Here the sign-off draws its own
strip, so it is legible wherever it lands. The cost is measured: 7 440 of 2 173 720
pixels on the reference sheet, where the strip starts three points above the
background band it sits on, and one extra layout node. It is flow content only
because footer chrome carries text today — one size, one colour, no glyph, where this
band needs two faces and a disc. Once feat/chrome-footer lands, the sign-off belongs
in a footer zone pinned to the foot of the last page and the strip goes away; both
class Javadocs say so.

Two details worth naming. Amounts take their mark from currencyCode() rather than a
second stated field, so the sheet cannot contradict itself; an unknown code prints
itself rather than leaving a figure bare. And the contact channels carry tel:,
mailto: and https: targets derived from their values, with a parenthesised trunk
prefix — the (0) in +44 (0)20 … — dropped from the dial target the way a caller
dialling from abroad drops it.

Also here: the example (invoice-luma-studio-v2), its showcase row and its committed
preview.

Tests

./mvnw -B -ntp clean verify -pl :graph-compose-core,:graph-compose-render-pdf,:graph-compose-render-docx,:graph-compose-render-pptx,:graph-compose-templates,:graph-compose-testing,:graph-compose-qa,:graph-compose-coverage -am — BUILD SUCCESS.

  • LumaStudioInvoiceSmokeTest (13) — identity, the canonical render, the empty
    document through every guard, the table / totals / bank text, the currency mark for a
    known, an unknown and a blank code, the link targets, a supplier with one
    registration and with none, every line priced on the overflow document, the repeated
    header and folio on a continuation page, and the sign-off landing on its own dark
    ground. The last one was sabotaged and watched go red.
  • LumaStudioInvoiceLayoutSnapshotTest (2) — an exact snapshot of the one-page sheet
    and of the three-page one, where the table spans the first two pages and the closing
    blocks move whole onto the third.
  • LumaStudioInvoiceVisualParityTest (1) — pixel baseline, same budget and tolerance
    as the other structured-invoice gates.

The port itself was proven before the gates were written: rendered against the
published bundle's own fixtures on this engine, 0 of 2 173 720 pixels differ on the
one-page sheet and 0 on all three pages of its overflow fixture
, with 121 of 121
layout nodes identical in geometry — the only differences being the four node names
the promotion deliberately changes. The sign-off strip above is the one change made
after that.

Stacked on #622, which it needs for monogramTop / monogramBottom,
taxRegistration*, shipTo, vatRate / Columns.vat and accountHolder / signOff.

Comment on lines +126 to +128
page.addRow("Masthead", row -> row
.spacing(0)
.gap(0)
Comment on lines +140 to +142
page.addRow("Parties", row -> row
.spacing(0)
.gap(0)
Comment on lines +157 to +159
page.addRow("Closing", row -> row
.spacing(0)
.gap(0)
@DemchaAV
DemchaAV changed the base branch from feat/structured-invoice-luma-fields to feature/template-promotion August 31, 2026 11:59
…model

The structured invoice model landed with one consumer. The fields added
beside it fitted a second published invoice; this is that invoice —
`luma-co-studio-invoice`, a studio sheet built around a cream sidebar —
brought into the templates module so it ships with the library.

It is the first promoted preset that has to paginate. The line-items table
repeats its dark header, the totals stack and each closing block stay whole,
and the paper tint, the sidebar column and the dark foot band are page
backgrounds, so every page carries the same frame and the folio always has a
dark ground.

The sign-off carries its own strip rather than relying on that background
band, which is the one deliberate departure from the sheet being ported: the
band is pinned to the paper's edge, so on the last page of a longer invoice
the published template sets white words on pale paper. Drawing the strip with
the words fixes it wherever they land, at 7,440 of 2,173,720 pixels on the
reference sheet and one extra layout node. It is flow content only because
footer chrome carries text today; once a footer zone can hold a node the
sign-off belongs in one.

Amounts take their mark from the data's currency code rather than a second
stated field, and the contact channels carry dial, mail and web targets
derived from their values, with a parenthesised trunk prefix dropped from the
dial target.

Guarded by a smoke test, an exact layout snapshot over a one-page and a
three-page invoice, and a pixel-parity gate; the examples showcase gains
`invoice-luma-studio-v2`.
@DemchaAV
DemchaAV force-pushed the feat/luma-studio-invoice-preset branch from bd0eed7 to b14607b Compare August 31, 2026 11:59
@DemchaAV
DemchaAV merged commit 361f769 into feature/template-promotion Aug 31, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the feat/luma-studio-invoice-preset branch August 31, 2026 12:06
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.

2 participants