You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a homeowner submitting a report to my bank or subsidy programme, I want the partial and deposit-reduced amount labels explained once in the document, so that the recipient can tell why a shown amount is lower than the invoice amount without asking me a follow-up question.
Parent Epic: none — part of the parent-less Bank Report Wizard cluster (#1876-#1879, #1898-#1901, #1923). Priority: Must Have
Problem
PR #1959 replaced the shared †/‡ footnote markers and their explanatory sentences with inline grey labels appended to the allocated amount: (partial) / (less deposit) (de: (Teilbetrag) / (abzgl. Abschlag)). The inline labels are an improvement as an in-row signal and are kept. But the sentences were removed entirely, not relocated:
sourceReports.table.splitFootnote — "Amount shown reflects only the portion allocated to this source."
sourceReports.table.depositReducedFootnote — "This position reflects deposits claimed separately."
Both keys still exist in en and de and are now unread by production code (the only remaining references are fixture strings in overviewPdf.test.ts).
Why the deposit sentence is load-bearing
(less deposit) states that a deposit was deducted. The footnote stated the deposit was claimed separately — i.e. it is accounted for in another submission. For a recipient auditing a Verwendungsnachweis / Mittelabruf those are materially different claims: "less deposit" is equally consistent with the deposit never being claimed at all, and it leaves a double-claim question open when the same deposit surfaces in a later submission. The missing word is separately, and it has audit consequences.
(partial) is the weaker case for a sentence: the table prints Invoice Amount and Allocated Amount side by side, so the label only has to name the reason for a difference the reader can already see. It is included below for symmetry, not because it is independently required.
This is a producer-only change — the rendering machinery is already live
ReportContentFootnote[] is still on the content model. buildReportContent.ts declares const footnotes: ReportContentFootnote[] = [] (L232) and returns it (L289) but never pushes to it.
overviewPdf.ts already appends reportContent.footnotes verbatim after the skip block (pinned by the overviewPdf.test.ts case "appends reportContent.footnotes verbatim after the skip block, without re-deriving text").
Both renderers therefore pick up legend entries automatically, and preview/PDF parity comes for free.
Acceptance Criteria
1. Legend content
1.1 Given a report where at least one included row has isSplit === true, When buildReportContent runs, Then the returned footnotes array contains exactly one entry whose text is t('sourceReports.table.splitFootnote') — with noVendor (Invoice No.) — prefix and no numeric suffix on its marker.
1.2 Given a report where at least one included row has isDepositReduced === true, When buildReportContent runs, Then footnotes contains exactly one entry whose text is t('sourceReports.table.depositReducedFootnote'), under the same no-prefix / no-numbering constraint.
1.3 Given a report where both flags occur across rows, Then footnotes has exactly two entries, ordered split first, deposit-reduced second.
1.4 Given a report where neither flag occurs on any included row, Then footnotes is empty and neither sentence appears in the preview DOM or in the rendered PDF's extracted text.
1.5 Given N > 1 rows carrying the same flag, Then the corresponding sentence appears exactly once in the rendered output — asserted by counting occurrences in the rendered preview DOM and in the rendered PDF text, not only by inspecting the array length.
2.2 No †, ‡, or numbered variant of either is reintroduced into any table cell. Asserted by absence in the rendered PDF's extracted text and in the preview DOM.
2.3 Each legend entry and the row label it explains share a literal string that appears in both (e.g. the row shows (partial) and the legend entry begins partial:), so the reader can join legend to row without a glyph. Asserted by extracting the shared token from the row cell and finding the same token in the legend entry. The exact join mechanism is the implementer's call; the shared-token property is the criterion.
3. Both surfaces, both locales
3.1 The legend renders identically in the editable HTML preview and in the exported PDF (same sentences, same order), asserted against a real render per the realRender.test.ts pattern — real i18n bundles, real formatters, no key-echoing t mock.
3.2 Both sentences resolve in en and de. splitFootnote and depositReducedFootnote are retained in both locale files, not deleted. German wording is unchanged from what is already in de/budget.json (already glossary-clean: Abschlagszahlungen in full).
3.3 The generation-time skipped-document footnotes (*1, *2, …) are unchanged in numbering, text, and position relative to the legend block.
This supersedes the orphan-key cleanup that was otherwise queued for these two keys. They are consumed here, so they must not be deleted. If this issue is ever closed Wont-Do, the alternative resolution is to delete both keys from en and de together (translator owns de/) — but not before.
[product-owner]
As a homeowner submitting a report to my bank or subsidy programme, I want the partial and deposit-reduced amount labels explained once in the document, so that the recipient can tell why a shown amount is lower than the invoice amount without asking me a follow-up question.
Parent Epic: none — part of the parent-less Bank Report Wizard cluster (#1876-#1879, #1898-#1901, #1923).
Priority: Must Have
Problem
PR #1959 replaced the shared
†/‡footnote markers and their explanatory sentences with inline grey labels appended to the allocated amount:(partial)/(less deposit)(de:(Teilbetrag)/(abzgl. Abschlag)). The inline labels are an improvement as an in-row signal and are kept. But the sentences were removed entirely, not relocated:sourceReports.table.splitFootnote— "Amount shown reflects only the portion allocated to this source."sourceReports.table.depositReducedFootnote— "This position reflects deposits claimed separately."Both keys still exist in
enanddeand are now unread by production code (the only remaining references are fixture strings inoverviewPdf.test.ts).Why the deposit sentence is load-bearing
(less deposit)states that a deposit was deducted. The footnote stated the deposit was claimed separately — i.e. it is accounted for in another submission. For a recipient auditing a Verwendungsnachweis / Mittelabruf those are materially different claims: "less deposit" is equally consistent with the deposit never being claimed at all, and it leaves a double-claim question open when the same deposit surfaces in a later submission. The missing word isseparately, and it has audit consequences.(partial)is the weaker case for a sentence: the table prints Invoice Amount and Allocated Amount side by side, so the label only has to name the reason for a difference the reader can already see. It is included below for symmetry, not because it is independently required.This is a producer-only change — the rendering machinery is already live
ReportContentFootnote[]is still on the content model.buildReportContent.tsdeclaresconst footnotes: ReportContentFootnote[] = [](L232) and returns it (L289) but never pushes to it.ReportContentEditor.tsxL445-450 already renderscontent.footnotes.overviewPdf.tsalready appendsreportContent.footnotesverbatim after the skip block (pinned by theoverviewPdf.test.tscase "appends reportContent.footnotes verbatim after the skip block, without re-deriving text").Both renderers therefore pick up legend entries automatically, and preview/PDF parity comes for free.
Acceptance Criteria
1. Legend content
isSplit === true, WhenbuildReportContentruns, Then the returnedfootnotesarray contains exactly one entry whose text ist('sourceReports.table.splitFootnote')— with noVendor (Invoice No.) —prefix and no numeric suffix on its marker.isDepositReduced === true, WhenbuildReportContentruns, Thenfootnotescontains exactly one entry whose text ist('sourceReports.table.depositReducedFootnote'), under the same no-prefix / no-numbering constraint.footnoteshas exactly two entries, ordered split first, deposit-reduced second.footnotesis empty and neither sentence appears in the preview DOM or in the rendered PDF's extracted text.2. Relationship to the inline labels
splitInlineLabel,depositReducedInlineLabel, and the constituted-depositattachmentType.depositlabel — are unchanged in text, placement, and styling. This issue is purely additive.†,‡, or numbered variant of either is reintroduced into any table cell. Asserted by absence in the rendered PDF's extracted text and in the preview DOM.(partial)and the legend entry beginspartial:), so the reader can join legend to row without a glyph. Asserted by extracting the shared token from the row cell and finding the same token in the legend entry. The exact join mechanism is the implementer's call; the shared-token property is the criterion.3. Both surfaces, both locales
realRender.test.tspattern — real i18n bundles, real formatters, no key-echoingtmock.enandde.splitFootnoteanddepositReducedFootnoteare retained in both locale files, not deleted. German wording is unchanged from what is already inde/budget.json(already glossary-clean:Abschlagszahlungenin full).*1,*2, …) are unchanged in numbering, text, and position relative to the legend block.4. Layout
Notes
enanddetogether (translatorownsde/) — but not before.splitKindto distinguish deposit-driven splits from line splits) — if that lands first, the legend wording may need a third variant; not a dependency.