# CRM Step 07 — Frontend: Orders Module ## Context Read `.claude/crm-build-plan.md` for full context, data models, and IMPORTANT NOTES. Steps 01–06 must be complete. ## Task Build the Orders section. ## Files to create ### `frontend/src/crm/orders/OrderList.jsx` - Fetch `GET /api/crm/orders` (query: status, payment_status) - Table: Order #, Customer name (resolve from customer_id via separate fetch or denormalize), Status badge, Total, Payment status, Date - Filter dropdowns: Status, Payment Status - "New Order" button → `/crm/orders/new` - Row click → `/crm/orders/:id` ### `frontend/src/crm/orders/OrderForm.jsx` Create/edit. Receives `orderId` prop and optional `customerId` from query param. **Sections:** 1. **Customer** — searchable dropdown (fetch `/api/crm/customers`). Shows name + organization. 2. **Order Info** — order_number (auto, editable), status (dropdown), currency 3. **Items** — dynamic list. Each item: - type selector: console_device | product | freetext - product: dropdown from `/api/crm/products` (auto-fills product_name, unit_price) - console_device: text input for device_id + label - freetext: description text input - quantity (number), unit_price (number), serial_numbers (comma-separated) - Remove row button - Add Item button 4. **Pricing** — show computed subtotal (sum of qty * unit_price). Discount: type toggle (% or fixed) + value input + reason. Show computed total = subtotal - discount. These values are sent to backend as-is. 5. **Payment** — payment_status dropdown, invoice_path (nextcloud path text input) 6. **Shipping** — method, carrier, tracking_number, destination, shipped_at (date), delivered_at (date) 7. **Notes** — textarea Save → POST or PUT. Delete with confirmation. ### `frontend/src/crm/orders/OrderDetail.jsx` Read-only view of a single order. - Header: order number, status badge, customer name (link to customer) - Items table: product/description, qty, unit price, line total - Pricing summary: subtotal, discount, total - Shipping card: all shipping fields - Payment card: status, invoice path (if set, show as link) - Notes - Edit button → OrderForm - Back to customer button ### `frontend/src/crm/orders/index.js` Export all components. ## Routing in `frontend/src/App.jsx` ```jsx } /> } /> } /> } /> ``` ## Sidebar update Add to CRM section: - Orders → `/crm/orders` ## Notes - Status badge colors: draft=grey, confirmed=blue, in_production=orange, shipped=purple, delivered=green, cancelled=red - Payment status: pending=yellow, partial=orange, paid=green - Discount calculation: if type=percentage → total = subtotal * (1 - value/100). if type=fixed → total = subtotal - value - When a product is selected from dropdown in item row, auto-fill unit_price from product.price (user can override) - Order list needs customer names — either fetch all customers once and build a map, or add customer_name as a denormalized field when creating/updating orders (simpler: fetch customer list once)