# 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`).**