feat(fusion_plating): kind.area_kind drives Shop Floor column routing
Add required area_kind Selection to fp.step.kind so each kind self-declares which plant-view column its steps belong in. Replaces the hardcoded _STEP_KIND_TO_AREA dict (removed in fp_job_step.py in the follow-up commit). - New `blast` kind for the Blasting column (sequence=35) - 26 existing kind records seeded with area_kind in XML - Pre-migrate 19.0.21.2.0 seeds existing rows BEFORE NOT NULL hits the schema; also activates derack/demask/gating that were deactivated in 19.0.20.6.0 but are needed for the full taxonomy - Step Kind form + list views surface area_kind (badge + chip) - Step Kind search adds Group By Shop Floor Column - Simple Editor kind picker shows "Masking — Masking column" suffix so authors see the routing at pick time - Add Hot Water Porosity Test (A-15) + Final Inspection / Packaging templates (used by 7+3 recipe nodes that previously had no library entry) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Fusion Plating',
|
'name': 'Fusion Plating',
|
||||||
'version': '19.0.21.1.3',
|
'version': '19.0.21.2.0',
|
||||||
'category': 'Manufacturing/Plating',
|
'category': 'Manufacturing/Plating',
|
||||||
'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.',
|
'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -484,8 +484,15 @@ class SimpleRecipeController(http.Controller):
|
|||||||
type='jsonrpc', auth='user')
|
type='jsonrpc', auth='user')
|
||||||
def kinds_list(self):
|
def kinds_list(self):
|
||||||
"""Sub 14b — Step Kind dropdown options for the inline library
|
"""Sub 14b — Step Kind dropdown options for the inline library
|
||||||
form. User-extensible via /fp/simple_recipe/kinds/create."""
|
form. User-extensible via /fp/simple_recipe/kinds/create.
|
||||||
|
|
||||||
|
2026-05-24 — payload now includes `area_kind` + a humanized
|
||||||
|
`area_kind_label` so the Simple Editor picker can render
|
||||||
|
"Masking — Masking column" and authors see which Shop Floor
|
||||||
|
column they're routing the step to.
|
||||||
|
"""
|
||||||
Kind = request.env['fp.step.kind']
|
Kind = request.env['fp.step.kind']
|
||||||
|
area_labels = dict(Kind._fields['area_kind'].selection)
|
||||||
return {
|
return {
|
||||||
'kinds': [
|
'kinds': [
|
||||||
{
|
{
|
||||||
@@ -494,6 +501,8 @@ class SimpleRecipeController(http.Controller):
|
|||||||
'name': k.name or '',
|
'name': k.name or '',
|
||||||
'icon': k.icon or '',
|
'icon': k.icon or '',
|
||||||
'sequence': k.sequence,
|
'sequence': k.sequence,
|
||||||
|
'area_kind': k.area_kind or '',
|
||||||
|
'area_kind_label': area_labels.get(k.area_kind, ''),
|
||||||
}
|
}
|
||||||
for k in Kind.search(
|
for k in Kind.search(
|
||||||
[('active', '=', True)], order='sequence, name',
|
[('active', '=', True)], order='sequence, name',
|
||||||
|
|||||||
@@ -18,7 +18,15 @@
|
|||||||
(covers all bath-based steps).
|
(covers all bath-based steps).
|
||||||
- `mask` covers Masking + De-Masking, `racking` covers
|
- `mask` covers Masking + De-Masking, `racking` covers
|
||||||
Racking + De-Racking — operators differentiate by the
|
Racking + De-Racking — operators differentiate by the
|
||||||
step name. -->
|
step name.
|
||||||
|
|
||||||
|
2026-05-24 update (19.0.21.2.0 — Shop Floor live-step fix):
|
||||||
|
- New `area_kind` field on fp.step.kind drives plant-view
|
||||||
|
column routing. Every record below carries an
|
||||||
|
area_kind. New `blast` kind for the Blasting column.
|
||||||
|
- `derack`, `demask`, `gating` get re-activated via the
|
||||||
|
pre-migrate (they're listed under "ACTIVE KINDS" here
|
||||||
|
now since they're meant to be active going forward). -->
|
||||||
|
|
||||||
<!-- ============================================================ -->
|
<!-- ============================================================ -->
|
||||||
<!-- ACTIVE KINDS — visible in dropdown -->
|
<!-- ACTIVE KINDS — visible in dropdown -->
|
||||||
@@ -29,13 +37,7 @@
|
|||||||
<field name="name">Other</field>
|
<field name="name">Other</field>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="icon">fa-circle-o</field>
|
<field name="icon">fa-circle-o</field>
|
||||||
</record>
|
<field name="area_kind">plating</field>
|
||||||
|
|
||||||
<record id="step_kind_wet_process" model="fp.step.kind">
|
|
||||||
<field name="code">wet_process</field>
|
|
||||||
<field name="name">Wet Process (Clean / Rinse / Etch / Dry / etc.)</field>
|
|
||||||
<field name="sequence">55</field>
|
|
||||||
<field name="icon">fa-tint</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="step_kind_receiving" model="fp.step.kind">
|
<record id="step_kind_receiving" model="fp.step.kind">
|
||||||
@@ -43,144 +45,182 @@
|
|||||||
<field name="name">Receiving / Incoming Inspection</field>
|
<field name="name">Receiving / Incoming Inspection</field>
|
||||||
<field name="sequence">10</field>
|
<field name="sequence">10</field>
|
||||||
<field name="icon">fa-truck</field>
|
<field name="icon">fa-truck</field>
|
||||||
|
<field name="area_kind">receiving</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_contract_review" model="fp.step.kind">
|
<record id="step_kind_contract_review" model="fp.step.kind">
|
||||||
<field name="code">contract_review</field>
|
<field name="code">contract_review</field>
|
||||||
<field name="name">Contract Review (QA-005)</field>
|
<field name="name">Contract Review (QA-005)</field>
|
||||||
<field name="sequence">20</field>
|
<field name="sequence">20</field>
|
||||||
<field name="icon">fa-file-text-o</field>
|
<field name="icon">fa-file-text-o</field>
|
||||||
|
<field name="area_kind">receiving</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_racking" model="fp.step.kind">
|
<record id="step_kind_racking" model="fp.step.kind">
|
||||||
<field name="code">racking</field>
|
<field name="code">racking</field>
|
||||||
<field name="name">Racking</field>
|
<field name="name">Racking</field>
|
||||||
<field name="sequence">30</field>
|
<field name="sequence">30</field>
|
||||||
<field name="icon">fa-server</field>
|
<field name="icon">fa-server</field>
|
||||||
|
<field name="area_kind">racking</field>
|
||||||
|
</record>
|
||||||
|
<record id="step_kind_blast" model="fp.step.kind">
|
||||||
|
<field name="code">blast</field>
|
||||||
|
<field name="name">Blasting / Media Blast</field>
|
||||||
|
<field name="sequence">35</field>
|
||||||
|
<field name="icon">fa-bullseye</field>
|
||||||
|
<field name="area_kind">blasting</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_mask" model="fp.step.kind">
|
<record id="step_kind_mask" model="fp.step.kind">
|
||||||
<field name="code">mask</field>
|
<field name="code">mask</field>
|
||||||
<field name="name">Masking</field>
|
<field name="name">Masking</field>
|
||||||
<field name="sequence">40</field>
|
<field name="sequence">40</field>
|
||||||
<field name="icon">fa-eye-slash</field>
|
<field name="icon">fa-eye-slash</field>
|
||||||
|
<field name="area_kind">masking</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_cleaning" model="fp.step.kind">
|
<record id="step_kind_cleaning" model="fp.step.kind">
|
||||||
<field name="code">cleaning</field>
|
<field name="code">cleaning</field>
|
||||||
<field name="name">Cleaning</field>
|
<field name="name">Cleaning</field>
|
||||||
<field name="sequence">50</field>
|
<field name="sequence">50</field>
|
||||||
<field name="icon">fa-tint</field>
|
<field name="icon">fa-tint</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
|
</record>
|
||||||
|
<record id="step_kind_wet_process" model="fp.step.kind">
|
||||||
|
<field name="code">wet_process</field>
|
||||||
|
<field name="name">Wet Process (Clean / Rinse / Etch / Dry / etc.)</field>
|
||||||
|
<field name="sequence">55</field>
|
||||||
|
<field name="icon">fa-tint</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_electroclean" model="fp.step.kind">
|
<record id="step_kind_electroclean" model="fp.step.kind">
|
||||||
<field name="code">electroclean</field>
|
<field name="code">electroclean</field>
|
||||||
<field name="name">Electroclean</field>
|
<field name="name">Electroclean</field>
|
||||||
<field name="sequence">60</field>
|
<field name="sequence">60</field>
|
||||||
<field name="icon">fa-bolt</field>
|
<field name="icon">fa-bolt</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_etch" model="fp.step.kind">
|
<record id="step_kind_etch" model="fp.step.kind">
|
||||||
<field name="code">etch</field>
|
<field name="code">etch</field>
|
||||||
<field name="name">Etch / Activation</field>
|
<field name="name">Etch / Activation</field>
|
||||||
<field name="sequence">70</field>
|
<field name="sequence">70</field>
|
||||||
<field name="icon">fa-flask</field>
|
<field name="icon">fa-flask</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_rinse" model="fp.step.kind">
|
<record id="step_kind_rinse" model="fp.step.kind">
|
||||||
<field name="code">rinse</field>
|
<field name="code">rinse</field>
|
||||||
<field name="name">Rinse</field>
|
<field name="name">Rinse</field>
|
||||||
<field name="sequence">80</field>
|
<field name="sequence">80</field>
|
||||||
<field name="icon">fa-tint</field>
|
<field name="icon">fa-tint</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_strike" model="fp.step.kind">
|
<record id="step_kind_strike" model="fp.step.kind">
|
||||||
<field name="code">strike</field>
|
<field name="code">strike</field>
|
||||||
<field name="name">Strike (Wood's Nickel / Activation)</field>
|
<field name="name">Strike (Wood's Nickel / Activation)</field>
|
||||||
<field name="sequence">90</field>
|
<field name="sequence">90</field>
|
||||||
<field name="icon">fa-bolt</field>
|
<field name="icon">fa-bolt</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_plate" model="fp.step.kind">
|
<record id="step_kind_plate" model="fp.step.kind">
|
||||||
<field name="code">plate</field>
|
<field name="code">plate</field>
|
||||||
<field name="name">Plating</field>
|
<field name="name">Plating</field>
|
||||||
<field name="sequence">100</field>
|
<field name="sequence">100</field>
|
||||||
<field name="icon">fa-shield</field>
|
<field name="icon">fa-shield</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_replenishment" model="fp.step.kind">
|
<record id="step_kind_replenishment" model="fp.step.kind">
|
||||||
<field name="code">replenishment</field>
|
<field name="code">replenishment</field>
|
||||||
<field name="name">Tank Replenishment</field>
|
<field name="name">Tank Replenishment</field>
|
||||||
<field name="sequence">110</field>
|
<field name="sequence">110</field>
|
||||||
<field name="icon">fa-plus-circle</field>
|
<field name="icon">fa-plus-circle</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_wbf_test" model="fp.step.kind">
|
<record id="step_kind_wbf_test" model="fp.step.kind">
|
||||||
<field name="code">wbf_test</field>
|
<field name="code">wbf_test</field>
|
||||||
<field name="name">Water Break Free Test</field>
|
<field name="name">Water Break Free Test</field>
|
||||||
<field name="sequence">120</field>
|
<field name="sequence">120</field>
|
||||||
<field name="icon">fa-check-square-o</field>
|
<field name="icon">fa-check-square-o</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_dry" model="fp.step.kind">
|
<record id="step_kind_dry" model="fp.step.kind">
|
||||||
<field name="code">dry</field>
|
<field name="code">dry</field>
|
||||||
<field name="name">Drying</field>
|
<field name="name">Drying</field>
|
||||||
<field name="sequence">130</field>
|
<field name="sequence">130</field>
|
||||||
<field name="icon">fa-sun-o</field>
|
<field name="icon">fa-sun-o</field>
|
||||||
|
<field name="area_kind">plating</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_bake" model="fp.step.kind">
|
<record id="step_kind_bake" model="fp.step.kind">
|
||||||
<field name="code">bake</field>
|
<field name="code">bake</field>
|
||||||
<field name="name">Bake (HE Relief / Stress Relief)</field>
|
<field name="name">Bake (HE Relief / Stress Relief)</field>
|
||||||
<field name="sequence">140</field>
|
<field name="sequence">140</field>
|
||||||
<field name="icon">fa-fire</field>
|
<field name="icon">fa-fire</field>
|
||||||
|
<field name="area_kind">baking</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_demask" model="fp.step.kind">
|
<record id="step_kind_demask" model="fp.step.kind">
|
||||||
<field name="code">demask</field>
|
<field name="code">demask</field>
|
||||||
<field name="name">De-Masking</field>
|
<field name="name">De-Masking</field>
|
||||||
<field name="sequence">150</field>
|
<field name="sequence">150</field>
|
||||||
<field name="icon">fa-eye</field>
|
<field name="icon">fa-eye</field>
|
||||||
|
<field name="area_kind">de_racking</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_derack" model="fp.step.kind">
|
<record id="step_kind_derack" model="fp.step.kind">
|
||||||
<field name="code">derack</field>
|
<field name="code">derack</field>
|
||||||
<field name="name">De-Racking</field>
|
<field name="name">De-Racking</field>
|
||||||
<field name="sequence">160</field>
|
<field name="sequence">160</field>
|
||||||
<field name="icon">fa-server</field>
|
<field name="icon">fa-server</field>
|
||||||
|
<field name="area_kind">de_racking</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_inspect" model="fp.step.kind">
|
<record id="step_kind_inspect" model="fp.step.kind">
|
||||||
<field name="code">inspect</field>
|
<field name="code">inspect</field>
|
||||||
<field name="name">Inspection</field>
|
<field name="name">Inspection</field>
|
||||||
<field name="sequence">170</field>
|
<field name="sequence">170</field>
|
||||||
<field name="icon">fa-search</field>
|
<field name="icon">fa-search</field>
|
||||||
|
<field name="area_kind">inspection</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_hardness_test" model="fp.step.kind">
|
<record id="step_kind_hardness_test" model="fp.step.kind">
|
||||||
<field name="code">hardness_test</field>
|
<field name="code">hardness_test</field>
|
||||||
<field name="name">Hardness Test (HV / HK / HRC)</field>
|
<field name="name">Hardness Test (HV / HK / HRC)</field>
|
||||||
<field name="sequence">180</field>
|
<field name="sequence">180</field>
|
||||||
<field name="icon">fa-tachometer</field>
|
<field name="icon">fa-tachometer</field>
|
||||||
|
<field name="area_kind">inspection</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_adhesion_test" model="fp.step.kind">
|
<record id="step_kind_adhesion_test" model="fp.step.kind">
|
||||||
<field name="code">adhesion_test</field>
|
<field name="code">adhesion_test</field>
|
||||||
<field name="name">Adhesion Test</field>
|
<field name="name">Adhesion Test</field>
|
||||||
<field name="sequence">190</field>
|
<field name="sequence">190</field>
|
||||||
<field name="icon">fa-link</field>
|
<field name="icon">fa-link</field>
|
||||||
|
<field name="area_kind">inspection</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_salt_spray" model="fp.step.kind">
|
<record id="step_kind_salt_spray" model="fp.step.kind">
|
||||||
<field name="code">salt_spray</field>
|
<field name="code">salt_spray</field>
|
||||||
<field name="name">Salt Spray / Corrosion Test</field>
|
<field name="name">Salt Spray / Corrosion Test</field>
|
||||||
<field name="sequence">200</field>
|
<field name="sequence">200</field>
|
||||||
<field name="icon">fa-cloud</field>
|
<field name="icon">fa-cloud</field>
|
||||||
|
<field name="area_kind">inspection</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_final_inspect" model="fp.step.kind">
|
<record id="step_kind_final_inspect" model="fp.step.kind">
|
||||||
<field name="code">final_inspect</field>
|
<field name="code">final_inspect</field>
|
||||||
<field name="name">Final Inspection</field>
|
<field name="name">Final Inspection</field>
|
||||||
<field name="sequence">210</field>
|
<field name="sequence">210</field>
|
||||||
<field name="icon">fa-check-circle</field>
|
<field name="icon">fa-check-circle</field>
|
||||||
|
<field name="area_kind">inspection</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_packaging" model="fp.step.kind">
|
<record id="step_kind_packaging" model="fp.step.kind">
|
||||||
<field name="code">packaging</field>
|
<field name="code">packaging</field>
|
||||||
<field name="name">Packaging / Pre-Ship</field>
|
<field name="name">Packaging / Pre-Ship</field>
|
||||||
<field name="sequence">220</field>
|
<field name="sequence">220</field>
|
||||||
<field name="icon">fa-archive</field>
|
<field name="icon">fa-archive</field>
|
||||||
|
<field name="area_kind">shipping</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_ship" model="fp.step.kind">
|
<record id="step_kind_ship" model="fp.step.kind">
|
||||||
<field name="code">ship</field>
|
<field name="code">ship</field>
|
||||||
<field name="name">Shipping</field>
|
<field name="name">Shipping</field>
|
||||||
<field name="sequence">230</field>
|
<field name="sequence">230</field>
|
||||||
<field name="icon">fa-paper-plane</field>
|
<field name="icon">fa-paper-plane</field>
|
||||||
|
<field name="area_kind">shipping</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="step_kind_gating" model="fp.step.kind">
|
<record id="step_kind_gating" model="fp.step.kind">
|
||||||
<field name="code">gating</field>
|
<field name="code">gating</field>
|
||||||
<field name="name">Gating</field>
|
<field name="name">Gating</field>
|
||||||
<field name="sequence">240</field>
|
<field name="sequence">240</field>
|
||||||
<field name="icon">fa-pause-circle</field>
|
<field name="icon">fa-pause-circle</field>
|
||||||
|
<field name="area_kind">receiving</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- ============================================================
|
<!-- ============================================================
|
||||||
@@ -955,5 +995,8 @@
|
|||||||
|
|
||||||
<!-- gating: intentionally no default inputs -->
|
<!-- gating: intentionally no default inputs -->
|
||||||
|
|
||||||
|
<!-- blast: intentionally no default inputs (operator picks
|
||||||
|
approach by step name + recipe instructions) -->
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -103,4 +103,30 @@
|
|||||||
]]></field>
|
]]></field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- 2026-05-24 additions (19.0.21.2.0 — Shop Floor live-step fix) -->
|
||||||
|
|
||||||
|
<record id="fp_step_template_hwp_a15" model="fp.step.template">
|
||||||
|
<field name="name">Hot Water Porosity Test (A-15)</field>
|
||||||
|
<field name="code">HWP_A15</field>
|
||||||
|
<field name="kind_id" ref="step_kind_inspect"/>
|
||||||
|
<field name="icon">fa-tint</field>
|
||||||
|
<field name="description"><![CDATA[
|
||||||
|
<p>Hot-water porosity test for plated samples. Verify continuity
|
||||||
|
of the deposit across the test panel; record any porosity sites
|
||||||
|
and attach a photo when a defect is found.</p>
|
||||||
|
]]></field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="fp_step_template_final_pkg_std" model="fp.step.template">
|
||||||
|
<field name="name">Final Inspection / Packaging</field>
|
||||||
|
<field name="code">FINAL_PKG_STD</field>
|
||||||
|
<field name="kind_id" ref="step_kind_final_inspect"/>
|
||||||
|
<field name="icon">fa-check-circle</field>
|
||||||
|
<field name="description"><![CDATA[
|
||||||
|
<p>Combined final visual + dimensional inspection followed by
|
||||||
|
packaging into the customer's original boxes for shipment.
|
||||||
|
Verify part count, attach certs, photo the sealed load.</p>
|
||||||
|
]]></field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2026 Nexa Systems Inc.
|
||||||
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||||
|
"""19.0.21.2.0 — Shop Floor live-step + kind taxonomy.
|
||||||
|
|
||||||
|
Seeds fp.step.kind.area_kind on existing kinds BEFORE the required
|
||||||
|
NOT NULL constraint on the new field hits the schema. Also activates
|
||||||
|
the three kinds (derack/demask/gating) that were deactivated in
|
||||||
|
19.0.20.6.0 but are needed for the full area_kind taxonomy.
|
||||||
|
|
||||||
|
Idempotent: only fills NULL / inactive rows.
|
||||||
|
|
||||||
|
See docs/superpowers/specs/2026-05-24-shopfloor-live-step-fix-design.md.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
KIND_TO_AREA = {
|
||||||
|
'other': 'plating',
|
||||||
|
'wet_process': 'plating',
|
||||||
|
'receiving': 'receiving',
|
||||||
|
'contract_review': 'receiving',
|
||||||
|
'gating': 'receiving',
|
||||||
|
'racking': 'racking',
|
||||||
|
'derack': 'de_racking',
|
||||||
|
'mask': 'masking',
|
||||||
|
'demask': 'de_racking',
|
||||||
|
'cleaning': 'plating',
|
||||||
|
'electroclean': 'plating',
|
||||||
|
'etch': 'plating',
|
||||||
|
'rinse': 'plating',
|
||||||
|
'strike': 'plating',
|
||||||
|
'plate': 'plating',
|
||||||
|
'replenishment': 'plating',
|
||||||
|
'wbf_test': 'plating',
|
||||||
|
'dry': 'plating',
|
||||||
|
'bake': 'baking',
|
||||||
|
'inspect': 'inspection',
|
||||||
|
'final_inspect': 'inspection',
|
||||||
|
'hardness_test': 'inspection',
|
||||||
|
'adhesion_test': 'inspection',
|
||||||
|
'salt_spray': 'inspection',
|
||||||
|
'packaging': 'shipping',
|
||||||
|
'ship': 'shipping',
|
||||||
|
'blast': 'blasting',
|
||||||
|
'bead_blast': 'blasting',
|
||||||
|
'media_blast': 'blasting',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
# Phase 1 — Pre-create the column NULL-permitting so we can seed it
|
||||||
|
# BEFORE Odoo's schema sync tries to enforce NOT NULL.
|
||||||
|
cr.execute(
|
||||||
|
"ALTER TABLE fp_step_kind "
|
||||||
|
"ADD COLUMN IF NOT EXISTS area_kind VARCHAR"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Phase 2 — Seed area_kind on existing kinds. Idempotent: only fills
|
||||||
|
# NULLs, so re-running -u is safe.
|
||||||
|
seeded = 0
|
||||||
|
for code, area in KIND_TO_AREA.items():
|
||||||
|
cr.execute(
|
||||||
|
"UPDATE fp_step_kind SET area_kind = %s "
|
||||||
|
"WHERE code = %s "
|
||||||
|
"AND (area_kind IS NULL OR area_kind = '')",
|
||||||
|
(area, code),
|
||||||
|
)
|
||||||
|
seeded += cr.rowcount
|
||||||
|
_logger.info(
|
||||||
|
'[live-step-fix] kind.area_kind seeded on %s known-code rows',
|
||||||
|
seeded,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Phase 3 — Fallback: any user-created custom kinds not in our seed
|
||||||
|
# map → 'plating'. Clears the NOT NULL constraint for any leftover.
|
||||||
|
cr.execute(
|
||||||
|
"UPDATE fp_step_kind SET area_kind = 'plating' "
|
||||||
|
"WHERE area_kind IS NULL OR area_kind = ''"
|
||||||
|
)
|
||||||
|
if cr.rowcount:
|
||||||
|
_logger.info(
|
||||||
|
'[live-step-fix] %s unknown kinds defaulted to plating',
|
||||||
|
cr.rowcount,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Phase 4 — Activate kinds we need for full coverage.
|
||||||
|
activated = 0
|
||||||
|
for code in ('derack', 'demask', 'gating'):
|
||||||
|
cr.execute(
|
||||||
|
"UPDATE fp_step_kind SET active = TRUE "
|
||||||
|
"WHERE code = %s AND active = FALSE",
|
||||||
|
(code,),
|
||||||
|
)
|
||||||
|
activated += cr.rowcount
|
||||||
|
_logger.info(
|
||||||
|
'[live-step-fix] %s kinds activated (derack/demask/gating)',
|
||||||
|
activated,
|
||||||
|
)
|
||||||
@@ -34,6 +34,32 @@ class FpStepKind(models.Model):
|
|||||||
string='Icon',
|
string='Icon',
|
||||||
default='fa-cog',
|
default='fa-cog',
|
||||||
)
|
)
|
||||||
|
# 2026-05-24 — Shop Floor live-step fix.
|
||||||
|
# Each kind self-declares which plant-view column its steps land in.
|
||||||
|
# Replaces the hardcoded _STEP_KIND_TO_AREA dict (removed from
|
||||||
|
# fusion_plating_jobs/models/fp_job_step.py). Pre-migrate
|
||||||
|
# 19.0.21.2.0 seeds existing rows before NOT NULL hits the schema.
|
||||||
|
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='Shop Floor Column',
|
||||||
|
required=True,
|
||||||
|
index=True,
|
||||||
|
tracking=True,
|
||||||
|
help='Determines which column on the Shop Floor plant kanban shows '
|
||||||
|
'cards whose active step uses this kind. Step kinds drive '
|
||||||
|
'routing automatically — picking a kind tells the system both '
|
||||||
|
'what gates fire AND where the card lives.',
|
||||||
|
)
|
||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
'res.company', string='Company',
|
'res.company', string='Company',
|
||||||
default=lambda self: self.env.company,
|
default=lambda self: self.env.company,
|
||||||
|
|||||||
@@ -509,6 +509,7 @@
|
|||||||
<t t-foreach="state.kindOptions || []" t-as="k" t-key="k.id">
|
<t t-foreach="state.kindOptions || []" t-as="k" t-key="k.id">
|
||||||
<option t-att-value="k.code" t-att-selected="k.code === state.libraryEditor.default_kind">
|
<option t-att-value="k.code" t-att-selected="k.code === state.libraryEditor.default_kind">
|
||||||
<t t-esc="k.name"/>
|
<t t-esc="k.name"/>
|
||||||
|
<t t-if="k.area_kind_label"> — <t t-esc="k.area_kind_label"/> column</t>
|
||||||
</option>
|
</option>
|
||||||
</t>
|
</t>
|
||||||
<!-- Manager-only inline create. The
|
<!-- Manager-only inline create. The
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
|
<field name="area_kind" decoration-info="True"/>
|
||||||
<field name="icon"/>
|
<field name="icon"/>
|
||||||
<field name="template_count"/>
|
<field name="template_count"/>
|
||||||
<field name="active" widget="boolean_toggle"/>
|
<field name="active" widget="boolean_toggle"/>
|
||||||
@@ -47,6 +48,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
|
<field name="area_kind" widget="badge"
|
||||||
|
help="Cards whose active step uses this kind appear in this column on the Shop Floor plant kanban."/>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="company_id"
|
<field name="company_id"
|
||||||
groups="base.group_multi_company"/>
|
groups="base.group_multi_company"/>
|
||||||
@@ -94,8 +97,13 @@
|
|||||||
<search>
|
<search>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
|
<field name="area_kind"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||||
|
<group>
|
||||||
|
<filter string="Shop Floor Column" name="group_area_kind"
|
||||||
|
context="{'group_by': 'area_kind'}"/>
|
||||||
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
Reference in New Issue
Block a user