Files
bellsystems-cp/.claude/crm-step-03.md

2.7 KiB

CRM Step 03 — Backend: Orders CRUD

Context

Read .claude/crm-build-plan.md first for full data models, conventions, and IMPORTANT NOTES. Steps 01 and 02 must be complete.

Task

Add Orders models, service, and router to backend/crm/.

What to build

1. Add to backend/crm/models.py

Enums:

  • OrderStatus — draft, confirmed, in_production, shipped, delivered, cancelled
  • PaymentStatus — pending, partial, paid

Structs:

  • OrderDiscount — type (str: "percentage" | "fixed"), value (float default 0), reason (Optional[str])
  • OrderShipping — method (Optional[str]), tracking_number (Optional[str]), carrier (Optional[str]), shipped_at (Optional[str]), delivered_at (Optional[str]), destination (Optional[str])
  • OrderItem:
    • type: str (console_device | product | freetext)
    • product_id: Optional[str]
    • product_name: Optional[str]
    • description: Optional[str] ← for freetext items
    • quantity: int default 1
    • unit_price: float default 0.0
    • serial_numbers: List[str] default []

Order models:

  • OrderCreate — customer_id (str), order_number (Optional[str] — auto-generated if not provided), status (OrderStatus default draft), items (List[OrderItem] default []), subtotal (float default 0), discount (Optional[OrderDiscount]), total_price (float default 0), currency (str default "EUR"), shipping (Optional[OrderShipping]), payment_status (PaymentStatus default pending), invoice_path (Optional[str]), notes (Optional[str])
  • OrderUpdate — all fields Optional
  • OrderInDB — extends OrderCreate + id, created_at, updated_at
  • OrderListResponse — orders: List[OrderInDB], total: int

2. Add to backend/crm/service.py

Firestore collection: crm_orders

Auto order number generation: ORD-{YYYY}-{NNN} — query existing orders for current year, increment max.

Functions:

  • list_orders(customer_id=None, status=None, payment_status=None) -> List[OrderInDB]
  • get_order(order_id) -> OrderInDB — 404 if not found
  • create_order(data: OrderCreate) -> OrderInDB — auto-generate order_number if not set
  • update_order(order_id, data: OrderUpdate) -> OrderInDB
  • delete_order(order_id) -> None

3. Add to backend/crm/router.py

Prefix /api/crm/orders:

  • GET / — list_orders (query: customer_id, status, payment_status)
  • GET /{order_id} — get_order
  • POST / — create_order
  • PUT /{order_id} — update_order
  • DELETE /{order_id} — delete_order

Register in backend/main.py.

Notes

  • subtotal and total_price are stored as-is (calculated by frontend before POST/PUT). Backend does not recalculate.
  • Order number generation doesn't need to be atomic/perfect — just a best-effort sequential label.