feat(jobs): add core-safe extension fields to fp.job

Scope was reduced from spec's full §5.1 list because 6 of the 10
plating-specific fields point to models in dependent modules
(configurator, quality, portal, logistics, bridge_mrp). Adding
those Many2ones in core would invert the dependency graph. They
move to their owning modules via _inherit = 'fp.job' and get
re-bundled by fusion_plating_jobs in Phase 2.

This commit lands the core-safe subset:
- sale_order_line_ids (sale_management is in core depends)
- recipe_id, start_at_node_id (process.node is in core)
- invoice_ids (account is reachable via sale_management → sale)
- Cost rollup: quoted_revenue / actual_cost / margin / margin_pct
  with placeholder compute (actual_cost = 0 until Task 1.5 wires
  fp.job.step.cost_total)
- current_location stub (full Bath/Oven rendering in Task 1.6)

Tests cover the cost-rollup math and the current_location stub.
Spec §5.1 has been re-tabulated with explicit 'Module' column.

Manifest 19.0.8.2.1 → 19.0.8.3.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 21:44:28 -04:00
parent b45a134aa4
commit 335dc2488e
3 changed files with 116 additions and 1 deletions

View File

@@ -62,3 +62,27 @@ class TestFpJobStateMachine(TransactionCase):
job.action_cancel()
with self.assertRaises(UserError):
job.action_cancel()
def test_current_location_for_draft(self):
job = self._make_job()
self.assertEqual(job.current_location, 'Not started')
def test_current_location_for_done(self):
job = self._make_job()
# Force state to 'done' (no public action yet)
job.state = 'done'
# Recompute — Odoo's compute is auto on read
self.assertEqual(job.current_location, 'Done')
def test_margin_zero_when_no_revenue(self):
job = self._make_job()
self.assertEqual(job.actual_cost, 0.0)
self.assertEqual(job.margin, 0.0)
self.assertEqual(job.margin_pct, 0.0)
def test_margin_with_revenue(self):
job = self._make_job(quoted_revenue=1000.0)
self.assertEqual(job.quoted_revenue, 1000.0)
self.assertEqual(job.actual_cost, 0.0)
self.assertEqual(job.margin, 1000.0)
self.assertEqual(job.margin_pct, 100.0)