From 47576de8b26fc4c020eaf275d81baa2935bad5f3 Mon Sep 17 00:00:00 2001 From: Chandresh Thakkar OSI Date: Mon, 17 May 2021 20:13:09 +0530 Subject: [PATCH] product_cost_rollup_to_bom: update the standard cost of a product --- product_cost_rollup_to_bom/README.rst | 101 +++++++++++++ product_cost_rollup_to_bom/__init__.py | 4 + product_cost_rollup_to_bom/__manifest__.py | 27 ++++ .../data/cost_rollup_scheduler.xml | 23 +++ .../data/email_template.xml | 28 ++++ product_cost_rollup_to_bom/models/__init__.py | 6 + product_cost_rollup_to_bom/models/mrp_bom.py | 102 +++++++++++++ product_cost_rollup_to_bom/models/product.py | 135 ++++++++++++++++++ .../models/res_config_settings.py | 39 +++++ .../readme/CONFIGURE.rst | 7 + .../readme/CONTRIBUTORS.rst | 6 + .../readme/DESCRIPTION.rst | 1 + product_cost_rollup_to_bom/readme/USAGE.rst | 3 + .../static/description/icon.png | Bin 0 -> 29346 bytes product_cost_rollup_to_bom/views/mrp_bom.xml | 14 ++ .../views/product_views.xml | 19 +++ .../views/res_config_settings.xml | 45 ++++++ .../odoo/addons/product_cost_rollup_to_bom | 1 + setup/product_cost_rollup_to_bom/setup.py | 6 + 19 files changed, 567 insertions(+) create mode 100644 product_cost_rollup_to_bom/README.rst create mode 100644 product_cost_rollup_to_bom/__init__.py create mode 100644 product_cost_rollup_to_bom/__manifest__.py create mode 100644 product_cost_rollup_to_bom/data/cost_rollup_scheduler.xml create mode 100644 product_cost_rollup_to_bom/data/email_template.xml create mode 100644 product_cost_rollup_to_bom/models/__init__.py create mode 100644 product_cost_rollup_to_bom/models/mrp_bom.py create mode 100644 product_cost_rollup_to_bom/models/product.py create mode 100644 product_cost_rollup_to_bom/models/res_config_settings.py create mode 100644 product_cost_rollup_to_bom/readme/CONFIGURE.rst create mode 100644 product_cost_rollup_to_bom/readme/CONTRIBUTORS.rst create mode 100644 product_cost_rollup_to_bom/readme/DESCRIPTION.rst create mode 100644 product_cost_rollup_to_bom/readme/USAGE.rst create mode 100644 product_cost_rollup_to_bom/static/description/icon.png create mode 100644 product_cost_rollup_to_bom/views/mrp_bom.xml create mode 100644 product_cost_rollup_to_bom/views/product_views.xml create mode 100644 product_cost_rollup_to_bom/views/res_config_settings.xml create mode 120000 setup/product_cost_rollup_to_bom/odoo/addons/product_cost_rollup_to_bom create mode 100644 setup/product_cost_rollup_to_bom/setup.py diff --git a/product_cost_rollup_to_bom/README.rst b/product_cost_rollup_to_bom/README.rst new file mode 100644 index 000000000..3b9886280 --- /dev/null +++ b/product_cost_rollup_to_bom/README.rst @@ -0,0 +1,101 @@ +======================= +Product BOM Cost Rollup +======================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github + :target: https://github.com/OCA/manufacture/tree/14.0/product_cost_rollup_to_bom + :alt: OCA/manufacture +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/manufacture-14-0/manufacture-14-0-product_cost_rollup_to_bom + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/129/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +With Standard Cost Method, products that have bill of materials defined show rollup cost from the BOM. This module allows the cost to be rolled up based on BOM's that have components change standard price. The module can be used from product template/product variant forms using "Compute BOM Cost Rollup" or from the Scheduled Job across all BOM's that need an update. The module sends an email on modified standard cost products to an email configured on the Manufacturing App. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +Go to Manufacturing/ Configuration/ Settings/ BoM Cost Rollup Email and add email that you want to send BoM cost rollup email to. + +Or + +Go to Settings/ Users & Companies/ Companies and add email that you want to send BoM cost rollup email to. + +Turn On Debugger mode Go to Settings/ Technical/ Automation/ Scheduled Actions Change the interval you want scheduler to run. + +Usage +===== + +* Set the BOM Cost Rollup Notification Email +* To update a single product: Click on the Compute BOM Cost Rollup button +* To run on BOMs that have changed, run the scheduler manually or in cron mode. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Open Source Integrators + +Contributors +~~~~~~~~~~~~ + +* `Open Source Integrators `: + + * Balaji Kannan + * Mayank Gosai + * Daniel Reis + * Chandresh Thakkar + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/manufacture `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_cost_rollup_to_bom/__init__.py b/product_cost_rollup_to_bom/__init__.py new file mode 100644 index 000000000..798e371ed --- /dev/null +++ b/product_cost_rollup_to_bom/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import models diff --git a/product_cost_rollup_to_bom/__manifest__.py b/product_cost_rollup_to_bom/__manifest__.py new file mode 100644 index 000000000..534e8dd7e --- /dev/null +++ b/product_cost_rollup_to_bom/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Product BOM Cost Rollup", + "version": "14.0.1.0.0", + "author": "Open Source Integrators, Odoo Community Association (OCA)", + "summary": """Update BOM costs by rolling up. Adds scheduled job for + unattended rollups.""", + "license": "AGPL-3", + "category": "Product", + "maintainer": "dreispt", + "development_status": "Alpha", + "website": "https://github.com/OCA/manufacture", + "depends": [ + "mrp_account", + "stock_account", + ], + "data": [ + "views/product_views.xml", + "views/mrp_bom.xml", + "views/res_config_settings.xml", + "data/cost_rollup_scheduler.xml", + "data/email_template.xml", + ], + "installable": True, +} diff --git a/product_cost_rollup_to_bom/data/cost_rollup_scheduler.xml b/product_cost_rollup_to_bom/data/cost_rollup_scheduler.xml new file mode 100644 index 000000000..80ab1e60e --- /dev/null +++ b/product_cost_rollup_to_bom/data/cost_rollup_scheduler.xml @@ -0,0 +1,23 @@ + + + + + + + + BoM Cost Rollup: run scheduler + + code + +model.compute_bom_cost_rollup() + + + + 30 + days + -1 + + + + + diff --git a/product_cost_rollup_to_bom/data/email_template.xml b/product_cost_rollup_to_bom/data/email_template.xml new file mode 100644 index 000000000..16776ba79 --- /dev/null +++ b/product_cost_rollup_to_bom/data/email_template.xml @@ -0,0 +1,28 @@ + + + + Event Scheduler Notification for event: BoM Cost Rollup + + + ${ctx["email_from"]} + ${ctx["email_to"]} + Event Scheduler Notification for event: BoM Cost Rollup + + - Date: ${datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}
+ - Total Product's updated: ${ctx["product_list_len"]}
+ % set line_dict = ctx.get('product_list',False) + % for key, value in line_dict.items() + Product ${key} Standard Cost: ${'%8.2f' % value}
+ % endfor + ]]> +
+
+
+
diff --git a/product_cost_rollup_to_bom/models/__init__.py b/product_cost_rollup_to_bom/models/__init__.py new file mode 100644 index 000000000..fc0c338ef --- /dev/null +++ b/product_cost_rollup_to_bom/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import product +from . import mrp_bom +from . import res_config_settings diff --git a/product_cost_rollup_to_bom/models/mrp_bom.py b/product_cost_rollup_to_bom/models/mrp_bom.py new file mode 100644 index 000000000..5b7f26a9c --- /dev/null +++ b/product_cost_rollup_to_bom/models/mrp_bom.py @@ -0,0 +1,102 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging +from datetime import datetime + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class MrpBom(models.Model): + _inherit = "mrp.bom" + + std_cost_update_date = fields.Datetime( + string="Standard Cost Update Date", + copy=False, + help="Last time the standard cost was performed on this BOM.", + ) + + def get_product_variants(self, product): + # Returns all the Variants for the requested product + return product.with_prefetch().product_variant_ids + + def _update_bom(self, bomdate): + self.ensure_one() + for line in self.bom_line_ids: + if line.child_bom_id: + result = line.child_bom_id._update_bom(self.std_cost_update_date) + if result: + return True + elif ( + not line.product_id.std_cost_update_date + or not self.std_cost_update_date + or line.product_id.std_cost_update_date > self.std_cost_update_date + or line.product_id.write_date > self.std_cost_update_date + or line.product_id.product_tmpl_id.write_date + > self.std_cost_update_date + or (bomdate and line.product_id.write_date > bomdate) + ): + return True + return False + + @api.model + def compute_bom_cost_rollup(self): + + _logger.info("BOM Cost Rollup Process Started") + + # Get BoM's whose product is using costing method as standard + current_time = datetime.now() + + bom_ids = self.sudo().search( + [("product_tmpl_id.categ_id.property_cost_method", "=", "standard")] + ) + for bom in bom_ids: + # Check if cost method is standard + if ( + bom.product_tmpl_id.categ_id.property_cost_method + and bom.product_tmpl_id.categ_id.property_cost_method == "standard" + ): + # Get all product variants for BoM product template + product_variants = self.get_product_variants(bom.product_tmpl_id) + # update only if necessary + if bom._update_bom(bom.std_cost_update_date): + product_variants.action_bom_cost() + + _logger.info("BOM Cost Rollup Process Completed") + + product_list = {} + # FIXME: code smell - variable name reused + bom_ids = self.sudo().search([("std_cost_update_date", ">=", current_time)]) + if bom_ids: + _logger.info("BOM Cost Rollup Email Process Started") + for bom in bom_ids: + product_variants = self.get_product_variants(bom.product_tmpl_id) + for variant in product_variants: + product_list[variant.default_code] = variant.standard_price + + # TODO: use an email template, no settings config will be needed then + # Log if no user email to notify + if not self.env.user.company_id.bom_cost_email: + _logger.error( + "Exception while executing \ + BoM Cost Rollup: \ + Please configure email to notify from Company." + ) + template_id = self.env.ref( + "product_cost_rollup_to_bom.bom_cost_rollup_email_template" + ) + template_id.with_context( + { + "product_list_len": len(product_list), + "email_to": self.env.user.company_id.bom_cost_email, + "email_from": self.env.user.partner_id.email, + "product_list": product_list, + } + ).send_mail(self.id, force_send=True) + + _logger.info("BOM Cost Rollup Email Process Completed") + else: + _logger.info("No changes to BOM Cost Rollup. No Email.") + return True diff --git a/product_cost_rollup_to_bom/models/product.py b/product_cost_rollup_to_bom/models/product.py new file mode 100644 index 000000000..d123e9456 --- /dev/null +++ b/product_cost_rollup_to_bom/models/product.py @@ -0,0 +1,135 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging +from datetime import datetime + +from odoo import _, fields, models +from odoo.exceptions import UserError +from odoo.tools import float_is_zero + +_logger = logging.getLogger(__name__) + + +class ProductProduct(models.Model): + _inherit = "product.product" + + std_cost_update_date = fields.Datetime( + string="Standard Cost Update Date", + copy=False, + help="Last time the standard cost was performed on this product.", + ) + + def action_bom_cost(self): + real_time_products = self.filtered( + lambda p: p.valuation == "real_time" and p.valuation == "fifo" + ) + if real_time_products: + raise UserError( + _( + "The costing method on some products %s is FIFO." + " The cost will be computed during manufacturing process." + " Use Standard Costing to update BOM cost manually." + ) + % (real_time_products.mapped("display_name")) + ) + # else: + boms_to_recompute = self.env["mrp.bom"].search( + [ + "|", + ("product_id", "in", self.ids), + "&", + ("product_id", "=", False), + ("product_tmpl_id", "in", self.mapped("product_tmpl_id").ids), + ] + ) + for product in self: + new_price = product._set_price_from_bom(boms_to_recompute) or 0.0 + # FIXME: precision rounding should be taken from configs + if product.cost_method == "standard" and not float_is_zero( + new_price - product.standard_price, precision_rounding=2 + ): + product._change_standard_price(new_price) + product.std_cost_update_date = datetime.now() + if product.product_tmpl_id.product_variant_count == 1: + _logger.info( + "Product : %s Standard Price: %s ", + product.default_code, + str(product.product_tmpl_id.standard_price), + ) + else: + _logger.info( + "Product : %s Standard Price: %s ", + product.default_code, + str(product.standard_price), + ) + + def _set_price_from_bom(self, boms_to_recompute=False): + self.ensure_one() + bom = self.env["mrp.bom"]._bom_find(product=self) + if bom: + self.standard_price = self.with_context(cost_all=True)._compute_bom_price( + bom, boms_to_recompute=boms_to_recompute + ) + bom.std_cost_update_date = datetime.now() + + def _compute_bom_price(self, bom, boms_to_recompute=False): + self.ensure_one() + if not boms_to_recompute: + boms_to_recompute = [] + total = 0 + for opt in bom.operation_ids: + duration_expected = ( + opt.workcenter_id.time_start + + opt.workcenter_id.time_stop + + opt.time_cycle + ) + total += (duration_expected / 60) * opt.workcenter_id.costs_hour + + for line in bom.bom_line_ids: + if line._skip_bom_line(self): + continue + + # Compute recursive if line has `child_line_ids` and the product + # has not been computed recently + if ( + line.child_bom_id + and ( + line.child_bom_id in boms_to_recompute + or self.env.context.get("cost_all", True) + ) + and ( + not bom.std_cost_update_date + or not line.product_id.std_cost_update_date + or line.child_bom_id._update_bom(bom.std_cost_update_date) + ) + ): + child_total = line.product_id._compute_bom_price( + line.child_bom_id, boms_to_recompute=boms_to_recompute + ) + total += ( + line.product_id.uom_id._compute_price( + child_total, line.product_uom_id + ) + * line.product_qty + ) + if not float_is_zero( + child_total - line.product_id.standard_price, + precision_rounding=2, + ): + line.product_id._change_standard_price(child_total) + line.product_id.std_cost_update_date = datetime.now() + _logger.info( + "Product : %s Standard Price: %s ", + line.product_id.default_code, + str(line.product_id.standard_price), + ) + else: + ctotal = ( + line.product_id.uom_id._compute_price( + line.product_id.standard_price, line.product_uom_id + ) + * line.product_qty + ) + total += ctotal + return bom.product_uom_id._compute_price(total / bom.product_qty, self.uom_id) diff --git a/product_cost_rollup_to_bom/models/res_config_settings.py b/product_cost_rollup_to_bom/models/res_config_settings.py new file mode 100644 index 000000000..dc848a503 --- /dev/null +++ b/product_cost_rollup_to_bom/models/res_config_settings.py @@ -0,0 +1,39 @@ +# Copyright (C) 2021, Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + bom_cost_email = fields.Char( + string="BoM cost rollup email", + related="company_id.bom_cost_email", + readonly=False, + help="BoM Cost rollup Email notification will be sent to this email address", + ) + + def get_values(self): + res = super(ResConfigSettings, self).get_values() + res.update( + bom_cost_email=self.env["ir.config_parameter"] + .sudo() + .get_param("product_cost_rollup_to_bom.bom_cost_email") + ) + return res + + def set_values(self): + super(ResConfigSettings, self).set_values() + self.env["ir.config_parameter"].sudo().set_param( + "product_cost_rollup_to_bom.bom_cost_email", self.bom_cost_email + ) + + +class ResCompany(models.Model): + _inherit = "res.company" + + bom_cost_email = fields.Char( + string="BoM cost rollup email", + help="BoM Cost rollup Email notification will be sent to this email address", + ) diff --git a/product_cost_rollup_to_bom/readme/CONFIGURE.rst b/product_cost_rollup_to_bom/readme/CONFIGURE.rst new file mode 100644 index 000000000..b09db59f5 --- /dev/null +++ b/product_cost_rollup_to_bom/readme/CONFIGURE.rst @@ -0,0 +1,7 @@ +Go to Manufacturing/ Configuration/ Settings/ BoM Cost Rollup Email and add email that you want to send BoM cost rollup email to. + +Or + +Go to Settings/ Users & Companies/ Companies and add email that you want to send BoM cost rollup email to. + +Turn On Debugger mode Go to Settings/ Technical/ Automation/ Scheduled Actions Change the interval you want scheduler to run. diff --git a/product_cost_rollup_to_bom/readme/CONTRIBUTORS.rst b/product_cost_rollup_to_bom/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..2d74f6c71 --- /dev/null +++ b/product_cost_rollup_to_bom/readme/CONTRIBUTORS.rst @@ -0,0 +1,6 @@ +* `Open Source Integrators `: + + * Balaji Kannan + * Mayank Gosai + * Daniel Reis + * Chandresh Thakkar diff --git a/product_cost_rollup_to_bom/readme/DESCRIPTION.rst b/product_cost_rollup_to_bom/readme/DESCRIPTION.rst new file mode 100644 index 000000000..127dd14d4 --- /dev/null +++ b/product_cost_rollup_to_bom/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +With Standard Cost Method, products that have bill of materials defined show rollup cost from the BOM. This module allows the cost to be rolled up based on BOM's that have components change standard price. The module can be used from product template/product variant forms using "Compute BOM Cost Rollup" or from the Scheduled Job across all BOM's that need an update. The module sends an email on modified standard cost products to an email configured on the Manufacturing App. diff --git a/product_cost_rollup_to_bom/readme/USAGE.rst b/product_cost_rollup_to_bom/readme/USAGE.rst new file mode 100644 index 000000000..5c7bfcee8 --- /dev/null +++ b/product_cost_rollup_to_bom/readme/USAGE.rst @@ -0,0 +1,3 @@ +* Set the BOM Cost Rollup Notification Email +* To update a single product: Click on the Compute BOM Cost Rollup button +* To run on BOMs that have changed, run the scheduler manually or in cron mode. diff --git a/product_cost_rollup_to_bom/static/description/icon.png b/product_cost_rollup_to_bom/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..84791119f6e93bfb3e59814787c14db9e58275e1 GIT binary patch literal 29346 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 literal 0 HcmV?d00001 diff --git a/product_cost_rollup_to_bom/views/mrp_bom.xml b/product_cost_rollup_to_bom/views/mrp_bom.xml new file mode 100644 index 000000000..42d4f3427 --- /dev/null +++ b/product_cost_rollup_to_bom/views/mrp_bom.xml @@ -0,0 +1,14 @@ + + + + + view.std.price.mrp.bom + mrp.bom + + +

+ +
+ + + diff --git a/product_cost_rollup_to_bom/views/product_views.xml b/product_cost_rollup_to_bom/views/product_views.xml new file mode 100644 index 000000000..a634f2963 --- /dev/null +++ b/product_cost_rollup_to_bom/views/product_views.xml @@ -0,0 +1,19 @@ + + + + + view.std.price.product.product + product.product + + + + + + + + + diff --git a/product_cost_rollup_to_bom/views/res_config_settings.xml b/product_cost_rollup_to_bom/views/res_config_settings.xml new file mode 100644 index 000000000..2cb90d378 --- /dev/null +++ b/product_cost_rollup_to_bom/views/res_config_settings.xml @@ -0,0 +1,45 @@ + + + + + + + view.email.res.settings + res.config.settings + + + +
+
+
+
+ +
+ BoM Cost rollup Email notification will be sent to this email address
+
+
+
+
+
+
+ + + + view.email.company + res.company + + + + + + + + +
diff --git a/setup/product_cost_rollup_to_bom/odoo/addons/product_cost_rollup_to_bom b/setup/product_cost_rollup_to_bom/odoo/addons/product_cost_rollup_to_bom new file mode 120000 index 000000000..3989e2123 --- /dev/null +++ b/setup/product_cost_rollup_to_bom/odoo/addons/product_cost_rollup_to_bom @@ -0,0 +1 @@ +../../../../product_cost_rollup_to_bom \ No newline at end of file diff --git a/setup/product_cost_rollup_to_bom/setup.py b/setup/product_cost_rollup_to_bom/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/product_cost_rollup_to_bom/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)