feat(plating): Phase 1 — plant-view kanban data model foundation
PV-T1: fp.work.centre.area_kind Selection (9 floor columns)
PV-T2: fp.job.step.area_kind compute + _STEP_KIND_TO_AREA fallback
(covers all 30+ step kinds in the project library, plus the
spec D4 rule that de_mask folds into de_racking)
PV-T3: fp.job.step.last_activity_at + write hook + message_post
override + fp.job.step.move.create() hook + _fp_is_idle helper
PV-T4: res.users.paired_work_centre_ids M2M (single-station for MVP,
forward-compatible for Phase 2 multi-station picker)
PV-T5: res.config.settings.x_fc_shopfloor_layout feature flag backed
by ir.config_parameter for the landing-action resolver
Migrations:
fusion_plating 19.0.21.0.0 — backfill area_kind from kind
fusion_plating_jobs 19.0.10.24.0 — backfill last_activity_at
Deployed + verified on entech:
- 9/9 fp.work.centre rows have area_kind set
- 400/400 fp.job.step rows have area_kind + last_activity_at
- paired_work_centre_ids M2M relation table created
- All 271 modules loaded cleanly, registry rebuilt in 27s
Part of the 2026-05-23 Shop Floor plant-view kanban redesign.
Plan: 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:
@@ -77,6 +77,27 @@ class FpJobStepMove(models.Model):
|
||||
string='Transition Input Values',
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Stamp last_activity_at on from_step + to_step so the plant-view
|
||||
idle gate (S16) sees moves as activity. Without this, a step that
|
||||
only ever gets moves (no chatter, no state edits) eventually
|
||||
trips the 8-hour idle warning falsely.
|
||||
"""
|
||||
moves = super().create(vals_list)
|
||||
Step = self.env['fp.job.step']
|
||||
step_ids = set()
|
||||
for m in moves:
|
||||
if m.from_step_id:
|
||||
step_ids.add(m.from_step_id.id)
|
||||
if m.to_step_id:
|
||||
step_ids.add(m.to_step_id.id)
|
||||
if step_ids:
|
||||
Step.browse(list(step_ids)).sudo().with_context(
|
||||
tracking_disable=True,
|
||||
).write({'last_activity_at': fields.Datetime.now()})
|
||||
return moves
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# S23 — required transition-input gate
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -48,6 +48,26 @@ class FpWorkCentre(models.Model):
|
||||
required=True,
|
||||
default='other',
|
||||
)
|
||||
area_kind = fields.Selection(
|
||||
[
|
||||
('receiving', 'Receiving'),
|
||||
('masking', 'Masking'),
|
||||
('blasting', 'Blasting'),
|
||||
('racking', 'Racking'),
|
||||
('plating', 'Plating'),
|
||||
('baking', 'Baking'),
|
||||
('de_racking', 'De-Racking'),
|
||||
('inspection', 'Final inspection'),
|
||||
('shipping', 'Shipping'),
|
||||
],
|
||||
string='Floor Column',
|
||||
help='Which Shop Floor column this work centre belongs to. '
|
||||
'Drives the plant-view kanban grouping — any job whose '
|
||||
'active step uses this work centre routes into this column. '
|
||||
'See docs/superpowers/specs/2026-05-23-shopfloor-plant-view-'
|
||||
'design.md §4.2 for the mapping rules.',
|
||||
index=True,
|
||||
)
|
||||
cost_per_hour = fields.Monetary(
|
||||
currency_field='currency_id',
|
||||
help='Used for fp.job.step cost rollups.',
|
||||
|
||||
Reference in New Issue
Block a user