Primary-source check against bas.se (BAS 2026 v2): the official kontoplan has no account 2012; the enskild firma equity block is 2010, 2011, 2013, 2017, 2018, 2019. 2012 'Avräkning för skatter och avgifter' is a program convention (Visma, Bokio, Björn Lundén), not standard BAS, and a non-standard account in BAS_REFERENCE leaks via the backfill into charts, SIE export and SRU filing. - remove 2012 from class-2-equity-liabilities.ts, with a tombstone comment - migration retargets 'Preliminär F-skatt (EF)' lines 2012 -> 2013 (system row plus any clones still carrying the seeded shape) - pin 2012's absence in bas-ef-equity-accounts.test.ts (2113 precedent) - correct the swedish-year-end-closing references that motivated #1388, regenerate atom seed migration Companies whose charts already got 2012 backfilled keep it: existing history stays valid; only future template use books 2013. Closes #1409 Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -152,5 +152,5 @@ All P&L accounts (classes 3-8) net to **8999** (Årets resultat).
|
||||
|
||||
### Enskild firma equity flow
|
||||
1. Year-end: Debit 8999 / Credit **2019** (Årets resultat, delägare 1)
|
||||
2. New year start: Zero all sub-accounts (**2011** egna varuuttag, **2012** avräkning skatter, **2013** övriga egna uttag, **2017** årets kapitaltillskott, **2018** övriga egna insättningar, **2019** årets resultat) → net into **2010** (Eget kapital)
|
||||
2. New year start: Zero all sub-accounts (**2011** egna varuuttag, **2013** övriga egna uttag inklusive ägarens egna skatter, **2017** årets kapitaltillskott, **2018** övriga egna insättningar, **2019** årets resultat) → net into **2010** (Eget kapital). Note: some programs (Visma, Bokio) add a non-standard **2012** "Avräkning för skatter och avgifter" for owner taxes; official BAS has no 2012, and Accounted books owner taxes on 2013.
|
||||
3. No bolagsstämma required
|
||||
@@ -117,8 +117,8 @@ Zero all of 2011-2019 into 2010:
|
||||
```
|
||||
Debit 2010 Eget kapital (for net credits from sub-accounts)
|
||||
Credit 2011 Egna varuuttag
|
||||
Credit 2012 Avräkning skatter och avgifter
|
||||
Credit 2013 Övriga egna uttag
|
||||
Credit 2013 Övriga egna uttag (incl. ägarens egna skatter; some programs use a
|
||||
non-standard 2012 for these, official BAS has no 2012)
|
||||
Debit 2017 Årets kapitaltillskott (reverse into 2010)
|
||||
Debit 2018 Övriga egna insättningar (reverse into 2010)
|
||||
Debit 2019 Årets resultat (reverse into 2010)
|
||||
|
||||
@@ -852,3 +852,4 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-08-09] Regeluppdat + docs-freshness scans (#1417) built as local loop skills with due-date self-gating, not cloud crons: cloud routines were retired 2026-07-20, and session crons die at 7 days, so weekly/monthly cadence is achieved by loop-ignite running each loop when its run marker says it is due. loop-regeluppdat files tickets only (no auto-fix PRs): regulatory changes touch money math and compliance logic, which .claude/loops.md forbids loops from changing. Docs check diffs the live .md mirror routes against repo-built markdown (exact, canonicalised both sides) instead of diffing the gnubok-website checkout, so it also catches deployed-but-stale and route-404 states.
|
||||
[2026-08-10] RC VAT template fix scoped to template-library.ts (applyTemplate + deriveTemplateLinesFromBooking): counterparty/SIE learned patterns already strip fiktiv-moms legs and regenerate them via generateReverseChargeLines with the gross base, so mapping-engine/counterparty paths were already correct and stay untouched.
|
||||
[2026-08-10] Receipt hunt cron keeps searchMail=false: the mailbox leg stays manual until its time budget is proven. A sweep of one 172-message mailbox took over 600s while the route's maxDuration is 300, so enabling it nightly would time out mid-run. Flip both this flag and RECEIPT_HUNT_COMPANY_IDS together once the per-company budget is measured.
|
||||
[2026-08-10] Account 2012 reverted from BAS_REFERENCE and the EF F-skatt template moved to 2013 (#1409): the primary source (bas.se BAS 2026 v2 PDF) has no 2012 anywhere; the EF equity block is 2010/2011/2013/2017/2018/2019. 2012 "Avräkning för skatter och avgifter" is a Visma/Bokio/BL program convention that the swedish-year-end-closing skill had absorbed as if standard. Kept per-company charts that already have 2012 untouched (their history is legal and the account is a valid free slot); only the reference, the seeded template and the skill guidance change.
|
||||
|
||||
@@ -2,37 +2,40 @@ import { describe, it, expect } from 'vitest'
|
||||
import { getBASReference } from '@/lib/bookkeeping/bas-reference'
|
||||
|
||||
/**
|
||||
* The enskild firma equity block must be complete.
|
||||
* The enskild firma equity block must match the official BAS kontoplan.
|
||||
*
|
||||
* 2012 was missing from the reference, which is not cosmetic:
|
||||
* `lib/bookkeeping/account-backfill.ts` only seeds accounts that appear in
|
||||
* BAS_REFERENCE, so an account absent from it can never be added to a company's
|
||||
* chart on demand. Any entry touching 2012 failed with AccountsNotInChartError,
|
||||
* which is exactly what the "Preliminär F-skatt (EF)" template did.
|
||||
*
|
||||
* The gap was found by the pack validator asserting that every account a
|
||||
* template references exists in BAS 2026.
|
||||
* 2012 "Avräkning för skatter och avgifter" was added in #1388 on the strength
|
||||
* of the swedish-year-end-closing skill alone. The primary-source check
|
||||
* (#1409, bas.se BAS 2026 v2) shows the official chart has no 2012: the block
|
||||
* runs 2010, 2011, 2013, 2017, 2018, 2019, and the official "Avräkning för
|
||||
* skatter och avgifter (skattekonto)" accounts are 1630/1640 (asset) and 2850
|
||||
* (liability). 2012 is a program convention (Visma, Bokio, Björn Lundén), not
|
||||
* standard BAS. A non-standard account in BAS_REFERENCE leaks into every chart
|
||||
* the backfill seeds, and from there into SIE export and SRU filing, so the
|
||||
* reference must not carry it. Owner taxes paid by the firm are an eget uttag
|
||||
* on 2013, which is what the "Preliminär F-skatt (EF)" template books since
|
||||
* migration 20260810120000.
|
||||
*/
|
||||
describe('enskild firma equity accounts (20xx)', () => {
|
||||
it('has no hole in the 2010-2013 run', () => {
|
||||
for (const account of ['2010', '2011', '2012', '2013']) {
|
||||
it('carries exactly the official BAS block for delägare 1', () => {
|
||||
for (const account of ['2010', '2011', '2013', '2017', '2018', '2019']) {
|
||||
expect(getBASReference(account), `${account} missing from BAS reference`).toBeDefined()
|
||||
}
|
||||
})
|
||||
|
||||
it('2012 is the owner-tax equity account, distinct from the 1630 skattekonto asset', () => {
|
||||
const equity = getBASReference('2012')
|
||||
const skattekonto = getBASReference('1630')
|
||||
|
||||
expect(equity?.account_type).toBe('equity')
|
||||
expect(equity?.normal_balance).toBe('debit')
|
||||
// Both are called "avräkning", which is precisely why they get confused.
|
||||
expect(skattekonto?.account_type).toBe('asset')
|
||||
expect(equity?.account_number).not.toBe(skattekonto?.account_number)
|
||||
it('does not carry 2012: not in official BAS, verified against bas.se in #1409', () => {
|
||||
// Pinned like 2113 below: prevents a well-meaning "fix" that re-adds the
|
||||
// program-convention account instead of keeping the reference official.
|
||||
expect(getBASReference('2012')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('shares the equity SRU code with its siblings, since they all net into 2010', () => {
|
||||
const siblings = ['2011', '2012', '2013', '2018'].map((a) => getBASReference(a)?.sru_code)
|
||||
it('keeps the skattekonto asset account the template settles against', () => {
|
||||
const skattekonto = getBASReference('1630')
|
||||
expect(skattekonto?.account_type).toBe('asset')
|
||||
})
|
||||
|
||||
it('shares the equity SRU code across the sub-accounts, since they all net into 2010', () => {
|
||||
const siblings = ['2011', '2013', '2018'].map((a) => getBASReference(a)?.sru_code)
|
||||
expect(new Set(siblings).size).toBe(1)
|
||||
expect(siblings[0]).toBe(getBASReference('2010')?.sru_code)
|
||||
})
|
||||
|
||||
@@ -23,21 +23,11 @@ export const CLASS_2_ACCOUNTS: BASReferenceAccount[] = [
|
||||
sru_code: '7221',
|
||||
k2_excluded: false,
|
||||
},
|
||||
{
|
||||
account_number: '2012',
|
||||
account_name: 'Avräkning för skatter och avgifter',
|
||||
account_class: 2,
|
||||
account_group: '20',
|
||||
account_type: 'equity',
|
||||
normal_balance: 'debit',
|
||||
description:
|
||||
'Enskild firma: ägarens egna skatter och avgifter (t.ex. preliminär F-skatt) som betalas ' +
|
||||
'av företaget. Ett eget uttag, inte en företagskostnad. Nollas mot 2010 Eget kapital vid ' +
|
||||
'nytt räkenskapsår. Ska inte förväxlas med 1630 Avräkning för skatter och avgifter ' +
|
||||
'(skattekonto), som är tillgångssidans saldo mot Skatteverket.',
|
||||
sru_code: '7221',
|
||||
k2_excluded: false,
|
||||
},
|
||||
// 2012 is deliberately absent: the official BAS kontoplan (bas.se, BAS 2026 v2)
|
||||
// has no 2012; the enskild firma equity block runs 2010, 2011, 2013, 2017,
|
||||
// 2018, 2019. "Avräkning för skatter och avgifter" as 2012 is a program
|
||||
// convention (Visma, Bokio, Björn Lundén), not standard BAS; owner taxes are
|
||||
// booked as eget uttag on 2013. Verified against the primary source in #1409.
|
||||
{
|
||||
account_number: '2013',
|
||||
account_name: 'Övriga egna uttag',
|
||||
|
||||
@@ -54,6 +54,15 @@ const INTENTIONAL_DIVERGENCES: Record<string, Divergence> = {
|
||||
seededName: 'Periodiseringsfond återföring (AB)',
|
||||
reason: 'Same 2113 fix as periodiseringsfond-avsattning-ab.',
|
||||
},
|
||||
'preliminar-f-skatt-ef': {
|
||||
seededName: 'Preliminär F-skatt (EF)',
|
||||
reason:
|
||||
'Seeded version debited 2012 "Avräkning för skatter och avgifter". The primary-source ' +
|
||||
'check in #1409 (bas.se BAS 2026 v2) shows official BAS has no 2012: the EF equity block ' +
|
||||
'is 2010/2011/2013/2017/2018/2019, and 2012 is a Visma/Bokio/BL program convention. Owner ' +
|
||||
'taxes paid by the firm are an eget uttag, so the template now debits 2013 Övriga egna ' +
|
||||
'uttag; migration 20260810120000 retargets the seeded rows the same way.',
|
||||
},
|
||||
'representation-avdragsgill-25-moms': {
|
||||
seededName: 'Representation (avdragsgill, 25% moms)',
|
||||
reason:
|
||||
|
||||
@@ -9,7 +9,7 @@ meta:
|
||||
description: >-
|
||||
Betalning av preliminär F-skatt från skattekontot (enskild firma).
|
||||
lines:
|
||||
- account: '2012'
|
||||
- account: '2013'
|
||||
label: 'Egna skatter'
|
||||
side: debit
|
||||
type: business
|
||||
|
||||
@@ -244,12 +244,12 @@
|
||||
"version": 3
|
||||
},
|
||||
"horizontal/swedish-year-end-closing/closing-process": {
|
||||
"hash": "bce8e129860dd26c04e5e406dc9312e2d42dea6aa8c0139f168de43529abf939",
|
||||
"version": 2
|
||||
"hash": "2d23c29bcf8a7f5d6ce72e677abe518efdf8300ed11360269377a342f51945b5",
|
||||
"version": 3
|
||||
},
|
||||
"horizontal/swedish-year-end-closing/journal-entries": {
|
||||
"hash": "acd171ade0305bcbb4142e0f9817482f845dc6e1b3620a62eb36b6e8eef6110a",
|
||||
"version": 2
|
||||
"hash": "b4891b88b6cf409f00c76c70b7acb9dbf20e13ac05814886f978b80b878ab0a9",
|
||||
"version": 3
|
||||
},
|
||||
"horizontal/swedish-year-end-closing/k2-vs-k3": {
|
||||
"hash": "e3fa066d0e1fe4284661df669736241daf05e08599f893b40f5a6f94722d0bce",
|
||||
|
||||
@@ -127,6 +127,9 @@ export function buildMigrationSql(atoms: DiscoveredAtom[], versions: Record<stri
|
||||
-- in-app agent read skill content from the DB (works on Vercel, Docker, self-hosted).
|
||||
-- Idempotent: ON CONFLICT refreshes content fields but leaves is_active and
|
||||
-- mcp_exposed under manual control (they take column defaults on first insert).
|
||||
-- The WHERE guard skips rows whose registry version is newer than this seed's:
|
||||
-- two branches can each carry a full seed, and the one that applies last can
|
||||
-- no longer downgrade atoms the other already bumped.
|
||||
`
|
||||
|
||||
const values = atoms.map((a) => buildValuesRow(a, versions[a.id])).join(',\n')
|
||||
@@ -147,7 +150,8 @@ ON CONFLICT (id) DO UPDATE SET
|
||||
parent_atom_id = EXCLUDED.parent_atom_id,
|
||||
version = EXCLUDED.version,
|
||||
schema_version = EXCLUDED.schema_version,
|
||||
updated_at = now();
|
||||
updated_at = now()
|
||||
WHERE public.agent_atom_registry.version <= EXCLUDED.version;
|
||||
`
|
||||
|
||||
return `${header}\n${insert}\nNOTIFY pgrst, 'reload schema';\n`
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
-- "Preliminär F-skatt (EF)" booked Debit 2012 / Credit 1630. Account 2012
|
||||
-- "Avräkning för skatter och avgifter" was added to BAS_REFERENCE in #1388 on
|
||||
-- the strength of the swedish-year-end-closing skill alone; the primary-source
|
||||
-- check (#1409, bas.se BAS 2026 v2) shows the official kontoplan has no 2012:
|
||||
-- the enskild firma equity block is 2010, 2011, 2013, 2017, 2018, 2019, and
|
||||
-- "Avräkning för skatter och avgifter (skattekonto)" is 1630/1640 (asset) and
|
||||
-- 2850 (liability). 2012 is a program convention (Visma, Bokio, Björn Lundén),
|
||||
-- not standard BAS, so the reference drops it and the template moves to 2013
|
||||
-- "Övriga egna uttag": owner taxes paid by an enskild firma are an eget uttag.
|
||||
--
|
||||
-- Scope: every enskild_firma template row still carrying a 2012 line, i.e. the
|
||||
-- seeded system row plus any clone of it. Charts that already had 2012
|
||||
-- backfilled keep the account and its history; only future template use moves
|
||||
-- to 2013. account-backfill seeds 2013 on demand (it is standard BAS), so the
|
||||
-- template works for charts that lack it.
|
||||
|
||||
UPDATE public.booking_template_library
|
||||
SET lines = (
|
||||
SELECT jsonb_agg(
|
||||
CASE
|
||||
WHEN line->>'account' = '2012' THEN jsonb_set(line, '{account}', '"2013"')
|
||||
ELSE line
|
||||
END
|
||||
ORDER BY ord
|
||||
)
|
||||
FROM jsonb_array_elements(lines) WITH ORDINALITY AS t(line, ord)
|
||||
)
|
||||
WHERE entity_type = 'enskild_firma'
|
||||
AND lines @> '[{"account": "2012"}]';
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user