* 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>
44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { formatPdfKronor } from '../pdf-format'
|
|
|
|
// Build the special characters from code points so the assertions cannot be
|
|
// corrupted by editor/encoding round-trips: U+00A0 is the sv-SE thousands
|
|
// separator, U+2212 is the locale minus that WinAnsi Helvetica cannot render.
|
|
const NBSP = String.fromCharCode(0x00a0)
|
|
const U2212 = String.fromCharCode(0x2212)
|
|
|
|
describe('formatPdfKronor', () => {
|
|
it('formats a loss with an ASCII hyphen-minus, never U+2212', () => {
|
|
const out = formatPdfKronor(-4684.24)
|
|
expect(out).toBe(`-4${NBSP}684`)
|
|
expect(out).not.toContain(U2212)
|
|
})
|
|
|
|
it('keeps sv-SE thousands grouping for positive amounts', () => {
|
|
expect(formatPdfKronor(1234567.89)).toBe(`1${NBSP}234${NBSP}568`)
|
|
})
|
|
|
|
it('pins the group separator to U+00A0 regardless of the ICU CLDR choice', () => {
|
|
// Newer CLDR data groups sv-SE with U+202F NARROW NO-BREAK SPACE, which
|
|
// is also missing from WinAnsi; the formatter must normalize to U+00A0.
|
|
const U202F = String.fromCharCode(0x202f)
|
|
const out = formatPdfKronor(-9876543)
|
|
expect(out).toBe(`-9${NBSP}876${NBSP}543`)
|
|
expect(out).not.toContain(U202F)
|
|
})
|
|
|
|
it('rounds to whole kronor and never renders "-0"', () => {
|
|
expect(formatPdfKronor(-0.4)).toBe('0')
|
|
expect(formatPdfKronor(-0.6)).toBe('-1')
|
|
expect(formatPdfKronor(0)).toBe('0')
|
|
})
|
|
|
|
it('always uses ASCII hyphen for negative amounts', () => {
|
|
for (const n of [-1, -999, -1000, -4684.24, -1_000_000.5]) {
|
|
const out = formatPdfKronor(n)
|
|
expect(out).not.toContain(U2212)
|
|
expect(out.startsWith('-')).toBe(true)
|
|
}
|
|
})
|
|
})
|