feat: implement skattekonto drift detection and alerting (#525)
* 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.
This commit is contained in:
@@ -317,6 +317,32 @@ export interface BankAccount {
|
||||
balance_updated_at?: string | null
|
||||
}
|
||||
|
||||
// Cash account — first-class entity for ledger-account routing decisions.
|
||||
// Backed by the cash_accounts table; bank_connections.accounts_data remains
|
||||
// the source for PSD2 sync metadata + UI display until a follow-up migration
|
||||
// drops it 30 days after this PR.
|
||||
export type CashAccountSource = 'enable_banking' | 'manual' | 'sie_import'
|
||||
|
||||
export interface CashAccount {
|
||||
id: string
|
||||
company_id: string
|
||||
bank_connection_id: string | null
|
||||
external_uid: string | null // PSD2 StoredAccount.uid
|
||||
iban: string | null
|
||||
bg_pg: string | null
|
||||
name: string | null
|
||||
currency: string // 3-char ISO; broader than Currency union to
|
||||
// tolerate future currencies without DB-driven enum drift
|
||||
ledger_account: string
|
||||
balance: number | null
|
||||
balance_updated_at: string | null
|
||||
enabled: boolean
|
||||
is_primary: boolean
|
||||
source: CashAccountSource
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
// Import source identifiers
|
||||
export type ImportSource =
|
||||
| 'enable_banking'
|
||||
@@ -384,6 +410,13 @@ export interface Transaction {
|
||||
import_source: string | null
|
||||
reference: string | null // OCR number, Bankgiro reference
|
||||
|
||||
// Counterparty identification from PSD2 (creditor for outflows, debtor for
|
||||
// inflows). The own-account transfer detector matches `counterparty_iban`
|
||||
// against cash_accounts.iban for the same company. `counterparty_account`
|
||||
// is the BG/PG/BBAN fallback for Swedish domestic transfers without IBAN.
|
||||
counterparty_iban: string | null
|
||||
counterparty_account: string | null
|
||||
|
||||
// Notes
|
||||
notes: string | null
|
||||
|
||||
@@ -2507,6 +2540,18 @@ export interface RawTransaction {
|
||||
reference?: string | null
|
||||
bank_connection_id?: string | null
|
||||
import_source?: string
|
||||
/**
|
||||
* Counterparty IBAN from PSD2 (creditor for outflows, debtor for inflows).
|
||||
* Used by the own-account transfer detector — when this matches another
|
||||
* cash_accounts row for the same company, both legs auto-book as a transfer.
|
||||
*/
|
||||
counterparty_iban?: string | null
|
||||
/**
|
||||
* Bankgiro / Plusgiro / BBAN fallback when no IBAN is available (typical
|
||||
* for Swedish domestic transfers). Kept distinct from IBAN so matching
|
||||
* doesn't accidentally collide BG numbers with IBAN strings.
|
||||
*/
|
||||
counterparty_account?: string | null
|
||||
}
|
||||
|
||||
/** Options for the transaction ingestion pipeline */
|
||||
|
||||
Reference in New Issue
Block a user