SPB Git

spb/air Public MIT

AIR — The Language of Accounting.

Python 100%
2.5 KB · 91 lines python
Raw Blame History
1# =============================================================================2# Projet : AIR — Accounting Intermediate Representation3# Auteur : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# Fichier : journal.py6# Description : Compiled output types — accounts, journal lines/entries, compiled journal.7# =============================================================================8"""Journal types: what the AIC compiler PRODUCES (never what the LLM writes).910Every journal line carries a provenance node id, so any posted figure can be11traced back through tax/FX derivations to the source economic event and its12document.13"""14from __future__ import annotations1516import enum17from dataclasses import dataclass, field18from datetime import date19from decimal import Decimal2021from core.money import Money22from core.provenance import ProvenanceGraph232425class AccountType(str, enum.Enum):26    ASSET = "asset"27    LIABILITY = "liability"28    EQUITY = "equity"29    REVENUE = "revenue"30    EXPENSE = "expense"3132    @property33    def normal_side(self) -> "Side":34        if self in (AccountType.ASSET, AccountType.EXPENSE):35            return Side.DEBIT36        return Side.CREDIT373839class Side(str, enum.Enum):40    DEBIT = "debit"41    CREDIT = "credit"424344@dataclass(frozen=True, slots=True)45class Account:46    code: str47    name: str48    type: AccountType495051@dataclass(frozen=True, slots=True)52class JournalLine:53    account: Account54    side: Side55    amount: Money                    # always >= 0; direction is carried by `side`56    memo: str = ""57    provenance_id: str | None = None5859    def signed(self) -> Decimal:60        """Debit-positive signed amount (for balance math)."""61        return self.amount.amount if self.side is Side.DEBIT else -self.amount.amount626364@dataclass(frozen=True, slots=True)65class JournalEntry:66    id: str67    date: date68    description: str69    lines: tuple[JournalLine, ...]70    source_event_id: str71    policy_set: str = ""72    policy_version: str = ""73    reverses: str | None = None      # id of the entry this one reverses, if any747576@dataclass77class CompiledJournal:78    """The result of one AIC compilation: entries + full provenance."""7980    entries: list[JournalEntry] = field(default_factory=list)81    provenance: ProvenanceGraph = field(default_factory=ProvenanceGraph)82    policy_set: str = ""83    policy_version: str = ""8485    def accounts(self) -> dict[str, Account]:86        out: dict[str, Account] = {}87        for entry in self.entries:88            for line in entry.lines:89                out[line.account.code] = line.account90        return out91