diff --git a/fusion_plating/fusion_plating_portal/controllers/portal.py b/fusion_plating/fusion_plating_portal/controllers/portal.py index bb9ba9b5..5e257c25 100644 --- a/fusion_plating/fusion_plating_portal/controllers/portal.py +++ b/fusion_plating/fusion_plating_portal/controllers/portal.py @@ -220,9 +220,13 @@ class FpCustomerPortal(CustomerPortal): Returns a list of 4 dicts: {key, label, docs}, where docs is a list of {label, sub, url, icon_class, icon, pending}. """ + # 5 fixed groups in display order. Indices used in the appends below + # โ€” if you reorder, update every groups[N] reference. + # 0 = from_you, 1 = specs, 2 = work_order, 3 = quality, 4 = shipping groups = [ {'key': 'from_you', 'label': 'From You', 'docs': []}, {'key': 'specs', 'label': 'Specifications', 'docs': []}, + {'key': 'work_order', 'label': 'Work Order', 'docs': []}, {'key': 'quality', 'label': 'Quality', 'docs': []}, {'key': 'shipping', 'label': 'Shipping', 'docs': []}, ] @@ -277,29 +281,7 @@ class FpCustomerPortal(CustomerPortal): 'icon': '๐Ÿ“„', }) - # WORK ORDER DETAIL โ€” separate group between specs and quality. - # Pulls the EN Plating WO Detail PDF (fusion_plating_jobs report). - # Requires a linked backend fp.job; placeholder otherwise. - wo_group = {'key': 'work_order', 'label': 'Work Order', 'docs': []} - if backend_job: - wo_group['docs'].append({ - 'label': 'Work Order Detail ยท %s' % job.name, - 'sub': 'EN Plating ยท process scope + recipe summary', - 'url': '/my/jobs/%s/wo_detail' % job.id, - 'icon_class': 'o_fp_doc_icon_spec', - 'icon': '๐Ÿ› ', - }) - else: - wo_group['docs'].append({ - 'label': 'Work Order Detail', - 'sub': 'Will appear once production is confirmed', - 'pending': True, - 'icon': '๐Ÿ› ', - }) - # Insert WO Detail group between Specifications (idx 1) and Quality (idx 2). - groups.insert(2, wo_group) - - # SPECIFICATIONS โ€” V1: placeholder (V2 will pull customer spec) + # SPECIFICATIONS (idx 1) โ€” V1: placeholder (V2 will pull customer spec) groups[1]['docs'].append({ 'label': 'Customer Specification', 'sub': 'Will appear when EN Plating links the spec', @@ -307,9 +289,28 @@ class FpCustomerPortal(CustomerPortal): 'icon': '๐Ÿ“‹', }) - # QUALITY โ€” CoC from coc_attachment_id (the legacy direct field) - if job.coc_attachment_id: + # WORK ORDER (idx 2) โ€” EN Plating WO Detail PDF via + # fusion_plating_jobs.report_fp_job_wo_detail_template. Requires a + # linked backend fp.job; placeholder otherwise. + if backend_job: groups[2]['docs'].append({ + 'label': 'Work Order Detail ยท %s' % job.name, + 'sub': 'EN Plating ยท process scope + recipe summary', + 'url': '/my/jobs/%s/wo_detail' % job.id, + 'icon_class': 'o_fp_doc_icon_spec', + 'icon': '๐Ÿ› ', + }) + else: + groups[2]['docs'].append({ + 'label': 'Work Order Detail', + 'sub': 'Will appear once production is confirmed', + 'pending': True, + 'icon': '๐Ÿ› ', + }) + + # QUALITY (idx 3) โ€” CoC from coc_attachment_id (the legacy direct field) + if job.coc_attachment_id: + groups[3]['docs'].append({ 'label': 'Certificate of Conformance', 'sub': 'EN Plating ยท %s ยท %s' % ( job.actual_ship_date and job.actual_ship_date.strftime('%b %d') or '', @@ -320,16 +321,16 @@ class FpCustomerPortal(CustomerPortal): 'icon': '๐Ÿ“‘', }) else: - groups[2]['docs'].append({ + groups[3]['docs'].append({ 'label': 'Certificate of Conformance', 'sub': 'Will appear after QC completes', 'pending': True, 'icon': '๐Ÿ“‘', }) - # SHIPPING โ€” packing list + tracking + # SHIPPING (idx 4) โ€” packing list + tracking if job.packing_list_attachment_id: - groups[3]['docs'].append({ + groups[4]['docs'].append({ 'label': 'Packing Slip', 'sub': 'EN Plating ยท %s ยท %s' % ( job.actual_ship_date and job.actual_ship_date.strftime('%b %d') or '', @@ -340,7 +341,7 @@ class FpCustomerPortal(CustomerPortal): 'icon': '๐Ÿ“ฆ', }) else: - groups[3]['docs'].append({ + groups[4]['docs'].append({ 'label': 'Packing Slip ยท Tracking #', 'sub': 'Available when shipped' + (' โ€” ' + job.tracking_ref if job.tracking_ref else ''), 'pending': not job.tracking_ref, diff --git a/fusion_plating/fusion_plating_portal/tests/test_portal_dashboard.py b/fusion_plating/fusion_plating_portal/tests/test_portal_dashboard.py index 275b6bc1..738efecb 100644 --- a/fusion_plating/fusion_plating_portal/tests/test_portal_dashboard.py +++ b/fusion_plating/fusion_plating_portal/tests/test_portal_dashboard.py @@ -117,8 +117,9 @@ class TestPortalDashboard(TransactionCase): statuses = [t['status'] for t in timeline] self.assertEqual(statuses, ['done', 'done', 'done', 'done', 'done']) - def test_group_documents_v1_returns_4_groups(self): - """V1 doc grouping returns 4 groups; quality populated when CoC set.""" + def test_group_documents_returns_5_groups(self): + """V1 doc grouping returns 5 groups: From You / Specs / Work Order / + Quality / Shipping. Quality populated when CoC set.""" from odoo.addons.fusion_plating_portal.controllers.portal import FpCustomerPortal Job = self.env['fusion.plating.portal.job'] att = self.env['ir.attachment'].create({ @@ -133,13 +134,16 @@ class TestPortalDashboard(TransactionCase): 'coc_attachment_id': att.id, }) groups = FpCustomerPortal()._fp_group_documents(job) - self.assertEqual(len(groups), 4) + self.assertEqual(len(groups), 5) keys = [g['key'] for g in groups] - self.assertEqual(keys, ['from_you', 'specs', 'quality', 'shipping']) + self.assertEqual(keys, ['from_you', 'specs', 'work_order', 'quality', 'shipping']) # Quality group has the CoC populated (not pending) quality = next(g for g in groups if g['key'] == 'quality') self.assertTrue(any(d['label'] == 'Certificate of Conformance' and not d.get('pending') for d in quality['docs'])) - # From You + Specifications are placeholders in V1 + # From You is a placeholder when no SO link (test job has no x_fc_job_id) from_you = next(g for g in groups if g['key'] == 'from_you') self.assertTrue(all(d.get('pending') for d in from_you['docs'])) + # Work Order is placeholder without a backend fp.job link + wo = next(g for g in groups if g['key'] == 'work_order') + self.assertTrue(all(d.get('pending') for d in wo['docs']))