Commit Graph

780 Commits

Author SHA1 Message Date
gsinghpal
2ba9b9d03d style(fusion_planning): widen portal nav item gap by 20% (16->19px)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:37:39 -04:00
gsinghpal
028c71452d chore(fusion_planning): bump version to bust asset bundle cache
Earlier nav-spacing CSS fix didn't bust the bundle hash because the
file's content alone determines the hash and the previous deploy
extracted into the wrong path so the CSS file on the server never
actually changed. After fixing the deploy and upgrading, bumping the
version + clearing ir_attachment forces a fresh bundle URL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:33:25 -04:00
gsinghpal
66e04caf21 fix(fusion_planning): keep portal nav items grouped at center
Previous CSS used flex:1 which stretched the 4 nav items across the
full viewport width, leaving big gaps between them on wider screens.
Reverted to the original centered layout and tightened per-item padding
from 24px to 16px so all 4 fit cleanly without stretching.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:26:00 -04:00
gsinghpal
19c1cbdf15 feat(fusion_planning): new module bridging fusion_clock with Odoo Planning
Adds a 'My Schedule' tab to the Fusion Clock portal that lists the current
employee's published planning.slot records, grouped by day. Reuses the
fusion_clock dark theme and reuses Odoo Planning's stock backend UI
(Gantt, send wizard, recurrence) unchanged.

- Controller /my/clock/schedule: pulls published slots in next 60 days
- Portal template with next-shift hero card, summary stats, grouped list
- Bottom-nav xpath inherits target the nav bar specifically (not the
  Recent Activity 'View All' link, which also linked to /my/clock/timesheets)
- 4-tab nav fits via reduced padding and flex sizing

Module depends on stock 'planning' (Enterprise) + fusion_clock.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:16:02 -04:00
gsinghpal
3b7dba32a4 fix(fusion_whitelabels): hide brand_promotion via class attr instead of replacing inner div
The nexa-branded inherit on web.brand_promotion replaced the entire
<div class="o_brand_promotion"> wrapper with an empty hidden div, which
also stripped out the <t t-call="web.brand_promotion_message"/> child.
Enterprise planning's planning.brand_promotion (primary inherit on
web.brand_promotion) then xpath'd onto that t-call and failed to install:
"Element <xpath expr=//t[@t-call='web.brand_promotion_message']>
cannot be located in parent view".

Switched to position="attributes" with add="d-none" so the wrapper still
gets hidden but its children stay in the merged arch for downstream
xpaths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:00:44 -04:00
gsinghpal
f02dc382b7 fix(fusion_whitelabels): keep brand_promotion t-call so other modules can xpath onto it
The footer-credit override used position="replace" against the parent div
of <t t-call="web.brand_promotion"/>, which deleted the element from the
merged web.frontend_layout view. Any later module that anchors on that
t-call (e.g. Enterprise planning's planning.frontend_layout) failed to
install with "Element <xpath expr=//t[@t-call='web.brand_promotion']>
cannot be located in parent view".

Switched to position="after" on the t-call element itself. Odoo's branding
remains hidden via the existing fusion_whitelabels_nexa_brand_promotion
inherit (d-none on .o_brand_promotion), and the Nexa credit still renders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:48:59 -04:00
gsinghpal
a713ec2fd3 changes 2026-05-04 02:17:47 -04:00
gsinghpal
586f05d567 chnages 2026-05-04 02:14:34 -04:00
gsinghpal
3cc393454d fix(simple-editor): HTML in chatter + library form + expand per-step inline edit
Three fixes from user feedback:

1. Chatter posting raw HTML
   _AUDIT_BODY in migration 19.0.18.8.0 was a plain str with <p>
   tags. message_post escaped it for safety, so the chatter pill
   rendered '<p><strong>...</strong></p>' literally to the recipe
   author. Wrapped in markupsafe.Markup so Odoo recognises it as
   safe HTML. Going forward: ANY message_post body containing HTML
   tags MUST be wrapped in Markup() — most callers already do this,
   the migration script was the outlier.

2. Library template editor showed raw <p> tags
   onOpenLibraryEdit was JSON-cloning the payload directly without
   running description through the existing _htmlToText helper that
   the per-step editor uses. Added the conversion. Save path
   (onSaveLibraryEditor + library_save) already wraps via
   _textToHtml so storage stays HTML-compatible.

3. Per-step inline form was missing critical fields — user had to
   delete + re-add a step to change Type/workflow trigger/parallel/signoff
   onToggleEdit now also captures default_kind, triggers_workflow_state_id,
   parallel_start, requires_signoff into the edit state. onSaveStep
   sends them in the write vals. Added _fpResetStepEdit helper to
   keep open/cancel/save reset paths in sync.

   New per-step form has:
     * Step Type (Default Kind) dropdown — drives workflow milestone
       triggers + step-kind routing (e.g. contract_review opens QA-005)
     * Triggers Workflow State dropdown (Sub 14) — per-step override
     * Parallel Start checkbox (Sub 13)
     * Require QA Sign-off checkbox

   step_write controller endpoint also gained a field whitelist —
   was previously accepting any vals dict from the client (security
   hole + opaque to maintainers).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 00:24:40 -04:00
gsinghpal
d6bd43b76e fix(jobs): workflow state — chatter + field cycle fix + force view reload
Three issues from user testing on entech:

1. RPC error: column fp_step_template.triggers_workflow_state_id
   does not exist
   Root cause: the field was declared in fusion_plating CORE, but
   its target model fp.job.workflow.state lives in fusion_plating_jobs.
   Odoo loads core BEFORE jobs (jobs depends on core), so when core's
   field declaration runs, the comodel doesn't exist yet — and Odoo
   silently skips creating the column.
   Fix: moved the field to fusion_plating_jobs/models/fp_job.py via
   _inherit. Now the column is added when jobs loads (after core),
   and the FK target is resolvable.

2. No chatter on the Workflow State form
   Added _inherit = ['mail.thread', 'mail.activity.mixin'] to
   fp.job.workflow.state. Tracking enabled on name/code/sequence so
   admins see who changed the milestone vocabulary. <chatter/> widget
   added to the form view.

3. Form layout still showed cramped 2-col help text
   The XML file on disk had my new alert-info card, but Odoo's DB
   ir_ui_view still held the old arch. The -u didn't refresh it
   (likely because the file's mtime didn't change between deploys).
   Fix: bump version + the next deploy will run a SQL DELETE on the
   ir_ui_view record so Odoo recreates it from XML on -u.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 00:11:17 -04:00
gsinghpal
e54ffe7309 feat(jobs): Sub 14 polish — workflow state form layout + Simple Editor field
Two follow-ups on the workflow state work:

1) Form layout
   The "How triggers combine" help text was crammed into a 2-column
   group, taking ~25% of the available width. Pulled it out of the
   group and rendered as a full-width <div class="alert alert-info">
   below the trigger fields. Same fix applied to Notes — uses a
   <separator> + bare <field> for full sheet width.

2) Simple Recipe Editor support
   The trigger field was only exposed in the Tree Editor. Added it
   to the Simple Editor's inline library form too:

   * fp.step.template.triggers_workflow_state_id (new Many2one) —
     per-template default, snapshot-copied to recipe nodes when
     dropped into a recipe (added to _SNAPSHOT_FIELDS).
   * /fp/simple_recipe/workflow_states/list — new endpoint to feed
     the dropdown. Soft-fails when fusion_plating_jobs isn't
     installed (returns []).
   * Library editor JS — _fpEnsureWorkflowStatesLoaded helper
     caches the catalog on first open (create + edit paths both
     warm it). Save vals carry the trigger id.
   * Library editor XML — dropdown rendered after the flag
     checkboxes. Hidden when the catalog is empty so the form
     doesn't show a useless "— None —" pick.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 00:04:59 -04:00
gsinghpal
28bf6b5071 fix(jobs): drop display_name override on workflow state — pills showed 'Name [code]'
The compute appended '[code]' so admin pages could disambiguate
states at a glance. But display_name is what the status-bar widget
uses to render each pill, so every pill came out as 'Received
[received]', 'In Progress [in_progress]', etc.

Removed the compute. Admin list view already shows code as a
separate column.
2026-05-03 23:53:34 -04:00
gsinghpal
6b4df48090 fix(jobs): move Workflow States menu under Configuration > Recipes & Steps
Earlier commit parented the new menu directly under menu_fp_config,
making it appear at the top alongside the 7 themed buckets instead
of inside one. Workflow milestones map directly to recipe-step
kinds, so 'Recipes & Steps' is the natural home.
2026-05-03 23:51:28 -04:00
gsinghpal
4e0b74d7ae feat(jobs): Sub 14 — configurable workflow state bar (Path B)
Replaces the generic Draft/Confirmed/In Progress/Done statusbar with
a shop-configurable list of plating-specific milestones. Bar advances
automatically as recipe steps complete; no manual button clicks.

What ships
==========

* New model: fp.job.workflow.state
  Catalog of milestones (name, code, sequence, color, triggers).
  Triggers can be:
    - trigger_default_kinds: "receiving,inspect" matches by step.default_kind
    - trigger_first_step_started: any wet/bake/mask/rack step started
    - trigger_all_steps_done: every non-cancelled step in done/skipped
    - block_when_quality_hold: held back while NCR/hold open
  Plus per-recipe-node override (see below).

* Default 7-state seed (data/fp_workflow_state_data.xml):
    Draft → Confirmed → Received → In Progress → Inspected → Shipped → Done
  noupdate=1 so per-shop edits survive module upgrade.

* Recipe-side trigger field on fusion.plating.process.node:
    triggers_workflow_state_id (Many2one, optional)
  Wins over default_kind matching. Lets the recipe author pin a
  specific step as a milestone trigger even when default_kind isn't
  set or doesn't match. Exposed in the Recipe Tree Editor properties
  panel (dropdown sourced from the catalog).

* fp.job.workflow_state_id (computed, stored)
  Iterates the catalog in sequence order; lands at the highest passed
  milestone. Recomputes on step state / kind / recipe_node / quality
  hold changes. Replaces fp.job.state on the form's statusbar.

* Settings UI: Configuration > Workflow States
  Standard list+form pages so admins can add / edit / deactivate
  states. Manager-group write permission, supervisor read.

What this does NOT do
=====================
  * Doesn't drop fp.job.state — that field still drives the internal
    state machine (button_confirm, action_cancel, etc.). Only the
    UI statusbar is reassigned.
  * No migration for existing jobs — they auto-recompute on next read
    because workflow_state_id is a stored compute with the right
    api.depends. Existing WH/JOB/00342 will display its current
    workflow state on next page load.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 23:39:38 -04:00
gsinghpal
4c6bad04c5 Revert "feat(jobs): step sequences are 1, 2, 3, ... not 10, 20, 30, ..."
This reverts commit 32d48ea44d.
2026-05-03 23:31:02 -04:00
gsinghpal
32d48ea44d feat(jobs): step sequences are 1, 2, 3, ... not 10, 20, 30, ...
User feedback: operators kept asking why their work order said "Step 10"
for the first row. The 10-spacing was originally there to allow midpoint
inserts (insert sequence 15 between 10 and 20 without renumbering).
Tradeoff is operator confusion, and recipe authors rarely insert in the
middle anyway. Switching to 1-based contiguous sequences.

Files changed (every step-sequence allocation in the codebase):

fusion_plating_jobs/models/fp_job.py
  _generate_steps_from_recipe — seq_counter starts at 1, increments by 1.
  This is the path that builds fp.job.step records, so new jobs now show
  Step 1, 2, 3, ... in the work order.

fusion_plating_bridge_mrp/models/mrp_production.py
  Same change for the legacy MRP bridge so customers still on
  mrp.production also get 1-based numbering.

fusion_plating/controllers/recipe_controller.py
  - create_node: max_seq + 1
  - reorder_nodes: idx + 1
  - swap renumber: i (was i * 10)
  - paste-import renumber: i (was i * 10)
  - move_node: max_seq + 1
  - _copy_subtree (recipe duplicate/import): i (was i * 10)

fusion_plating/controllers/simple_recipe_controller.py
  - _sequence_for_position rewritten — always renumbers siblings to
    keep them contiguous. Returns pos + 1 for the inserted node.
    Old code used midpoint-with-fallback-to-renumber (10/20/30 spacing).
  - step_reorder: i (was i * 10)
  - library_input_add + step_add_input: existing_max + 1

What this DOESN'T do
  Existing fp.job.step records keep their old sequences (10, 20, ...).
  Re-confirm the SO to spawn a fresh job if you want the clean 1-based
  numbering on a current test job. No data migration — we're in dev
  and the user explicitly said test data is disposable.

What this DOES do
  Every NEW job created from this commit forward shows Step 1, 2, 3, ...
  Every NEW recipe step inserted via the simple editor / tree editor
  also gets sequence 1, 2, 3, ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:58:21 -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
2f8db6d592 fix(jobs): header Finish & Next propagates button_start's action
Bug: action_finish_current_step (the header-level Finish & Next
button on the job form) called button_start() without capturing its
return value. So when button_start returned an action (e.g. the new
QA-005 redirect for contract_review steps from 21e42e7), the header
method threw it away and returned True. Result: operator clicked
Finish & Next, the step started, but no navigation. They had to
click again — the second click found the in_progress step, called
action_finish_and_advance, which returned the QA-005 action.

Two clicks instead of one to land on QA-005.

Fix: capture button_start's return value. If it's a dict (= an
action), return it. Otherwise return True (the normal case).

User reproduction (WH/JOB/00341):
  Header > Finish & Next (1st click) → step starts + QA-005 opens
  Sign / dismiss QA-005 → back to job
  Header > Finish & Next (2nd click) → step finishes + next starts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:39:39 -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
328599d539 fix(jobs): v3 wizard — chrome on <td>, verified from Odoo source (16.3)
I was wrong about the DOM. Verified from Odoo 19 source on entech:

  web/static/src/views/fields/float/float_field.xml
  web/static/src/views/fields/char/char_field.xml
  web/static/src/views/list/list_renderer.xml

Float/Char fields render as a BARE <span> (read mode) or BARE
<input class="o_input"> (edit mode) directly inside the <td>.
There is NO .o_field_widget wrapper. So all my prior CSS targeting
.o_field_widget matched nothing.

Also discovered: Odoo's getCellClass() in list_renderer.js calls
canUseFormatter() which strips custom <field> classes when the
column has widget="..." set:

    canUseFormatter(column, record) {
        if (column.widget) {
            return false;   // ← class stripped here
        }
        ...
    }

So o_fp_iw_value class doesn't even land on cells with
widget="boolean_toggle"/"image". Those cells render natively;
boolean toggle and image styling now targets the widgets directly
wherever they appear (.o_boolean_toggle, .o_field_image).

Fix: put visible chrome (border, bg, padding, min-height) on the
<td> itself for prompt/meta/value/extras cells. Make inner span
and input transparent + inherit. Focus ring travels up via
:focus-within on the td.

Cells now look like obvious input boxes from first paint, regardless
of whether the user has clicked into edit mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:06:53 -04:00
gsinghpal
875828c588 fix(jobs): v3 wizard — chrome on wrapper, not <input> (v19.0.8.16.2)
Root cause user kept seeing inputs as bare/borderless text:
  Odoo's <list editable="bottom"> renders each cell as a read-mode
  <span> inside .o_field_widget UNTIL the user clicks the cell.
  Only then does an <input> swap in. My CSS was targeting
  `td.o_fp_iw_value input { ... }` so the chrome only appeared on
  focus. Every other (unclicked) cell looked like dead text.

Fix:
  Move all input chrome (border, bg, padding, min-height) to the
  .o_field_widget wrapper which is ALWAYS in the DOM. Then make
  the inner <input> / <span> transparent so they inherit. Effect:
  the cell looks like an input box from first paint, regardless
  of focus state. Focus ring travels up via :focus-within.

Special widgets (boolean toggle, photo upload, multi-point,
bath panel) opt OUT of the wrapper chrome via :has() so they
keep their own visual treatment.

Same fix applied to .o_fp_iw_extra cells (composite types).

User reproduction: WH/JOB/00339 → Record on Masking step. After
hard-refresh + this build, every value cell should read as an
obvious input box even before the operator clicks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 21:58:34 -04:00
gsinghpal
efef7859cd fix(jobs): Record Inputs v3 wizard — visual bug fixes (v19.0.8.16.1)
Four visible bugs reported by user after deploy:

1. Type + Unit pills overlapped at top-right of every card.
   Root cause: both <field>s carried the same .o_fp_iw_meta class
   AND both mapped to grid-area: meta. CSS Grid stacked them on
   top of each other so the labels rendered as overlap garbage
   (e.g. "eachnber", "Time(secs)Time(seconds)").
   Fix: distinct classes (.o_fp_iw_meta_type / .o_fp_iw_meta_unit)
   each in its own grid column. Grid is now 4 columns wide:
     "prompt | type | unit | trash"

2. Input borders barely visible in dark mode (#343942 on #22262d).
   Operators couldn't tell where to click.
   Fix: brighter border using $fp-iw-ink-faint instead of $fp-iw-border.
   Hover bumps to $fp-iw-ink-mute. Focus uses brand purple. Also
   added a slight surface tint ($fp-iw-page) so empty inputs read
   as obviously-interactive instead of blending into the card.

3. Photo widget rendered enormous (full card width).
   Root cause: max-width applied only to the preview image, not
   to the .o_field_image container itself.
   Fix: max-width 240px on .o_field_image AND its inner controls.

4. Numeric values floated centered in empty space.
   Root cause: input width wasn't stretching to its grid cell;
   default Odoo numeric-cell text-align: right plus our missing
   width: 100% left tiny inputs centered in the value area.
   Fix: explicit width: 100%, text-align: left, and 420px
   max-width on the .o_field_widget container.

Bonus polish:
  * Trash icon hidden by default (opacity: 0), reveals to 0.6 on
    row hover, full opacity on direct hover. Reduces visual noise
    for the common case where operator just types and saves.
  * Boolean toggle scale bumped from 1.4 to 1.5 + adds left margin
    so the switch sits properly inside the value cell.
  * Mobile (<900px) grid collapses to: prompt|trash / type|unit /
    value / extras — keeps the type+unit pair on one row but lets
    them flow naturally below the prompt.

No model changes. SCSS + XML view only. v2 view still in place
for instant rollback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 21:38:06 -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
1da27ed6bf changes 2026-05-01 00:20:40 -04:00
gsinghpal
bdcbd86db2 changes 2026-04-30 18:08:36 -04:00
gsinghpal
4213c44e51 feat(simple-editor): node_type bug fix + inline library authoring + back nav
Bucket 1 — Generation bug fix
- post-migrate.py for 19.0.18.8.0 promotes flat 'step' children of
  recipes to 'operation' so fp.job._generate_steps() picks them up.
  Filter is narrow: only direct children of node_type='recipe' get
  flipped, tree-editor sub-steps (parent.node_type='operation') are
  untouched. Idempotent. Posts an audit chatter note on each affected
  recipe.
- Simple Editor controller hardcodes node_type='operation' on insert
  + snapshot-import path so future recipes start correct.

Bucket 2 — Inline library authoring
- 6 new JSONRPC routes (/fp/simple_recipe/library/load + save +
  seed_defaults + input/{add,write,remove}, /fp/simple_recipe/tank/list).
- + New Step button in the right pane opens an inline form with name /
  kind / icon / instructions / stations / flags / prompts table.
- Pencil icon on each library row reopens the same form prefilled.
- Step Kind picker leads with 'Generic — no automatic behaviour'.
- 'Seed defaults from kind' calls action_seed_default_inputs server-side
  for kinds that have curated default prompts.

Bucket 3 — Back nav
- '← Recipes' button in the header (or '← Part' when opened from
  Process Composer) mirrors recipe_tree_editor.js, with
  clearBreadcrumbs:true to avoid stack pollution.

Verified on entech: LGPS1104's 19 'step' children now show as
'operation', migration chatter note posted on the recipe, asset cache
busted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 16:16:14 -04:00
gsinghpal
b8d064b180 docs(simple-editor): design — bug fix + inline library authoring + breadcrumbs
Spec for the upcoming Simple Recipe Editor refinement:
- Fix node_type bug so Simple-Editor recipes generate job steps
- Inline + New Step / pencil-edit library authoring with prompts
- Back button + breadcrumb-aware navigation (mirrors tree editor)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 16:08:34 -04:00
gsinghpal
c5d21e0519 changes 2026-04-30 00:21:08 -04:00
gsinghpal
f990f29019 feat(plating-jobs): state-aware sort + default Open filter on Plating Jobs
The Plating Jobs list was sorted priority-desc, deadline-asc, id-desc — which
mixed Done (closed) jobs in with Confirmed (open) jobs and made the list look
chaotic to managers. Done jobs from weeks ago surfaced above active work.

Two changes:

1. New stored compute fp.job.state_priority (Integer, indexed) ranks states
   by managerial relevance: in_progress=0, confirmed=1, draft=2, on_hold=3,
   done=4, cancelled=5. _order now leads with state_priority asc, then
   priority desc, then date_deadline asc, then id desc. Active work bubbles
   to the top automatically.

2. Plating Jobs action defaults to a new 'Open' filter
   (state not in done, cancelled). Managers see only active work by default;
   they untick the filter to see history. Added On Hold + Cancelled filters
   too for full state coverage.

Verified on entech: top 10 jobs are now all in_progress, sorted by deadline
ascending. Existing 26-row list goes from chaotic to focused.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:48:34 -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
875548c547 fix(operator-wizard): surface office-authored instructions to operators
Critical UX gap discovered in production-environment battle test: when
operator hits "Mark Done" and the input wizard fires, they only saw the
measurement prompts list. The rich-text instructions written by the
office (recipe_node.description) never reached the operator at the
exact moment they need them.

Fixed: wizard model gains instructions (Html, computed from
step.recipe_node_id.description) + has_instructions flag.
Form view renders the instructions in a prominent blue alert at the
top of the wizard, above the Measurements list. Hidden when blank
so operators on instruction-less steps don't see noise.

Also: extend default_kind Selection on fusion.plating.process.node to
match fp.step.template — both models now have the same 24 kinds. Without
this, recipe authors could pick a kind in the library template form
that the recipe-node Selection rejected with a ValueError.

Battle test artifact:
- Recipe "Hard Anodize Type III + Dye + Seal" (id=1863) — 23 steps,
  105 measurement prompts, rich-text operator instructions per step
- SO S00278 for ABC Manufactoring confirmed → fp.job 1236 / WH/JOB/00337
  with all 23 steps materialized, 105 prompts visible to operators
- Wizard test: step "11. Hard Anodize Type III" → 516 chars of
  instructions render + 7 input prompts in the form

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:05:21 -04:00
gsinghpal
ec0a07fbe9 fix(audit-trail): 3 production bugs found via end-to-end Anodize battle test
Battle-tested complete workflow on entech: ABC Manufacturing + Anodize
recipe (id=136) cloned to part-variant (id=1775) → SO S00276 confirmed →
fp.job 1234 with 17 steps → recorded 56 measurement values exercising all
13 input types (incl. all 4 new types) → CoC chronological report renders
69KB with all values incl. photo thumbnails.

Bugs found and fixed:

1. fp.process.node.input_ids missing copy=True — when a master recipe
   was cloned per-part (the standard variant pattern), the operator
   prompts on each step did NOT get copied to the variant. Result: jobs
   built from variants ran with zero prompts even though the master had
   them. Fixed: input_ids now copy=True so cloning auto-duplicates.

2. CoC chronological template read dest.input_ids where dest is
   fp.job.step. Steps don't carry input_ids — that field lives on the
   recipe node. Result: AttributeError aborted the entire CoC render.
   Fixed: walk via dest.recipe_node_id.input_ids; preserves the existing
   collect=True filter.

3. CoC chronological template used hasattr() in a t-value expression.
   QWeb's expression engine doesn't expose Python builtins, raised
   KeyError: 'hasattr'. Fixed: use 'collect' in i._fields instead.

Also enhanced photo rendering in CoC: was just "[Attachment]" placeholder;
now renders an actual <img> thumbnail (max 80px tall) plus the filename.

Battle-test script saved to fusion_plating/scripts/bt_e2e_anodize_v2.py
for re-runs / regression testing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 22:53:59 -04:00
gsinghpal
b187192c58 feat(step-library): full plating workflow coverage + per-recipe configurability + audit
Implements 2026-04-29-step-library-audit-design.md. Bumps fusion_plating
to 19.0.18.7.0, fusion_plating_jobs to 19.0.8.12.0, fusion_plating_reports
to 19.0.10.2.0.

LIBRARY EXPANSION
- 8 new Step Kinds: Receiving, Electroclean, Strike, Salt Spray,
  Adhesion Test, Hardness Test, Packaging, Tank Replenishment
- 4 new input types: photo, multi_point_thickness, bath_chemistry_panel, ph
- DEFAULT_INPUTS_BY_KIND rewritten to seed audit-grade prompts on every
  kind (bath IDs, photos, multi-point thickness, signatures, etc.)
- + Common Audit Fields one-click button on the library template form
- Default Operator Instructions relabel + alert callout

PER-RECIPE CONFIGURABILITY
- collect (Boolean) per recipe-step input prompt — opt out without delete
- collect_measurements (Boolean) master switch on recipe step — when off,
  wizard skips entirely
- template_input_id (Many2one) traceability link from recipe to library
- Recipe-step backend form view exposes the new fields with handle drag,
  toggle, target range, and library-source column

RUNTIME WIRING
- Step input wizard filters node.input_ids to step_input AND collect=True;
  short-circuits on collect_measurements=False
- New input types: photo (image widget + ir.attachment), multi-point
  thickness (5 readings + auto avg, skips empty cells), bath chemistry
  panel (pH/conc/temp/bath bundle), pH (0-14 numeric)
- Composite values JSON-serialized into value_text; photo via attachment

CoC REPORT
- Filters captured prompts to collect=True only
- Renders new input types with appropriate format

MIGRATION (post-migrate.py for 19.0.18.7.0)
- Backfills collect=True on recipe-step inputs
- Backfills collect_measurements=True on recipe steps
- Re-runs action_seed_default_inputs on every existing template
  (idempotent, preserves user edits)
- Backfills template_input_id by name-matching against source library
  template (handles JSONB vs varchar name columns)

SEED DATA
- 8 example templates (one per new kind) in fp_step_template_data.xml
  with noupdate=1

BATTLE TEST
- bt_step_library_audit.py: 29 assertions all PASS on entech

OWL EDITOR EXTENSION DEFERRED
- The simple recipe editor's per-step Instructions/Measurements
  expansions were not implemented in this pass; users configure via the
  backend recipe-step form. Track follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 22:13:54 -04:00
gsinghpal
bbf2476f01 plan(step-library): full implementation plan for audit expansion + per-recipe configurability
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:56:18 -04:00
gsinghpal
9401afb21d spec(step-library): full plating workflow coverage + per-recipe configurability + audit
Adds 8 new Step Kinds (Receiving, Electroclean, Strike, Salt Spray,
Adhesion Test, Hardness Test, Packaging, Replenishment) with industry-
standard default measurements. Adds 4 new input types (photo,
multi_point_thickness, bath_chemistry_panel, ph). Beefs up existing
kinds (cleaning, etch, plate, bake, ship, etc.) with bath ID, photos,
multi-point thickness, signatures.

Per-recipe configurability: each recipe step can disable, rename,
retarget, reorder prompts; add custom prompts; toggle entire-step
data collection. Library is the smart default; recipe is final say.

Office-to-operator instructions: relabel as Default Operator
Instructions in the library; per-recipe override surfaced in the
simple recipe editor; falls back to library default at runtime when
recipe override is empty.

Battle test plan covers 18 assertions end-to-end on entech.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:48:12 -04:00
gsinghpal
df43737b1b spec(deadlines): per-part effective deadlines with customer-profile cascade
Resolution chain: explicit override → days offset → part lead time → order
commitment. Adds x_fc_default_lead_time_days on part catalog; per-line
effective_part_deadline + effective_internal_deadline computes; order-level
completion_date rollup + is_late_forecast warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:08:21 -04:00
gsinghpal
a2fe1fcbcc changes 2026-04-29 03:35:33 -04:00
gsinghpal
6ac6d24da6 CHANGES 2026-04-28 19:43:16 -04:00
gsinghpal
2a9fd478f5 Update fp_racking_inspection_views.xml 2026-04-28 19:42:41 -04:00
gsinghpal
13e300d90e changes 2026-04-28 19:39:37 -04:00
gsinghpal
2d42b33d68 docs(claude.md): log Sub 12a/12b/12c + Phase 1/2/3 menu reorg + ergo fixes
Records full session work for future Claude Code sessions:

Sub 12a — Simple Recipe Editor + Step Library
  3 new models, additive fields on process.node + node.input,
  fp_simple_recipe_editor OWL action with drop-position simulator,
  11 JSONRPC endpoints, snapshot semantics, post_init seeding.

Sub 12b — Move Parts / Move Rack / Rack Parts / Stop Timer dialogs
  fp.rack.tag, fp.job.step.move + .input.value, racking_state on
  fusion.plating.rack (orthogonal to wear state), state machine on
  existing fp.job.step.timelog (no parallel labor model), 12 tablet
  endpoints, 4 OWL dialogs with fp-resolve-rack custom event,
  manager-bypass flags, plant overview Racks pane.

Sub 12c — Reports + Labor History
  Operator Traveller v2 (A4 landscape, paper-style), chronological
  CoC body via fp.certificate.body_style + coc_body_router,
  Labor History views, gap-fix bundle (rack travel ticket PDF,
  per-customer cert statement 3-tier resolution, captured Actual
  values from move.input.value).

Phase 1/2/3 — Menu reorganization
  Top-level: 17 → 6 (operator-visible). Industry verticals nested
  under Compliance hub. Move Log/Labor History/Maintenance under
  Operations. Certificates under Quality.
  Configuration: 36 flat → 7 themed folders + Settings sibling.
  Group-gating: KPIs/Move Log/Replenishment Suggestions →
  supervisor+. Operator now sees ~5 top-levels instead of ~10.

Landing page resolver
  action_fp_resolve_plating_landing server action, user override →
  company default → Sale Orders fallback. x_fc_pickable_landing
  Boolean tag for curated picklist.

Production Line / Routing Station rename
  fusion.plating.work.center → 'Production Line' (shop-layout, owns
  tanks). fp.work.centre → 'Routing Station' (per-step routing,
  cost-per-hour, mrp.workcenter replacement). Model IDs unchanged.

Other ergonomics
  Tank field labels (Code → Tank Number, Tank → Tank Name) +
  state-control header buttons. SO smart-button 'Plating Jobs' → 'WO'.
  Default landing screen = Sale Orders.
  Drop-position simulator in Simple Recipe Editor.

Updated 'Menu Structure' section near top of CLAUDE.md to reflect
new 6-top-level layout + 7-folder Configuration grouping.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:06:25 -04:00
gsinghpal
afcd128f83 fix: rename ambiguous 'Work Center' / 'Work Centres' menus
Two distinct entities were both labelled 'Work Centre' (US/UK spelling
the only differentiator — confusing). Renamed by purpose, model IDs
unchanged so all 12+9 existing cross-refs keep working:

fusion.plating.work.center → 'Production Line'
  Physical shop-layout grouping that owns tanks. Examples: 'Line 1 —
  EN', 'Anodize Line', 'Prep Bay'. Has tank_ids (O2M),
  supported_process_ids (M2M), capacity_per_day. The thing tanks live
  in.

fp.work.centre → 'Routing Station'
  Per-job-step routing entity (post-Sub-11 mrp.workcenter replacement).
  Has 'kind' selection (wet_line / bake / mask / rack / inspect),
  cost_per_hour for fp.job.step rollup, default_bath_id +
  default_tank_id for release-ready validation. The thing a job step
  routes through.

Conceptually a Production Line CONTAINS many Routing Stations (e.g.
'EN Line' production line has wet-line, bake, inspect routing
stations on it).

Updated:
- _description on both models
- string= on the name fields
- list/form/search view strings
- act_window names ('Production Lines' / 'Routing Stations')
- menu items in fp_menu.xml + fp_jobs_menu.xml
- doc comments in both model files explaining the distinction

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:55:39 -04:00
gsinghpal
5f6c7af2a7 feat(phase3): tighten group-gating on operator-irrelevant top-levels
Three targeted gates so operators no longer see admin/audit views:

- KPIs (menu_fp_dashboard) → supervisor+. Operators don't need
  dashboards; their tablet shows what they need to do next.
- Move Log (menu_fp_job_step_move) → supervisor+. Operators see
  their own moves on the tablet; this top-level menu is the
  audit-of-everyone-else view.
- Replenishment Suggestions (menu_fp_replenishment_suggestions) →
  supervisor+. Purchasing decision, not operator concern.

Other top-levels were already correctly gated:
- Sales / Configurator → estimator
- Shipping & Receiving → group_fp_receiving
- Compliance hub → supervisor+
- Configuration → manager
- Shop Floor / Quality → operator (correctly visible to floor staff)
- Operations parent stays open; child menus enforce per-action gates

Net effect: a fresh operator now sees ~5 top-level menus instead of
the previous ~10. Supervisors see ~8. Managers see all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:51:30 -04:00
gsinghpal
46715410a9 fix(phase2): restructure fp_menu.xml so buckets defined before children
Within fp_menu.xml itself, the menu_fp_replenishment_rules entry
referenced menu_fp_config_materials_tanks which was defined later in
the same file. Odoo's data loader is strictly top-down within a file.

Reorganized by section: 1) root, 2) Configuration + 7 buckets,
3) Compliance hub, 4) Operations parent, 5) all child menus (referencing
parents already defined above).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:48:06 -04:00
gsinghpal
62c1315997 fix(phase2): load fp_menu.xml first so bucket folders exist before refs
fp_rack_tag_views.xml (and several other view files) reference the
new Phase-2 Configuration sub-folder menus (menu_fp_config_*) defined
in fp_menu.xml. Odoo's data loader is strictly sequential within a
module, so fp_menu.xml must come before any file that references
its bucket xmlids.

Caught by entech upgrade (ParseError on rack-tag menuitem).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:46:53 -04:00
gsinghpal
3641b78a66 feat(phase2): Configuration grouped into 7 themed folders
Collapses the flat ~36-entry Configuration list into 7 navigable
folders + Settings (sibling, stays at top of Configuration). Existing
menu IDs unchanged so bookmarks + cross-module data refs still work
— only parent-id moves.

New folder menus (defined in fusion_plating core):
  menu_fp_config_shop_setup       Shop Setup
  menu_fp_config_recipes_steps    Recipes & Steps
  menu_fp_config_materials_tanks  Materials & Tanks
  menu_fp_config_workforce        Workforce
  menu_fp_config_quality_docs     Quality & Documents
  menu_fp_config_pricing_billing  Pricing & Billing
  menu_fp_config_reference_data   Reference Data

Routing per item (sources updated in their owning module):
  Shop Setup       Facilities, Work Centers, Work Centres, Process
                   Categories, Process Types, Bake Ovens, Shopfloor
                   Stations, Vehicles
  Recipes & Steps  Step Library, QC Checklist Templates, Quality Points
  Materials & Tanks  Bath Parameters, Replenishment Rules, Chemicals,
                     Rack Tags, Calibration Equipment, Calibration Events
  Workforce        Operator Certifications, Shop Roles, Training Types,
                   Quality Teams
  Quality & Documents  Customer Specs, Approved Vendor List, Quality
                       Tags, Quality Reasons, Quality Stages, N299
                       Levels, Notification Templates, Notification Log
  Pricing & Billing  Invoice Strategy Defaults, Account Holds
  Reference Data   Value Sets, Value Rotations
  (Settings remains as a sibling at top of Configuration, manager-gated)

Versions bumped: fusion_plating, fusion_plating_quality, _safety,
_shopfloor, _logistics, _culture, _invoicing, _notifications, _nuclear.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:45:21 -04:00
gsinghpal
0ad382e1a6 feat(phase1): top-level menu consolidation + landing-page resolver
Phase 1 collapses the Plating app's 17 top-level menus down to 6
domains (Sales, Operations, Receiving & Shipping, Quality,
Compliance, Configuration) so users no longer scroll a 17-item
sidebar to find one thing.

Re-parented (no XML id changes — bookmarks still work):
- fusion_plating_compliance.menu_fp_compliance_root
    → menu_fp_compliance_hub  (renamed 'General')
- fusion_plating_safety.menu_fp_safety_root
    → menu_fp_compliance_hub  (renamed 'Safety / WHMIS')
- fusion_plating_aerospace.menu_fp_aerospace
    → menu_fp_compliance_hub  (renamed 'Aerospace (AS9100 / Nadcap)')
- fusion_plating_nuclear.menu_fp_nuclear
    → menu_fp_compliance_hub  (renamed 'Nuclear (CSA N299 / CNSC)')
- fusion_plating_cgp.menu_fp_cgp
    → menu_fp_compliance_hub  (renamed 'Controlled Goods (CGP)')
- fusion_plating_certificates.menu_fp_certificates
    → menu_fp_quality (Certs are a Quality output, not a separate
      top-level concern)
- fusion_plating_bridge_maintenance.menu_fp_maintenance
    → menu_fp_operations
- fusion_plating.menu_fp_job_step_move (Move Log)
    → menu_fp_operations
- fusion_plating.menu_fp_job_step_timelog (Labor History)
    → menu_fp_operations

The new menu_fp_compliance_hub is supervisor-gated; underlying
verticals retain their own group locks (CGP officer, etc.).

Settings menu remains manager-gated through inheritance from
menu_fp_config (already in place).

NEW — Plating landing-page resolver:
- ir.actions.act_window.x_fc_pickable_landing  (Boolean tag for
  curated picklist; flagged on Sale Orders, Quotations, Process
  Recipes for Phase 1; more in Phase 2)
- res.company.x_fc_default_landing_action_id (admin sets fallback)
- res.users.x_fc_plating_landing_action_id (per-user override)
- ir.actions.server action_fp_resolve_plating_landing — picks
  user → company → Sale Orders fallback at click time
- menu_fp_root rewired to call the resolver
- User profile + Settings tabs surface the dropdowns

Configurator's earlier menu_fp_root override (action_fp_sale_orders
direct) removed — core's resolver now owns the routing.

Versions bumped: fusion_plating 19.0.11.0.0, configurator
19.0.17.16.0, plus 7 dependent modules patched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:33:37 -04:00