From 44812ed3634a8dfacb9041e09521c51b761a3e2a Mon Sep 17 00:00:00 2001 From: Victor Champonnois Date: Fri, 16 Sep 2022 15:48:01 +0200 Subject: [PATCH] [REF] refactor following PR 320 --- beesdoo_product/models/beesdoo_product.py | 101 +------------ beesdoo_product/readme/DESCRIPTION.rst | 3 +- .../models/product_template.py | 38 +++++ .../readme/DESCRIPTION.rst | 2 + .../views/product_template_views.xml | 5 + .../wizard/adapt_sales_price_wizard.py | 7 + .../models/product_template.py | 134 ++++++++++++------ .../models/res_config_settings.py | 8 +- 8 files changed, 154 insertions(+), 144 deletions(-) create mode 100644 sale_adapt_price_wizard/models/product_template.py diff --git a/beesdoo_product/models/beesdoo_product.py b/beesdoo_product/models/beesdoo_product.py index 65c064f60..0604f202b 100644 --- a/beesdoo_product/models/beesdoo_product.py +++ b/beesdoo_product/models/beesdoo_product.py @@ -5,7 +5,7 @@ import uuid from odoo import api, fields, models -from odoo.exceptions import UserError, ValidationError +from odoo.exceptions import UserError from odoo.tools.translate import _ from odoo.addons import decimal_precision as dp @@ -103,6 +103,11 @@ class BeesdooProduct(models.Model): readonly=True, store=True, ) + purchase_price = fields.Float( + string="Purchase Price", + compute="_compute_purchase_price", + inverse="_inverse_purchase_price", + ) @api.depends("uom_id", "uom_id.category_id", "uom_id.category_id.type") @api.multi @@ -242,100 +247,6 @@ def _unit_same_category(self): ) ) - @api.multi - @api.depends("purchase_price", "seller_ids") - def _compute_purchase_price_write_date(self): - for product in self: - supplierinfo = product._get_main_supplier_info() - product.purchase_price_write_date = supplierinfo.price_write_date - - def write(self, vals): - if ( - self.env["ir.config_parameter"] - .sudo() - .get_param("beesdoo_product.auto_write_suggested_price") - ): - purchase_price = vals.get("purchase_price") - if purchase_price and purchase_price != self.purchase_price: - # force update of purchase_price (which actually modifies the - # suppliers’ price) to ensure that the next computations that - # depend on it are correct. there are 3 things to do: - # 1. set value in cache - with self.env.do_in_draft(): - self.purchase_price = purchase_price - # 2. call inverse compute method - self._inverse_purchase_price() - # 3. remove the value from vals, to avoid the process to happen a - # second time - del vals["purchase_price"] - - # Important note: The list price is _only_ changed here if the - # `purchase_price` field of the product is changed. If the - # `price` field of the supplierinfo changes normally, the list price - # here is NOT automatically affected. - self.adapt_list_price(vals) - - list_price = vals.get("list_price") - if list_price and list_price != self.list_price: - vals["list_price_write_date"] = fields.Datetime.now() - - super().write(vals) - - @api.multi - def adapt_list_price(self, vals, suggested_price=None): - self.ensure_one() - if suggested_price is None: - suggested_price = self.suggested_price - vals.setdefault("list_price", suggested_price) - - @api.multi - def calculate_suggested_price(self, price=None): - self.ensure_one() - suggested_price_reference = ( - self.env["ir.config_parameter"] - .sudo() - .get_param("beesdoo_product.suggested_price_reference") - ) - supplier = self._get_main_supplier_info() - if not supplier: - raise ValueError(_("No supplier found for product {}").format(self.id)) - if price is None: - price = supplier.price - product_category = supplier.product_tmpl_id.categ_id - supplier_taxes = self.supplier_taxes_id.filtered( - lambda t: t.amount_type == "percent" and t.price_include - ) - supplier_taxes_factor = 1 / (1 + sum(supplier_taxes.mapped("amount")) / 100) - sale_taxes = self.taxes_id.filtered( - lambda t: t.amount_type == "percent" and t.price_include - ) - sale_taxes_factor = 1 + sum(sale_taxes.mapped("amount")) / 100 - profit_margin_supplier = supplier.name.profit_margin - profit_margin_product_category = product_category.profit_margin - profit_margin = profit_margin_supplier or profit_margin_product_category - profit_margin_factor = ( - 1 / (1 - profit_margin / 100) - if suggested_price_reference == "sale_price" - else (1 + profit_margin / 100) - ) - - # price of purchase is given for uom_po_id - # suggested *sale* price must be adapted to uom_id - uom_factor = self.uom_po_id.factor / self.uom_id.factor - - suggested_price = ( - price - * uom_factor - * supplier_taxes_factor - * sale_taxes_factor - * profit_margin_factor - ) - - if product_category.should_round_suggested_price: - suggested_price = product_category._round(suggested_price) - - return suggested_price - @api.multi def create_request_label_printing_wizard(self): context = {"active_ids": self.ids} diff --git a/beesdoo_product/readme/DESCRIPTION.rst b/beesdoo_product/readme/DESCRIPTION.rst index 37dd9cac6..12262b018 100644 --- a/beesdoo_product/readme/DESCRIPTION.rst +++ b/beesdoo_product/readme/DESCRIPTION.rst @@ -31,8 +31,7 @@ Modification of product module for the needs of beescoop The only editable field is Purchase Price. Through "Action > Adapt Sales Price", the user can, on the selected products, adapt the Sales Price according to the Suggested Price. - Alternatively, 'Automatically write suggested price' can be enabled to make - this last step automatic. + Please note that this model makes assumptions when computing the suggested price: diff --git a/sale_adapt_price_wizard/models/product_template.py b/sale_adapt_price_wizard/models/product_template.py new file mode 100644 index 000000000..37234d027 --- /dev/null +++ b/sale_adapt_price_wizard/models/product_template.py @@ -0,0 +1,38 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def write(self, vals): + if self.env["ir.config_parameter"].get_param( + "beesdoo_product.auto_write_suggested_price" + ): + purchase_price = vals.get("purchase_price") + if purchase_price and purchase_price != self.purchase_price: + # force update of purchase_price (which actually modifies the + # suppliers’ price) to ensure that the next computations that + # depend on it are correct. there are 3 things to do: + # 1. set value in cache + with self.env.do_in_draft(): + self.purchase_price = purchase_price + # 2. call inverse compute method + self._inverse_purchase_price() + # 3. remove the value from vals, to avoid the process to happen a + # second time + del vals["purchase_price"] + + # Important note: The list price is _only_ changed here if the + # `purchase_price` field of the product is changed. If the + # `price` field of the supplierinfo changes normally, the list price + # here is NOT automatically affected. + self.adapt_list_price(vals) + + list_price = vals.get("list_price") + if list_price and list_price != self.list_price: + vals["list_price_write_date"] = fields.Datetime.now() + + super().write(vals) diff --git a/sale_adapt_price_wizard/readme/DESCRIPTION.rst b/sale_adapt_price_wizard/readme/DESCRIPTION.rst index fc3ef29a4..1fa9db127 100644 --- a/sale_adapt_price_wizard/readme/DESCRIPTION.rst +++ b/sale_adapt_price_wizard/readme/DESCRIPTION.rst @@ -12,3 +12,5 @@ The only editable field is Purchase Price. Through "Action > Adapt Sales Price", the user can, on the selected products, adapt the Sales Price according to the Suggested Price. + Alternatively, 'Automatically write suggested price' can be enabled to make + this last step automatic. diff --git a/sale_adapt_price_wizard/views/product_template_views.xml b/sale_adapt_price_wizard/views/product_template_views.xml index 6416ca81c..8f31dbc3f 100644 --- a/sale_adapt_price_wizard/views/product_template_views.xml +++ b/sale_adapt_price_wizard/views/product_template_views.xml @@ -14,6 +14,10 @@ options="{'no_open': True, 'no_create': True, 'no_create_edit': True }" /> + +