176 lines
6.8 KiB
Markdown
176 lines
6.8 KiB
Markdown
|
|
# LEDGER_ARCHITECTURE.md — Hållbar struktur för LandveX ekonomisystem
|
|||
|
|
*Beslutad: 2026-06-17*
|
|||
|
|
|
|||
|
|
## Nuläge (vad som faktiskt finns och fungerar)
|
|||
|
|
|
|||
|
|
### ✅ Fungerar
|
|||
|
|
- `aamos-ledger` kör på port 3250, 1 092 journalposter, audit trail, multi-tenant
|
|||
|
|
- Reconciliation Engine (E1-004) — API finns, POST-routes registrerade
|
|||
|
|
- Period Close Workflow (E1-005) — state machine open→review→approved→closed
|
|||
|
|
- SIE4 Export (E1-006) — endpoint finns
|
|||
|
|
- BAS 2024 kontoplan, 38 konton aktiva
|
|||
|
|
- Fortnox-klonen UI på https://landvex.com/ouroboros/finance/
|
|||
|
|
|
|||
|
|
### ⚠️ Trasigt/ofullständigt
|
|||
|
|
- trial-balance returnerar `balanced: null` (aggregering bruten)
|
|||
|
|
- Reconciliation saknar GET /sessions (lista)
|
|||
|
|
- Ingen period är stängd — alla 6 perioder `open`
|
|||
|
|
- 1689 Observationskonto: 966k oklassificerat
|
|||
|
|
- Auth mot Identity Service inte kopplad
|
|||
|
|
- Diff D:5 803 792 vs C:5 928 838 = **−125 046 kr obalans**
|
|||
|
|
|
|||
|
|
### 🔴 Affärskritiskt
|
|||
|
|
- Q1-moms 202 787 kr OBETALD
|
|||
|
|
- Leon-fordran 212 922 kr
|
|||
|
|
- Konto 2990 Omföringskonto: 244 899 kr residual — betyder att omföringar inte är nollade
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Arkitekturen — tre lager
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|||
|
|
│ LAGER 3 — AUTOMATION & API │
|
|||
|
|
│ Webhooks · n8n-flows · Skatteverket · Bank-API · Stripe │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ LAGER 2 — INTELLIGENCE & PUSH │
|
|||
|
|
│ Checkpoint-motor · Nudge-engine · Task-lista · Dashboards │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ LAGER 1 — KÄRNAN (aamos-ledger) │
|
|||
|
|
│ Journal · Kontoplan · Perioder · Reconciliation · SIE4 │
|
|||
|
|
└─────────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Principen:** Lager 1 måste vara komplett och stabil innan Lager 2 byggs. Lager 3 kopplas på när Lager 2 fungerar.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Lager 1 — Fixa kärnan (denna sprint)
|
|||
|
|
|
|||
|
|
### L1-FIX-001: trial-balance aggregering
|
|||
|
|
trial-balance returnerar `balanced: null`. Buggen: totalDebit/totalCredit beräknas inte server-side.
|
|||
|
|
**Fix:** Summera i route-hanteraren.
|
|||
|
|
|
|||
|
|
### L1-FIX-002: Reconciliation GET /sessions
|
|||
|
|
Saknar `GET /api/ledger/reconciliation/sessions` — listan syns aldrig.
|
|||
|
|
**Fix:** Lägg till GET-route.
|
|||
|
|
|
|||
|
|
### L1-FIX-003: Stäng perioder 2026-01 t.o.m. 2026-05
|
|||
|
|
Alla 6 perioder är `open`. En stängd period = oföränderlig historik.
|
|||
|
|
**Workflow:** submit-review → approve → close
|
|||
|
|
**Förutsättning:** trial-balance måste vara balanserad per period.
|
|||
|
|
|
|||
|
|
### L1-FIX-004: Rensa konto 2990 (Omföringskonto)
|
|||
|
|
Residual 244 899 kr. Det ska alltid vara 0 — det är ett transitkonto.
|
|||
|
|
**Fix:** Identifiera och bokför rättelseposter.
|
|||
|
|
|
|||
|
|
### L1-FIX-005: Förklara den -125 046 kr differensen
|
|||
|
|
D:5 803 792 vs C:5 928 838. Kan vara FX-poster, ej bokförda kostnader, eller periodfel.
|
|||
|
|
**Fix:** Spåra källan, bokför rättelse.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Lager 2 — Intelligence & Push (nästa sprint)
|
|||
|
|
|
|||
|
|
### L2-001: Checkpoint-motor (det som pushar dig)
|
|||
|
|
|
|||
|
|
En `ledger_checkpoints`-tabell med regler som körs automatiskt:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Checkpoint | Trigger | Åtgärd
|
|||
|
|
---------------------------|----------------------|---------------------------
|
|||
|
|
Öppen period > 30 dagar | Nightly cron | Push: "2026-03 ej stängd"
|
|||
|
|
Konto 1689 > 0 | On journal save | Push: "Oklassificerade poster"
|
|||
|
|
Moms förfallen | Kalenderbaserad | Push: "Q1-moms OBETALD"
|
|||
|
|
Fordran > 60 dagar | Nightly cron | Push: "Leon-fordran 92 dagar"
|
|||
|
|
Debet ≠ Kredit i period | On journal save | Blockera post
|
|||
|
|
2990 > 0 vid månadsslut | Period close trigger | Push: "Omföringskonto ej nollat"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### L2-002: Task-lista med status
|
|||
|
|
|
|||
|
|
Varje checkpoint genererar en task. Tasks har:
|
|||
|
|
- `id`, `type`, `title`, `due_date`, `status` (open/snoozed/done), `amount`, `period`
|
|||
|
|
- API: `GET /api/ledger/tasks` → lista med prioritet
|
|||
|
|
- UI: Tasks-panel i Fortnox-klonen
|
|||
|
|
|
|||
|
|
### L2-003: Dashboard-siffror rätt
|
|||
|
|
|
|||
|
|
Koppla trial-balance till P&L och balansräkning korrekt:
|
|||
|
|
- Intäkter: klass 3 (credit-saldo)
|
|||
|
|
- Kostnader: klass 5-7 (debet-saldo)
|
|||
|
|
- Resultat: intäkter − kostnader
|
|||
|
|
- Balansräkning: tillgångar vs skulder+eget kapital
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Lager 3 — Automationer & API (framtida)
|
|||
|
|
|
|||
|
|
### Prioritetsordning
|
|||
|
|
|
|||
|
|
1. **Momsdeklaration API** (Skatteverket eSkattedeklaration)
|
|||
|
|
- Trigger: Period close av kvartalets sista period
|
|||
|
|
- Flow: Beräkna moms → skapa XML → POST till Skatteverket
|
|||
|
|
|
|||
|
|
2. **AGI-fil automatisk** (Arbetsgivardeklaration)
|
|||
|
|
- Trigger: Lönekörning bokförd
|
|||
|
|
- Flow: Summera löneposter → generera AGI-fil → skicka till Skatteverket
|
|||
|
|
|
|||
|
|
3. **Bank-synk automatisk** (Nordea Open Banking / Revolut Webhooks)
|
|||
|
|
- Trigger: Ny banktransaktion
|
|||
|
|
- Flow: Importera → auto-kategorisera → skapa draft → notify
|
|||
|
|
|
|||
|
|
4. **SIE4 till revisor automatisk**
|
|||
|
|
- Trigger: Periodeclose
|
|||
|
|
- Flow: Generera SIE4 → e-posta till andreas.vretblom@kpmg.se
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Stängningsceremonin — hur man stänger böckerna
|
|||
|
|
|
|||
|
|
**Varje månad (när Lager 1+2 är klara):**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. Checkpoint-lista = tom (alla poster kategoriserade)
|
|||
|
|
2. Konto 1689 = 0
|
|||
|
|
3. Konto 2990 = 0
|
|||
|
|
4. D = C (trial-balance balanced: true)
|
|||
|
|
5. Kör: POST /api/ledger/periods/2026-05/submit-review
|
|||
|
|
6. Kör: POST /api/ledger/periods/2026-05/approve
|
|||
|
|
7. Kör: POST /api/ledger/periods/2026-05/close
|
|||
|
|
8. → Period låst. Kan ej ändras.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Kvartalsvis tillägg:**
|
|||
|
|
- Beräkna momsunderlag (konto 2611, 2645)
|
|||
|
|
- Deklarera och betala moms
|
|||
|
|
|
|||
|
|
**Årsvis (FY 2025/2026, deadline 31 okt 2026):**
|
|||
|
|
- Alla 12 perioder stängda
|
|||
|
|
- Årsredovisning = P&L + Balansräkning från trial-balance
|
|||
|
|
- SIE4-export till Andreas Vretblom / KPMG
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Sprint-plan
|
|||
|
|
|
|||
|
|
### Sprint 1 (nu — denna session)
|
|||
|
|
- [ ] L1-FIX-001: trial-balance aggregering
|
|||
|
|
- [ ] L1-FIX-002: Reconciliation GET /sessions
|
|||
|
|
- [ ] L1-FIX-003: Stäng 2026-01 → 2026-03 (de klara perioderna)
|
|||
|
|
- [ ] L1-FIX-004: Diagnostik på 2990 och -125k differensen
|
|||
|
|
|
|||
|
|
### Sprint 2
|
|||
|
|
- [ ] L1-FIX-005: Rensa 1689 (auto-kategorisering av Revolut-poster)
|
|||
|
|
- [ ] L2-001: Checkpoint-motor (5 basregler)
|
|||
|
|
- [ ] L2-002: Tasks-API + Tasks-panel i UI
|
|||
|
|
|
|||
|
|
### Sprint 3
|
|||
|
|
- [ ] L2-003: Dashboard P&L och balansräkning korrekt
|
|||
|
|
- [ ] L3-001: Momsdeklaration-flow
|
|||
|
|
- [ ] L3-004: SIE4 automatisk till revisor vid period-close
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*Bernt äger arkitekturen. Erik godkänner.*
|