feat(jobs): Phase 5 — fp.job reports (sticker + traveller)

Two parallel report definitions for the native job model:

1. Job Sticker (6x4 inch custom paperformat) bound to fp.job. Prints
   WH/JOB/... ID, customer, SO, qty, due date, recipe, step
   progress. QR encodes /fp/job/<id> for scan-to-job navigation.

2. Job Traveller bound to fp.job, A4 portrait. Job header + all
   fp.job.step rows in sequence order with operator sign-off
   column.

Coexists with fusion_plating_reports' MO/WO bindings — both print
menus stay live during migration.

Deferred reports (use existing during migration; rebind at cutover):
- BoL, Packing Slip, Invoice (read from SO, no fp.job change needed)
- WO Margin (cost rollup; rebuild against fp.job.step.cost_total
  in phase-end polish)

Adds fusion_plating_reports to fusion_plating_jobs depends.

Tests deferred to post-Tailscale-restore: 3 new tests verify
report actions are registered + sticker template renders without
QWeb errors. Module file content verified locally as
well-formed XML.

Manifest 19.0.1.7.0 → 19.0.1.8.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-25 00:05:48 -04:00
parent 51a5cbbe5d
commit c528d581c2
6 changed files with 225 additions and 1 deletions

View File

@@ -503,3 +503,32 @@ class TestPhase4Refactors(TransactionCase):
})
job.action_confirm() # Should not raise even with no templates
self.assertEqual(job.state, 'confirmed')
class TestReports(TransactionCase):
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_sticker_report_action_exists(self):
action = self.env.ref('fusion_plating_jobs.action_report_fp_job_sticker', raise_if_not_found=False)
self.assertTrue(action)
self.assertEqual(action.model, 'fp.job')
def test_traveller_report_action_exists(self):
action = self.env.ref('fusion_plating_jobs.action_report_fp_job_traveller', raise_if_not_found=False)
self.assertTrue(action)
self.assertEqual(action.model, 'fp.job')
def test_sticker_renders_for_a_job(self):
# Smoke test: the QWeb template should render without error.
job = self.env['fp.job'].create({
'partner_id': self.partner.id,
'product_id': self.product.id,
'qty': 1.0,
})
report = self.env.ref('fusion_plating_jobs.action_report_fp_job_sticker')
# Render HTML (faster than PDF; doesn't need wkhtmltopdf)
html, _ = report._render_qweb_html(report.report_name, job.ids)
self.assertIn(job.name, html.decode() if isinstance(html, bytes) else html)