docs(configurator): E1 - Express Orders smoke test runbook

This commit is contained in:
gsinghpal
2026-05-26 21:22:43 -04:00
parent aab842d6d3
commit 27af984f28

View File

@@ -0,0 +1,235 @@
# Express Orders — Smoke Test Runbook
End-to-end manual checks for the Express Orders feature. Run after every deploy that touches `fusion_plating_configurator`, `fusion_plating_jobs`, or `fusion_plating`. Expect ~10 minutes if everything works; longer if a test fails and you have to dig into logs.
Spec: [docs/superpowers/specs/2026-05-26-express-orders-design.md](../../docs/superpowers/specs/2026-05-26-express-orders-design.md)
Plan: [docs/superpowers/plans/2026-05-26-express-orders-plan.md](../../docs/superpowers/plans/2026-05-26-express-orders-plan.md)
---
## Setup
1. Open Odoo (entech: https://erp.enplating.com, local: http://localhost:8069)
2. Log in as a user with the Estimator role
3. Navigate to: **Plating → Sales → + New Express Order**
4. Confirm the Express form opens (NOT the legacy form). The header should say "Express Order Entry" and there should be a "Switch to Legacy View" button.
If the menu is missing or the wrong form opens, the deploy didn't land correctly. Check the manifest's `data` list includes `views/fp_express_order_views.xml`.
---
## Test 1 — Happy path with mask ON + bake non-empty
Goal: confirm the SO → job → step pipeline works for the simplest case (everything on).
1. Pick customer **WESTIN HEALTHCARE INC.** (or any partner with at least one part in the catalog)
2. Confirm `partner_shipping_id` auto-fills to the customer's first child address
3. Confirm `pricelist_id` defaults to the customer's pricelist (currency pill should match)
4. Type PO# **`PO-SMOKE-01`** and upload any PDF
5. Add a line: pick a part with a recipe. Auto-fill should populate description / thickness / process / masking checkbox (on) / bake text (from the part's defaults)
6. Set quantity **5**, price **42.00**
7. Click **Confirm Order**
Expected:
- A `sale.order` is created in `quotation` state
- The wizard transitions to `confirmed`
- The "Open Sale Order" button appears
- Clicking it opens the SO with the lines you entered
Verify via SQL (entech LXC 111):
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT id, name, partner_id, state FROM sale_order WHERE x_fc_po_number = '\''PO-SMOKE-01'\'';\""'
```
---
## Test 2 — Masking opt-out
Goal: unchecking masking on a line should spawn override rows for masking + de_masking nodes.
1. Repeat Test 1 setup with a fresh PO# `PO-SMOKE-02`
2. **Uncheck the Mask toggle on the line**
3. Set bake to a non-empty text (e.g. `350F x 4hr`) so bake doesn't also opt out
4. Confirm Order
5. The SO confirms; an `fp.job` should be auto-created. Find it via:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT j.id, j.name FROM fp_job j JOIN sale_order so ON j.sale_order_id=so.id WHERE so.x_fc_po_number='\''PO-SMOKE-02'\'';\""'
```
Expected:
- `fp.job.node.override` rows exist with `included=False` for the recipe's masking + de_masking nodes:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT ov.id, n.name, n.default_kind, ov.included FROM fp_job_node_override ov JOIN fusion_plating_process_node n ON ov.node_id=n.id WHERE ov.job_id=<job-id-from-above>;\""'
```
- Open the job in the UI. The audit chatter should contain: **"Masking + de-masking steps opted out (per SO line)"**
---
## Test 3 — Bake opt-out
Goal: emptying the bake cell should spawn an override for the recipe's baking node.
1. Fresh order with PO# `PO-SMOKE-03`
2. Keep Mask checked
3. **Clear the Bake cell** (the value should be empty / "no bake")
4. Confirm Order
5. Verify the resulting `fp.job` has `fp.job.node.override` row(s) for nodes with `default_kind='baking'`, `included=False`
6. Audit chatter on the job: **"Baking steps opted out (per SO line)"**
---
## Test 4 — Bake instructions write through to step
Goal: typed bake instructions should appear on the operator tablet's bake step.
1. Fresh order with PO# `PO-SMOKE-04`
2. Set bake to **`375F x 2hr`** on the line
3. Confirm Order
4. **Assign To Me** on the resulting SO (this calls `fp.job.action_confirm` which generates steps)
5. Open the job's step list; find the step with `recipe_node_id.default_kind='baking'`
Expected:
- The bake step's `instructions` field reads **`375F x 2hr`**
- Audit chatter: **"Bake step instructions set to: 375F x 2hr"**
Verify via SQL:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT s.id, s.name, s.instructions FROM fp_job_step s JOIN fusion_plating_process_node n ON s.recipe_node_id=n.id WHERE n.default_kind='\''baking'\'' AND s.job_id=<job-id>;\""'
```
---
## Test 5 — Part-default write-back
Goal: values typed on the line should persist to the part's defaults for next time.
1. Pick a part that has NO `default_bake_instructions` set yet
2. Type bake `400F x 1hr` and Specification `Per drawing rev C, mirror finish`
3. Confirm Order
4. Reload the part record:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT part_number, default_bake_instructions, default_specification_text, default_masking_enabled FROM fp_part_catalog WHERE id=<part-id>;\""'
```
Expected:
- `default_bake_instructions = '400F x 1hr'`
- `default_specification_text = 'Per drawing rev C, mirror finish'`
- `default_masking_enabled` matches what was on the line
Next, fresh order with the SAME part:
- Auto-fill should pre-populate the bake + specification cells from the part defaults
---
## Test 6 — Customer line ref (ABC/DEF/GHJ)
Goal: per-line customer reference persists to the SO line and prints on docs.
1. Fresh order with 2 lines
2. Type `ABC` in Line Job # on line 1, `DEF` on line 2
3. Confirm Order
4. Open the resulting SO; the two lines should have the same Line Job # values
5. Print the Sale Order PDF — the Customer Line Job # should appear in the line table column
Verify via SQL:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"SELECT id, x_fc_customer_line_ref FROM sale_order_line WHERE order_id=<so-id>;\""'
```
---
## Test 7 — Bulk-add serials (existing wizard, new trigger)
Goal: confirm the `+ bulk` button on the part cell's serial row opens the bulk-add wizard.
1. Open a draft Express Order. Pick a part on a line.
2. (v1 deferment: the inline `+ bulk` button isn't on the form yet — this test currently has to use the standard Serials field directly. Skip until C polish lands.)
---
## Test 8 — DWG / OPEN buttons per line
Goal: drawings upload to the part record, OPEN navigates to the part form.
(v1 deferment: not on the form yet — comes in C polish.)
---
## Test 9 — Currency switch
Goal: changing the pricelist updates the currency pill and triggers a price recompute prompt.
1. Open a draft. Pricelist defaults to CAD.
2. Add a line at $42.00 CAD.
3. Switch the Pricelist to a USD pricelist.
4. Odoo prompts: **"Update Prices?"** Click Yes.
Expected:
- The line's `unit_price` recomputes via the USD pricelist's rules
- The Grand Total currency pill flips to USD
- The line subtotal shows in USD
If you don't have a USD pricelist, this test can't run — confirm with admin that at least one alternative-currency pricelist exists.
---
## Test 10 — Round-trip with legacy view
Goal: Express drafts open in Express, Legacy drafts open in Legacy, but each can be flipped via the header button.
1. Create a draft in Express (PO `PO-SMOKE-10A`, don't confirm — just save)
2. Go to **Plating → Sales → Direct Order Drafts**
3. The list shows a `view_source` badge column. Your draft has `EXPRESS` (blue).
4. Click the **Open** button on the row → confirm it opens in Express
5. From the Express form, click **Switch to Legacy View** → confirms legacy form loads with same data
6. Back to drafts list. Click Open again — should re-route to Legacy (because the draft's `view_source` is now... wait, the switch button doesn't change `view_source`, just temporarily renders in a different view. So Open should still go to Express.)
Verify behaviour above. Then:
7. From **Plating → Sales → + New Direct Order (Legacy)**, create a draft. Save without confirming.
8. Open the drafts list: this draft has `view_source = LEGACY` (muted badge).
9. Click Open → legacy form opens.
---
## Quick PG verification — every Express field
After deploy, confirm all 17 new schema fields are present:
```bash
ssh pve-worker5 'pct exec 111 -- bash -c "cd /tmp && sudo -u postgres psql -d admin -t -c \"
SELECT table_name, column_name FROM information_schema.columns WHERE
(table_name=\\\"fp_part_catalog\\\" AND column_name IN (\\\"default_specification_text\\\",\\\"default_bake_instructions\\\",\\\"default_masking_enabled\\\")) OR
(table_name=\\\"sale_order_line\\\" AND column_name IN (\\\"x_fc_customer_line_ref\\\",\\\"x_fc_masking_enabled\\\",\\\"x_fc_bake_instructions\\\")) OR
(table_name=\\\"sale_order\\\" AND column_name IN (\\\"x_fc_material_process\\\",\\\"x_fc_internal_notes\\\",\\\"x_fc_print_terms\\\")) OR
(table_name=\\\"fp_direct_order_wizard\\\" AND column_name IN (\\\"terms_and_conditions\\\",\\\"internal_notes\\\",\\\"material_process\\\",\\\"pricelist_id\\\",\\\"validity_date\\\",\\\"view_source\\\")) OR
(table_name=\\\"fp_direct_order_line\\\" AND column_name IN (\\\"customer_line_ref\\\",\\\"masking_enabled\\\",\\\"bake_instructions\\\"))
ORDER BY table_name, column_name;
\""'
```
Expected: 17 rows. If fewer, the upgrade didn't fully land — re-run the canonical CLAUDE.md upgrade command.
---
## Common failure modes
| Symptom | Likely cause | Fix |
|---|---|---|
| Menu "+ New Express Order" doesn't appear | manifest doesn't include `views/fp_express_order_views.xml`, OR module wasn't upgraded | Check manifest data list; re-run `-u fusion_plating_configurator` |
| Form opens but bake/masking columns are empty | onchange `_onchange_part_default_thickness` didn't fire | Check `fp.direct.order.line.bake_instructions` field exists; check the onchange extension landed |
| Confirm Order errors with `KeyError: 'x_fc_masking_enabled'` | `sale.order.line` field missing | Re-run module upgrade |
| Job created but no override rows | `_fp_auto_create_job` hook missing | Check `fusion_plating_jobs/models/sale_order.py` for the Express overrides block after `Job.create(vals)` |
| Override rows present but bake step.instructions empty | The second hook (in `fp.job.action_confirm`) didn't fire, OR steps weren't generated yet | Check `fusion_plating_jobs/models/fp_job.py` for the Express block after `_generate_steps_from_recipe()` |
| Customer line ref blank on SO line | `_prepare_order_line_vals` carry-through missing | Check `fp_direct_order_wizard.py` for `x_fc_customer_line_ref` in the `so_vals['order_line'].append` block |
---
## Deploy command (canonical CLAUDE.md pattern)
```bash
ssh pve-worker5 "pct exec 111 -- bash -c 'systemctl stop odoo && su - odoo -s /bin/bash -c \"/usr/bin/odoo -c /etc/odoo/odoo.conf -d admin -u fusion_plating_configurator,fusion_plating_jobs,fusion_plating --stop-after-init\" > /tmp/odoo-up.log 2>&1; systemctl start odoo; tail -25 /tmp/odoo-up.log'"
```
Expected: 20-30 seconds, exit 0, log ends with **"Modules loaded."**
Do NOT add `--test-enable` — it caused a 20-minute hang during the original deploy by getting tangled with production HTTP traffic. Run tests separately if needed (`--no-http --test-enable --test-tags fp_express`).