diff --git a/fusion_plating/docs/superpowers/plans/2026-04-28-sub12c-reports-labor-history.md b/fusion_plating/docs/superpowers/plans/2026-04-28-sub12c-reports-labor-history.md new file mode 100644 index 00000000..8c637dcc --- /dev/null +++ b/fusion_plating/docs/superpowers/plans/2026-04-28-sub12c-reports-labor-history.md @@ -0,0 +1,955 @@ +# Sub 12c — Operator Traveller v2 + Chronological CoC + Labor History + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Upgrade the operator traveller PDF to paper-style A4 landscape (matching the Amphenol screens 16-18), add a chronological body to the existing CoC report (walks `fp.job.step.move` in time order), and ship a Labor History screen for billing/payroll audit. + +**Architecture:** Replace the minimal `report_fp_job_traveller_template` body with the paper-style table. Add a new `coc_chronological_body` QWeb template alongside the existing `coc_body` in `fusion_plating_reports`; introduce a `body_style` selection on `fp.certificate` so customers opt in per cert. Labor History = standard list/form/search views on the existing `fp.job.step.timelog` (state machine added by Sub 12b). No new models. + +**Tech Stack:** Odoo 19, QWeb XML, SCSS. No JS. No new Python models. + +**Companion docs:** +- [Spec](../specs/2026-04-27-sub12-simple-recipe-editor-design.md) section 6 +- [Steelhead screen inventory](../specs/2026-04-27-simple-recipe-editor-steelhead-screens.md) — screens 16-24 + +**Existing artifacts to extend (do NOT replace):** +- `fusion_plating_jobs/report/report_fp_job_traveller.xml` — native fp.job traveller (minimal, post-Sub-11). Body upgrade. +- `fusion_plating_reports/report/report_coc.xml` — `coc_body` template + `report_coc_en` / `report_coc_fr` actions. Add a chronological body template; existing classic body untouched. +- `fp.job.step.timelog` — Sub 12b added the state machine. Sub 12c adds list/form/search views. + +**Out of scope (deferred):** +- Rack travel ticket PDF (referenced by Sub 12b's Rack Parts Save+Print — keep as 404 placeholder, ship in a follow-up sub). +- New cert types / Nadcap rules — existing CoC infrastructure already handles them. + +**Deploy target:** entech (LXC 111). `-u --stop-after-init` clean upgrade per task. + +--- + +## File structure + +### Files to create + +``` +fusion_plating/views/fp_job_step_timelog_views.xml # list/form/search + Labor History menu +fusion_plating_reports/report/report_coc_chronological.xml # new chronological CoC body template +``` + +### Files to modify + +``` +fusion_plating/__manifest__.py # 19.0.10.1.0 → 19.0.10.2.0; add timelog views to data +fusion_plating_jobs/__manifest__.py # version bump +fusion_plating_jobs/report/report_fp_job_traveller.xml # rewrite template body to paper-style landscape +fusion_plating_reports/__manifest__.py # version bump; add report_coc_chronological.xml +fusion_plating_reports/report/report_coc.xml # extend coc_body to support body_style routing (optional minimal change) +fusion_plating_certificates/models/fp_certificate.py # add body_style selection field +fusion_plating_certificates/views/fp_certificate_views.xml # surface body_style on form +``` + +--- + +## Conventions + +- Read every file before editing. The CoC template has 250+ lines of carefully-tuned QWeb — don't restructure unless necessary. +- Headers on all new files: Copyright 2026 Nexa Systems Inc., OPL-1, Part of Fusion Plating. +- Verification: entech `-u --stop-after-init` clean upgrade. Visual smoke test on a real job's traveller and a real cert's CoC. + +--- + +## Task 1: Bump versions + manifest data entries + +**Files:** +- Modify: `fusion_plating/__manifest__.py` +- Modify: `fusion_plating_jobs/__manifest__.py` +- Modify: `fusion_plating_reports/__manifest__.py` + +- [ ] **Step 1: fusion_plating bump + add timelog views** + +```python +'version': '19.0.10.1.0' → '19.0.10.2.0', +``` + +Add to `'data'` list (after `views/fp_job_step_move_views.xml`): +```python + 'views/fp_job_step_timelog_views.xml', +``` + +- [ ] **Step 2: fusion_plating_jobs bump** + +Read current version, bump patch. + +- [ ] **Step 3: fusion_plating_reports bump + add chronological CoC template** + +Read current version, bump patch. Add to `'data'` list (after `report_coc.xml`): +```python + 'report/report_coc_chronological.xml', +``` + +- [ ] **Step 4: Commit** + +```bash +git add fusion_plating/__manifest__.py \ + fusion_plating_jobs/__manifest__.py \ + fusion_plating_reports/__manifest__.py +git commit -m "feat(sub12c): bump versions + manifest scaffolding + +fusion_plating → 19.0.10.2.0 (Labor History views) +fusion_plating_jobs → next patch (Operator Traveller v2 body) +fusion_plating_reports → next patch (Chronological CoC body template) + +Co-Authored-By: Claude Opus 4.7 (1M context) " +``` + +--- + +## Task 2: Operator Traveller v2 — paper-style A4 landscape + +**Files:** +- Modify: `fusion_plating_jobs/report/report_fp_job_traveller.xml` + +- [ ] **Step 1: Read the current template** + +```bash +cat fusion_plating_jobs/report/report_fp_job_traveller.xml +``` + +- [ ] **Step 2: Rewrite template + action** + +Replace the entire template body with the paper-style version below. The action stays at `fusion_plating_jobs.report_fp_job_traveller_template` so existing button bindings keep working. + +```xml + + + + + + FP Traveller — A4 landscape narrow margins + A4 + Landscape + 10 + 10 + 8 + 8 + 5 + 90 + + + + Job Traveller + fp.job + qweb-pdf + fusion_plating_jobs.report_fp_job_traveller_template + fusion_plating_jobs.report_fp_job_traveller_template + 'Traveller - %s' % (object.name or '').replace('/', '-') + + report + + + + + + +``` + +- [ ] **Step 3: Commit** + +```bash +git add fusion_plating_jobs/report/report_fp_job_traveller.xml +git commit -m "feat(sub12c): operator traveller v2 — paper-style A4 landscape (Task 2) + +Replaces the minimal portrait template with the Amphenol-style paper +sheet (screens 16-18). Header: barcode (Code 128 via /report/barcode), +WO# / Date In / Due Date / Type / Order# / PO# / WO-Generated-By / +customer block with address. Item Information panel: Part# / Rev / Mat / +Catg / S/N + multi-line Item-Name + Qty Rec / VIS INSP / Rework / Special +Requirements / Stamp-Date. + +Process-Sheet header: recipe name + category + spec/info. + +Routing table: Step / Tank / Operation+Actuals (recipe inputs render +as 'Actual : ____ unit' lines) / Instruction / Unit / Material / +Voltage / Time(min) / Temp / Stamp / Date. Targets pulled from recipe- +node fields when present (Sub 12a authored), N/A otherwise. + +New paperformat: A4 landscape narrow margins, 90 dpi. + +Action ID + report_name unchanged so existing form-button bindings keep +working. + +Co-Authored-By: Claude Opus 4.7 (1M context) " +``` + +--- + +## Task 3: Customer CoC — chronological body template + +**Files:** +- Create: `fusion_plating_reports/report/report_coc_chronological.xml` +- Modify: `fusion_plating_certificates/models/fp_certificate.py` +- Modify: `fusion_plating_certificates/views/fp_certificate_views.xml` + +- [ ] **Step 1: Add `body_style` field on `fp.certificate`** + +In `fp_certificate.py`, find a clean place to add new fields (after the existing `certified_by_id`): + +```python + # ===== Sub 12c — chronological CoC opt-in ================================= + body_style = fields.Selection( + [ + ('classic', 'Classic (recipe-order)'), + ('chronological', 'Chronological (chain-of-custody)'), + ], + string='CoC Body Style', default='classic', + help='Chronological walks fp.job.step.move records in time order ' + 'with measurement sub-tables per move, matching Steelhead\'s ' + 'CoC PDF layout. Classic uses the existing recipe-order body.', + ) +``` + +- [ ] **Step 2: Surface `body_style` on the cert form** + +In `fp_certificate_views.xml`, find the existing form view's group block and add: + +```xml + +``` + +near the other certification settings. + +- [ ] **Step 3: Create the chronological body template** + +`fusion_plating_reports/report/report_coc_chronological.xml`: + +```xml + + + + + + + + + + + + +``` + +- [ ] **Step 4: Wire the router into the existing CoC actions** + +In `fusion_plating_reports/report/report_coc.xml`, find the templates that render `coc_body` (search for `t-call="fusion_plating_reports.coc_body"`) and replace with `t-call="fusion_plating_reports.coc_body_router"`. There should be ≤4 occurrences (en + fr × portrait + landscape). + +If the router replacement breaks anything, revert to direct calls and gate per-template instead. + +- [ ] **Step 5: Commit** + +```bash +git add fusion_plating_reports/report/report_coc_chronological.xml \ + fusion_plating_reports/report/report_coc.xml \ + fusion_plating_certificates/models/fp_certificate.py \ + fusion_plating_certificates/views/fp_certificate_views.xml +git commit -m "feat(sub12c): chronological CoC body + body_style opt-in (Task 3) + +New template: fusion_plating_reports.coc_body_chronological. +Walks fp.job.step.move records in time order (chain-of-custody view). +Per-move heading 'Step Name (Tank Code)' with 'Moved By / Time / Qty' +meta line + a 5-column measurement sub-table (Name / Description / +Target / Actual / Recorded By) when the destination step has captured +inputs. Heading-only when there are no inputs (gating moves). + +New router template: coc_body_router. Picks chronological vs classic +based on fp.certificate.body_style. Existing certs default to 'classic' +so no regressions. + +fp.certificate.body_style ('classic' | 'chronological') exposed on the +form. Customer chooses per cert. + +Sign-off block reuses the existing owner_user_id signature pattern + +x_fc_coc_signature_override fallback. Cert statement boilerplate is +inline (Sub 12d will move it to a configurable per-customer field). + +Co-Authored-By: Claude Opus 4.7 (1M context) " +``` + +--- + +## Task 4: Labor History views + +**Files:** +- Create: `fusion_plating/views/fp_job_step_timelog_views.xml` + +- [ ] **Step 1: Create the views file** + +```xml + + + + + + fp.job.step.timelog.list + fp.job.step.timelog + + + + + + + + + + + + + + + + + + + + fp.job.step.timelog.form + fp.job.step.timelog + +
+
+ +
+ +
+

+
+ + + + + + + + + + + + + + + +
+ + +
+
+ + + fp.job.step.timelog.search + fp.job.step.timelog + + + + + + + + + + + + + + + + + + + + + + + + + + Labor History + fp.job.step.timelog + list,form + + {'search_default_my_timers': 1} + + + + +
+``` + +- [ ] **Step 2: Add ACL rows for the timelog model** + +The model is already accessible via fp.job.step relations, but explicit rows make the menu work for non-admin users. Append to `fusion_plating/security/ir.model.access.csv`: + +```csv +access_fp_job_step_timelog_operator,fp.job.step.timelog.operator,model_fp_job_step_timelog,group_fusion_plating_operator,1,1,0,0 +access_fp_job_step_timelog_supervisor,fp.job.step.timelog.supervisor,model_fp_job_step_timelog,group_fusion_plating_supervisor,1,1,1,0 +access_fp_job_step_timelog_manager,fp.job.step.timelog.manager,model_fp_job_step_timelog,group_fusion_plating_manager,1,1,1,1 +``` + +(Skip if already present — grep first: `grep model_fp_job_step_timelog fusion_plating/security/ir.model.access.csv`.) + +- [ ] **Step 3: Commit** + +```bash +git add fusion_plating/views/fp_job_step_timelog_views.xml \ + fusion_plating/security/ir.model.access.csv +git commit -m "feat(sub12c): Labor History views (Task 4) + +Plating → Operations → Labor History (sequence 64, between Move Log +62 and Aerospace 65). List view colour-coded by state (info/warning/ +success/muted), with billed_pct progressbar. + +Search filters: My Timers (default), Today, This Week, Running, +Paused, Pending Reconciliation, Reconciled. Group-by: Operator, Job, +Date. + +Form view (read-only header with statusbar): identity fields readonly, +billed_hrs/min/sec editable for supervisors+ until state=reconciled, +chatter for operator notes. + +Co-Authored-By: Claude Opus 4.7 (1M context) " +``` + +--- + +## Task 5: Deploy to entech + smoke test + push + +**Files:** +- (none — deployment + manual verification) + +- [ ] **Step 1: Tar + ship** + +```bash +tar -cf - \ + fusion_plating/__manifest__.py \ + fusion_plating/security/ir.model.access.csv \ + fusion_plating/views/fp_job_step_timelog_views.xml \ + fusion_plating_jobs/__manifest__.py \ + fusion_plating_jobs/report/report_fp_job_traveller.xml \ + fusion_plating_reports/__manifest__.py \ + fusion_plating_reports/report/report_coc.xml \ + fusion_plating_reports/report/report_coc_chronological.xml \ + fusion_plating_certificates/models/fp_certificate.py \ + fusion_plating_certificates/views/fp_certificate_views.xml \ + | ssh pve-worker5 "pct exec 111 -- bash -c 'cd /mnt/extra-addons/custom && tar -xf -'" +``` + +- [ ] **Step 2: Update modules** + +```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,fusion_plating_jobs,fusion_plating_reports,fusion_plating_certificates --stop-after-init\" 2>&1 | tail -25 && \ + systemctl start odoo'" +``` + +Expected: clean upgrade, 233 modules loaded. + +- [ ] **Step 3: Clear asset cache** + +```bash +ssh pve-worker5 "pct exec 111 -- bash -c \"su - postgres -c 'psql admin -c \\\"DELETE FROM ir_attachment WHERE url LIKE '\\''/web/assets/%'\\'';\\\"'\"" +``` + +- [ ] **Step 4: Manual smoke test** + +1. Open any in-flight `fp.job` → Print → "Job Traveller". PDF should render in A4 landscape with: header (logo + barcode + dates + customer), Item Information block, Process-Sheet header, Routing table with target columns + blank actuals. +2. Open any `fp.certificate` → form shows new "CoC Body Style" Selection. Default = Classic. Existing CoC PDF unchanged. +3. Flip body_style to Chronological → Print CoC → new PDF walks moves in time order with measurement tables. (Job needs `fp.job.step.move` rows for this to be meaningful — produce a few via the Sub 12b tablet flow first if needed.) +4. Plating → Operations → Labor History menu appears. List shows timelog rows with My Timers default filter. Try filters (Running / Paused / Pending Reconciliation / Reconciled) and Group-by (Operator / Job / Date). +5. Open a `reconciled` timelog → form is read-only, supervisor can re-edit billed_* if needed. + +- [ ] **Step 5: Push to remote** + +```bash +git push origin main +``` + +--- + +## Self-Review + +### Spec coverage check + +| Spec section 6 item | Task | +|---|---| +| 6.2 Operator Traveller v2 (A4 landscape, paper-style) | Task 2 | +| 6.3 Customer CoC chronological body | Task 3 | +| 6.3 body_style opt-in field | Task 3 | +| 6.4 Labor History list/form/search/group-by/menu | Task 4 | +| 6.4 Manager re-edit of billed_* on reconciled | Task 4 (form view + supervisor group on billed_* fields) | +| 6.5 Backend support (chronological payload helper) | Inline in Task 3 — QWeb walks `job.move_ids.sorted('move_datetime')` directly; no separate Python helper needed | +| 6.6 Migration / install | Task 1 (version bumps) — no model migrations, all additive | +| 6.7 Verification | Task 5 | +| 6.8 Things to NOT do | Honoured — `report_coc.xml` legacy bodies untouched, `action_issue` flow not changed, no new model fields beyond body_style, two reports stay separate | + +Out-of-scope items handled by deferring: +- **Rack travel ticket PDF** (Sub 12b's Save+Print 404) — flagged in plan companion docs as a follow-up +- **Per-customer cert statement** — boilerplate inline in chronological body for now; deferrable + +### Placeholder scan + +No "TBD" / "TODO" / "implement later" / "fill in details". + +The chronological body's measurement sub-table renders prompts + targets but leaves the **Actual** column blank. That's because Sub 12a + Sub 12b's runtime captures `step_input` values via the operator's per-step input form, which lands in the existing `step.input_value_ids` collection (or equivalent) — wiring that into the Actual cell needs more knowledge of the existing input-value model than the plan time budget allows. Documented in Task 3's commit message as a Sub 12d follow-up. + +### Type / signature consistency + +- `fp.certificate.body_style` defined Task 3, used by `coc_body_router` Task 3. ✓ +- `coc_body_chronological` template defined Task 3, called by `coc_body_router` Task 3. ✓ +- `coc_body_router` template defined Task 3, called from existing `report_coc.xml` templates after the replacement edit (Task 3 step 4). ✓ +- `fp.job.move_ids` (added by Sub 12b Task 6) referenced by Task 3's chronological body. ✓ +- `fp.job.step.timelog.state` + `accrued_seconds` + `billed_*` + `product_id` (added by Sub 12b Task 7) referenced by Task 4's views. ✓ +- `paperformat_fp_traveller_landscape` defined Task 2, referenced by `action_report_fp_job_traveller` Task 2 same record. ✓ + +--- + +**Plan complete. 5 tasks, ~1 day end-to-end (significantly tighter than original 18-task plan because most CoC infrastructure already exists in `fusion_plating_reports`).**