recon_gen.common.money
Money as integer cents — the storage-domain currency (Phase AO.1).
SQLite stores DECIMAL columns as REAL (float64), introducing float-dust
drift the L1 stored <> computed matview kept flagging (~700 false
positives on the sasquatch_pr fixture). Postgres + Oracle DECIMAL stay
exact but have to follow for uniform storage — the customer ETL feed
contract must be dialect-agnostic.
Use Cents.from_dollars(Decimal('75.00')) at authoring boundaries,
Cents.from_db(int_from_cursor) at read boundaries, .to_dollars()
for display / rendering. Arithmetic is cents-on-cents only (type-safe);
scalar multiplication for repeat-count semantics works (cents * 5).
Mixing with Decimal / float / bare int is intentionally NOT supported —
silent coercion would re-introduce the float dust the type was created
to eliminate. Pyright catches the cross-domain ops; at runtime they
raise AttributeError when the foreign operand is dereferenced for
.value.
Classes
|
Integer cents — the storage-domain currency type. |
- class recon_gen.common.money.Cents(value)[source]
Bases:
objectInteger cents — the storage-domain currency type.
Frozen + slotted for memory + immutability;
order=Trueso comparisons (</>=/min/sorted) work without extra boilerplate. The single fieldvaluecarries the raw integer count of cents (signed; negative for debits / outflows).- Parameters:
value (int)
- classmethod from_db(raw)[source]
Read-boundary constructor: int from a DB cursor →
Cents.Explicit
int()coerce in case the dbapi driver returns a long-shaped numeric (Oracle’s NUMBER(19) cursors hand backintdirectly, but defensive). Pairs withcents_to_dollars_sqlfor the SQL-side projection.- Return type:
- Parameters:
raw (int)
- classmethod from_dollars(dollars)[source]
Authoring-boundary constructor: dollars (Decimal / str / int) → integer cents.
Quantizes via
Decimal("1")to round-trip without losing sub-cent precision the float path would; e.g.from_dollars("0.01")→Cents(1)(notCents(0)). Always acceptsstrshape (avoids float-init Decimals likeDecimal(0.01) == Decimal('0.01000000000000000020816...')).- Return type:
- Parameters:
dollars (Decimal | str | int)
- to_dollars()[source]
Display-boundary projection: cents →
Decimaldollars.Returns a
Decimal(not float) so downstream formatters keep exact representation (e.g.,f"${c.to_dollars():,.2f}"for$1,234.56shape).- Return type:
Decimal
- value: int