feat(plant_kanban): post-shop states visible on board (Tasks 9-13)
Controller (plant_kanban.py):
- Widen domain: state IN (confirmed, in_progress, awaiting_cert,
awaiting_ship). Done jobs still drop off.
- _resolve_card_area: state=awaiting_cert → 'inspection' column,
state=awaiting_ship → 'shipping' column. State drives column
regardless of recipe shape.
- _state_chip: 🏷️ Awaiting CoC (amber) + 📦 Ready to ship (green).
- _SORT_PRIORITY: awaiting_cert=3.5, awaiting_ship=8.5.
- KPI dict: awaiting_cert + awaiting_ship counts.
- Filter clauses for the two new chips.
Model (fp_job.py):
- _compute_card_state handles new states in BOTH branches: the
no-active-step early return (where awaiting_cert/ship cards
land — all steps terminal) AND the per-step branch (defensive).
- _compute_mini_timeline_json: awaiting_cert paints inspection
dot 'current'; awaiting_ship paints shipping dot 'current'.
All earlier dots show 'done'.
SCSS (_plant_tokens.scss + _plant_card.scss):
- New tokens for amber (cert) + green (ship), light + dark variants
via the existing $o-webclient-color-scheme compile-time branch.
- .state-awaiting_cert / .state-awaiting_ship modifier classes
match the existing border-left pattern.
XML (plant_kanban.xml):
- Two new KPI tiles + two new filter chips wired to the state
filter clauses.
Manifest: fusion_plating_shopfloor 19.0.33.2.0 → 19.0.34.0.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,11 +38,13 @@ _SORT_PRIORITY = {
|
||||
'no_parts': 1,
|
||||
'bake_due': 2,
|
||||
'awaiting_signoff': 3,
|
||||
'awaiting_cert': 3.5, # spec 2026-05-25 — after awaiting_signoff
|
||||
'awaiting_qc': 4,
|
||||
'ready_mine': 5,
|
||||
'running_mine': 6,
|
||||
'ready': 7,
|
||||
'running': 8,
|
||||
'awaiting_ship': 8.5, # spec 2026-05-25 — after running
|
||||
'idle_warning': 9,
|
||||
'predecessor_locked': 10,
|
||||
'contract_review': 11,
|
||||
@@ -65,13 +67,18 @@ class PlantKanbanController(http.Controller):
|
||||
else env['fp.work.centre'])
|
||||
paired_area = paired.area_kind if paired else None
|
||||
|
||||
# Base domain — only in-flight jobs.
|
||||
# Base domain — in-flight jobs.
|
||||
# 2026-05-24 (spec 2026-05-24-shopfloor-live-step-fix-design.md
|
||||
# Defect 4 / Change 3): done + cancelled jobs drop off the live
|
||||
# board. They stay reachable via smart buttons, the Plating Jobs
|
||||
# backend list, and history reports.
|
||||
# 2026-05-25 (spec post-shop-cert-shipping-job-states): awaiting_cert
|
||||
# + awaiting_ship are included so completed-but-uncertified /
|
||||
# ready-to-ship jobs stay visible in the Final inspection /
|
||||
# Shipping columns.
|
||||
domain = [
|
||||
('state', 'in', ('confirmed', 'in_progress')),
|
||||
('state', 'in', ('confirmed', 'in_progress',
|
||||
'awaiting_cert', 'awaiting_ship')),
|
||||
]
|
||||
filters = filters or {}
|
||||
if filters.get('overdue'):
|
||||
@@ -88,6 +95,11 @@ class PlantKanbanController(http.Controller):
|
||||
)))
|
||||
if filters.get('mine'):
|
||||
domain.append(('card_state', 'in', ('ready_mine', 'running_mine')))
|
||||
# Spec 2026-05-25 — post-shop state filter chips
|
||||
if filters.get('awaiting_cert'):
|
||||
domain.append(('state', '=', 'awaiting_cert'))
|
||||
if filters.get('awaiting_ship'):
|
||||
domain.append(('state', '=', 'awaiting_ship'))
|
||||
if filters.get('fair'):
|
||||
# Match either part-catalog or partner level requires_first_article
|
||||
domain.append('|')
|
||||
@@ -133,6 +145,13 @@ class PlantKanbanController(http.Controller):
|
||||
'on_hold': sum(
|
||||
1 for j in jobs if j.card_state == 'on_hold'
|
||||
),
|
||||
# Spec 2026-05-25 — post-shop state KPIs
|
||||
'awaiting_cert': sum(
|
||||
1 for j in jobs if j.state == 'awaiting_cert'
|
||||
),
|
||||
'awaiting_ship': sum(
|
||||
1 for j in jobs if j.state == 'awaiting_ship'
|
||||
),
|
||||
'overdue': sum(
|
||||
1 for j in jobs
|
||||
if j.date_deadline and j.date_deadline.date() < date.today()
|
||||
@@ -181,6 +200,14 @@ def _resolve_card_area(job):
|
||||
# active step is — the receiver is who acts.
|
||||
if job.card_state == 'no_parts':
|
||||
return 'receiving'
|
||||
# 2026-05-25 (spec post-shop-cert-shipping-job-states): state drives
|
||||
# column for the two post-shop states. The recipe may not even have
|
||||
# a step with inspection / shipping area_kind, but the card belongs
|
||||
# in those columns once the job has cleared all shop steps.
|
||||
if job.state == 'awaiting_cert':
|
||||
return 'inspection'
|
||||
if job.state == 'awaiting_ship':
|
||||
return 'shipping'
|
||||
if job.active_step_id and job.active_step_id.area_kind:
|
||||
return job.active_step_id.area_kind
|
||||
# Orphan fallback — represents a data integrity issue, not a
|
||||
@@ -319,6 +346,11 @@ def _state_chip(card_state, step):
|
||||
return {'label': _('📦 Parts in transit'), 'kind': 'no_parts'}
|
||||
if card_state == 'contract_review':
|
||||
return {'label': _('📋 QA-005 review'), 'kind': 'paperwork'}
|
||||
# Spec 2026-05-25 — post-shop states
|
||||
if card_state == 'awaiting_cert':
|
||||
return {'label': _('🏷️ Awaiting CoC'), 'kind': 'awaiting_cert'}
|
||||
if card_state == 'awaiting_ship':
|
||||
return {'label': _('📦 Ready to ship'), 'kind': 'awaiting_ship'}
|
||||
if card_state == 'done':
|
||||
return {'label': _('✓ Ready for pickup'), 'kind': 'done'}
|
||||
return {'label': '', 'kind': ''}
|
||||
|
||||
Reference in New Issue
Block a user