feat(shopfloor): Phase 5 — flip default to v2 plant view + docs

PV-Phase5 of the plant-view redesign. Final phase — flips the default
of x_fc_shopfloor_layout from 'legacy' to 'v2' and updates CLAUDE.md
with the new architecture rule.

Verified on entech:
  - HTTP 200 on /web/login
  - Shopfloor module loads cleanly with all 19 new frontend files
  - /fp/landing/plant_kanban returns the assembled payload with 9
    columns + denormalized cards
  - Card state distribution: 22 contract_review + 8 no_parts + 1 running
    (sample data only — dev system)
  - Asset bundle re-compiled (9 stale attachments cleared)
  - ir.config_parameter['fusion_plating_shopfloor.layout'] = 'v2' set

To switch back to legacy: Settings → Fusion Plating → Shop Floor
Layout, or UPDATE ir_config_parameter SET value='legacy' WHERE
key='fusion_plating_shopfloor.layout'.

CLAUDE.md gets a new ~80-line section documenting:
  - Why the redesign (per-step kanban produced duplicate cards)
  - 9-column layout + step-kind → area mapping (spec D3, D4, D5)
  - 13-state catalog + precedence dispatch in _compute_card_state
  - Backend single-endpoint payload shape (/fp/landing/plant_kanban)
  - Frontend OWL component tree + critical implementation gotchas
    (rule 20 OWL scope, rule 8 SCSS @import, dark-mode compile-time)
  - How to switch back to legacy

Closes the 20-task plan in
  docs/superpowers/plans/2026-05-23-shopfloor-plant-view-plan.md

Spec: docs/superpowers/specs/2026-05-23-shopfloor-plant-view-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-23 20:59:44 -04:00
parent 8b9b4d60ad
commit a60506a645
2 changed files with 102 additions and 1 deletions

View File

@@ -420,6 +420,107 @@ Plan: [docs/superpowers/plans/2026-05-22-shopfloor-tablet-redesign-plan.md](docs
- Don't add `web.assets_web_dark` entries to the manifest — Odoo 19 auto-compiles `web.assets_backend` SCSS into both bundles
- Don't bypass `_fp_should_block_predecessors()` when computing step blockers — keep `blocker_kind=predecessor` logic in sync with `can_start`
## Shop Floor — Plant View kanban (2026-05-23 redesign)
**Default Shop Floor surface** for new installs (gated by feature flag
`ir.config_parameter['fusion_plating_shopfloor.layout']`, values `legacy`
or `v2`). Legacy per-step kanban (`fp_shopfloor_landing`) remains
accessible by flipping the flag back to `legacy` in Settings → Fusion
Plating.
**Why redesign:** the per-step kanban produced one card per recipe step
per column, so a 14-step recipe spawned 9+ cards for ONE job across the
board. With 17 active jobs the board showed 100+ duplicate cards across
narrow columns. The new design is **one card per `fp.job`** at the
**department level** — recipe step count no longer drives layout width.
**Spec:** `docs/superpowers/specs/2026-05-23-shopfloor-plant-view-design.md`
**Plan:** `docs/superpowers/plans/2026-05-23-shopfloor-plant-view-plan.md`
### Layout — 9 fixed columns in process sequence
`Receiving → Masking → Blasting → Racking → Plating → Baking →
De-Racking → Final inspection → Shipping`
Columns are first-class — they always render in this exact order, never
reorder, never collapse when empty. Driven by `fp.work.centre.area_kind`
Selection (added 2026-05-23). Each `fp.job.step.area_kind` is computed
(stored) from `work_centre.area_kind` with a fallback to a step-kind
dispatch table (`_STEP_KIND_TO_AREA` in `fusion_plating_jobs/models/fp_job_step.py`).
**Spec D3:** all wet-line steps (Soak Clean, Electroclean, Acid Dip,
Etch, Desmut, Zincate, Rinse, E-Nickel, Chrome, Anodize, Black Oxide,
Drying) roll up into the **Plating** column. The tank chip on the card
distinguishes them.
**Spec D4:** De-Masking folds into De-Racking (no separate column).
**Spec D5:** Contract Review (paperwork) cards live in Receiving with a
purple "📋 QA-005" chip — they're admin gates, not physical work.
### Card state catalog — 13 mutually-exclusive states
`fp.job.card_state` is a stored Char computed in `_compute_card_state`
(see `fusion_plating_jobs/models/fp_job.py`). Explicit precedence
dispatch matching spec §6.2 — first match wins:
`no_parts → on_hold → awaiting_signoff → awaiting_qc → bake_due →
predecessor_locked → idle_warning → done → contract_review →
running_mine/running → ready_mine/ready`
Each state has a distinct background tint + left-border color + chip +
mini-timeline marker color. See `_plant_card.scss` for the mapping. The
"mine" variants (`ready_mine`, `running_mine`) light up only when the
active step's work centre is in `res.users.paired_work_centre_ids` (the
M2M holds one row in MVP, mirrors the existing single-station picker).
### Backend — single endpoint, denormalized payload
`/fp/landing/plant_kanban` (controller in
`fusion_plating_shopfloor/controllers/plant_kanban.py`) returns
`{ok, mode, paired_station, kpis, columns, cards}` in one JSONRPC call.
Frontend has zero per-card RPCs — every card field comes pre-formatted
from the controller's `_render_card`. State-chip text (with elapsed
times, operator names, hours-idle) is interpolated server-side.
### Frontend — OWL component tree
```
FpPlantKanban (client action 'fp_plant_kanban')
└── FpTabletLock (PIN gate wrapper)
├── PlantHeader (KPIs + filter chips + mode toggle + station picker)
└── Board (9 × Column)
├── FpColumnHeader (with 'You're here' badge for paired column)
└── FpPlantCard[] (each with FpMiniTimeline)
```
Polls every 10s. Filter state persists in localStorage. All 13 card
states styled via `.state-<name>` CSS modifier classes on a single
shared `.o_fp_plant_card` base. The mini-timeline renders 9 colored
dots driven by `fp.job.mini_timeline_json` (Python emits the array
shape — frontend just maps state → CSS class).
### Critical implementation gotchas (project rules applied)
- **OWL templates only expose `Math` as a JS global** (Rule 20). All
coercion (String, Number, parseInt) MUST happen in JS — `tag_chip_class()`
/ `progress_style` etc. live in plant_card.js, not in the XML.
- **SCSS @import is forbidden** (Rule 8). `_plant_tokens.scss` loads
FIRST in the manifest's `web.assets_backend`; subsequent component
partials get the `$plant-*` vars via the concatenated bundle.
- **Dark mode** via `$o-webclient-color-scheme == dark` compile-time
branch in `_plant_tokens.scss` (NOT runtime class selectors).
### How to switch back to legacy
```sql
UPDATE ir_config_parameter SET value = 'legacy'
WHERE key = 'fusion_plating_shopfloor.layout';
```
Or use Settings → Fusion Plating → Shop Floor Layout. Both surfaces
write the same `ir.config_parameter` key.
## Deployment
### odoo-entech (LXC 111 on pve-worker5)

View File

@@ -23,7 +23,7 @@ class ResConfigSettings(models.TransientModel):
('v2', 'Plant View (one card per job, 9 columns)'),
],
string='Shop Floor Layout',
default='legacy',
default='v2',
config_parameter='fusion_plating_shopfloor.layout',
help='Switches the Shop Floor client action between the legacy '
'per-step kanban and the v2 plant view. Defaults to legacy '