spb/air Public MIT
AIR — The Language of Accounting.
Python 100%
1# =============================================================================2# Projet : AIR — Accounting Intermediate Representation3# Auteur : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# Fichier : unit.py6# Description : CompilationUnit — the mutable state threaded through AIC passes.7# =============================================================================8"""The compilation unit: AIR document in, journal entries out.910Passes read the immutable AIR events and accumulate derived state here11(subtotals, tax lines, FX conversions, classifications), all anchored in the12provenance graph. The pass manager verifies the double-entry invariant on13`entries` after every pass.14"""15from __future__ import annotations1617from dataclasses import dataclass, field1819from aic.diagnostics import Diagnostic20from alsl.model import PolicySet21from core.events import AirDocument, EconomicEvent22from core.journal import JournalEntry23from core.money import Money24from core.provenance import ProvenanceGraph252627@dataclass28class TaxLineState:29 """A computed tax amount for one event (transaction currency)."""3031 code: str32 amount: Money33 node_id: str34 payable_role: str35 receivable_role: str36 recoverable: bool37 policy: str # name of the ALSL policy that produced it383940@dataclass41class EventState:42 """Everything the passes derive for a single event."""4344 # transaction-currency amounts45 subtotal: Money | None = None46 subtotal_node: str | None = None47 taxes: list[TaxLineState] = field(default_factory=list)4849 # classification (purchases): account role for the debit side50 classify_as: str | None = None # "asset" | "expense"51 classification_role: str | None = None52 classification_policy: str | None = None5354 # functional-currency amounts, ready for posting (set by the FX pass)55 post_subtotal: Money | None = None56 post_subtotal_node: str | None = None57 post_taxes: list[TaxLineState] = field(default_factory=list)5859 # settlement FX difference (payments): + = more functional units than booked60 fx_diff: Money | None = None61 fx_diff_node: str | None = None62 booked_amount: Money | None = None # functional value at booking rate636465@dataclass66class CompilationUnit:67 document: AirDocument68 policies: PolicySet69 provenance: ProvenanceGraph = field(default_factory=ProvenanceGraph)70 state: dict[str, EventState] = field(default_factory=dict)71 entries: list[JournalEntry] = field(default_factory=list)72 diagnostics: list[Diagnostic] = field(default_factory=list)7374 def event_state(self, event_id: str) -> EventState:75 return self.state.setdefault(event_id, EventState())7677 def find_event(self, event_id: str) -> EconomicEvent | None:78 for event in self.document.events:79 if event.id == event_id:80 return event81 return None82