* feat: add INK2 declaration improvements, invoice delivery date, and Swedish compliance skills Expand INK2 engine with full INK2S/INK2R support and improved SRU generation. Add delivery_date field to invoices and corresponding PDF/migration support. Add Claude skills for Swedish asset accounting, invoice compliance, SIE import/export, SRU filing, and tax planning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review — map BAS 4500–4899, strip CRLF in SRU, document P3 - Map BAS accounts 4500–4599 (legoarbeten), 4700–4899 (diverse varuinköpskostnader) to SRU 7512 so they are not silently dropped from INK2R declarations - Strip \r\n in sanitizeString to prevent CRLF injection in SRU fields - Document P3 period suffix limitation for brutet räkenskapsår Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: correct BAS 4500-4599, 4700-4899 mapping from 7512 to 7511 Per the official BAS-to-SRU mapping, these account ranges are cost of goods (legoarbeten, inkurans, svinn) and belong under 7511 (Råvaror och förnödenheter), not 7512 (Handelsvaror). 7512 remains 4600-4699. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.4 KiB
4.4 KiB
SIE4 Character Encoding Reference
The spec vs. reality
The SIE4 spec mandates IBM PC Codepage 437 (declared as #FORMAT PC8). Modern cloud accounting software exports UTF-8. Many programs write #FORMAT PC8 regardless of actual encoding. This mismatch is the single largest source of SIE interoperability failures.
Byte values for Swedish characters
| Char | CP437 (hex) | Latin-1 (hex) | UTF-8 (hex) |
|---|---|---|---|
| å | 0x86 | 0xE5 | 0xC3 0xA5 |
| ä | 0x84 | 0xE4 | 0xC3 0xA4 |
| ö | 0x94 | 0xF6 | 0xC3 0xB6 |
| Å | 0x8F | 0xC5 | 0xC3 0x85 |
| Ä | 0x8E | 0xC4 | 0xC3 0x84 |
| Ö | 0x99 | 0xD6 | 0xC3 0x96 |
| é | 0x82 | 0xE9 | 0xC3 0xA9 |
Mojibake diagnosis patterns
UTF-8 bytes misread as Latin-1/CP1252
- å →
Ã¥, ä →ä, ö →ö - Å →
Ã…, Ä →Ä, Ö →Ö - Telltale: The
Ãprefix always indicates UTF-8 content decoded as single-byte - Fix: Re-read the file as UTF-8
CP437 bytes misread as Latin-1/CP1252
- å →
†, ä →„, ö →" - Å → control char (0x8F), Ä → control char (0x8E), Ö →
™ - Telltale: Typographic characters like
†„"™in account names - Fix: Re-read the file as CP437
Latin-1 bytes misread as CP437
- å →
σ, ä →Σ, ö →÷ - Telltale: Greek letters or math symbols in Swedish text
- Fix: Re-read the file as Latin-1 (ISO 8859-1)
Double-encoding (UTF-8 encoded twice)
- å →
ã¥or similar multi-byte garbage - Telltale: 3+ byte sequences where 2 were expected
- Fix: Decode as UTF-8, then decode the result as UTF-8 again (strip one layer)
Encoding detection algorithm
Apply in this order, stop at first match:
- UTF-8 BOM check: Bytes 0xEF 0xBB 0xBF at file start → UTF-8
- Strict UTF-8 validation: Attempt full decode. If valid AND multi-byte sequences found → UTF-8. Pure ASCII files are ambiguous (proceed to next step).
- CP437 byte scan: Look for bytes in range 0x80-0x9F in text contexts (account names, descriptions). If bytes 0x84, 0x86, 0x8E, 0x8F, 0x94, 0x99 appear → CP437
- Latin-1 byte scan: Look for bytes in range 0xC0-0xFF in text contexts. If bytes 0xC4, 0xC5, 0xD6, 0xE4, 0xE5, 0xF6 appear → Latin-1
- #PROGRAM heuristic: Extract program name from the file (readable in any encoding since it's typically ASCII):
- Cloud software → assume UTF-8
- Desktop software → assume CP437
- Fallback: Latin-1 (every byte 0x00-0xFF is valid, never fails)
Per-software encoding behaviors
| Software | Platform | Typical encoding | Notes |
|---|---|---|---|
| Fortnox | Cloud | UTF-8 | May declare #FORMAT PC8. Largest market share. |
| Visma Administration | Desktop | CP437 or Win-1252 | Legacy Windows app. Requires non-UTF-8 locale. |
| Visma eEkonomi | Cloud | UTF-8 or Latin-1 | Known garbage character issues in exports. |
| Visma Compact | Desktop | CP437 | Standards-compliant. Referenced in SIE spec examples. |
| BL Administration (Björn Lundén) | Desktop | CP437 | Standards-compliant. |
| Lundify (BL cloud) | Cloud | UTF-8 | Modern cloud version of BL. |
| SpeedLedger | Cloud | UTF-8 (likely) | Web-based Unicode environment. |
| PE Accounting | Cloud | UTF-8 (likely) | Web-based. |
| Bokio | Cloud | UTF-8 | Parser-level normalization documented. |
| Dooer | Cloud | UTF-8 | Parser-level normalization documented. |
| Hogia | Desktop/Cloud | CP437 or UTF-8 | Depends on product version. |
#KSUMMA and encoding interaction
The CRC-32 checksum (#KSUMMA) is defined to operate on CP437 byte values. When a file is actually encoded in UTF-8:
- Swedish characters have different byte representations (2 bytes in UTF-8 vs 1 byte in CP437)
- The checksum computed on UTF-8 bytes will NOT match the expected CP437-based value
- Recommendation: When non-CP437 encoding is detected, skip #KSUMMA validation entirely
- When generating SIE files, either: (a) write CP437 with correct KSUMMA, or (b) write UTF-8 and omit KSUMMA
Normalization strategy for import
Best practice for robust SIE import:
- Read raw bytes from file
- Detect encoding using the algorithm above
- Decode to Unicode/UTF-8 internal representation
- Validate #KSUMMA only if encoding is CP437
- Parse all records from the Unicode text
- Store internally as UTF-8
- When exporting: write CP437 if standards compliance is critical (auditors, Skatteverket), otherwise UTF-8 with a note that KSUMMA is omitted