* fix(vat): momsdeklaration defaults respect the configured cadence and persist manual changes The period picker re-seeded from scratch on every visit: an arsmoms user whose moms_period was never set landed on a silently guessed quarterly declaration (companies without a company_settings row bypassed every gate), and a manually chosen cadence evaporated on the next visit. - Gate the view when no company_settings row exists, matching the existing "registered but no period" gate: a declaration for the wrong period type is a compliance hazard, not a convenience. - Persist the manually chosen cadence per company (localStorage, FyPicker pattern) and restore it while moms_period is unchanged; the concrete period still re-seeds to the most recently ended one, and a changed setting discards the stored cadence. - Extract the seeding decision into lib/vat/period-selection.ts with unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012pQn9kC742B9R7Ggi8wdn9 * fix(vat): drop cadence persistence; the moms_period re-seed is the control Skeptic review refuted the persistence half of the previous commit twice: the render-phase localStorage restore diverged from SSR (hydration error on every visit once a cadence was stored), and restoring a manually chosen cadence that deviates from moms_period kept the filing pipeline open on the wrong period type across visits, with no downstream path validating period type against the setting. The redovisningsperiod has exactly one lawful value per company, so the mount-time re-seed from company_settings.moms_period is the self-healing control, not a bug. The settings-row gate and the extracted, tested seeding resolver stay. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012pQn9kC742B9R7Ggi8wdn9 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { resolveInitialVatPeriodSelection } from '../period-selection'
|
|
|
|
describe('resolveInitialVatPeriodSelection', () => {
|
|
const today = new Date(2026, 7, 27) // 2026-08-27
|
|
|
|
it('seeds yearly cadence from a yearly setting', () => {
|
|
expect(
|
|
resolveInitialVatPeriodSelection({ momsPeriod: 'yearly', over40m: false, today }),
|
|
).toEqual({ periodType: 'yearly', year: 2026, period: 1 })
|
|
})
|
|
|
|
it('seeds the most recently ended quarter for a quarterly setting', () => {
|
|
expect(
|
|
resolveInitialVatPeriodSelection({ momsPeriod: 'quarterly', over40m: false, today }),
|
|
).toEqual({ periodType: 'quarterly', year: 2026, period: 2 })
|
|
})
|
|
|
|
it('rolls a quarterly seed back across the year boundary in Q1', () => {
|
|
expect(
|
|
resolveInitialVatPeriodSelection({
|
|
momsPeriod: 'quarterly',
|
|
over40m: false,
|
|
today: new Date(2026, 1, 10),
|
|
}),
|
|
).toEqual({ periodType: 'quarterly', year: 2025, period: 4 })
|
|
})
|
|
|
|
it('seeds monthly filers from the deadline-aware default', () => {
|
|
// 2026-08-06: June's declaration is due 17 Aug, so June is the open one.
|
|
expect(
|
|
resolveInitialVatPeriodSelection({
|
|
momsPeriod: 'monthly',
|
|
over40m: false,
|
|
today: new Date(2026, 7, 6),
|
|
}),
|
|
).toEqual({ periodType: 'monthly', year: 2026, period: 6 })
|
|
})
|
|
|
|
it('honors the over-40M monthly rule (always the most recently ended month)', () => {
|
|
expect(
|
|
resolveInitialVatPeriodSelection({
|
|
momsPeriod: 'monthly',
|
|
over40m: true,
|
|
today: new Date(2026, 7, 6),
|
|
}),
|
|
).toEqual({ periodType: 'monthly', year: 2026, period: 7 })
|
|
})
|
|
|
|
it('falls back to quarterly when moms_period is unset (state is gated, never rendered)', () => {
|
|
expect(
|
|
resolveInitialVatPeriodSelection({ momsPeriod: null, over40m: false, today }),
|
|
).toEqual({ periodType: 'quarterly', year: 2026, period: 2 })
|
|
})
|
|
})
|