From aec7659a2e6ec8661cf41bfc81f57a6ae38599f1 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Sun, 12 Apr 2026 18:43:02 -0400 Subject: [PATCH] =?UTF-8?q?fix(configurator):=20address=20code=20review=20?= =?UTF-8?q?findings=20=E2=80=94=20pricing=20engine=20+=20views?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix thickness factor: now scales linearly (thickness * factor), not multiplicatively. Default factor=1.0 means price scales 1:1 with mils. - Fix batch_size: setup fee now multiplied by ceil(qty/batch_size) batches - Fix hardcoded $ in price breakdown HTML: uses currency_id.symbol - Add coating_config_id.certification_level to @api.depends - Remove readonly on x_fc_receiving_status (placeholder until receiving module) - Add currency_id to treatment list view for Monetary widget Co-Authored-By: Claude Opus 4.6 (1M context) --- .../models/fp_quote_configurator.py | 56 +++++++++++-------- .../views/fp_treatment_views.xml | 1 + .../views/sale_order_views.xml | 2 +- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/fusion-plating/fusion_plating_configurator/models/fp_quote_configurator.py b/fusion-plating/fusion_plating_configurator/models/fp_quote_configurator.py index fe6c60ab..1a8ee8ab 100644 --- a/fusion-plating/fusion_plating_configurator/models/fp_quote_configurator.py +++ b/fusion-plating/fusion_plating_configurator/models/fp_quote_configurator.py @@ -3,6 +3,8 @@ # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Plating product family. +import math + from odoo import api, fields, models, _ from odoo.exceptions import UserError @@ -117,7 +119,7 @@ class FpQuoteConfigurator(models.Model): 'masking_zones', 'complexity', 'substrate_material', 'quantity', 'batch_size', 'rush_order', 'shipping_fee', 'delivery_fee', - 'coating_config_id', + 'coating_config_id', 'coating_config_id.certification_level', ) def _compute_price(self): for rec in self: @@ -143,10 +145,12 @@ class FpQuoteConfigurator(models.Model): else: # flat_rate unit_price = rule.base_rate - # --- Thickness factor --- + # --- Thickness scaling --- + # thickness_factor is a per-mil multiplier. A factor of 1.0 + # means linear scaling by thickness (e.g. 3 mils = 3x price). + # A factor of 0.8 gives a volume discount (3 mils = 2.4x). thickness = rec.thickness_requested or 1.0 - if rule.thickness_factor and rule.thickness_factor != 1.0: - unit_price *= rule.thickness_factor * thickness + unit_price *= thickness * rule.thickness_factor # --- Complexity surcharge --- surcharge_pct = 0 @@ -159,8 +163,13 @@ class FpQuoteConfigurator(models.Model): # --- Masking --- masking_cost = (rec.masking_zones or 0) * rule.masking_rate_per_zone - # --- Quantity --- - subtotal = (unit_price * rec.quantity) + masking_cost + rule.setup_fee + # --- Quantity + batch setup fees --- + num_batches = ( + math.ceil(rec.quantity / rec.batch_size) if rec.batch_size + else 1 + ) + total_setup = rule.setup_fee * num_batches + subtotal = (unit_price * rec.quantity) + masking_cost + total_setup # --- Rush surcharge --- rush_amount = 0 @@ -178,40 +187,43 @@ class FpQuoteConfigurator(models.Model): rec.calculated_price = total # --- Build breakdown HTML --- + sym = rec.currency_id.symbol or '$' lines = [] + method_label = dict( + rule._fields['pricing_method'].selection + ).get(rule.pricing_method, '') lines.append( - 'Base (%s)$%.2f x %d' - % (dict(rule._fields['pricing_method'].selection).get(rule.pricing_method, ''), - unit_price, rec.quantity) + 'Base (%s)%s%.2f x %d' + % (method_label, sym, unit_price, rec.quantity) ) if masking_cost: lines.append( - 'Masking (%d zones)$%.2f' - % (rec.masking_zones, masking_cost) + 'Masking (%d zones)%s%.2f' + % (rec.masking_zones, sym, masking_cost) ) - if rule.setup_fee: + if total_setup: lines.append( - 'Setup Fee$%.2f' - % rule.setup_fee + 'Setup Fee (x%d batches)%s%.2f' + % (num_batches, sym, total_setup) ) if rush_amount: lines.append( - 'Rush Surcharge (%.0f%%)$%.2f' - % (rule.rush_surcharge_percent, rush_amount) + 'Rush Surcharge (%.0f%%)%s%.2f' + % (rule.rush_surcharge_percent, sym, rush_amount) ) if rec.shipping_fee: lines.append( - 'Shipping$%.2f' - % rec.shipping_fee + 'Shipping%s%.2f' + % (sym, rec.shipping_fee) ) if rec.delivery_fee: lines.append( - 'Delivery$%.2f' - % rec.delivery_fee + 'Delivery%s%.2f' + % (sym, rec.delivery_fee) ) lines.append( - 'Total$%.2f' - % total + 'Total%s%.2f' + % (sym, total) ) rec.price_breakdown_html = ( diff --git a/fusion-plating/fusion_plating_configurator/views/fp_treatment_views.xml b/fusion-plating/fusion_plating_configurator/views/fp_treatment_views.xml index 083402a2..1b801c82 100644 --- a/fusion-plating/fusion_plating_configurator/views/fp_treatment_views.xml +++ b/fusion-plating/fusion_plating_configurator/views/fp_treatment_views.xml @@ -16,6 +16,7 @@ + diff --git a/fusion-plating/fusion_plating_configurator/views/sale_order_views.xml b/fusion-plating/fusion_plating_configurator/views/sale_order_views.xml index d9659ac0..e95d5235 100644 --- a/fusion-plating/fusion_plating_configurator/views/sale_order_views.xml +++ b/fusion-plating/fusion_plating_configurator/views/sale_order_views.xml @@ -39,7 +39,7 @@ - +