Files
accounted/lib/reports/ink2/__tests__/ink2-engine.test.ts
T
Jakob Wennberg 091d043c85 feat: UI polish, lint fixes, onboarding redesign, help page expansion, and test improvements
Broad update across dashboard pages, components, extensions, and lib code. Includes ESLint config additions, onboarding flow redesign, settings page refactor, help page content expansion, dead code removal, and test mock fixes. Adds dev docs and public assets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 23:05:49 +01:00

258 lines
9.7 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { INK2_ACCOUNT_MAPPINGS, isAccountInMapping } from '../ink2-engine'
import type { INK2SRUCode } from '../types'
/**
* Helper to find which SRU code an account maps to
*/
function findSRUCodeForAccount(accountNumber: string): INK2SRUCode | null {
for (const mapping of INK2_ACCOUNT_MAPPINGS) {
if (isAccountInMapping(accountNumber, mapping)) {
return mapping.sruCode
}
}
return null
}
describe('INK2 Account Mappings', () => {
describe('completeness', () => {
it('has 19 mappings covering all INK2 fields', () => {
expect(INK2_ACCOUNT_MAPPINGS).toHaveLength(19)
})
it('covers all SRU codes', () => {
const codes = INK2_ACCOUNT_MAPPINGS.map(m => m.sruCode)
const expectedCodes: INK2SRUCode[] = [
'7201', '7202', '7203', '7210', '7211', '7212',
'7220', '7221', '7222', '7230', '7231',
'7310', '7320', '7330', '7340', '7350', '7360', '7370', '7380',
]
expect(codes).toEqual(expectedCodes)
})
})
describe('Balance sheet - Assets', () => {
it('1000-1099 -> 7201 (Immateriella AT)', () => {
expect(findSRUCodeForAccount('1000')).toBe('7201')
expect(findSRUCodeForAccount('1050')).toBe('7201')
expect(findSRUCodeForAccount('1099')).toBe('7201')
})
it('1100-1299 -> 7202 (Materiella AT)', () => {
expect(findSRUCodeForAccount('1100')).toBe('7202')
expect(findSRUCodeForAccount('1210')).toBe('7202')
expect(findSRUCodeForAccount('1299')).toBe('7202')
})
it('1300-1399 -> 7203 (Finansiella AT)', () => {
expect(findSRUCodeForAccount('1300')).toBe('7203')
expect(findSRUCodeForAccount('1350')).toBe('7203')
expect(findSRUCodeForAccount('1399')).toBe('7203')
})
it('1400-1499 -> 7210 (Varulager)', () => {
expect(findSRUCodeForAccount('1400')).toBe('7210')
expect(findSRUCodeForAccount('1460')).toBe('7210')
expect(findSRUCodeForAccount('1499')).toBe('7210')
})
it('1500-1599 -> 7211 (Kundfordringar)', () => {
expect(findSRUCodeForAccount('1500')).toBe('7211')
expect(findSRUCodeForAccount('1510')).toBe('7211')
expect(findSRUCodeForAccount('1599')).toBe('7211')
})
it('1600-1999 -> 7212 (Övriga OT)', () => {
expect(findSRUCodeForAccount('1600')).toBe('7212')
expect(findSRUCodeForAccount('1930')).toBe('7212')
expect(findSRUCodeForAccount('1999')).toBe('7212')
})
})
describe('Balance sheet - Equity & Liabilities', () => {
it('2081 -> 7220 (Aktiekapital)', () => {
expect(findSRUCodeForAccount('2081')).toBe('7220')
})
it('2081 does NOT go to 7221', () => {
expect(findSRUCodeForAccount('2081')).not.toBe('7221')
})
it('2000-2080 -> 7221 (Övrigt EK)', () => {
expect(findSRUCodeForAccount('2000')).toBe('7221')
expect(findSRUCodeForAccount('2010')).toBe('7221')
expect(findSRUCodeForAccount('2080')).toBe('7221')
})
it('2082-2098 -> 7221 (Övrigt EK)', () => {
expect(findSRUCodeForAccount('2082')).toBe('7221')
expect(findSRUCodeForAccount('2090')).toBe('7221')
expect(findSRUCodeForAccount('2098')).toBe('7221')
})
it('2099 -> 7222 (Årets resultat)', () => {
expect(findSRUCodeForAccount('2099')).toBe('7222')
})
it('2099 does NOT go to 7221', () => {
expect(findSRUCodeForAccount('2099')).not.toBe('7221')
})
it('2100-2499 -> 7230 (Obeskattade reserver, avsättningar, skulder)', () => {
expect(findSRUCodeForAccount('2100')).toBe('7230')
expect(findSRUCodeForAccount('2150')).toBe('7230') // Obeskattade reserver
expect(findSRUCodeForAccount('2250')).toBe('7230') // Avsättningar
expect(findSRUCodeForAccount('2440')).toBe('7230') // Leverantörsskulder
expect(findSRUCodeForAccount('2499')).toBe('7230')
})
it('2500-2999 -> 7231 (Övriga skulder)', () => {
expect(findSRUCodeForAccount('2500')).toBe('7231')
expect(findSRUCodeForAccount('2611')).toBe('7231') // Utgående moms
expect(findSRUCodeForAccount('2710')).toBe('7231') // Personalens källskatt
expect(findSRUCodeForAccount('2999')).toBe('7231')
})
})
describe('Income statement', () => {
it('3000-3999 -> 7310 (Nettoomsättning)', () => {
expect(findSRUCodeForAccount('3000')).toBe('7310')
expect(findSRUCodeForAccount('3001')).toBe('7310')
expect(findSRUCodeForAccount('3100')).toBe('7310')
expect(findSRUCodeForAccount('3999')).toBe('7310')
})
it('4000-4999 -> 7320 (Varuinköp)', () => {
expect(findSRUCodeForAccount('4000')).toBe('7320')
expect(findSRUCodeForAccount('4010')).toBe('7320')
expect(findSRUCodeForAccount('4999')).toBe('7320')
})
it('5000-6999 -> 7330 (Övriga externa kostnader)', () => {
expect(findSRUCodeForAccount('5000')).toBe('7330')
expect(findSRUCodeForAccount('5460')).toBe('7330')
expect(findSRUCodeForAccount('6200')).toBe('7330')
expect(findSRUCodeForAccount('6999')).toBe('7330')
})
it('7000-7699 -> 7340 (Personalkostnader)', () => {
expect(findSRUCodeForAccount('7000')).toBe('7340')
expect(findSRUCodeForAccount('7210')).toBe('7340')
expect(findSRUCodeForAccount('7699')).toBe('7340')
})
it('7700-7899 -> 7350 (Avskrivningar)', () => {
expect(findSRUCodeForAccount('7700')).toBe('7350')
expect(findSRUCodeForAccount('7820')).toBe('7350')
expect(findSRUCodeForAccount('7899')).toBe('7350')
})
it('7900-7999 -> 7360 (Övriga rörelsekostnader)', () => {
expect(findSRUCodeForAccount('7900')).toBe('7360')
expect(findSRUCodeForAccount('7970')).toBe('7360')
expect(findSRUCodeForAccount('7999')).toBe('7360')
})
it('8000-8499 -> 7370 (Finansiella poster)', () => {
expect(findSRUCodeForAccount('8000')).toBe('7370')
expect(findSRUCodeForAccount('8310')).toBe('7370') // Ränteintäkter
expect(findSRUCodeForAccount('8400')).toBe('7370') // Räntekostnader
expect(findSRUCodeForAccount('8499')).toBe('7370')
})
it('8500-8999 -> 7380 (Extraordinära poster)', () => {
expect(findSRUCodeForAccount('8500')).toBe('7380')
expect(findSRUCodeForAccount('8910')).toBe('7380') // Skatt
expect(findSRUCodeForAccount('8999')).toBe('7380')
})
})
describe('no overlap between mappings', () => {
it('each account matches exactly one mapping', () => {
// Test a representative sample across boundaries
const testAccounts = [
'1099', '1100', // 7201/7202 boundary
'1299', '1300', // 7202/7203 boundary
'1399', '1400', // 7203/7210 boundary
'1499', '1500', // 7210/7211 boundary
'1599', '1600', // 7211/7212 boundary
'1999', '2000', // 7212/7221 boundary
'2080', '2081', '2082', // 7221/7220/7221
'2098', '2099', '2100', // 7221/7222/7230 boundary
'2499', '2500', // 7230/7231 boundary
'2999', '3000', // 7231/7310 boundary
'3999', '4000', // 7310/7320 boundary
'4999', '5000', // 7320/7330 boundary
'6999', '7000', // 7330/7340 boundary
'7699', '7700', // 7340/7350 boundary
'7899', '7900', // 7350/7360 boundary
'7999', '8000', // 7360/7370 boundary
'8499', '8500', // 7370/7380 boundary
]
for (const account of testAccounts) {
let matchCount = 0
for (const mapping of INK2_ACCOUNT_MAPPINGS) {
if (isAccountInMapping(account, mapping)) {
matchCount++
}
}
expect(matchCount).toBe(1)
}
})
})
describe('section assignments', () => {
it('asset mappings have section "assets"', () => {
const assetMappings = INK2_ACCOUNT_MAPPINGS.filter(m => m.section === 'assets')
expect(assetMappings.map(m => m.sruCode)).toEqual(['7201', '7202', '7203', '7210', '7211', '7212'])
})
it('equity/liability mappings have section "equity_liabilities"', () => {
const eqMappings = INK2_ACCOUNT_MAPPINGS.filter(m => m.section === 'equity_liabilities')
expect(eqMappings.map(m => m.sruCode)).toEqual(['7220', '7221', '7222', '7230', '7231'])
})
it('income statement mappings have section "income_statement"', () => {
const isMappings = INK2_ACCOUNT_MAPPINGS.filter(m => m.section === 'income_statement')
expect(isMappings.map(m => m.sruCode)).toEqual(['7310', '7320', '7330', '7340', '7350', '7360', '7370', '7380'])
})
})
describe('normal balance assignments', () => {
it('asset accounts are debit-normal', () => {
const assetMappings = INK2_ACCOUNT_MAPPINGS.filter(m => m.section === 'assets')
for (const m of assetMappings) {
expect(m.normalBalance).toBe('debit')
}
})
it('equity/liability accounts are credit-normal', () => {
const eqMappings = INK2_ACCOUNT_MAPPINGS.filter(m => m.section === 'equity_liabilities')
for (const m of eqMappings) {
expect(m.normalBalance).toBe('credit')
}
})
it('revenue (7310) is credit-normal', () => {
const revenue = INK2_ACCOUNT_MAPPINGS.find(m => m.sruCode === '7310')
expect(revenue?.normalBalance).toBe('credit')
})
it('expense accounts (7320-7360) are debit-normal', () => {
const expenseCodes: INK2SRUCode[] = ['7320', '7330', '7340', '7350', '7360']
for (const code of expenseCodes) {
const mapping = INK2_ACCOUNT_MAPPINGS.find(m => m.sruCode === code)
expect(mapping?.normalBalance).toBe('debit')
}
})
it('financial and extraordinary items (7370, 7380) are net', () => {
const financial = INK2_ACCOUNT_MAPPINGS.find(m => m.sruCode === '7370')
const extraordinary = INK2_ACCOUNT_MAPPINGS.find(m => m.sruCode === '7380')
expect(financial?.normalBalance).toBe('net')
expect(extraordinary?.normalBalance).toBe('net')
})
})
})