Commit Graph

14 Commits

Author SHA1 Message Date
gsinghpal
6b7b44264a changes 2026-05-10 10:25:12 -04:00
gsinghpal
e37eab9f23 fix(jobs): Sub 13 gate was DEAD due to duplicate button_start
User reproduced on WH/JOB/00342: clicked Start on Incoming Inspection
while Contract Review was still in_progress. Sub 13 should have raised
UserError. It didn't. Both steps ended up in_progress.

Investigation:
  $ grep "def button_start" fusion_plating_jobs/models/fp_job_step.py
  88:    def button_start(self):     ← Sub 13 gate code
  876:   def button_start(self):     ← Policy B + Sub 8 (older)

Two definitions of the same method in the same class. Python uses the
SECOND. My Sub 13 gate at line 88 was dead code from the moment it
landed. WH/JOB/00342's Contract Review and Incoming Inspection both
ran in_progress because the live button_start (line 876) only did
Policy B Contract Review auto-open and Sub 8 Racking auto-open — no
predecessor check.

Fix:
  * Removed the duplicate button_start at line 88 (left a marker
    comment so the next person doesn't redo this footgun)
  * Merged the Sub 13 predecessor gate AND the receiving soft check
    into the line-876 button_start so all four behaviours run from
    one method:
      1. Predecessor gate (raise UserError if blocking)
      2. Contract Review auto-open (route to QA-005)
      3. Racking auto-open (route to inspection)
      4. super().button_start() + receiving check + serial promotion

Helpers _fp_should_block_predecessors / can_start / _compute_can_start
preserved (used by view + Move wizard too).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:49:01 -04:00
gsinghpal
21e42e7b48 feat(jobs): button_start auto-routes contract_review steps to QA-005
User feedback on WH/JOB/00341 (S00279 retest): clicking Start on
the Contract Review step changed state to in_progress but didn't
take them to QA-005. They had to then click Finish & Next twice
to land on the form — confusing flow.

Better UX: when an operator clicks Start on a step where
recipe_node.default_kind='contract_review', the step starts AND
the QA-005 form opens immediately. Operator signs/dismisses,
navigates back, hits Finish & Next once → step finishes + advances.

Implementation:
  fp.job.step.button_start, after super() returns and the
  receiving check runs, calls _fp_contract_review_redirect()
  (existing helper). If it returns an action, return that
  instead of the parent's result. Single-record only — bulk
  button_start (job-level start-all) shouldn't navigate.

Helper logic unchanged — same gate matrix:
  * recipe_node.default_kind == 'contract_review'
  * job has part_catalog_id
  * review state NOT in (complete, dismissed)

When review is already complete, the gate clears: button_start
returns the normal True so the operator can advance the step
without bouncing through QA-005 again.

Tests:
  test_button_start_routes_cr_step_to_qa005 — start opens QA-005
  test_button_start_does_not_route_when_review_complete — start
    does NOT redirect once review is signed off

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:33:55 -04:00
gsinghpal
d53fd53b80 feat(jobs): Record Inputs OWL Dialog (v4) — replaces list-as-cards hack
Scrapped the v2/v3 form-view + list-as-cards CSS approach after
extensive failure to make Odoo's editable list look like cards.
Built a proper OWL Dialog component instead, mirroring the pattern
used by fusion_plating_shopfloor's move_parts_dialog.js.

What changed
============
* New OWL Dialog: fp_record_inputs_dialog.js
  - Loads step + prompt definitions via /fp/record_inputs/load
  - Renders each prompt as a semantic <div class="o_fp_ri_card">
  - Per-row widget chosen by input_type:
      numeric/temperature/thickness/time_seconds/ph -> number input
      boolean/pass_fail   -> custom CSS toggle (clearer than Bootstrap)
      date                -> datetime-local input
      photo               -> file picker w/ preview + clear
      multi_point_thickness -> 5-cell grid + live average
      bath_chemistry_panel  -> pH/Conc/Temp/Bath grid
      selection           -> dropdown sourced from selection_options
      text/signature/...  -> text input
  - Live in-range hint for numeric prompts
      ("in range" / "below target" / "above target")
  - Save validates ad-hoc rows have a Prompt label
  - Save dispatches the next_action returned by the wizard model
    (e.g. action_finish_and_advance for the Finish & Next flow)

* New XML template: fp_record_inputs_dialog.xml
  Full DOM control. No fighting Odoo's list view, no class-stripping
  bugs from canUseFormatter, no read-mode-vs-edit-mode CSS dance.

* New SCSS: fp_record_inputs_dialog.scss
  - Dark mode aware (compile-time @if $o-webclient-color-scheme==dark)
  - Pure semantic selectors (.o_fp_ri_card, .o_fp_ri_input, etc.)
  - 14 surface tokens with light/dark hex pairs
  - Tablet polish via @media (max-width: 768px)
  - Custom toggle widget (no <input type="checkbox"> hidden trick)

* New controller: controllers/record_inputs.py
  - /fp/record_inputs/load: returns step + prompts payload
  - /fp/record_inputs/commit: creates a wizard, populates lines,
    calls action_commit (reuses existing audit-trail / synthetic
    move semantics — no commit logic duplicated)

* fp_job_step.py wired to dispatch the new action
  - _fp_open_input_wizard returns
    { type: 'ir.actions.client', tag: 'fp_record_inputs_dialog' }
  - action_open_input_wizard same
  - Contract-review redirect gate preserved (Sub 4 work intact)

* Manifest registers JS/XML/SCSS in BOTH backend + dark bundles
  per the dark-mode pattern in CLAUDE.md.

What was kept
=============
* fp.job.step.input.wizard TransientModel — UNCHANGED. The new
  controller's commit endpoint creates a wizard record and calls
  action_commit() on it, so all the audit-trail / synthetic-move
  / chatter logic stays in Python where it belongs.
* v2 + v3 form views still exist in the XML file. If the OWL
  dialog ever fails, switch action_open_input_wizard back to
  ir.actions.act_window with view_id=v2 or v3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:17:30 -04:00
gsinghpal
9794a98de9 feat(jobs): Sub 13 sequential step enforcement + Sub 12e v3 wizard
Two coherent feature drops shipping together because their fp_job_step
edits overlap. Both target operator workflow correctness.

## Sub 13 — Sequential step enforcement (recipe + per-step)

Background:
  Investigation on WH/JOB/00339 showed operators starting Incoming
  Inspection while Contract Review was still in_progress. Audit:
  98.7% of recipe operations system-wide had requires_predecessor_done
  = false (the legacy per-step opt-in defaults off, recipe authors
  rarely tick the box).

Architecture:
  Recipe-level toggle + per-step opt-out (Option A from /investigate).
  * fusion.plating.process.node.enforce_sequential — Boolean on the
    recipe root. Default True. When True, every operation under this
    recipe waits for earlier-sequence steps to finish before it can
    start.
  * fusion.plating.process.node.parallel_start — Boolean on operation
    nodes. When True, this step bypasses the sequential gate (e.g.
    paperwork or QA review that runs alongside production).
  * Mirrored on fp.step.template (parallel_start) so library steps
    carry the flag into snapshots.
  * fp.job.enforce_sequential — related from recipe_id. Snapshotted
    at job creation so a recipe author flipping the recipe's flag
    AFTER job generation does NOT change behaviour mid-run.
  * fp.job.step.parallel_start — related from recipe_node_id.
  * Decision matrix (encapsulated in
    fp.job.step._fp_should_block_predecessors):
        recipe.enforce_sequential | step.parallel_start | step.req_pred_done | block?
        --------------------------|---------------------|--------------------|------
                 True             |       False         |        any         |  YES
                 True             |       True          |        any         |   no
                 False            |        any          |       True         |  YES
                 False            |        any          |       False        |   no
  * Manager bypass via context fp_skip_predecessor_check=True (existing).

Runtime gates:
  * fp.job.step.button_start — calls _fp_should_block_predecessors;
    raises UserError naming the blocking earlier step(s).
  * fp.job.step.can_start — computed Boolean for view-side disable.
  * Move wizard predecessor check
    (fusion_plating_shopfloor/controllers/move_controller.py) — uses
    the same helper so tablet + backend behave identically.

UI surface:
  * Recipe form (fp_process_node_views.xml) — enforce_sequential
    toggle on recipe root, parallel_start checkbox on operations.
  * Step template form — parallel_start checkbox.
  * Simple Recipe Editor (inline library form) — Parallel Start
    checkbox + legacy flag demoted with muted styling + supervisor
    group gate.
  * Recipe Tree Editor (properties panel) — both flags exposed,
    only-show on the right node_type.
  * Controllers updated to allowlist + payload the new fields.

Migration:
  fusion_plating/migrations/19.0.18.12.0/post-migrate.py — sets
  enforce_sequential = TRUE on every existing recipe-root node.
  Idempotent. User confirmed dev-stage data, so retroactive flip
  is safe (no production jobs to disrupt).

Tests:
  TestSequentialEnforcement (10 tests) covering:
    * sequential mode blocks out-of-order start
    * first step always startable
    * predecessor finish/skip unlocks next
    * parallel_start opts out of gate
    * free-flow mode bypasses gate
    * legacy requires_predecessor_done still honoured in free-flow
    * manager bypass via context
    * can_start compute reflects state correctly
    * library template parallel_start snapshots into recipe-node

## Sub 12e — Record Inputs Wizard v3 (card layout, dark-mode aware)

Background:
  v2 wizard was a 17-column wide editable table. Operators got lost
  finding which value column applied to their row's type, horizontal
  scroll required on tablets, composite types crammed into one row.

New layout:
  * Each measurement renders as a stacked card (CSS Grid + display
    transformation on the existing list widget — preserves inline
    editing, no JS rewrite).
  * Card header: prompt name (large, bold) + type/unit pills.
  * Card body: ONLY the value widget for this row's type
    (number / boolean / date / text / photo / multi-point / panel).
  * Composite types (multi-point thickness 5x reading + avg, bath
    panel 4 fields) get inline sub-grid inside the card.
  * Empty state ("no measurement prompts") with friendly CTA.

Dark mode:
  * SCSS branches at compile time on $o-webclient-color-scheme
    (per fusion-plating/CLAUDE.md note).
  * Tokens: 7 surface colours + 4 ink levels with light/dark hex
    pairs, all behind var(--fp-*) custom properties for per-deploy
    override.
  * Registered in BOTH web.assets_backend AND web.assets_web_dark
    so each bundle compiles its own palette.

Tablet polish:
  @media (max-width: 900px) — collapse meta below prompt + bump
  numeric input min-height to 56px.

Defensive:
  * v2 view kept in the XML file (instant rollback by changing one
    view_id ref).
  * `:has(.o_invisible_modifier)` rule drops empty cells out of the
    grid so Odoo's invisible="..." doesn't punch holes in layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 21:24:12 -04:00
gsinghpal
ee80673579 fix(contract-review): WO step routes to QA-005 + auto-stage on part create
Two bugs fixed in one drop, both targeting the contract review (QA-005)
enforcement gap reported on entech.

## Bug 1 — WO step routed to wrong wizard

Symptom: clicking Finish & Next or Record on a Contract Review step in
WH/JOB/00339 opened the generic measurement wizard with three fake
prompts (Reviewer Initials / Date Reviewed / QA-005 Approved). No path
to the actual QA-005 form from the work order.

Root cause: action_finish_and_advance + action_open_input_wizard had no
branch for recipe_node.default_kind == 'contract_review'. The step.kind
mapping collapses contract_review -> 'other' so kind-based detection
wouldn't have worked either; gate has to live at the recipe-node layer.

Fix in fusion_plating_jobs/models/fp_job_step.py (v19.0.8.14.6):
- action_finish_and_advance:329 calls _fp_contract_review_redirect
  before the input-wizard branch
- action_open_input_wizard:844 same gate, keeps Record button consistent
- _fp_contract_review_redirect:866 (new) returns the part's
  action_start_contract_review() unless review.state in
  (complete, dismissed) — gate clears so the step can finish after
  the operator signs QA-005.

## Bug 2 — Part create did not enforce contract review

Symptom: spec called for a banner-only UX. User wanted true automatic
enforcement on first part creation under an enforced customer.

Fix in fusion_plating_quality/models/fp_part_catalog.py (v19.0.4.10.0):
- @api.model_create_multi def create() override
- _fp_enforce_contract_review_on_create() helper auto-stages the
  fp.contract.review record AND surfaces three prominent reminders:
    1. Sticky bus.bus warning toast (top-right, doesn't auto-dismiss)
    2. mail.activity (To Do) on the part for the current user
    3. Smart button on the part form lights up (review now exists)
- Idempotent: skips parts that already carry a review id
- Soft-fails: bus or activity outage doesn't block part creation
- create()-only — write/update flows never re-trigger

Sub 4's existing info banner stays as a fourth surface.

## Tests

- fusion_plating_jobs/tests/test_fp_job_extensions.py:
  +TestContractReviewStepRouting (5 tests covering both routing methods,
  the complete/dismissed gate-clear, and non-CR step regression)
- fusion_plating_quality/tests/test_part_catalog_contract_review_enforcement.py
  (NEW): 9 tests covering auto-create, batch create, idempotency,
  activity surface, bus surface, write-must-not-retrigger, soft-fail.
- docs/superpowers/tests/2026-04-22-sub4-smoke.py: flipped the
  "no review yet" assertion to "review auto-created" to match new
  behavior. Sign-flow assertions unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 20:02:52 -04:00
gsinghpal
c5d21e0519 changes 2026-04-30 00:21:08 -04:00
gsinghpal
f7fcd03bfc fix(quick-look): dark-mode-aware instructions panel
The Operator Instructions panel had a hardcoded inline style
(background: #f8f9fa) which became a white-on-dark unreadable blob
in dark mode. Replaced with a CSS class backed by an SCSS file that
branches at compile-time via $o-webclient-color-scheme — registered
in both web.assets_backend (light) and web.assets_web_dark (dark)
bundles per the CLAUDE.md pattern.

Tokens: panel bg #f8f9fa light / #22262d dark; border #d8dadd /
#3a3f47; text #212529 / #e8eaed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:40:55 -04:00
gsinghpal
555dd5421f feat(jobs): step details quick-look modal for backend managers
Click a step's name in the embedded job-form list → opens a read-only
modal with everything a manager wants in one scroll: equipment,
schedule, master collect-measurements banner, operator instructions
(rich-text from recipe_node.description), measurement prompts list,
and values recorded so far.

Implementation: separate read-only form view bound to the embedded
field via context={'form_view_ref': '...'}. The standalone editable
form view stays registered for the Job Steps menu, so direct
navigation still loads the editable variant.

Three new computed/related fields on fp.job.step:
- quick_look_instructions (Html, related from recipe_node_id.description)
- quick_look_prompt_ids (filtered+sorted recipe_node.input_ids, step_input only)
- quick_look_recorded_value_ids (search across moves: input_value rows
  whose move.from_step_id == self.id)

Plus a small action_open_full_form method that escapes from the modal
to the editable form when the manager actually needs to edit.

Edge cases:
- No recipe_node_id → instructions panel shows empty-state hint
- collect_measurements=False → amber banner: "Master switch off — no
  values will be collected at runtime"
- Multiple moves on same step → values list shows all, newest first

Spec: docs/superpowers/specs/2026-04-30-step-details-modal-design.md.
Verified on entech: step "11. Hard Anodize Type III" populates with
516 chars instructions + 7 prompts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:35:08 -04:00
gsinghpal
a2fe1fcbcc changes 2026-04-29 03:35:33 -04:00
gsinghpal
13e300d90e changes 2026-04-28 19:39:37 -04:00
gsinghpal
f08f328688 changes 2026-04-27 00:11:18 -04:00
gsinghpal
d9f58b9851 changes 2026-04-26 15:05:17 -04:00
gsinghpal
7f84e66b72 feat(jobs): finish original plan — Job Margin, polish, legacy hide
Three batched changes that close out the original 10-phase
migration plan.

1. Phase 5 — Job Margin report bound to fp.job (replaces the
   mrp.production-bound report_wo_margin). Per-step labour cost
   table + margin summary using existing fp.job.step.cost_total
   from Phase 1.

2. Polish:
   - Real implementations for fp.job.step.button_pause,
     button_skip, button_cancel (was NotImplementedError stubs).
     button_pause closes the open timelog and sums duration_actual,
     mirroring button_finish; button_skip/cancel transition state
     with UserError guards.
   - Explicit ondelete= policies on fp.job's cross-module Many2ones
     (part_catalog/coating restrict, customer_spec/portal/delivery
     set null) — was implicit set null.
   - Standard Nexa Systems author/website/maintainer/support block
     on fusion_plating_jobs manifest, suppressing the install
     warning.

3. Legacy hide:
   - New 'Plating Legacy Menus' group (group_fusion_plating_legacy_menus)
     — nobody in it by default.
   - Old shopfloor Manager Desk + Plant Overview + Tablet Station
     menus restricted to that group, hiding them from operators
     now that the native equivalents under 'Plating Jobs (Native)'
     exist. (Note: ir.ui.menu uses group_ids in Odoo 19, not the
     deprecated groups_id alias.)

Manifest 19.0.2.4.0 → 19.0.3.0.0. fusion_plating_shopfloor added
to depends so the legacy menu xmlid references resolve at install
time.

Part of: native job model migration (spec 2026-04-25)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 04:49:44 -04:00