feat(jobs): add fp.job.node.override for per-job opt-in/out decisions

Mirror of fusion.plating.job.node.override from bridge_mrp, but
bound to fp.job. bridge_mrp's version stays alive for legacy MO
flow during the migration. Both coexist.

Adds override_ids One2many to fp.job via _inherit, plus
unique(job_id, node_id) constraint.

Note: spec-suggested _sql_constraints syntax is deprecated in
Odoo 19 ("Model attribute '_sql_constraints' is no longer
supported, please define model.Constraint on the model"). Used
the new class-attribute form: _unique_job_node = models.Constraint(...).
Verified the UNIQUE index is created on the table.

3 new tests: create, uniqueness, one2many backref.

Manifest 19.0.1.1.1 -> 19.0.1.2.0.

Part of: native job model migration (spec 2026-04-25)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-24 23:12:53 -04:00
parent 36b9f30528
commit 4c68327b9c
6 changed files with 107 additions and 1 deletions

View File

@@ -6,3 +6,4 @@
# task-by-task in Tasks 2.2 onwards.
from . import fp_job
from . import fp_job_node_override

View File

@@ -36,3 +36,8 @@ class FpJob(models.Model):
'fusion.plating.delivery',
string='Delivery',
)
override_ids = fields.One2many(
'fp.job.node.override',
'job_id',
string='Recipe Overrides',
)

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
#
# fp.job.node.override — per-job opt-in/out decisions for opt_in/opt_out
# recipe nodes. Mirrors fusion.plating.job.node.override from bridge_mrp,
# but bound to fp.job instead of mrp.production.
#
# bridge_mrp keeps its version alive so legacy MO-flow keeps working.
# Both coexist during the migration period.
from odoo import fields, models
class FpJobNodeOverride(models.Model):
_name = 'fp.job.node.override'
_description = 'Plating Job Recipe Node Override'
_order = 'job_id, node_id'
job_id = fields.Many2one(
'fp.job',
required=True,
ondelete='cascade',
index=True,
)
node_id = fields.Many2one(
'fusion.plating.process.node',
string='Recipe Node',
required=True,
domain="[('opt_in_out', 'in', ('opt_in', 'opt_out'))]",
)
included = fields.Boolean(
string='Included',
default=True,
help='When True, this opt-in/out node is included in step generation.',
)
_unique_job_node = models.Constraint(
'unique(job_id, node_id)',
'A job can only have one override per recipe node.',
)