Initial commit: aamos-ledger source + CLAUDE.md context
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- AAMOS Ledger Engine — PostgreSQL Schema
|
||||
-- Etapp 1 — Vertikal stängning
|
||||
-- Principer: Audit First · Tenant Isolation · Deterministic · Reproducible
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
-- ── Chart of Accounts (Kontoplan) ───────────────────────────────────────────
|
||||
-- Separerad från Rule Engine per arkitekturprincipen.
|
||||
-- Stöder: BAS (SE), IFRS, US GAAP, lokala kontoplaner
|
||||
CREATE TABLE IF NOT EXISTS ledger_accounts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
account_number TEXT NOT NULL, -- t.ex. '1910', '3000'
|
||||
name TEXT NOT NULL,
|
||||
account_type TEXT NOT NULL, -- 'asset'|'liability'|'equity'|'revenue'|'expense'
|
||||
normal_balance TEXT NOT NULL, -- 'debit'|'credit'
|
||||
coa_standard TEXT NOT NULL DEFAULT 'BAS', -- 'BAS'|'IFRS'|'USGAAP'|'custom'
|
||||
parent_account TEXT, -- för kontostruktur/gruppering
|
||||
vat_code TEXT, -- koppling till momsregel
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
metadata JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (tenant_id, account_number, coa_standard)
|
||||
);
|
||||
|
||||
-- ── Journal Entries (Verifikationer) ────────────────────────────────────────
|
||||
-- Ledgerns sanning. IMMUTABLE efter posted.
|
||||
-- Alla fält för full spårbarhet per BYGGPLAN 0.001.
|
||||
CREATE TABLE IF NOT EXISTS ledger_journal_entries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
entry_number BIGINT, -- löpnummer per tenant+räkenskapsår
|
||||
fiscal_year INTEGER NOT NULL, -- t.ex. 2026
|
||||
period TEXT NOT NULL, -- 'YYYY-MM'
|
||||
entry_date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
reference TEXT, -- externt ref (fakturanr, kvittonr)
|
||||
source_type TEXT NOT NULL, -- 'manual'|'import_sie'|'import_csv'|'bank'|'system'
|
||||
source_id TEXT, -- ID i källsystemet
|
||||
status TEXT NOT NULL DEFAULT 'draft', -- 'draft'|'posted'|'voided'
|
||||
void_reason TEXT,
|
||||
voided_at TIMESTAMPTZ,
|
||||
voided_by TEXT,
|
||||
-- Observability / Trace
|
||||
trace_id TEXT NOT NULL,
|
||||
correlation_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
decision_source TEXT NOT NULL DEFAULT 'user', -- 'user'|'system'|'agent'
|
||||
-- Metadata
|
||||
metadata JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
posted_at TIMESTAMPTZ,
|
||||
CONSTRAINT chk_status CHECK (status IN ('draft','posted','voided')),
|
||||
CONSTRAINT chk_source CHECK (source_type IN ('manual','import_sie','import_csv','bank','system','agent'))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS ledger_entry_number_seq START 1;
|
||||
|
||||
-- ── Journal Lines (Verifikationsrader) ──────────────────────────────────────
|
||||
-- Dubbelbokföring: sum(debit) == sum(credit) enforced i applikationskoden.
|
||||
CREATE TABLE IF NOT EXISTS ledger_journal_lines (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entry_id UUID NOT NULL REFERENCES ledger_journal_entries(id) ON DELETE CASCADE,
|
||||
tenant_id TEXT NOT NULL,
|
||||
line_number INTEGER NOT NULL, -- rad 1, 2, 3…
|
||||
account_number TEXT NOT NULL,
|
||||
account_name TEXT, -- denormaliserat för rapporter
|
||||
debit NUMERIC(18,2),
|
||||
credit NUMERIC(18,2),
|
||||
currency TEXT NOT NULL DEFAULT 'SEK',
|
||||
amount_base NUMERIC(18,2), -- belopp i basvaluta
|
||||
vat_code TEXT, -- momsregel vid tidpunkten
|
||||
vat_amount NUMERIC(18,2),
|
||||
cost_center TEXT,
|
||||
project_code TEXT,
|
||||
description TEXT,
|
||||
metadata JSONB NOT NULL DEFAULT '{}',
|
||||
CONSTRAINT chk_debit_credit CHECK (
|
||||
(debit IS NOT NULL AND credit IS NULL) OR
|
||||
(debit IS NULL AND credit IS NOT NULL)
|
||||
),
|
||||
CONSTRAINT chk_positive_debit CHECK (debit IS NULL OR debit > 0),
|
||||
CONSTRAINT chk_positive_credit CHECK (credit IS NULL OR credit > 0)
|
||||
);
|
||||
|
||||
-- ── Audit Log ────────────────────────────────────────────────────────────────
|
||||
-- Varje förändring i ledgern genererar en auditpost.
|
||||
-- APPEND ONLY — aldrig DELETE eller UPDATE.
|
||||
CREATE TABLE IF NOT EXISTS ledger_audit_log (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
trace_id TEXT NOT NULL,
|
||||
correlation_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
entity_type TEXT NOT NULL, -- 'journal_entry'|'account'|'period'
|
||||
entity_id TEXT NOT NULL,
|
||||
action TEXT NOT NULL, -- 'created'|'posted'|'voided'|'imported'
|
||||
decision_source TEXT NOT NULL,
|
||||
before_state JSONB,
|
||||
after_state JSONB,
|
||||
ip_address TEXT,
|
||||
session_id TEXT,
|
||||
ts TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ── Periods ──────────────────────────────────────────────────────────────────
|
||||
-- Workflow-styrd periodstängning.
|
||||
CREATE TABLE IF NOT EXISTS ledger_periods (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
fiscal_year INTEGER NOT NULL,
|
||||
period TEXT NOT NULL, -- 'YYYY-MM'
|
||||
status TEXT NOT NULL DEFAULT 'open', -- 'open'|'review'|'approved'|'closed'
|
||||
opened_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
closed_at TIMESTAMPTZ,
|
||||
closed_by TEXT,
|
||||
workflow_id UUID, -- referens till workflow engine
|
||||
trial_balance JSONB, -- snapshot vid stängning
|
||||
trace_id TEXT NOT NULL,
|
||||
metadata JSONB NOT NULL DEFAULT '{}',
|
||||
UNIQUE (tenant_id, fiscal_year, period),
|
||||
CONSTRAINT chk_period_status CHECK (status IN ('open','review','approved','closed'))
|
||||
);
|
||||
|
||||
-- ── Indexes ───────────────────────────────────────────────────────────────────
|
||||
CREATE INDEX IF NOT EXISTS idx_journal_tenant_period
|
||||
ON ledger_journal_entries (tenant_id, fiscal_year, period);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_journal_status
|
||||
ON ledger_journal_entries (tenant_id, status);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_journal_date
|
||||
ON ledger_journal_entries (tenant_id, entry_date);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_journal_reference
|
||||
ON ledger_journal_entries (tenant_id, reference);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_lines_entry
|
||||
ON ledger_journal_lines (entry_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_lines_account
|
||||
ON ledger_journal_lines (tenant_id, account_number);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_entity
|
||||
ON ledger_audit_log (tenant_id, entity_type, entity_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_trace
|
||||
ON ledger_audit_log (trace_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_tenant
|
||||
ON ledger_accounts (tenant_id, account_number);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_periods_tenant
|
||||
ON ledger_periods (tenant_id, fiscal_year, period);
|
||||
|
||||
-- ── BAS 2024 — Bas-konton för Wavult Group (seed) ───────────────────────────
|
||||
-- Läggs in via seed-script, inte här. Schema är rent.
|
||||
Reference in New Issue
Block a user