changes
This commit is contained in:
@@ -199,6 +199,41 @@ class FpProcessNode(models.Model):
|
||||
tracking=True,
|
||||
)
|
||||
|
||||
# ---- Recipe-only fields (apply when node_type='recipe') -----------------
|
||||
# These migrate Steelhead's recipe-level metadata: lead time, the
|
||||
# product/service tied to this recipe, the contract review approver
|
||||
# roster, and the pricing builders to apply when this recipe is on
|
||||
# a quote. They're loose-coupled to keep non-recipe nodes clean.
|
||||
|
||||
default_lead_time = fields.Float(
|
||||
string='Default Lead Time (days)',
|
||||
digits=(8, 2),
|
||||
help='When an MO is created using this recipe, '
|
||||
'date_planned_finished is set to NOW + lead_time.',
|
||||
tracking=True,
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Service / Product',
|
||||
ondelete='set null',
|
||||
help='The plating service product this recipe sells. When the '
|
||||
'product appears on a sale order, the resulting MO can '
|
||||
'auto-pick this recipe.',
|
||||
tracking=True,
|
||||
)
|
||||
contract_review_user_ids = fields.Many2many(
|
||||
'res.users',
|
||||
relation='fp_process_node_contract_review_user_rel',
|
||||
column1='node_id',
|
||||
column2='user_id',
|
||||
string='Contract Review Approvers',
|
||||
help='Users authorised to sign off the Contract Review work order '
|
||||
'on jobs running this recipe. Anyone outside this list will '
|
||||
'be blocked from finishing the WO.',
|
||||
)
|
||||
# NB. `pricing_rule_ids` lives in fusion_plating_configurator
|
||||
# (added there so this core module doesn't depend on the configurator).
|
||||
|
||||
# ---- Computed fields -----------------------------------------------------
|
||||
|
||||
display_name = fields.Char(
|
||||
@@ -270,6 +305,73 @@ class FpProcessNode(models.Model):
|
||||
raise ValidationError(
|
||||
_('A process node cannot be its own ancestor.'))
|
||||
|
||||
# ---- Version auto-bump ---------------------------------------------------
|
||||
# Any meaningful edit / add / delete inside a recipe bumps the recipe
|
||||
# root's `version` field by one. Lets shop managers see at a glance
|
||||
# how stable a recipe is and (later) lets a job pin to a specific
|
||||
# recipe revision so already-running MOs don't see mid-flight changes.
|
||||
|
||||
# Fields that don't represent a "meaningful" change — adjusting these
|
||||
# alone does not bump the version. `version` itself is in the list to
|
||||
# avoid an infinite write loop.
|
||||
_FP_NON_VERSIONED_FIELDS = {
|
||||
'version', 'write_date', 'write_uid',
|
||||
'create_date', 'create_uid',
|
||||
'parent_path', 'display_name', 'recipe_root_id', 'depth',
|
||||
}
|
||||
|
||||
def _fp_bump_recipe_versions(self):
|
||||
"""Increment `version` by 1 on the distinct recipe roots covering
|
||||
the current recordset."""
|
||||
roots = self.mapped('recipe_root_id')
|
||||
# _compute_recipe_root_id falls back to self for nodes whose
|
||||
# parent_path isn't yet stored — pick those up too.
|
||||
for rec in self:
|
||||
if not rec.recipe_root_id and rec.node_type == 'recipe':
|
||||
roots |= rec
|
||||
if not roots:
|
||||
return
|
||||
# Use a direct SQL update so we (a) skip our own write override
|
||||
# and (b) avoid touching write_date / write_uid on the root,
|
||||
# which would itself be a no-op-but-noisy chatter event.
|
||||
self.env.cr.execute(
|
||||
'UPDATE fusion_plating_process_node '
|
||||
'SET version = COALESCE(version, 0) + 1 '
|
||||
'WHERE id IN %s',
|
||||
(tuple(roots.ids),),
|
||||
)
|
||||
roots.invalidate_recordset(['version'])
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
records = super().create(vals_list)
|
||||
# Skip non-recipe roots — only count when the new node lives
|
||||
# inside an existing recipe.
|
||||
descendants = records.filtered(lambda r: r.node_type != 'recipe')
|
||||
if descendants:
|
||||
descendants._fp_bump_recipe_versions()
|
||||
return records
|
||||
|
||||
def write(self, vals):
|
||||
meaningful = bool(set(vals.keys()) - self._FP_NON_VERSIONED_FIELDS)
|
||||
res = super().write(vals)
|
||||
if meaningful and self:
|
||||
self._fp_bump_recipe_versions()
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
# Snapshot the affected recipe roots BEFORE delete, otherwise
|
||||
# recipe_root_id becomes unreachable on the deleted records.
|
||||
roots = self.mapped('recipe_root_id')
|
||||
descendants = self.filtered(lambda r: r.node_type != 'recipe')
|
||||
# Delete first so we don't bump the version of a recipe that's
|
||||
# being removed entirely.
|
||||
res = super().unlink()
|
||||
survivors = roots.exists()
|
||||
if descendants and survivors:
|
||||
survivors._fp_bump_recipe_versions()
|
||||
return res
|
||||
|
||||
# ---- Tree data for OWL component -----------------------------------------
|
||||
|
||||
def get_tree_data(self):
|
||||
|
||||
Reference in New Issue
Block a user