|
|
|
@@ -0,0 +1,192 @@
|
|
|
|
|
-- 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';
|