From 15eac309ee3f44a05eabdd36c17e1d70e0c0d19c Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 12 May 2026 08:37:19 -0400 Subject: [PATCH] feat(jobs): persist deadlines + planned start + notes on fp.job Tier 2 of the SO->fp.job persistence audit. Four operational metadata fields mirrored from sale.order: - x_fc_internal_deadline (Date) - shop's internal target finish date, ahead of the customer-facing deadline. Kept separate from date_deadline (which scheduling code may adjust). - x_fc_planned_start_date (Date) - customer-quoted planned start date. Kept separate from date_planned_start (Datetime, capacity-adjusted). - x_fc_internal_note (Text) - shop-internal notes from the order. - x_fc_external_note (Text) - customer-facing notes, printed on traveller / BoL / cert. All four populate at SO confirm via _fp_auto_create_job, and surface on sale.order.line as stored related fields for per-line visibility. fp.job form view gets a Notes group alongside the Customer References group from Tier 1. Co-Authored-By: Claude Opus 4.7 (1M context) --- fusion_plating/fusion_plating/__manifest__.py | 2 +- .../fusion_plating/models/fp_job.py | 31 +++++++++++++++++++ .../fusion_plating/views/fp_job_views.xml | 6 ++++ .../__manifest__.py | 2 +- .../models/sale_order_line.py | 25 +++++++++++++++ .../fusion_plating_jobs/__manifest__.py | 2 +- .../fusion_plating_jobs/models/sale_order.py | 16 ++++++++++ 7 files changed, 81 insertions(+), 3 deletions(-) diff --git a/fusion_plating/fusion_plating/__manifest__.py b/fusion_plating/fusion_plating/__manifest__.py index 528320b8..73807f6e 100644 --- a/fusion_plating/fusion_plating/__manifest__.py +++ b/fusion_plating/fusion_plating/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating', - 'version': '19.0.18.15.6', + 'version': '19.0.18.15.7', 'category': 'Manufacturing/Plating', 'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.', 'description': """ diff --git a/fusion_plating/fusion_plating/models/fp_job.py b/fusion_plating/fusion_plating/models/fp_job.py index 9068bcc4..b81ddbc2 100644 --- a/fusion_plating/fusion_plating/models/fp_job.py +++ b/fusion_plating/fusion_plating/models/fp_job.py @@ -289,6 +289,37 @@ class FpJob(models.Model): 'job form to know it\'s rush.', ) + # ---- Scheduling targets mirrored from sale.order ----------------- + # These are kept separate from the operational date_planned_start / + # date_deadline fields (which may be tweaked by scheduling logic) — + # this preserves the ORIGINAL customer-facing dates entered on the SO. + x_fc_internal_deadline = fields.Date( + string='Internal Deadline', + tracking=True, + help='Shop\'s internal target finish date, copied from sale.order. ' + 'Buffer ahead of the customer-facing deadline.', + ) + x_fc_planned_start_date = fields.Date( + string='Planned Start (SO)', + tracking=True, + help='Customer-quoted planned start date copied from sale.order. ' + 'Different from date_planned_start (which scheduling logic ' + 'may adjust based on shop capacity).', + ) + + # ---- Operational notes mirrored from sale.order ------------------ + x_fc_internal_note = fields.Text( + string='Internal Note', + tracking=True, + help='Shop-internal notes from the order. Not shown to customer.', + ) + x_fc_external_note = fields.Text( + string='External Note', + tracking=True, + help='Customer-facing notes copied from the sale order. Printed ' + 'on traveller / BoL / cert.', + ) + qty_received = fields.Integer( string='Qty Received', help='Paper traveller "Qty Rec." column.', diff --git a/fusion_plating/fusion_plating/views/fp_job_views.xml b/fusion_plating/fusion_plating/views/fp_job_views.xml index 4d629a5e..ddc9633b 100644 --- a/fusion_plating/fusion_plating/views/fp_job_views.xml +++ b/fusion_plating/fusion_plating/views/fp_job_views.xml @@ -41,6 +41,12 @@ + + + + + + diff --git a/fusion_plating/fusion_plating_configurator/__manifest__.py b/fusion_plating/fusion_plating_configurator/__manifest__.py index f210ad14..67aa5e18 100644 --- a/fusion_plating/fusion_plating_configurator/__manifest__.py +++ b/fusion_plating/fusion_plating_configurator/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Configurator', - 'version': '19.0.18.10.0', + 'version': '19.0.18.10.1', 'category': 'Manufacturing/Plating', 'summary': 'Quotation configurator with part catalog, coating configs, and formula-based pricing engine.', 'description': """ diff --git a/fusion_plating/fusion_plating_configurator/models/sale_order_line.py b/fusion_plating/fusion_plating_configurator/models/sale_order_line.py index 0c6524da..f272fb10 100644 --- a/fusion_plating/fusion_plating_configurator/models/sale_order_line.py +++ b/fusion_plating/fusion_plating_configurator/models/sale_order_line.py @@ -659,3 +659,28 @@ class SaleOrderLine(models.Model): readonly=True, store=True, ) + + x_fc_internal_deadline = fields.Date( + related='order_id.x_fc_internal_deadline', + string='Internal Deadline', + readonly=True, + store=True, + ) + x_fc_planned_start_date = fields.Date( + related='order_id.x_fc_planned_start_date', + string='Planned Start', + readonly=True, + store=True, + ) + x_fc_internal_note = fields.Text( + related='order_id.x_fc_internal_note', + string='Internal Note', + readonly=True, + store=True, + ) + x_fc_external_note = fields.Text( + related='order_id.x_fc_external_note', + string='External Note', + readonly=True, + store=True, + ) diff --git a/fusion_plating/fusion_plating_jobs/__manifest__.py b/fusion_plating/fusion_plating_jobs/__manifest__.py index 9f964b22..0d7b7ab1 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.8.21.2', + 'version': '19.0.8.21.3', '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/models/sale_order.py b/fusion_plating/fusion_plating_jobs/models/sale_order.py index 4c04c59b..b249192c 100644 --- a/fusion_plating/fusion_plating_jobs/models/sale_order.py +++ b/fusion_plating/fusion_plating_jobs/models/sale_order.py @@ -332,6 +332,22 @@ class SaleOrder(models.Model): if 'x_fc_rush_order' in self._fields: vals['x_fc_rush_order'] = bool(self.x_fc_rush_order) + # Scheduling targets — mirror the SO's customer-facing dates. + if 'x_fc_internal_deadline' in self._fields \ + and self.x_fc_internal_deadline: + vals['x_fc_internal_deadline'] = self.x_fc_internal_deadline + if 'x_fc_planned_start_date' in self._fields \ + and self.x_fc_planned_start_date: + vals['x_fc_planned_start_date'] = self.x_fc_planned_start_date + + # Operational notes — mirror so the shop has them on the WO. + if 'x_fc_internal_note' in self._fields \ + and self.x_fc_internal_note: + vals['x_fc_internal_note'] = self.x_fc_internal_note + if 'x_fc_external_note' in self._fields \ + and self.x_fc_external_note: + vals['x_fc_external_note'] = self.x_fc_external_note + # Customer spec / facility / manager — copy from SO if present if 'x_fc_customer_spec_id' in self._fields and self.x_fc_customer_spec_id: vals['customer_spec_id'] = self.x_fc_customer_spec_id.id