diff --git a/fusion_plating/fusion_plating_jobs/__manifest__.py b/fusion_plating/fusion_plating_jobs/__manifest__.py index 706d5e31..6bfee105 100644 --- a/fusion_plating/fusion_plating_jobs/__manifest__.py +++ b/fusion_plating/fusion_plating_jobs/__manifest__.py @@ -3,7 +3,7 @@ # License OPL-1 (Odoo Proprietary License v1.0) { 'name': 'Fusion Plating — Native Jobs', - 'version': '19.0.9.0.0', + 'version': '19.0.9.1.0', 'category': 'Manufacturing/Plating', 'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.', 'author': 'Nexa Systems Inc.', diff --git a/fusion_plating/fusion_plating_jobs/report/report_fp_job_sticker.xml b/fusion_plating/fusion_plating_jobs/report/report_fp_job_sticker.xml index c60de5a4..cb5b6e4a 100644 --- a/fusion_plating/fusion_plating_jobs/report/report_fp_job_sticker.xml +++ b/fusion_plating/fusion_plating_jobs/report/report_fp_job_sticker.xml @@ -57,6 +57,7 @@ + @@ -99,6 +100,7 @@ + diff --git a/fusion_plating/fusion_plating_jobs/report/report_fp_job_traveller.xml b/fusion_plating/fusion_plating_jobs/report/report_fp_job_traveller.xml index 8b65f561..35217114 100644 --- a/fusion_plating/fusion_plating_jobs/report/report_fp_job_traveller.xml +++ b/fusion_plating/fusion_plating_jobs/report/report_fp_job_traveller.xml @@ -200,7 +200,10 @@ - + + + + diff --git a/fusion_plating/fusion_plating_quality/__manifest__.py b/fusion_plating/fusion_plating_quality/__manifest__.py index b48547d6..2987e8f3 100644 --- a/fusion_plating/fusion_plating_quality/__manifest__.py +++ b/fusion_plating/fusion_plating_quality/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Quality (QMS)', - 'version': '19.0.5.2.0', + 'version': '19.0.5.3.0', 'category': 'Manufacturing/Plating', 'summary': 'Native QMS for plating shops: NCR, CAPA, calibration, AVL, FAIR, ' 'internal audits, customer specs, document control. CE + EE compatible.', diff --git a/fusion_plating/fusion_plating_quality/models/sale_order_line_inherit.py b/fusion_plating/fusion_plating_quality/models/sale_order_line_inherit.py index fa23da5c..3bf57007 100644 --- a/fusion_plating/fusion_plating_quality/models/sale_order_line_inherit.py +++ b/fusion_plating/fusion_plating_quality/models/sale_order_line_inherit.py @@ -6,6 +6,29 @@ from odoo import api, fields, models +class SaleOrder(models.Model): + """Add an order-level Specification mirror so reports can print it + in the header summary section. Computed from the lines (first + spec wins; falls back to blank when lines have no spec). + """ + _inherit = 'sale.order' + + x_fc_customer_spec_id = fields.Many2one( + 'fusion.plating.customer.spec', + string='Specification', + compute='_compute_x_fc_customer_spec_id', + store=True, + help='First specification cited on this order (or blank). ' + 'Drives the order-level header in customer-facing PDFs.', + ) + + @api.depends('order_line.x_fc_customer_spec_id') + def _compute_x_fc_customer_spec_id(self): + for so in self: + specs = so.order_line.mapped('x_fc_customer_spec_id') + so.x_fc_customer_spec_id = specs[:1] if specs else False + + class SaleOrderLine(models.Model): """Add the Specification picker to the SO line. diff --git a/fusion_plating/fusion_plating_reports/__manifest__.py b/fusion_plating/fusion_plating_reports/__manifest__.py index ee749e06..62f482af 100644 --- a/fusion_plating/fusion_plating_reports/__manifest__.py +++ b/fusion_plating/fusion_plating_reports/__manifest__.py @@ -3,7 +3,7 @@ # License OPL-1 (Odoo Proprietary License v1.0) { 'name': 'Fusion Plating — Reports', - 'version': '19.0.10.16.0', + 'version': '19.0.11.0.0', 'category': 'Manufacturing/Plating', 'summary': 'PDF reports for Fusion Plating: quote, SO, WO, packing, BoL, CoC, invoice, receipt, quality + compliance.', 'depends': [ diff --git a/fusion_plating/fusion_plating_reports/report/report_fp_job_traveller.xml b/fusion_plating/fusion_plating_reports/report/report_fp_job_traveller.xml index dc8c81d5..629463a1 100644 --- a/fusion_plating/fusion_plating_reports/report/report_fp_job_traveller.xml +++ b/fusion_plating/fusion_plating_reports/report/report_fp_job_traveller.xml @@ -110,9 +110,12 @@ - Coating Config + Specification - + + + + diff --git a/fusion_plating/fusion_plating_reports/report/report_fp_sale.xml b/fusion_plating/fusion_plating_reports/report/report_fp_sale.xml index 5da32a0c..e79f5582 100644 --- a/fusion_plating/fusion_plating_reports/report/report_fp_sale.xml +++ b/fusion_plating/fusion_plating_reports/report/report_fp_sale.xml @@ -75,19 +75,19 @@ - + - + - +
PARTCOATING CONFIGSPECIFICATION DELIVERY METHOD
@@ -340,12 +340,12 @@
- + - + @@ -353,7 +353,7 @@ - +
PART CATALOGCOATING CONFIGURATIONSPECIFICATION INVOICE STRATEGY DEPOSIT %
diff --git a/fusion_plating/fusion_plating_reports/report/report_fp_wo_sticker.xml b/fusion_plating/fusion_plating_reports/report/report_fp_wo_sticker.xml index ec497d9f..515fe6e7 100644 --- a/fusion_plating/fusion_plating_reports/report/report_fp_wo_sticker.xml +++ b/fusion_plating/fusion_plating_reports/report/report_fp_wo_sticker.xml @@ -19,7 +19,8 @@ * _mo — the mrp.production record (or False) * _so, _line — the originating sale order / line * _part — fp.part.catalog - * _coating — fp.coating.config + * _coating — fp.coating.config (legacy; removed in Phase E) + * _spec — fusion.plating.customer.spec (the audit-tracked spec the cert prints) * _process — the resolved fusion.plating.process.node tree * _due — datetime/date for "Due Date" row * _qty — float for "Qty" row @@ -48,6 +49,7 @@ or False"/> + + @@ -499,6 +502,7 @@ + diff --git a/fusion_plating/fusion_plating_shopfloor/__manifest__.py b/fusion_plating/fusion_plating_shopfloor/__manifest__.py index 4f9f596a..8ce35aa9 100644 --- a/fusion_plating/fusion_plating_shopfloor/__manifest__.py +++ b/fusion_plating/fusion_plating_shopfloor/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Shop Floor', - 'version': '19.0.25.2.1', + 'version': '19.0.26.0.0', 'category': 'Manufacturing/Plating', 'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, ' 'first-piece inspection gates.', diff --git a/fusion_plating/fusion_plating_shopfloor/controllers/shopfloor_controller.py b/fusion_plating/fusion_plating_shopfloor/controllers/shopfloor_controller.py index a2921465..1111c721 100644 --- a/fusion_plating/fusion_plating_shopfloor/controllers/shopfloor_controller.py +++ b/fusion_plating/fusion_plating_shopfloor/controllers/shopfloor_controller.py @@ -1137,11 +1137,16 @@ class FpShopfloorController(http.Controller): # Now we walk each unique job once and stash the answers. unique_jobs = steps.mapped('job_id') # Prefetch the fields we'll touch (saves N+1 SQL fetches) - unique_jobs.read([ + # customer_spec_id present when fusion_plating_quality is installed + # (added there as an inherit on fp.job). + job_read_fields = [ 'name', 'origin', 'priority', 'partner_id', 'product_id', 'qty', 'qty_done', 'date_planned_start', 'date_deadline', 'part_catalog_id', 'coating_config_id', - ]) + ] + if 'customer_spec_id' in unique_jobs._fields: + job_read_fields.append('customer_spec_id') + unique_jobs.read(job_read_fields) step_idx_by_id = {} # step_id → 1-based ordinal in its job job_step_count_by_id = {} # job_id → total step count queued_start_by_step_id = {} # step_id → predecessor's date_finished @@ -1554,6 +1559,12 @@ class FpShopfloorController(http.Controller): job.coating_config_id if 'coating_config_id' in job._fields else False ) + # Specification (added by fusion_plating_quality) + spec = ( + job.customer_spec_id + if 'customer_spec_id' in job._fields else False + ) + spec_label = (spec.display_name if spec else '') or '' part_number = '' part_revision = '' if part: @@ -1622,6 +1633,7 @@ class FpShopfloorController(http.Controller): 'part_number': part_number, 'part_revision': part_revision, 'coating_label': coating_label, + 'spec_label': spec_label, # ISO deadline for sort tiebreaker (v19.0.24.8.0) 'date_deadline_iso': ( _flds.Datetime.to_string(job.date_deadline)