From c3bef6e83d5af845017869e7bb94bb10ca833b0b Mon Sep 17 00:00:00 2001 From: Alfredo Date: Thu, 17 Oct 2024 07:54:44 +0200 Subject: [PATCH] [16.0][ADD] mrp_product_loss_cost: Calculate the cost of product scrap. --- mrp_product_loss_cost/README.rst | 29 ++++++++ mrp_product_loss_cost/__init__.py | 1 + mrp_product_loss_cost/__manifest__.py | 18 +++++ mrp_product_loss_cost/i18n/ca_ES.po | 54 +++++++++++++++ mrp_product_loss_cost/i18n/en_GB.po | 54 +++++++++++++++ mrp_product_loss_cost/i18n/es.po | 54 +++++++++++++++ mrp_product_loss_cost/i18n/fr.po | 54 +++++++++++++++ .../i18n/mrp_product_loss_cost.pot | 54 +++++++++++++++ mrp_product_loss_cost/models/__init__.py | 2 + .../models/mrp_production.py | 34 +++++++++ mrp_product_loss_cost/models/stock_scrap.py | 69 +++++++++++++++++++ .../views/mrp_production_views.xml | 38 ++++++++++ .../views/stock_scrap_views.xml | 40 +++++++++++ .../odoo/addons/mrp_product_loss_cost | 1 + setup/mrp_product_loss_cost/setup.py | 6 ++ 15 files changed, 508 insertions(+) create mode 100644 mrp_product_loss_cost/README.rst create mode 100644 mrp_product_loss_cost/__init__.py create mode 100644 mrp_product_loss_cost/__manifest__.py create mode 100644 mrp_product_loss_cost/i18n/ca_ES.po create mode 100644 mrp_product_loss_cost/i18n/en_GB.po create mode 100644 mrp_product_loss_cost/i18n/es.po create mode 100644 mrp_product_loss_cost/i18n/fr.po create mode 100644 mrp_product_loss_cost/i18n/mrp_product_loss_cost.pot create mode 100644 mrp_product_loss_cost/models/__init__.py create mode 100644 mrp_product_loss_cost/models/mrp_production.py create mode 100644 mrp_product_loss_cost/models/stock_scrap.py create mode 100644 mrp_product_loss_cost/views/mrp_production_views.xml create mode 100644 mrp_product_loss_cost/views/stock_scrap_views.xml create mode 120000 setup/mrp_product_loss_cost/odoo/addons/mrp_product_loss_cost create mode 100644 setup/mrp_product_loss_cost/setup.py diff --git a/mrp_product_loss_cost/README.rst b/mrp_product_loss_cost/README.rst new file mode 100644 index 000000000..176cb5c9e --- /dev/null +++ b/mrp_product_loss_cost/README.rst @@ -0,0 +1,29 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +===================== +Mrp product loss cost +===================== + +* Calculate the cost of product scrap. +* In MO new fields "Scrap Cost" and "Total MO Cost". + +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 smash it by providing detailed and welcomed feedback. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Contributors +------------ + +* Ana Juaristi +* Alfredo de la Fuente diff --git a/mrp_product_loss_cost/__init__.py b/mrp_product_loss_cost/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/mrp_product_loss_cost/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mrp_product_loss_cost/__manifest__.py b/mrp_product_loss_cost/__manifest__.py new file mode 100644 index 000000000..7a3d55eba --- /dev/null +++ b/mrp_product_loss_cost/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2024 Alfredo de la Fuente - AvanzOSC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +{ + "name": "Mrp Product Loss Cost", + "version": "16.0.1.0.0", + "category": "Manufacturing/Manufacturing", + "website": "https://github.com/avanzosc/mrp-addons", + "author": "AvanzOSC", + "license": "AGPL-3", + "depends": [ + "mrp_stock_move_cost", + ], + "data": [ + "views/mrp_production_views.xml", + "views/stock_scrap_views.xml", + ], + "installable": True, +} diff --git a/mrp_product_loss_cost/i18n/ca_ES.po b/mrp_product_loss_cost/i18n/ca_ES.po new file mode 100644 index 000000000..07e6cee7c --- /dev/null +++ b/mrp_product_loss_cost/i18n/ca_ES.po @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_product_loss_cost +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-17 05:50+0000\n" +"PO-Revision-Date: 2024-10-17 05:50+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__price_unit_cost +msgid "Cost Unit Price" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_mrp_production +msgid "Production Order" +msgstr "Ordre de producció" + +#. module: mrp_product_loss_cost +#: model:ir.actions.server,name:mrp_product_loss_cost.action_cost_in_mrp_production +msgid "Put Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_stock_scrap +msgid "Scrap" +msgstr "Deixalla" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__scrap_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__scrap_cost +msgid "Scrap Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__total_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +msgid "Total MO Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.stock_scrap_tree_view +msgid "Total Scrap Cost" +msgstr "" diff --git a/mrp_product_loss_cost/i18n/en_GB.po b/mrp_product_loss_cost/i18n/en_GB.po new file mode 100644 index 000000000..adc3cee3f --- /dev/null +++ b/mrp_product_loss_cost/i18n/en_GB.po @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_product_loss_cost +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-17 05:50+0000\n" +"PO-Revision-Date: 2024-10-17 05:50+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__price_unit_cost +msgid "Cost Unit Price" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.actions.server,name:mrp_product_loss_cost.action_cost_in_mrp_production +msgid "Put Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_stock_scrap +msgid "Scrap" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__scrap_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__scrap_cost +msgid "Scrap Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__total_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +msgid "Total MO Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.stock_scrap_tree_view +msgid "Total Scrap Cost" +msgstr "" diff --git a/mrp_product_loss_cost/i18n/es.po b/mrp_product_loss_cost/i18n/es.po new file mode 100644 index 000000000..cd0969b7b --- /dev/null +++ b/mrp_product_loss_cost/i18n/es.po @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_product_loss_cost +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-17 05:51+0000\n" +"PO-Revision-Date: 2024-10-17 05:51+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__price_unit_cost +msgid "Cost Unit Price" +msgstr "Precio coste unitario" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_mrp_production +msgid "Production Order" +msgstr "Orden de producción" + +#. module: mrp_product_loss_cost +#: model:ir.actions.server,name:mrp_product_loss_cost.action_cost_in_mrp_production +msgid "Put Cost" +msgstr "Poner coste" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_stock_scrap +msgid "Scrap" +msgstr "Desechar" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__scrap_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__scrap_cost +msgid "Scrap Cost" +msgstr "Coste desecho" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__total_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +msgid "Total MO Cost" +msgstr "Total coste OF" + +#. module: mrp_product_loss_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.stock_scrap_tree_view +msgid "Total Scrap Cost" +msgstr "Total coste desecho" diff --git a/mrp_product_loss_cost/i18n/fr.po b/mrp_product_loss_cost/i18n/fr.po new file mode 100644 index 000000000..066efd2a9 --- /dev/null +++ b/mrp_product_loss_cost/i18n/fr.po @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_product_loss_cost +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-17 05:50+0000\n" +"PO-Revision-Date: 2024-10-17 05:50+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__price_unit_cost +msgid "Cost Unit Price" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_mrp_production +msgid "Production Order" +msgstr "Ordre de production" + +#. module: mrp_product_loss_cost +#: model:ir.actions.server,name:mrp_product_loss_cost.action_cost_in_mrp_production +msgid "Put Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_stock_scrap +msgid "Scrap" +msgstr "Rebut" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__scrap_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__scrap_cost +msgid "Scrap Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__total_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +msgid "Total MO Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.stock_scrap_tree_view +msgid "Total Scrap Cost" +msgstr "" diff --git a/mrp_product_loss_cost/i18n/mrp_product_loss_cost.pot b/mrp_product_loss_cost/i18n/mrp_product_loss_cost.pot new file mode 100644 index 000000000..da8ea7afc --- /dev/null +++ b/mrp_product_loss_cost/i18n/mrp_product_loss_cost.pot @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_product_loss_cost +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-17 05:49+0000\n" +"PO-Revision-Date: 2024-10-17 05:49+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__price_unit_cost +msgid "Cost Unit Price" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.actions.server,name:mrp_product_loss_cost.action_cost_in_mrp_production +msgid "Put Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model,name:mrp_product_loss_cost.model_stock_scrap +msgid "Scrap" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__scrap_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_stock_scrap__scrap_cost +msgid "Scrap Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model:ir.model.fields,field_description:mrp_product_loss_cost.field_mrp_production__total_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +msgid "Total MO Cost" +msgstr "" + +#. module: mrp_product_loss_cost +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.mrp_production_tree_view +#: model_terms:ir.ui.view,arch_db:mrp_product_loss_cost.stock_scrap_tree_view +msgid "Total Scrap Cost" +msgstr "" diff --git a/mrp_product_loss_cost/models/__init__.py b/mrp_product_loss_cost/models/__init__.py new file mode 100644 index 000000000..79dcf54b2 --- /dev/null +++ b/mrp_product_loss_cost/models/__init__.py @@ -0,0 +1,2 @@ +from . import mrp_production +from . import stock_scrap diff --git a/mrp_product_loss_cost/models/mrp_production.py b/mrp_product_loss_cost/models/mrp_production.py new file mode 100644 index 000000000..f3a11116f --- /dev/null +++ b/mrp_product_loss_cost/models/mrp_production.py @@ -0,0 +1,34 @@ +# Copyright 2024 Alfredo de la Fuente - AvanzOSC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + scrap_cost = fields.Float(digits="Product Price", copy=False) + total_cost = fields.Float( + string="Total MO Cost", digits="Product Price", copy=False + ) + + def update_prodution_cost(self): + result = super().update_prodution_cost() + scrap_cost = 0 + price_unit_cost = 0 + if self.scrap_ids: + scrap_cost = sum(self.scrap_ids.mapped("scrap_cost")) + total_of_cost = self.cost + scrap_cost + if total_of_cost and self.move_finished_ids: + for move in self.move_finished_ids: + if move.qty_done > 0: + move.price_unit_cost = total_of_cost / move.qty_done + if total_of_cost and self.qty_producing: + price_unit_cost = total_of_cost / self.qty_producing + self.scrap_cost = scrap_cost + self.total_cost = total_of_cost + self.price_unit_cost = price_unit_cost + if self.lot_producing_id: + self.lot_producing_id.with_context(from_production=True).purchase_price = ( + price_unit_cost + ) + return result diff --git a/mrp_product_loss_cost/models/stock_scrap.py b/mrp_product_loss_cost/models/stock_scrap.py new file mode 100644 index 000000000..4d9f757f3 --- /dev/null +++ b/mrp_product_loss_cost/models/stock_scrap.py @@ -0,0 +1,69 @@ +# Copyright 2024 Alfredo de la Fuente - AvanzOSC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import api, fields, models + + +class StockScrap(models.Model): + _inherit = "stock.scrap" + + price_unit_cost = fields.Float( + string="Cost Unit Price", digits="Product Price", copy=False + ) + scrap_cost = fields.Float(digits="Product Price", copy=False) + + @api.onchange("product_id") + def _onchange_product_id(self): + if self.product_id and self.product_id.standard_price: + self.price_unit_cost = self.product_id.standard_price + return super()._onchange_product_id() + + @api.onchange("lot_id") + def _onchange_serial_number(self): + result = super()._onchange_serial_number() + if self.lot_id and self.lot_id.purchase_price: + self.price_unit_cost = self.lot_id.purchase_price + return result + + @api.onchange("price_unit_cost", "scrap_qty") + def _onchange_price_unit_cost(self): + self.scrap_cost = self.price_unit_cost * self.scrap_qty + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if "price_unit_cost" not in vals: + vals = self._calculate_price_unit_cost(vals) + scraps = super().create(vals_list) + for scrap in scraps.filtered(lambda x: x.state == "done"): + scrap.production_id.update_prodution_cost() + return scraps + + def write(self, vals): + if "price_unit_cost" not in vals: + vals = self._calculate_price_unit_cost(vals) + result = super().write(vals) + for scrap in self.filtered(lambda x: x.state == "done"): + scrap.production_id.update_prodution_cost() + return result + + def unlink(self): + productions = self.env["mrp.production"] + scraps_with_productions = self.filtered(lambda x: x.production_id) + if scraps_with_productions: + productions = scraps_with_productions.mapped("production_id") + result = super().unlink() + for production in productions: + production.update_prodution_cost() + return result + + def _calculate_price_unit_cost(self, vals): + if "product_id" in vals: + product = self.env["product.product"].browse("product_id") + vals["price_unit_cost"] = product.standard_price + if "lot_id" in vals and vals.get("lot_id", False): + lot = self.env["stock.lot"].browse("lot_id") + if lot.purchase_price: + vals["price_unit_cost"] = lot.purchase_price + if vals.get("price_unit_cost") and vals.get("scrap_qty"): + vals["scrap_cost"] = vals.get("price_unit_cost") * vals.get("scrap_qty") + return vals diff --git a/mrp_product_loss_cost/views/mrp_production_views.xml b/mrp_product_loss_cost/views/mrp_production_views.xml new file mode 100644 index 000000000..241ce299c --- /dev/null +++ b/mrp_product_loss_cost/views/mrp_production_views.xml @@ -0,0 +1,38 @@ + + + + mrp.production + + + + + + + + + + + + + mrp.production + + + + + + + + + + + Put Cost + + + ir.actions.server + code + + if records: + records._put_cost_in_mrp_production() + + + diff --git a/mrp_product_loss_cost/views/stock_scrap_views.xml b/mrp_product_loss_cost/views/stock_scrap_views.xml new file mode 100644 index 000000000..f0202d4a4 --- /dev/null +++ b/mrp_product_loss_cost/views/stock_scrap_views.xml @@ -0,0 +1,40 @@ + + + + stock.scrap + + + + + + + + + + + stock.scrap + + + + + + + + + + + stock.scrap + + + + + + + + + diff --git a/setup/mrp_product_loss_cost/odoo/addons/mrp_product_loss_cost b/setup/mrp_product_loss_cost/odoo/addons/mrp_product_loss_cost new file mode 120000 index 000000000..9f1ad5688 --- /dev/null +++ b/setup/mrp_product_loss_cost/odoo/addons/mrp_product_loss_cost @@ -0,0 +1 @@ +../../../../mrp_product_loss_cost \ No newline at end of file diff --git a/setup/mrp_product_loss_cost/setup.py b/setup/mrp_product_loss_cost/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/mrp_product_loss_cost/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)