1818
1919@dataclass (frozen = True )
2020class LedgerEvent :
21+ """Immutable representation of one activity, revenue, or cost event."""
22+
2123 id : str
2224 category : str
2325 event_type : str
@@ -34,6 +36,8 @@ class LedgerEvent:
3436
3537@dataclass (frozen = True )
3638class TeamSummary :
39+ """Aggregated financial and approval state for one team and currency."""
40+
3741 team_id : str
3842 currency : str
3943 revenue : Decimal
@@ -47,6 +51,7 @@ class EventLedger:
4751 """SQLite-backed ledger suitable for simulation and a later API adapter."""
4852
4953 def __init__ (self , connection : sqlite3 .Connection ):
54+ """Initialize the ledger and migrate an existing database if needed."""
5055 self ._lock = RLock ()
5156 database_path = connection .execute ("PRAGMA database_list" ).fetchone ()[2 ]
5257 if database_path :
@@ -86,6 +91,7 @@ def __init__(self, connection: sqlite3.Connection):
8691 self ._connection .commit ()
8792
8893 def _migrate_legacy_amount_column (self ) -> None :
94+ """Rewrite legacy REAL amounts as text to preserve exact decimals."""
8995 columns = self ._connection .execute ("PRAGMA table_info(ledger_events)" ).fetchall ()
9096 amount_column = next ((column for column in columns if column ["name" ] == "amount" ), None )
9197 if amount_column is None or amount_column ["type" ].upper () != "REAL" :
@@ -142,6 +148,7 @@ def record(
142148 metadata : dict [str , Any ] | None = None ,
143149 created_at : datetime | None = None ,
144150 ) -> LedgerEvent :
151+ """Validate and persist one ledger event, returning its immutable record."""
145152 if category not in {"activity" , "revenue" , "cost" }:
146153 raise ValueError ("category must be activity, revenue, or cost" )
147154 if not team_id or not agent_id or not event_type :
@@ -194,6 +201,7 @@ def record(
194201 return event
195202
196203 def approve (self , event_id : str , approver_id : str ) -> LedgerEvent :
204+ """Approve a pending event and return the updated record."""
197205 if not approver_id :
198206 raise ValueError ("approver_id is required" )
199207 with self ._lock :
@@ -211,6 +219,7 @@ def approve(self, event_id: str, approver_id: str) -> LedgerEvent:
211219 return self .get (event_id )
212220
213221 def get (self , event_id : str ) -> LedgerEvent :
222+ """Load one event by ID or raise when it does not exist."""
214223 with self ._lock :
215224 row = self ._connection .execute (
216225 "SELECT * FROM ledger_events WHERE id = ?" , (event_id ,)
@@ -220,6 +229,7 @@ def get(self, event_id: str) -> LedgerEvent:
220229 return self ._row_to_event (row )
221230
222231 def list_events (self , team_id : str | None = None , limit : int | None = None ) -> list [LedgerEvent ]:
232+ """Return newest events, optionally filtered by team and limited in count."""
223233 limit_sql = "" if limit is None else " LIMIT ?"
224234 limit_params : tuple [Any , ...] = () if limit is None else (limit ,)
225235 with self ._lock :
@@ -238,6 +248,7 @@ def list_events(self, team_id: str | None = None, limit: int | None = None) -> l
238248 def list_pending_approvals (
239249 self , team_id : str | None = None , limit : int | None = None
240250 ) -> list [LedgerEvent ]:
251+ """Return newest events that still require human approval."""
241252 query = "SELECT * FROM ledger_events WHERE requires_approval = 1"
242253 params : tuple [Any , ...] = ()
243254 if team_id is not None :
@@ -252,6 +263,7 @@ def list_pending_approvals(
252263 return [self ._row_to_event (row ) for row in rows ]
253264
254265 def summarize (self , team_id : str | None = None ) -> list [TeamSummary ]:
266+ """Aggregate revenue, costs, activity, and approvals by team and currency."""
255267 where = "" if team_id is None else "WHERE team_id = ?"
256268 params : tuple [Any , ...] = () if team_id is None else (team_id ,)
257269 with self ._lock :
@@ -298,6 +310,7 @@ def summarize(self, team_id: str | None = None) -> list[TeamSummary]:
298310
299311 @staticmethod
300312 def _row_to_event (row : sqlite3 .Row ) -> LedgerEvent :
313+ """Convert a SQLite row into the public immutable event model."""
301314 return LedgerEvent (
302315 id = row ["id" ],
303316 category = row ["category" ],
0 commit comments