feat(templates): carry a monogram, a ship-to, per-line tax and a payee on the structured invoice - #622
Merged
DemchaAV merged 1 commit intoAug 31, 2026
Conversation
…e on the structured invoice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The structured invoice model landed in #611 with one consumer,
ConsultingInvoice. A model shaped around one document is a model nobody has tested, and the next published invoice — a UK studio's, with a drawn monogram, a delivery address and VAT per line — found six things it could not say.Each of them is general rather than one design's whim, which is the test this change had to pass before touching a public record.
What changed
InvoiceBrand.monogramTop/monogramBottom— a lockup drawn as two lines of initials rather than an image.hasMonogram()answers it the wayhasLogo()already answers the other.InvoiceContactBlock.taxRegistrationLabel/taxRegistrationNumber— a second labelled registration. A UK sender prints both a company number and a VAT number; the model had room for one, and the labels are content because they differ by jurisdiction.StructuredInvoiceData.shipTo— the delivery address beside the billing one. It normalises to the empty recipient rather than null, like every other block, so preset code reads it without a check.InvoiceServiceLines.Line.vatRateandColumns.vat— the tax rate printed per line and the column heading it sits under. It is a String, not a number, because what a sheet prints is20%in one jurisdiction and something else in another, and the model should not decide the wording.InvoicePaymentBlock.accountHolder/signOff— who the money is paid to, set above the fields, and the closing line beside the due notice.Every addition is blank when absent. Every constructor that predates one is kept explicitly.
Verification
Full reactor gate → BUILD SUCCESS; the invoice suites 27/27.
The compatibility promise is pinned twice over.
StructuredInvoiceCompatibilityTestexercises each old constructor and asserts the new field comes back blank, plus that an absentshipTonormalises to the empty recipient rather than null. AndConsultingInvoice— the model's existing consumer — passes its exact layout snapshot and its pixel baseline untouched, which is the stronger proof: had any of this been more than additive, those two would have moved.Notes
luma-co-studio-invoice, whose entrypoint had to be reconstructed before it could be ported at all.Lane: canonical (templates.data.invoice + qa) — no engine changes, no preset changes.