Files
boc/IOM_LEDGER_INTEGRATION.md
T

502 lines
12 KiB
Markdown
Raw Normal View History

# IOM ↔ aamos-ledger Integration
> Hur Infrastructure Object Model kopplas till bokföringsmotorn
> Status: Utkast | 2026-06-26
---
## Översikt
IOM och aamos-ledger delar ett gemensamt mål: **spårbarhet**. IOM spårar fysiska objekt över tid. Ledger spårar ekonomiska transaktioner över tid. Integrationen skapar en **helhetsbild där varje krona kan kopplas till ett fysiskt objekt och varje objekt har en ekonomisk historia**.
---
## Mappning: IOM → Ledger
### 1. Objekt som Anläggningstillgångar
| IOM | Ledger | Exempel |
|---|---|---|
| `goid` | `asset_id` | "TRN-BRG-ABT-CON-001" |
| `installation_date` | `acquisition_date` | "2019-03-15" |
| `design_lifespan` | `useful_life_years` | 50 |
| `owner` | `cost_center` | "kommun:stockholm" |
| `material` + `dimensions` | `asset_description` | "Betongbrofäste C35, 12.5x3.2x2.1m" |
### 2. Kontomappning
```yaml
# BAS-konton för IOM-objekt
accounts:
# Anläggningstillgångar
1220:
name: "Byggnader och markanläggningar"
object_types: ["bridge", "tunnel", "road"]
depreciation: "linear"
1230:
name: "Maskiner och inventarier"
object_types: ["transformer", "charger", "pump"]
depreciation: "linear"
1240:
name: "Fastighetsförbättringar"
object_types: ["facade", "roof", "window"]
depreciation: "linear"
# Underhåll
6110:
name: "Reparation och underhåll"
transaction_types: ["maintenance", "repair", "component_replacement"]
6130:
name: "Entreprenadkostnader"
transaction_types: ["contractor_work"]
# Avskrivningar
7830:
name: "Avskrivningar byggnader"
auto_generated: true
# Försäkring
6310:
name: "Försäkringspremier"
transaction_types: ["insurance_premium"]
# Förlust
7970:
name: "Nedskrivningar"
transaction_types: ["impairment", "write_off"]
```
---
## Transaktionsflöden
### Scenario 1: Nyinstallation
```yaml
# Händelse: Ny brofäste installeras
event:
type: "installation"
date: "2026-08-15"
object:
goid: "TRN-BRG-ABT-CON-002"
type: "abutment"
material: ["concrete_c35"]
cost: 5200000 # SEK
# Ledger-transaktion
ledger_entry:
date: "2026-08-15"
verno: "2026-0001847"
transactions:
- account: "1220" # Dr: Anläggningstillgång
amount: 5200000
- account: "2440" # Kr: Leverantörsskuld
amount: -5200000
- account: "2640" # Kr: Ingående moms
amount: -1300000
- account: "1220" # Dr: Moms ingår i tillgångsvärdet
amount: 1300000
metadata:
goid: "TRN-BRG-ABT-CON-002"
project: "Bromöllan bro etapp 2"
contractor: "Skanska AB"
```
### Scenario 2: Underhåll (Observation → Kostnad)
```yaml
# Händelse: Sprickreparation efter observation
event:
type: "maintenance"
triggered_by: "OBS-2028-006633" # Observation med spricka 5mm
date: "2028-05-20"
object:
goid: "TRN-BRG-ABT-CON-001"
work:
description: "Injektion av spricka, armeringsskydd"
cost: 350000
contractor: "Cementa AB"
# Ledger-transaktion
ledger_entry:
date: "2028-05-20"
verno: "2028-0000521"
transactions:
- account: "6110" # Dr: Reparation och underhåll
amount: 350000
- account: "2440" # Kr: Leverantörsskuld
amount: -350000
metadata:
goid: "TRN-BRG-ABT-CON-001"
observation_id: "OBS-2028-006633"
defect_code: "1300" # Betongspricka
risk_before: 5.2
risk_after: 2.1
```
### Scenario 3: Komponentbyte (BOM-uppdatering)
```yaml
# Händelse: LED-modul byts i gatlykta
event:
type: "component_replacement"
date: "2029-03-10"
parent_object:
goid: "TRN-LGT-STR-LED-0001"
name: "Gatlykta Drottningholm"
old_component:
goid: "TRN-LGT-ARM-LED-0001-v1"
status: "retired"
new_component:
goid: "TRN-LGT-ARM-LED-0001-v2"
type: "LED_armature_v2"
cost: 8500
# Ledger-transaktion
ledger_entry:
date: "2029-03-10"
verno: "2029-0000184"
transactions:
- account: "6110" # Dr: Reparation och underhåll
amount: 8500
- account: "2440" # Kr: Leverantörsskuld
amount: -8500
metadata:
parent_goid: "TRN-LGT-STR-LED-0001"
component_goid: "TRN-LGT-ARM-LED-0001-v2"
replaced_goid: "TRN-LGT-ARM-LED-0001-v1"
remaining_value_old: 3200 # Ev. kvarvarande värde att skriva av
```
### Scenario 4: Avskrivning (Automatisk)
```yaml
# Händelse: Årlig avskrivning
event:
type: "depreciation"
date: "2026-12-31"
object:
goid: "TRN-BRG-ABT-CON-001"
acquisition_value: 4500000
accumulated_depreciation: 720000 # 8 år x 90k
remaining_value: 3780000
# Ledger-transaktion (auto-genererad)
ledger_entry:
date: "2026-12-31"
verno: "2026-0099999" # Auto-vernr för avskrivningar
auto_generated: true
transactions:
- account: "7830" # Dr: Avskrivningar
amount: 90000
- account: "1229" # Kr: Ackumulerade avskrivningar
amount: -90000
metadata:
goid: "TRN-BRG-ABT-CON-001"
depreciation_method: "linear"
annual_amount: 90000
useful_life: 50
years_depreciated: 9
```
### Scenario 5: Nedskrivning (Riskbaserad)
```yaml
# Händelse: Objekt med risk > 8 triggar nedskrivningsprövning
event:
type: "impairment_review"
triggered_by: "OBS-2031-001847"
date: "2031-06-15"
object:
goid: "TRN-BRG-ABT-CON-001"
book_value: 3600000
recoverable_amount: 2100000 # Nytt verkligt värde
impairment_loss: 1500000
# Ledger-transaktion
ledger_entry:
date: "2031-06-15"
verno: "2031-0000522"
transactions:
- account: "7970" # Dr: Nedskrivningar
amount: 1500000
- account: "1220" # Kr: Anläggningstillgång
amount: -1500000
metadata:
goid: "TRN-BRG-ABT-CON-001"
observation_id: "OBS-2031-001847"
risk_level: 8.5
defect_codes: ["1300", "1200"] # Spricka + genomrost
assessor: "KPMG"
```
---
## Automatiska flöden
### 1. Observation → Underhållskostnad
```python
def on_observation_created(observation):
"""
När en observation skapas med viss allvarlighetsgrad,
skapa en reservation för framtida underhåll.
"""
if observation.risk_level >= 7:
# Skapa prognos (ej verifikat, men budgetpost)
create_maintenance_provision(
goid=observation.object_goid,
estimated_cost=estimate_repair_cost(observation),
due_date=observation.ai_analysis.next_observation_due
)
```
### 2. Komponentlivslängd → Avskrivning
```python
def on_component_installed(component):
"""
När en komponent installeras, skapa separat avskrivning
om komponentens livslängd skiljer sig från förälderns.
"""
parent = get_object(component.parent_goid)
if component.design_lifespan != parent.design_lifespan:
# Komponenten har egen avskrivningsplan
create_depreciation_schedule(
asset_id=component.goid,
acquisition_value=component.cost,
useful_life=component.design_lifespan,
start_date=component.installation_date
)
```
### 3. Riskförändring → Värdering
```python
def on_risk_threshold_exceeded(object_goid, new_risk_level):
"""
När risknivå överstiger tröskel, trigga värdering.
"""
if new_risk_level >= 8:
# Skapa uppgift för mänsklig granskning
create_impairment_review_task(
goid=object_goid,
trigger_risk=new_risk_level,
priority="high"
)
# Notera i ledger (ej bokföring, men logg)
log_valuation_event(
goid=object_goid,
event_type: "risk_threshold_exceeded",
risk_level: new_risk_level
)
```
---
## Rapportering
### Objektets ekonomiska livscykel
```yaml
report: "object_economic_lifecycle"
goid: "TRN-BRG-ABT-CON-001"
summary:
acquisition_value: 4500000
accumulated_depreciation: 810000 # 9 år
book_value: 3690000
maintenance_cost_5y: 680000
projected_maintenance_5y: 920000
impairment_history:
- date: "2031-06-15"
amount: 1500000
reason: "Structural degradation"
timeline:
- date: "2019-03-15"
event: "installation"
value: 4500000
- date: "2026-12-31"
event: "depreciation"
value_change: -90000
- date: "2028-05-20"
event: "maintenance"
cost: 350000
risk_after: 2.1
- date: "2031-06-15"
event: "impairment"
value_change: -1500000
reason: "Risk level 8.5"
- date: "2034-03-15"
event: "projected_end_of_life"
remaining_value: 0
```
### Kontradiktionsrapport (Landvex specialitet)
```yaml
report: "contradiction_analysis"
period: "2026-Q2"
# Kommunens rapportering
official:
source: "kommun:stockholm"
reported_bridges_good_condition: 12
reported_maintenance_budget: 2500000
# quiXzoom-observationer
observed:
total_observations: 847
objects_with_defects: 9
average_risk_level: 4.3
high_risk_observations: 34
# Kontradiktioner
contradictions:
- type: "condition_discrepancy"
severity: "high"
description: "Kommunen rapporterar 12 broar i gott skick, men observationer visar strukturella avvikelser på 9 av dem"
affected_objects: ["TRN-BRG-...", "TRN-BRG-..."]
estimated_underreporting: 75%
- type: "budget_insufficiency"
severity: "medium"
description: "Uppskattad underhållskostnad baserat på observationer: 4.2M, budget: 2.5M"
gap: 1700000
- type: "risk_underestimation"
severity: "critical"
description: "3 objekt med risknivå > 8 har ingen planerad åtgärd i kommunens system"
objects: ["TRN-BRG-ABT-CON-001", "TRN-BRG-...", "TRN-BRG-..."]
```
---
## Teknisk implementation
### API-endpoints
```yaml
# IOM → Ledger
POST /ledger/assets
body: {goid, acquisition_value, installation_date, ...}
POST /ledger/transactions
body: {goid, type, amount, date, metadata}
GET /ledger/assets/{goid}/value
response: {book_value, accumulated_depreciation, remaining_life}
GET /ledger/assets/{goid}/maintenance-cost
params: {from_date, to_date}
response: {total, breakdown_by_year}
# Ledger → IOM
POST /iom/objects/{goid}/financial-event
body: {event_type, amount, date, ledger_verno}
GET /iom/objects/{goid}/observations
params: {with_cost: true}
response: [observation + associated_costs]
```
### Databasschema (förenklat)
```sql
-- Kopplingstabell
CREATE TABLE iom_ledger_mapping (
goid VARCHAR(50) PRIMARY KEY,
asset_account VARCHAR(4) NOT NULL,
acquisition_value DECIMAL(15,2),
acquisition_date DATE,
useful_life_years INT,
depreciation_method VARCHAR(20),
cost_center VARCHAR(50),
-- IOM-referenser
object_type VARCHAR(50),
material JSON,
installation_date DATE,
-- Ledger-referenser
last_depreciation_date DATE,
accumulated_depreciation DECIMAL(15,2),
book_value DECIMAL(15,2),
-- Metadata
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Transaktionshistorik
CREATE TABLE iom_ledger_transactions (
id SERIAL PRIMARY KEY,
goid VARCHAR(50) REFERENCES iom_ledger_mapping(goid),
verno VARCHAR(20) NOT NULL,
transaction_date DATE NOT NULL,
transaction_type VARCHAR(50) NOT NULL,
account VARCHAR(4) NOT NULL,
amount DECIMAL(15,2) NOT NULL,
-- IOM-kontext
observation_id VARCHAR(20),
defect_code VARCHAR(4),
risk_level DECIMAL(3,1),
-- Metadata
description TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- Index
CREATE INDEX idx_iom_ledger_goid ON iom_ledger_transactions(goid);
CREATE INDEX idx_iom_ledger_date ON iom_ledger_transactions(transaction_date);
CREATE INDEX idx_iom_ledger_type ON iom_ledger_transactions(transaction_type);
```
---
## Sammanfattning
Integrationen mellan IOM och aamos-ledger skapar:
1. **Spårbarhet**: Varje krona kopplad till ett fysiskt objekt
2. **Prediktion**: Underhållskostnader baserade på observationer
3. **Transparens**: Kontradiktioner mellan rapporterad och observerad verklighet
4. **Automatisering**: Avskrivningar, nedskrivningar och reservationer triggar av data
5. **Beslutsstöd**: Ekonomisk livscykel per objekt, inte bara per konto
**Resultat**: En kommun kan inte längre rapportera "alla broar är i gott skick" utan att systemet automatiskt flaggar att observationer visar motsatsen — och vad det kostar.