feat(promote-customer-spec): NADCAP recipe lock (Phase A+)
Per client review: NADCAP-qualified recipes need manager-only edit permission. Word-doc external approval workflow stays outside ERP; this is the in-app enforcement. - New field fp.process.node.is_locked (recipe root) - write() override blocks non-manager edits when recipe root is_locked Lock checks via recipe_root_id so child ops/steps are also protected Manager bypass via group + env.su (sudo) bypass for system jobs - Amber "LOCKED — Manager Edit Only" ribbon at top of recipe form - Toggle on Specification & Bake page under "Change Control (NADCAP)" - Spec doc updated with Decision 6.5 + backlog from client review: approvals list, doc control auto-sync, oven recorder sync, SOP word-doc workflow, final-inspection signoff on cert Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating',
|
||||
'version': '19.0.19.0.0',
|
||||
'version': '19.0.19.1.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.',
|
||||
'description': """
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Part of the Fusion Plating product family.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
from .fp_tz import fp_isoformat_utc
|
||||
from ._fp_uom_selection import FP_UOM_SELECTION
|
||||
@@ -393,6 +393,20 @@ class FpProcessNode(models.Model):
|
||||
help='Minimum bake hold time at temperature. Typical 23h.',
|
||||
)
|
||||
|
||||
# ---- NADCAP / change-control lock (recipe root) ----
|
||||
# Per client direction: NADCAP-qualified recipes need manager-only
|
||||
# edit permission once they're checked into the system. The Word-doc
|
||||
# change-control workflow lives outside the ERP; this flag is the
|
||||
# ERP-side enforcement point.
|
||||
is_locked = fields.Boolean(
|
||||
string='Locked (Manager-Edit Only)',
|
||||
help='When True, only users in the Manager group can modify '
|
||||
'this recipe (or any of its child operations / steps). '
|
||||
'Use for NADCAP-qualified processes that need '
|
||||
'change-control sign-off before any edit. The flag itself '
|
||||
'can only be toggled by a manager.',
|
||||
)
|
||||
|
||||
# NB. `applicable_spec_ids` (reverse of customer.spec.recipe_ids) is
|
||||
# defined as an inherit in fusion_plating_quality (the module that
|
||||
# owns fusion.plating.customer.spec). Core can't reference it
|
||||
@@ -591,6 +605,22 @@ class FpProcessNode(models.Model):
|
||||
return records
|
||||
|
||||
def write(self, vals):
|
||||
# NADCAP / change-control lock — block writes on locked recipes
|
||||
# (and their descendants) for non-manager users. Manager bypass
|
||||
# so the lock can be toggled off.
|
||||
if (self
|
||||
and not self.env.su
|
||||
and not self.env.user.has_group(
|
||||
'fusion_plating.group_fusion_plating_manager')):
|
||||
for rec in self:
|
||||
root = (rec if (rec.node_type == 'recipe' and not rec.parent_id)
|
||||
else rec.recipe_root_id)
|
||||
if root and root.is_locked:
|
||||
raise UserError(_(
|
||||
"Recipe '%s' is locked (NADCAP / change-control). "
|
||||
"Only managers can edit it. Ask a manager to "
|
||||
"unlock the recipe first."
|
||||
) % (root.display_name or root.name or '?'))
|
||||
meaningful = bool(set(vals.keys()) - self._FP_NON_VERSIONED_FIELDS)
|
||||
res = super().write(vals)
|
||||
if meaningful and self:
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
icon="fa-list-ol"
|
||||
invisible="node_type != 'recipe'"/>
|
||||
</header>
|
||||
<widget name="web_ribbon" title="LOCKED — Manager Edit Only"
|
||||
bg_color="text-bg-warning"
|
||||
invisible="not is_locked"/>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_open_tree_editor" type="object"
|
||||
@@ -248,6 +251,10 @@
|
||||
invisible="not requires_bake_relief"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Change Control (NADCAP)">
|
||||
<field name="is_locked" widget="boolean_toggle"
|
||||
help="When ON, only managers can edit this recipe and its child operations / steps. Use for NADCAP-qualified processes."/>
|
||||
</group>
|
||||
<group string="Thickness Options">
|
||||
<field name="thickness_option_ids" nolabel="1">
|
||||
<list editable="bottom">
|
||||
|
||||
Reference in New Issue
Block a user