-- Correct BAS account names in seed_chart_of_accounts where the seeded label -- contradicted what the engine actually books on the account (#nyckeltal -- mislabel report, 2026-07-31): -- -- 7210 was seeded as 'Semesterlöner', but BAS 7210 is 'Löner till -- tjänstemän' and the payroll engine books gross salaries there -- (lib/salary/account-mapping.ts: monthly_salary/hourly_salary -> -- '7210'; vacation pay goes to 7285). Every seeded aktiebolag that -- ran payroll showed its salary costs under a "Semesterlöner" row, -- e.g. in the Nyckeltal "Största kostnaderna" list. -- 7010 was seeded as the bare 'Löner'; BAS 7010 is 'Löner till -- kollektivanställda'. -- 3002 was seeded as 'Försäljning varor 25%', but 3002 is the 12% revenue -- account everywhere else: invoice booking routes 12% lines there -- (lib/bookkeeping/invoice-entries.ts), category mapping does the -- same, and 20260728120000 seeds default_vat_rate = 0.12 on it. -- 3001 was seeded as 'Försäljning tjänster 25%' although it receives ALL -- 25% revenue (goods and services alike); it gets the BAS name too. -- 2631 carried a double space ('Sverige, 6%'); cosmetic, fixed while the -- literals are re-emitted. -- -- Two parts: (1) redefine the seed function with the corrected literals so -- new companies are right from the start; (2) backfill existing rows, but -- ONLY where the name is still byte-identical to a seeded literal (or its -- pre-20260516 ASCII fold) and the row is a system account, so an account a -- user renamed on purpose is never touched. Bookings are not affected: -- account_name is a label, the account_number is the identity. -- -- The function body is otherwise identical to 20260516130000 (the latest -- definition). Signature unchanged, so CREATE OR REPLACE keeps the EXECUTE -- grant restored by that migration. CREATE OR REPLACE FUNCTION public.seed_chart_of_accounts(p_company_id uuid, p_entity_type text) RETURNS void LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE v_account_count integer; v_user_id uuid; BEGIN SELECT created_by INTO v_user_id FROM public.companies WHERE id = p_company_id; SELECT count(*) INTO v_account_count FROM public.chart_of_accounts WHERE company_id = p_company_id; IF v_account_count > 0 THEN RETURN; END IF; -- Assets (1xxx) INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '1510', 'Kundfordringar', 1, '15', 'asset', 'debit', 'k1', true, '7211'), (v_user_id, p_company_id, '1910', 'Kassa', 1, '19', 'asset', 'debit', 'k1', true, '7212'), (v_user_id, p_company_id, '1930', 'Företagskonto / checkkonto', 1, '19', 'asset', 'debit', 'k1', true, '7212'), (v_user_id, p_company_id, '1940', 'Övriga bankkonton', 1, '19', 'asset', 'debit', 'k1', true, '7212'); -- Equity (2xxx) IF p_entity_type = 'enskild_firma' THEN -- Enskild firma equity accounts: sru_code intentionally NULL. -- BAS reference maps these to INK2 SRU 7221 ("Övrigt eget kapital"), -- which is the aktiebolag tax form. EF entities file NE-bilaga, not -- INK2, and owner drawings/contributions on 2013/2018 must not be -- reported as balance-sheet equity by SIE/INK2 consumers. INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '2010', 'Eget kapital', 2, '20', 'equity', 'credit', 'k1', true, NULL), (v_user_id, p_company_id, '2013', 'Övriga egna uttag', 2, '20', 'equity', 'credit', 'k1', true, NULL), (v_user_id, p_company_id, '2018', 'Övriga egna insättningar', 2, '20', 'equity', 'credit', 'k1', true, NULL); END IF; IF p_entity_type = 'aktiebolag' THEN INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '2081', 'Aktiekapital', 2, '20', 'equity', 'credit', 'k1', true, '7220'), (v_user_id, p_company_id, '2091', 'Balanserat resultat', 2, '20', 'equity', 'credit', 'k1', true, '7221'), (v_user_id, p_company_id, '2099', 'Årets resultat', 2, '20', 'equity', 'credit', 'k1', true, '7222'); END IF; -- Liabilities (2xxx) - BAS 2026 VAT account labels INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '2440', 'Leverantörsskulder', 2, '24', 'liability', 'credit', 'k1', true, '7230'), (v_user_id, p_company_id, '2611', 'Utgående moms försäljning inom Sverige, 25%', 2, '26', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2621', 'Utgående moms försäljning inom Sverige, 12%', 2, '26', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2631', 'Utgående moms försäljning inom Sverige, 6%', 2, '26', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2641', 'Debiterad ingående moms', 2, '26', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2650', 'Redovisningskonto för moms', 2, '26', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2710', 'Personalskatt', 2, '27', 'liability', 'credit', 'k1', true, '7231'), (v_user_id, p_company_id, '2731', 'Avräkning socialavgifter', 2, '27', 'liability', 'credit', 'k1', true, '7231'); IF p_entity_type = 'aktiebolag' THEN INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '2893', 'Skuld till aktieägare', 2, '28', 'liability', 'credit', 'k1', true, '7231'); END IF; -- Revenue (3xxx). 3001/3002 carry the official BAS 2026 names: 3001 takes -- ALL 25% revenue and 3002 is the 12% account (invoice booking, category -- mapping and default_vat_rate all treat it as 12%), so the name must say -- so. INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '3001', 'Försäljning inom Sverige, 25 % moms', 3, '30', 'revenue', 'credit', 'k1', true, '7310'), (v_user_id, p_company_id, '3002', 'Försäljning inom Sverige, 12 % moms', 3, '30', 'revenue', 'credit', 'k1', true, '7310'), (v_user_id, p_company_id, '3100', 'Momsfri försäljning', 3, '31', 'revenue', 'credit', 'k1', true, '7311'), (v_user_id, p_company_id, '3900', 'Övriga rörelseintäkter', 3, '39', 'revenue', 'credit', 'k1', true, '7311'), (v_user_id, p_company_id, '3960', 'Valutakursvinster', 3, '39', 'revenue', 'credit', 'k1', true, '7310'); -- COGS (4xxx) INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '4000', 'Varuinköp', 4, '40', 'expense', 'debit', 'k1', true, '7320'); -- External expenses (5xxx-6xxx) INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '5010', 'Lokalhyra', 5, '50', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '5410', 'Förbrukningsinventarier', 5, '54', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '5420', 'Programvaror', 5, '54', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '5460', 'Förbrukningsmaterial', 5, '54', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '5800', 'Resekostnader', 5, '58', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '5910', 'Annonsering', 5, '59', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6071', 'Representation avdragsgill', 6, '60', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6110', 'Kontorsmateriel', 6, '61', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6212', 'Mobiltelefon', 6, '62', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6230', 'Datakommunikation', 6, '62', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6530', 'Redovisningstjänster', 6, '65', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6570', 'Bankavgifter', 6, '65', 'expense', 'debit', 'k1', true, '7321'), (v_user_id, p_company_id, '6991', 'Övriga avdragsgilla kostnader', 6, '69', 'expense', 'debit', 'k1', true, '7330'); -- Personnel (7xxx). BAS names: 7010 kollektivanställda, 7210 tjänstemän. -- The payroll engine books gross salaries to 7210 and vacation pay to -- 7285 (auto-created with its BAS name when first needed). IF p_entity_type = 'aktiebolag' THEN INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '7010', 'Löner till kollektivanställda', 7, '70', 'expense', 'debit', 'k1', true, '7322'), (v_user_id, p_company_id, '7210', 'Löner till tjänstemän', 7, '72', 'expense', 'debit', 'k1', true, '7322'), (v_user_id, p_company_id, '7510', 'Arbetsgivaravgifter', 7, '75', 'expense', 'debit', 'k1', true, '7322'); END IF; INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '7960', 'Valutakursförluster', 7, '79', 'expense', 'debit', 'k1', true, '7360'); -- Financial (8xxx) INSERT INTO public.chart_of_accounts (user_id, company_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code) VALUES (v_user_id, p_company_id, '8310', 'Ränteintäkter', 8, '83', 'revenue', 'credit', 'k1', true, '7313'), (v_user_id, p_company_id, '8410', 'Räntekostnader', 8, '84', 'expense', 'debit', 'k1', true, '7323'); END; $$; -- Backfill existing companies. Exact-literal matches only (current form plus -- the pre-20260516 ASCII fold), restricted to seeded system accounts, so any -- name a user set themselves survives untouched. UPDATE public.chart_of_accounts SET account_name = 'Löner till tjänstemän' WHERE account_number = '7210' AND is_system_account = true AND account_name IN ('Semesterlöner', 'Semesterloner'); UPDATE public.chart_of_accounts SET account_name = 'Löner till kollektivanställda' WHERE account_number = '7010' AND is_system_account = true AND account_name IN ('Löner', 'Loner'); UPDATE public.chart_of_accounts SET account_name = 'Försäljning inom Sverige, 25 % moms' WHERE account_number = '3001' AND is_system_account = true AND account_name IN ('Försäljning tjänster 25%', 'Forsaljning tjanster 25%'); UPDATE public.chart_of_accounts SET account_name = 'Försäljning inom Sverige, 12 % moms' WHERE account_number = '3002' AND is_system_account = true AND account_name IN ('Försäljning varor 25%', 'Forsaljning varor 25%'); UPDATE public.chart_of_accounts SET account_name = 'Utgående moms försäljning inom Sverige, 6%' WHERE account_number = '2631' AND is_system_account = true AND account_name IN ('Utgående moms försäljning inom Sverige, 6%', 'Utgaende moms forsaljning inom Sverige, 6%'); NOTIFY pgrst, 'reload schema';