feat(settings): standard verifikationsserier for new companies, opt-in action for existing (#2358)

* feat(settings): standard verifikationsserier for new companies, opt-in action for existing (#2184)

A new company_settings row now defaults to the standard series set
(A manual/bank, B kundfakturor, C inbetalningar, D leverantörsfakturor,
E utbetalningar, H periodisering, I bokslut, K lön, L kontantfaktura,
M moms) instead of everything on A. The set lives once, as the
exhaustive STANDARD_VOUCHER_SERIES_MAP in the resolver; a pg-real test
holds the column default equal to it and to the source_type CHECK.

Existing rows are not remapped: the per-type settings form gets an
"Använd standarduppsättningen" action that fills the set for review
and save through the existing PUT, so the switch is a deliberate,
audited act rather than a mid-year numbering change nobody decided.
Payment rows bound to the other bokföringsmetod are dimmed, not hidden.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvMaHcTnwAfxzgYD1fGYX1

* test(bookkeeping): fresh company_settings row asserts the standard series set, not all-A

voucher-series-defaults.pg.test.ts codified the pre-#2184 column default
(every source type on A). Migration 20260906210500 replaces that default
with the standard set, so the "freshly inserted row" case now asserts the
representative letters and full equality with STANDARD_VOUCHER_SERIES_MAP.
The explicit-override case keeps proving a company's own layout replaces
the default wholesale. No other pg or tool test asserted on the old map.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvMaHcTnwAfxzgYD1fGYX1

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-09-06 21:18:22 +02:00
committed by GitHub
co-authored by Claude Fable 5.1 Jakob Wennberg
parent 4fce2d7b94
commit bf7773d74b
11 changed files with 465 additions and 34 deletions
+26
View File
@@ -42,6 +42,7 @@ vi.mock('@/lib/tax/deadline-generator', async (importOriginal) => {
import { PUT } from '../route'
import { regenerateTaxDeadlinesForUser } from '@/lib/tax/deadline-generator'
import { STANDARD_VOUCHER_SERIES_MAP } from '@/lib/bookkeeping/voucher-series-resolver'
describe('PUT /api/settings', () => {
beforeEach(() => {
@@ -123,6 +124,31 @@ describe('PUT /api/settings', () => {
expect(findCall('company_settings', 'update')?.[0]).toEqual({ voucher_series_labels: { L: 'Lön' } })
})
it('stores the standard voucher series set as sent (Använd standarduppsättningen)', async () => {
const standard = { ...STANDARD_VOUCHER_SERIES_MAP }
enqueueMany([
{ data: { entity_type: 'aktiebolag', onboarding_complete: true } }, // fetch oldSettings
{ data: { id: 's1', default_voucher_series_per_source_type: standard } }, // update ... returning
{ data: null, count: 5 }, // deadlines count
])
const request = createMockRequest('/api/settings', {
method: 'PUT',
body: { default_voucher_series_per_source_type: standard },
})
const response = await PUT(request, { params: Promise.resolve({}) })
const { status, body } = await parseJsonResponse<{
data: { default_voucher_series_per_source_type: Record<string, string> }
}>(response)
expect(status).toBe(200)
expect(body.data.default_voucher_series_per_source_type).toEqual(standard)
// Every source type, storno and correction included, reaches the row unchanged.
expect(findCall('company_settings', 'update')?.[0]).toEqual({
default_voucher_series_per_source_type: standard,
})
})
it('rejects a voucher_series_labels key that is not a single uppercase letter', async () => {
const request = createMockRequest('/api/settings', {
method: 'PUT',