fix(salary): exempt F-skatt compensation from arbetsgivaravgifter (#1372)

* fix(salary): exempt F-skatt compensation from arbetsgivaravgifter

calculateAvgifterRate() never checked fSkattStatus, so F-skatt earners
were charged the standard 31.42% employer contributions even though
they pay their own egenavgifter. This overstated employer cost by ~31%
and booked incorrect 7510/2731 entries.

Add an early return in calculateAvgifterRate for f_skatt (rate 0,
category exempt) before any age-based rules, and zero the avgifter
basis in calculateSalary so salary reports and AGI totals do not carry
a false contribution basis. The FK011/FK131 AGI rendering defect stays
scoped to issue #315.

Fixes #314

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(salary): assert full exempt return contract for F-skatt

CodeRabbit review: calculateSalary does not read amount/basis from
AvgifterCalculation, so the direct-return test must pin both to zero
to catch a regression in the exempt early return.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-08-03 17:56:09 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 24911abde0
commit bb1eddcccf
3 changed files with 39 additions and 2 deletions
+11 -1
View File
@@ -475,7 +475,7 @@ export function calculateSalary(
// ─── Step 8: Employer contributions (avgifter) ───
const avgifterCalc = calculateAvgifterRate(input, config, paymentYear)
const avgifterBasis = r(grossSalary + totalBenefits)
const avgifterBasis = input.fSkattStatus === 'f_skatt' ? 0 : r(grossSalary + totalBenefits)
// Handle salary caps for youth and växa-stöd:
// Reduced rate applies only up to the cap, standard rate on the rest
@@ -632,6 +632,16 @@ export function calculateAvgifterRate(
): AvgifterCalculation {
const steps: CalculationStep[] = []
if (input.fSkattStatus === 'f_skatt') {
steps.push({
label: 'Avgiftskategori',
formula: 'F-skatt: inga arbetsgivaravgifter',
input: {},
output: null,
})
return { rate: 0, amount: 0, basis: 0, category: 'exempt', steps }
}
// Decrypt personnummer to calculate age
let pnr: string
try {