Project: ledger-api · Branch: main · Mode: default · Model: claude-sonnet-4-6
Summary
Bootstrapped the invoicing service: FastAPI app factory, SQLAlchemy 2.0 models for customers, invoices and line items, Alembic baseline migration, and a pytest fixture that spins up Postgres in Docker. Money is stored as integer minor units from day one.
Conversation
Turn 1 — User
Scaffold a FastAPI service for invoices. Postgres, SQLAlchemy 2.0, Alembic. Money must never be a float.
Turn 1 — Assistant
Plan: app factory in ledger/app.py, typed models in ledger/models.py, amounts as BIGINT minor units plus an ISO-4217 currency column, Alembic baseline, Docker-based Postgres fixture for tests.
class LineItem(Base):
__tablename__ = "line_items"
id: Mapped[int] = mapped_column(primary_key=True)
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoices.id"))
description: Mapped[str] = mapped_column(String(200))
quantity: Mapped[int] = mapped_column(default=1)
unit_amount: Mapped[int] # minor units (cents)
currency: Mapped[str] = mapped_column(String(3))
Tools used in this turn:
Write: ledger/app.pyWrite: ledger/models.pyBash: alembic init migrations — exit 0
Turn 2 — User
Add the line-item total as a computed column.
Turn 2 — Assistant
Done as a SQLAlchemy column_property summing quantity * unit_amount; invoice totals are derived, never stored, so they cannot drift. 9 tests pass.
Tools used in this turn:
Edit: ledger/models.py — column_property for totalsBash: pytest -q — 9 passed
Connections
- [[ledger-api]]
- [[FastAPI]]
- [[SQLAlchemy]]
- [[Alembic]]
- [[MoneyAsMinorUnits]]