feat(jobs): Phase 3 light refactors — parallel job/step links on dependent models

Adds x_fc_job_id / x_fc_step_id Many2ones via _inherit on:
- fusion.plating.batch (workorder_id stays for legacy MRP-bound batches)
- fusion.plating.quality.hold
- fp.certificate
- fp.thickness.reading
- fusion.plating.delivery (parallel to existing job_ref Char)
- fp.racking.inspection (parallel to existing production_id)

fp.job.action_confirm now also calls a best-effort racking-inspection
auto-create. The current fp.racking.inspection still has a required
production_id, so the helper skips cleanly when this job has no MO link
(pure-native mode). Phase 9 cutover flips the required FK to fp.job.

Strategy: parallel coexistence — bridge_mrp's existing fields stay
populated; this adds NEW fields populated by the native flow. Phase 9
cutover stops populating the old fields.

Adds fusion_plating_batch + fusion_plating_receiving to jobs module
depends.

Note: spec referenced fp.batch / fp.quality.hold; the actual models
in this codebase are fusion.plating.batch / fusion.plating.quality.hold
— used the real model names.

Manifest 19.0.1.5.0 → 19.0.1.6.0. 29 jobs tests pass.

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:34:05 -04:00
parent dd88afdf53
commit b359be3745
10 changed files with 265 additions and 4 deletions

View File

@@ -382,3 +382,83 @@ class TestJobLifecycleHooks(TransactionCase):
job.action_cancel()
with self.assertRaises(UserError):
job.button_mark_done()
class TestPhase3Refactors(TransactionCase):
"""Phase 3 — verify parallel job/step links exist on the dependent
modules' models. Field-presence is enough; the migration logic is
Phase 9's concern."""
def setUp(self):
super().setUp()
self.partner = self.env['res.partner'].create({'name': 'C'})
self.product = self.env['product.product'].create({'name': 'P'})
def test_fusion_plating_batch_has_x_fc_step_id(self):
self.assertIn('x_fc_step_id', self.env['fusion.plating.batch']._fields)
self.assertIn('x_fc_job_id', self.env['fusion.plating.batch']._fields)
# Verify comodels
self.assertEqual(
self.env['fusion.plating.batch']._fields['x_fc_step_id'].comodel_name,
'fp.job.step',
)
self.assertEqual(
self.env['fusion.plating.batch']._fields['x_fc_job_id'].comodel_name,
'fp.job',
)
def test_fusion_plating_quality_hold_has_x_fc_job_id(self):
self.assertIn(
'x_fc_job_id',
self.env['fusion.plating.quality.hold']._fields,
)
self.assertIn(
'x_fc_step_id',
self.env['fusion.plating.quality.hold']._fields,
)
def test_fp_certificate_has_x_fc_job_id(self):
self.assertIn('x_fc_job_id', self.env['fp.certificate']._fields)
self.assertEqual(
self.env['fp.certificate']._fields['x_fc_job_id'].comodel_name,
'fp.job',
)
def test_fp_thickness_reading_has_x_fc_job_id(self):
self.assertIn('x_fc_job_id', self.env['fp.thickness.reading']._fields)
self.assertIn('x_fc_step_id', self.env['fp.thickness.reading']._fields)
def test_fusion_plating_delivery_has_x_fc_job_id(self):
self.assertIn(
'x_fc_job_id',
self.env['fusion.plating.delivery']._fields,
)
self.assertEqual(
self.env['fusion.plating.delivery']._fields['x_fc_job_id'].comodel_name,
'fp.job',
)
def test_fp_racking_inspection_has_x_fc_job_id(self):
self.assertIn(
'x_fc_job_id',
self.env['fp.racking.inspection']._fields,
)
def test_racking_inspection_helper_skips_without_mo(self):
"""The auto-create helper should silently skip when the job
has no production_id (pure-native mode). Should NOT raise."""
job = self.env['fp.job'].create({
'partner_id': self.partner.id,
'product_id': self.product.id,
'qty': 1.0,
})
# action_confirm should run cleanly even though we cannot
# satisfy the model's required production_id today.
job.action_confirm()
# No exception is the assertion. No inspection should exist
# for this job since the helper skipped.
if 'x_fc_job_id' in self.env['fp.racking.inspection']._fields:
inspections = self.env['fp.racking.inspection'].search(
[('x_fc_job_id', '=', job.id)],
)
self.assertFalse(inspections)