* fix(arsredovisning): losses lost their minus sign in the PDF
toLocaleString('sv-SE') formats negatives with U+2212 MINUS SIGN, which
react-pdf's built-in Helvetica (WinAnsi encoding) has no glyph for, so the
sign was silently dropped: a loss rendered as a profit on 'Arets resultat'
and 'Summa fritt eget kapital' while all totals stayed correct. Reported by
a user whose -4 684,24 kr loss displayed as +4 684 kr.
Add formatPdfKronor (absolute value + ASCII hyphen-minus) and route the K2
and K3 PDF templates and the PDF-bound note builders through it. Display
only; no ledger or iXBRL changes (the iXBRL writer already handles signs
via the sign attribute and its own presentational minus).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CBPBCdBr5P75MQCt4qcnE
* fix(arsredovisning): pin PDF group separator to U+00A0 across ICU versions
Newer CLDR data groups sv-SE thousands with U+202F NARROW NO-BREAK SPACE,
which WinAnsi Helvetica also lacks: digits would silently run together the
same way the minus sign was dropped. Normalize the separator to U+00A0 in
formatPdfKronor so the rendering does not depend on the runtime's ICU.
Addresses the PR Agent reviewer-guide finding on #2013.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CBPBCdBr5P75MQCt4qcnE
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
24 lines
1.0 KiB
TypeScript
24 lines
1.0 KiB
TypeScript
/**
|
||
* Whole-krona amount formatting for text that react-pdf renders with the
|
||
* built-in Helvetica font (the K2/K3 arsredovisning PDFs and their notes).
|
||
*
|
||
* `toLocaleString('sv-SE')` formats negative numbers with U+2212 MINUS SIGN,
|
||
* which WinAnsi-encoded standard fonts cannot encode; react-pdf drops the
|
||
* glyph silently, so a loss like -4 684 printed as "−4 684" loses its
|
||
* sign and reads as a profit. Format the absolute value and prepend an ASCII
|
||
* hyphen-minus instead. The sv-SE thousands separator (U+00A0 NBSP) is in
|
||
* WinAnsi and renders fine.
|
||
*/
|
||
const NBSP = String.fromCharCode(0x00a0)
|
||
|
||
export function formatPdfKronor(amount: number): string {
|
||
const rounded = Math.round(amount)
|
||
// Pin the group separator to U+00A0: depending on the Node/ICU CLDR
|
||
// version, sv-SE groups with U+00A0 or U+202F NARROW NO-BREAK SPACE, and
|
||
// U+202F is missing from WinAnsi too (digits would silently run together).
|
||
const grouped = Math.abs(rounded)
|
||
.toLocaleString('sv-SE')
|
||
.replace(/\s/g, NBSP)
|
||
return rounded < 0 ? `-${grouped}` : grouped
|
||
}
|