erp-brick-sales-order — Sales orders
Turn an accepted quote into a confirmed order in one step, track what has been delivered, and invoice exactly what is due (on order or on delivery, with deposits up front) without anyone re-typing a line.
A brick on erp-platform (namespace so, tables so_*), built from the signed sales-order module spec (v2). An accepted
quote becomes a draft order (never re-priced); a rep confirms it behind readiness gates {gate, met, reason, fix};
deliveries are recorded line by line; invoicing is asked for exactly what is due; amendments are revisions; the one-off Odoo
migration brings open orders in live and the rest as read-only history. It asks product (every price), tax (every tax),
payments (the credit hold) and invoicing (every invoice) through ports; it keeps none of their rules. See AGENTS.md.
src/brick_sales_order/
domain/ the rules, plain Python: SalesOrder, gates (readiness), NumberSeries, values, events
application/ the use cases — each declared once, served as an API route AND an MCP tool; odoo_migration.py
infrastructure/ the tables and repositories, the ports to neighbours (seams.py), business time, AI-step modes
app.py the ASGI app: routes, /mcp, the sign-in metadata for agents
schema.sql the tables (generated from the same model as infrastructure/tables.py)
migrations/ 00001_init/{up,down}.sql, journal `so_schema_migrations`
tests/ rules, one test per story, scenarios, access, both doors, adapters, Odoo migration, schema
Run it.
pip install -e '.[test]'
pytest -q # no bucket needed
BUCKET=my-bucket erp-migrate --schema src/brick_sales_order/schema.sql --brick so=0.1.0
BUCKET=my-bucket DEV_ALLOW_ANON=1 DEV_USER_PERMISSIONS=so:order:read,so:order:write,so:order:confirm,so:order:deliver,so:order:invoice,so:order:cancel,so:order:approve,so:settings:write,so:settings:controls,so:sales_order:read_all \
uvicorn brick_sales_order.app:app # API at /docs, agents at /mcp
Migrations. migrations/00001_init/{up,down}.sql is the versioned layout with a per-brick journal;
erp-platform has no migrator for it yet, so erp-migrate --schema schema.sql is what applies the tables today.
Neighbours. PRODUCT_BASE_URL, TAX_BASE_URL, PAY_BASE_URL, AR_BASE_URL, BP_BASE_URL (or in one process at tier 1).
A neighbour that is not installed is said so in the readiness answer; the order never guesses a price, a rate or a balance.
Odoo migration reads ODOO_URL, ODOO_DB, ODOO_LOGIN, ODOO_PASSWORD (read only) behind so:order:import.