dodil/erp-brick-sales-order

DODIL ERP brick: sales order

README.md

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.