diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b424d59c..70382047 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,13 @@ version: 2 +# Deliberately throttled to avoid a PR flood. Two knobs do the work: +# - open-pull-requests-limit: 1 -> at most ONE open PR per ecosystem at a +# time. Dependabot will not open next week's PR until the current one is +# merged or closed, so PRs can never pile up. +# - groups (patterns: "*") -> every available bump (major/minor/patch) +# is batched into that single PR instead of one PR per package. +# Combined with the weekly schedule this means: normally one npm PR a week (or +# none), and only in a rare week where Docker/Actions also move do you see more +# than one PR at all. updates: # Base images in the root Dockerfile (node:22-alpine). - package-ecosystem: docker @@ -6,7 +15,11 @@ updates: schedule: interval: weekly day: monday - open-pull-requests-limit: 5 + open-pull-requests-limit: 1 + groups: + docker: + patterns: + - "*" labels: - dependencies - docker @@ -17,7 +30,11 @@ updates: schedule: interval: weekly day: monday - open-pull-requests-limit: 5 + open-pull-requests-limit: 1 + groups: + docker-cron: + patterns: + - "*" labels: - dependencies - docker @@ -28,7 +45,11 @@ updates: schedule: interval: weekly day: monday - open-pull-requests-limit: 5 + open-pull-requests-limit: 1 + groups: + github-actions: + patterns: + - "*" labels: - dependencies - ci @@ -39,16 +60,15 @@ updates: schedule: interval: weekly day: monday - open-pull-requests-limit: 10 + open-pull-requests-limit: 1 labels: - dependencies - npm groups: - # Batch low-risk minor/patch bumps so the reviewer queue stays small. - minor-and-patch: - update-types: - - minor - - patch + # Batch ALL bumps (major/minor/patch) into a single weekly PR. + npm: + patterns: + - "*" ignore: # @anthropic-ai/bedrock-sdk is PINNED to an exact version in package.json. # 0.32.0 arrived inside a grouped minor-and-patch bump (#884) and broke diff --git a/app/api/bookkeeping/accounts/__tests__/accounts.test.ts b/app/api/bookkeeping/accounts/__tests__/accounts.test.ts index 9e8117fc..80255d72 100644 --- a/app/api/bookkeeping/accounts/__tests__/accounts.test.ts +++ b/app/api/bookkeeping/accounts/__tests__/accounts.test.ts @@ -131,6 +131,29 @@ describe('POST /api/bookkeeping/accounts', () => { expect(status).toBe(409) expect(body.error).toContain('5010') }) + + it('forwards default_vat_rate into the insert', async () => { + const { supabase, calls } = createCapturingSupabase([ + { data: { account_number: '3740', default_vat_rate: 0 } }, + ]) + auth(supabase) + const req = createMockRequest('/api/bookkeeping/accounts', { + method: 'POST', + body: { + account_number: '3740', + account_name: 'Öres- och kronutjämning', + account_type: 'revenue', + normal_balance: 'debit', + default_vat_rate: 0, + }, + }) + const { status } = await parseJsonResponse(await createPOST(req, routeParams)) + expect(status).toBe(200) + const insertArg = calls.find((c) => c.method === 'insert')?.args[0] as { + default_vat_rate?: number | null + } + expect(insertArg?.default_vat_rate).toBe(0) + }) }) describe('DELETE /api/bookkeeping/accounts/[number]', () => { @@ -218,6 +241,25 @@ describe('PUT /api/bookkeeping/accounts/[number]', () => { expect(status).toBe(200) expect(body.data.account_name).toBe('Nytt namn') }) + + it('forwards default_vat_rate into the update', async () => { + const { supabase, calls } = createCapturingSupabase([ + { data: { account_number: '3740', default_vat_rate: 0 } }, + ]) + auth(supabase) + const req = createMockRequest('/api/bookkeeping/accounts/3740', { + method: 'PUT', + body: { default_vat_rate: 0 }, + }) + const { status } = await parseJsonResponse( + await PUT(req, { params: Promise.resolve({ number: '3740' }) }) + ) + expect(status).toBe(200) + const updateArg = calls.find((c) => c.method === 'update')?.args[0] as { + default_vat_rate?: number | null + } + expect(updateArg?.default_vat_rate).toBe(0) + }) }) describe('POST /api/bookkeeping/accounts/activate', () => { diff --git a/app/api/bookkeeping/accounts/route.ts b/app/api/bookkeeping/accounts/route.ts index a50ca43c..d51671bb 100644 --- a/app/api/bookkeeping/accounts/route.ts +++ b/app/api/bookkeeping/accounts/route.ts @@ -79,6 +79,7 @@ export const POST = withRouteContext( is_system_account: false, description: body.description || null, default_vat_code: body.default_vat_code || null, + default_vat_rate: body.default_vat_rate ?? null, sru_code: body.sru_code || null, sort_order: parseInt(body.account_number), }) diff --git a/components/bookkeeping/AddAccountDialog.tsx b/components/bookkeeping/AddAccountDialog.tsx index d40c89ff..ff42e280 100644 --- a/components/bookkeeping/AddAccountDialog.tsx +++ b/components/bookkeeping/AddAccountDialog.tsx @@ -37,7 +37,9 @@ export function AddAccountDialog({ const [accountNumber, setAccountNumber] = useState('') const [accountName, setAccountName] = useState('') const [description, setDescription] = useState('') - const [defaultVatCode, setDefaultVatCode] = useState('') + // "Standard moms": the moms-sats a booking line defaults to when this konto is + // picked. 'none' = no default. SelectItem values are stringified decimals. + const [defaultVatRate, setDefaultVatRate] = useState('none') const [sruCode, setSruCode] = useState('') const [normalBalance, setNormalBalance] = useState<'debit' | 'credit'>('debit') const [isSaving, setIsSaving] = useState(false) @@ -84,7 +86,7 @@ export function AddAccountDialog({ account_type: derived?.account_type || 'expense', normal_balance: normalBalance, description: description || null, - default_vat_code: defaultVatCode || null, + default_vat_rate: defaultVatRate === 'none' ? null : parseFloat(defaultVatRate), sru_code: sruCode || null, }), }) @@ -100,7 +102,7 @@ export function AddAccountDialog({ setAccountNumber('') setAccountName('') setDescription('') - setDefaultVatCode('') + setDefaultVatRate('none') setSruCode('') onCreated(createdAccount) onOpenChange(false) @@ -197,12 +199,19 @@ export function AddAccountDialog({
+ {t('arrival_start_help')} +
+