8a6ce7093e
* feat: implement skattekonto drift detection and alerting - Add skattekonto drift computation logic to compare Skatteverket's saldo with GL 1630 sum. - Implement alerting mechanism for significant drift changes, with throttling to prevent alert spamming. - Introduce database functions to sum GL 1630 entries and list unbooked skattekonto rows. feat: create own account transfer detection - Develop logic to detect transfers between a company's own cash accounts based on counterparty IBAN. - Implement tests to validate detection logic under various scenarios, including matching and non-matching IBANs. feat: establish cash accounts as a first-class entity - Create cash_accounts table to manage routable cash accounts, replacing ad-hoc JSONB structures. - Implement functions for listing, upserting, and managing cash accounts, including primary account designation. feat: enhance GL line reconciliation functionality - Modify get_unlinked_1930_lines RPC to accept any account number for reconciliation, improving flexibility for different currencies. - Update related functions to ensure compatibility with the new cash_accounts structure. feat: capture counterparty IBAN in transactions - Add counterparty_iban column to transactions table to facilitate intra-account transfer detection. - Create index for efficient lookups based on counterparty IBAN. * feat: Enhance cash account handling and reconciliation processes - Updated reconciliation routes to enforce cash account validation for all account numbers, including '1930'. - Improved error handling for unknown cash accounts in reconciliation status and unmatched entries routes. - Changed CashAccountSelector to use sessionStorage instead of localStorage for better data privacy. - Fixed mapping for employer payroll taxes to route to the correct account (2730 instead of 2731). - Added safety checks for company IDs in the guessCounterAccount function to prevent injection vulnerabilities. - Introduced atomic RPC for setting primary cash accounts to avoid intermediate states during updates. - Seeded default cash accounts for new companies to ensure reconciliation routes are accessible from day one. - Updated email notifications for drift detection to avoid exposing sensitive financial data. - Enhanced bank reconciliation logic to handle multi-currency transactions correctly. - Renamed and updated tests to reflect changes in the underlying RPCs and ensure accurate coverage. - Migrated existing cash account rules to correct mappings in compliance with Swedish accounting standards.
73 lines
2.5 KiB
PL/PgSQL
73 lines
2.5 KiB
PL/PgSQL
-- Migration: parametrise the unmatched-GL-lines RPC so reconciliation works on
|
|
-- any settlement account, not just 1930.
|
|
--
|
|
-- Why: until now `get_unlinked_1930_lines` hardcoded the bank-side BAS account.
|
|
-- EUR/USD customers can't self-reconcile their 1932/1933 accounts and the
|
|
-- skattekonto, payment-provider clearing, and BG/PG flows have no path. Now that
|
|
-- cash_accounts exists, the RPC accepts an account number parameter and the UI
|
|
-- can offer an account selector populated from that table.
|
|
--
|
|
-- The old function is dropped (no backwards-compatibility shim): the two
|
|
-- in-repo callers (lib/reconciliation/bank-reconciliation.ts and
|
|
-- app/api/reconciliation/bank/unmatched-entries/route.ts) are updated in the
|
|
-- same PR. Anyone calling the RPC over the REST surface must switch to the new
|
|
-- name + parameter at the same time.
|
|
|
|
DROP FUNCTION IF EXISTS public.get_unlinked_1930_lines(uuid, date, date);
|
|
|
|
CREATE FUNCTION public.get_unlinked_gl_lines(
|
|
p_company_id UUID,
|
|
p_account_number TEXT DEFAULT '1930',
|
|
p_date_from DATE DEFAULT NULL,
|
|
p_date_to DATE DEFAULT NULL
|
|
)
|
|
RETURNS TABLE (
|
|
line_id UUID,
|
|
journal_entry_id UUID,
|
|
debit_amount NUMERIC,
|
|
credit_amount NUMERIC,
|
|
line_description TEXT,
|
|
entry_date DATE,
|
|
voucher_number INT,
|
|
voucher_series TEXT,
|
|
entry_description TEXT,
|
|
source_type TEXT
|
|
)
|
|
LANGUAGE sql
|
|
STABLE
|
|
SECURITY DEFINER
|
|
SET search_path = public
|
|
AS $$
|
|
SELECT
|
|
jel.id AS line_id,
|
|
je.id AS journal_entry_id,
|
|
jel.debit_amount,
|
|
jel.credit_amount,
|
|
jel.line_description,
|
|
je.entry_date,
|
|
je.voucher_number,
|
|
je.voucher_series,
|
|
je.description AS entry_description,
|
|
je.source_type
|
|
FROM public.journal_entry_lines jel
|
|
JOIN public.journal_entries je ON je.id = jel.journal_entry_id
|
|
WHERE jel.account_number = p_account_number
|
|
AND je.company_id = p_company_id
|
|
AND je.status = 'posted'
|
|
-- IB lines never have a counterpart in the bank feed — the bank statement
|
|
-- starts at IB and accumulates from there. Keep them excluded from the
|
|
-- unmatched set so reconciliation doesn't surface a phantom voucher.
|
|
AND je.source_type IS DISTINCT FROM 'opening_balance'
|
|
AND (p_date_from IS NULL OR je.entry_date >= p_date_from)
|
|
AND (p_date_to IS NULL OR je.entry_date <= p_date_to)
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM public.transactions t
|
|
WHERE t.journal_entry_id = je.id
|
|
AND t.company_id = p_company_id
|
|
)
|
|
ORDER BY je.entry_date, je.voucher_number;
|
|
$$;
|
|
|
|
NOTIFY pgrst, 'reload schema';
|