diff --git a/mrp_default_workorder_time/README.rst b/mrp_default_workorder_time/README.rst new file mode 100644 index 00000000000..f8d562fa19f --- /dev/null +++ b/mrp_default_workorder_time/README.rst @@ -0,0 +1,98 @@ +========================== +MRP Default Workorder Time +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:beb803741965ff28f8c1834060d5369607aa38ab7cbe90d9169194803765a358 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github + :target: https://github.com/OCA/manufacture/tree/18.0/mrp_default_workorder_time + :alt: OCA/manufacture +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/manufacture-18-0/manufacture-18-0-mrp_default_workorder_time + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +There are occasions when the registration of work orders is not +completed with the correct times, this module allows you to configure a +threshold percentage that assigns the projected time as fully productive +time if a work time less than this percentage is detected. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +In the production module configurations, the "Record standard projected +order time" feature must be activated, by default the minimum percentage +is ten but it can be changed as needed. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ForgeFlow + +Contributors +------------ + +- Christopher Ormaza + +- Trobz (https://trobz.com) + + - Do Anh Duy + +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. + +.. |maintainer-ChrisOForgeFlow| image:: https://github.com/ChrisOForgeFlow.png?size=40px + :target: https://github.com/ChrisOForgeFlow + :alt: ChrisOForgeFlow + +Current `maintainer `__: + +|maintainer-ChrisOForgeFlow| + +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/mrp_default_workorder_time/__init__.py b/mrp_default_workorder_time/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/mrp_default_workorder_time/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mrp_default_workorder_time/__manifest__.py b/mrp_default_workorder_time/__manifest__.py new file mode 100644 index 00000000000..a99e98b6f51 --- /dev/null +++ b/mrp_default_workorder_time/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "MRP Default Workorder Time", + "version": "18.0.1.0.0", + "development_status": "Beta", + "license": "LGPL-3", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "maintainers": ["ChrisOForgeFlow"], + "summary": "Adds an MRP default workorder time", + "website": "https://github.com/OCA/manufacture", + "category": "Manufacturing", + "depends": ["mrp", "stock"], + "data": [ + "views/res_config_settings_view.xml", + ], + "demo": [], + "installable": True, + "application": True, +} diff --git a/mrp_default_workorder_time/i18n/es.po b/mrp_default_workorder_time/i18n/es.po new file mode 100644 index 00000000000..1230310d59d --- /dev/null +++ b/mrp_default_workorder_time/i18n/es.po @@ -0,0 +1,107 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_default_workorder_time +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-03-25 21:33+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"" +msgstr "" +"" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_company +msgid "Companies" +msgstr "Compañías" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_config_settings +msgid "Config Settings" +msgstr "Ajustes Config" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"Fully Productive Time is not configured on system, please contact with your " +"administrator" +msgstr "" +"El Tiempo Productivo Completo no está configurado en el sistema, póngase en " +"contacto con su administrador" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"If time recorded on workorder is not between this percentages, projected " +"time will be used instead" +msgstr "" +"Si el tiempo registrado en la orden de trabajo no se encuentra entre estos " +"porcentajes, se utilizará en su lugar el tiempo proyectado" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__maximum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__maximum_order_time_threshold +msgid "Maximum order time threshold(%)" +msgstr "Umbral de tiempo máximo de pedido(%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Maximum:" +msgstr "Máximo:" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__minimum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__minimum_order_time_threshold +msgid "Minimum order time threshold(%)" +msgstr "Umbral de tiempo máximo de pedido(%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Minimum:" +msgstr "Mínimo:" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Record standard projected order time" +msgstr "Registrar el tiempo de pedido proyectado estándar" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__use_projected_time_work_orders +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__use_projected_time_work_orders +msgid "Use projected time work orders?" +msgstr "¿Utilizar órdenes de trabajo de tiempo proyectado?" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_mrp_workorder +msgid "Work Order" +msgstr "Orden de Trabajo" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"You should plan orders to set default production time on work orders, please" +" check" +msgstr "" +"Usted debe planificar las órdenes para establecer el tiempo de producción " +"por defecto en las órdenes de trabajo, por favor revise" diff --git a/mrp_default_workorder_time/i18n/hr.po b/mrp_default_workorder_time/i18n/hr.po new file mode 100644 index 00000000000..e7a75fd4ab5 --- /dev/null +++ b/mrp_default_workorder_time/i18n/hr.po @@ -0,0 +1,105 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_default_workorder_time +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-06-17 15:35+0000\n" +"Last-Translator: Bole \n" +"Language-Team: none\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.17\n" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_company +msgid "Companies" +msgstr "Tvrtke" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_config_settings +msgid "Config Settings" +msgstr "Konfiguracijske postavke" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"Fully Productive Time is not configured on system, please contact with your " +"administrator" +msgstr "" +"Potpuno produktivno vrijeme nije postavljeno u sustavu, molimo kontaktirajte " +"administratora" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"If time recorded on workorder is not between this percentages, projected " +"time will be used instead" +msgstr "" +"Ako ubilježeno vrijeme na radnom nalogu nije između ovih postotaka, " +"projektno vrijeme će biti korišteno" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__maximum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__maximum_order_time_threshold +msgid "Maximum order time threshold(%)" +msgstr "Prag maksimalnog vremena naloga(%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Maximum:" +msgstr "Maksimum:" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__minimum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__minimum_order_time_threshold +msgid "Minimum order time threshold(%)" +msgstr "Prag minimalnog vremena naloga (%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Minimum:" +msgstr "Minimum:" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Record standard projected order time" +msgstr "Zabilježi standardno projecirano vrijeme naloga" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__use_projected_time_work_orders +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__use_projected_time_work_orders +msgid "Use projected time work orders?" +msgstr "Koristi projecirano vrijeme za radne naloge?" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_mrp_workorder +msgid "Work Order" +msgstr "Radni nalog" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"You should plan orders to set default production time on work orders, please" +" check" +msgstr "" +"Trebate planirati naloge za postavljanje vremena proizvodnje na radnim " +"nalozima, molimo provjerite" diff --git a/mrp_default_workorder_time/i18n/it.po b/mrp_default_workorder_time/i18n/it.po new file mode 100644 index 00000000000..667da31ef6d --- /dev/null +++ b/mrp_default_workorder_time/i18n/it.po @@ -0,0 +1,106 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_default_workorder_time +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-03-04 15:33+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"" +msgstr "" +"" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_company +msgid "Companies" +msgstr "Aziende" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_config_settings +msgid "Config Settings" +msgstr "Impostazioni di configurazione" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"Fully Productive Time is not configured on system, please contact with your " +"administrator" +msgstr "" +"L'orario di lavoro non è configurato nel sistema, contattare l'amministratore" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"If time recorded on workorder is not between this percentages, projected " +"time will be used instead" +msgstr "" +"Se l'orario registrato negli ordini di lavoro non è all'interno di questa " +"percentuale, verrà utilizzato l'orario previsto" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__maximum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__maximum_order_time_threshold +msgid "Maximum order time threshold(%)" +msgstr "Soglia orario ordine massimo (%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Maximum:" +msgstr "Massimo:" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__minimum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__minimum_order_time_threshold +msgid "Minimum order time threshold(%)" +msgstr "Soglia orario ordine minima (%)" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Minimum:" +msgstr "Minimo:" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Record standard projected order time" +msgstr "Registra orario ordine previsto standard" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__use_projected_time_work_orders +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__use_projected_time_work_orders +msgid "Use projected time work orders?" +msgstr "Usare orario previsto ordini di lavoro?" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_mrp_workorder +msgid "Work Order" +msgstr "Ordine di lavoro" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"You should plan orders to set default production time on work orders, please" +" check" +msgstr "" +"Bisogna pianiicare gli ordini per impostare l'orario di produzione " +"predefinito negli ordini di lavoro, verificare" diff --git a/mrp_default_workorder_time/i18n/mrp_default_workorder_time.pot b/mrp_default_workorder_time/i18n/mrp_default_workorder_time.pot new file mode 100644 index 00000000000..7a04c696e3c --- /dev/null +++ b/mrp_default_workorder_time/i18n/mrp_default_workorder_time.pot @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_default_workorder_time +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \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_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_company +msgid "Companies" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"Fully Productive Time is not configured on system, please contact with your " +"administrator" +msgstr "" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "" +"If time recorded on workorder is not between this percentages, projected " +"time will be used instead" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__maximum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__maximum_order_time_threshold +msgid "Maximum order time threshold(%)" +msgstr "" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Maximum:" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__minimum_order_time_threshold +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__minimum_order_time_threshold +msgid "Minimum order time threshold(%)" +msgstr "" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Minimum:" +msgstr "" + +#. module: mrp_default_workorder_time +#: model_terms:ir.ui.view,arch_db:mrp_default_workorder_time.res_config_settings_view_form +msgid "Record standard projected order time" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_company__use_projected_time_work_orders +#: model:ir.model.fields,field_description:mrp_default_workorder_time.field_res_config_settings__use_projected_time_work_orders +msgid "Use projected time work orders?" +msgstr "" + +#. module: mrp_default_workorder_time +#: model:ir.model,name:mrp_default_workorder_time.model_mrp_workorder +msgid "Work Order" +msgstr "" + +#. module: mrp_default_workorder_time +#. odoo-python +#: code:addons/mrp_default_workorder_time/models/workorder.py:0 +#, python-format +msgid "" +"You should plan orders to set default production time on work orders, please" +" check" +msgstr "" diff --git a/mrp_default_workorder_time/models/__init__.py b/mrp_default_workorder_time/models/__init__.py new file mode 100644 index 00000000000..ff59718f2fb --- /dev/null +++ b/mrp_default_workorder_time/models/__init__.py @@ -0,0 +1,3 @@ +from . import company +from . import res_config_settings +from . import workorder diff --git a/mrp_default_workorder_time/models/company.py b/mrp_default_workorder_time/models/company.py new file mode 100644 index 00000000000..2fe11bac23a --- /dev/null +++ b/mrp_default_workorder_time/models/company.py @@ -0,0 +1,21 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + use_projected_time_work_orders = fields.Boolean( + string="Use projected time work orders?", + default=True, + ) + minimum_order_time_threshold = fields.Float( + string="Minimum order time threshold(%)", + default=10, + ) + maximum_order_time_threshold = fields.Float( + string="Maximum order time threshold(%)", + default=150, + ) diff --git a/mrp_default_workorder_time/models/res_config_settings.py b/mrp_default_workorder_time/models/res_config_settings.py new file mode 100644 index 00000000000..2e0ab4df509 --- /dev/null +++ b/mrp_default_workorder_time/models/res_config_settings.py @@ -0,0 +1,18 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + use_projected_time_work_orders = fields.Boolean( + related="company_id.use_projected_time_work_orders", readonly=False + ) + minimum_order_time_threshold = fields.Float( + related="company_id.minimum_order_time_threshold", readonly=False + ) + maximum_order_time_threshold = fields.Float( + related="company_id.maximum_order_time_threshold", readonly=False + ) diff --git a/mrp_default_workorder_time/models/workorder.py b/mrp_default_workorder_time/models/workorder.py new file mode 100644 index 00000000000..f54e58b39c9 --- /dev/null +++ b/mrp_default_workorder_time/models/workorder.py @@ -0,0 +1,83 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from dateutil.relativedelta import relativedelta + +from odoo import Command, models +from odoo.exceptions import UserError +from odoo.tools import float_compare + + +class MrpWorkOrder(models.Model): + _inherit = "mrp.workorder" + + def add_time_to_work_order(self, fully_productive_time): + self.ensure_one() + date_start = self.date_start + if not date_start: + raise UserError( + self.env._( + "You should plan orders to set default " + "production time on work orders, please check" + ) + ) + date_end = self.date_start + relativedelta(minutes=self.duration_expected) + if self.time_ids: + minutes_to_add = self.duration_expected - self.duration + if float_compare(minutes_to_add, 0, precision_digits=6) == -1: + return + date_start = max(self.time_ids.mapped("date_end")) + date_end = date_start + relativedelta(minutes=minutes_to_add) + self.write( + { + "time_ids": [ + Command.create( + { + "user_id": self.env.user.id, + "date_start": date_start, + "date_end": date_end, + "loss_id": fully_productive_time.id, + "workcenter_id": self.workcenter_id.id, + "description": fully_productive_time.name, + }, + ) + ] + } + ) + + def reduce_time_to_workorder(self, fully_productive_time): + self.ensure_one() + self.time_ids.filtered( + lambda x: x.loss_id.id == fully_productive_time.id + ).sudo().unlink() + self.add_time_to_work_order(fully_productive_time) + + def button_finish(self): + res = super().button_finish() + fully_productive_time = self.env["mrp.workcenter.productivity.loss"].search( + [("loss_type", "=", "performance")], limit=1 + ) + if not fully_productive_time: + raise UserError( + self.env._( + "Fully Productive Time is not configured on system, " + "please contact with your administrator" + ) + ) + for workorder in self.filtered( + lambda x: x.state == "done" + and ( + not x.time_ids + or ( + (100 - x.duration_percent) + <= x.production_id.company_id.minimum_order_time_threshold + ) + ) + and x.production_id.company_id.use_projected_time_work_orders + ): + workorder.add_time_to_work_order(fully_productive_time) + if ( + 100 - workorder.duration_percent + ) > workorder.production_id.company_id.maximum_order_time_threshold: + workorder.reduce_time_to_workorder(fully_productive_time) + return res diff --git a/mrp_default_workorder_time/pyproject.toml b/mrp_default_workorder_time/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/mrp_default_workorder_time/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mrp_default_workorder_time/readme/CONTRIBUTORS.md b/mrp_default_workorder_time/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..85f3b90843a --- /dev/null +++ b/mrp_default_workorder_time/readme/CONTRIBUTORS.md @@ -0,0 +1,4 @@ +- Christopher Ormaza \ + +- Trobz () + - Do Anh Duy \<\> diff --git a/mrp_default_workorder_time/readme/DESCRIPTION.md b/mrp_default_workorder_time/readme/DESCRIPTION.md new file mode 100644 index 00000000000..dacf5df3792 --- /dev/null +++ b/mrp_default_workorder_time/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +There are occasions when the registration of work orders is not +completed with the correct times, this module allows you to configure a +threshold percentage that assigns the projected time as fully productive +time if a work time less than this percentage is detected. diff --git a/mrp_default_workorder_time/readme/USAGE.md b/mrp_default_workorder_time/readme/USAGE.md new file mode 100644 index 00000000000..3437c9881a8 --- /dev/null +++ b/mrp_default_workorder_time/readme/USAGE.md @@ -0,0 +1,3 @@ +In the production module configurations, the "Record standard projected +order time" feature must be activated, by default the minimum percentage +is ten but it can be changed as needed. diff --git a/mrp_default_workorder_time/static/description/icon.png b/mrp_default_workorder_time/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/mrp_default_workorder_time/static/description/icon.png differ diff --git a/mrp_default_workorder_time/static/description/index.html b/mrp_default_workorder_time/static/description/index.html new file mode 100644 index 00000000000..fba48807e48 --- /dev/null +++ b/mrp_default_workorder_time/static/description/index.html @@ -0,0 +1,439 @@ + + + + + +MRP Default Workorder Time + + + +
+

MRP Default Workorder Time

+ + +

Beta License: LGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

+

There are occasions when the registration of work orders is not +completed with the correct times, this module allows you to configure a +threshold percentage that assigns the projected time as fully productive +time if a work time less than this percentage is detected.

+

Table of contents

+ +
+

Usage

+

In the production module configurations, the “Record standard projected +order time” feature must be activated, by default the minimum percentage +is ten but it can be changed as needed.

+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

Current maintainer:

+

ChrisOForgeFlow

+

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/mrp_default_workorder_time/tests/__init__.py b/mrp_default_workorder_time/tests/__init__.py new file mode 100644 index 00000000000..1260322ffcd --- /dev/null +++ b/mrp_default_workorder_time/tests/__init__.py @@ -0,0 +1 @@ +from . import test_workorder_times diff --git a/mrp_default_workorder_time/tests/test_workorder_times.py b/mrp_default_workorder_time/tests/test_workorder_times.py new file mode 100644 index 00000000000..7bd9d24d2b9 --- /dev/null +++ b/mrp_default_workorder_time/tests/test_workorder_times.py @@ -0,0 +1,124 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from dateutil.relativedelta import relativedelta + +from odoo.fields import Command +from odoo.fields import Datetime as Dt +from odoo.tests import Form + +from odoo.addons.mrp.tests.common import TestMrpCommon + + +class TestMrpDefaultWorkorderTime(TestMrpCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.bom_2.type = "normal" + + def _create_production_with_workorders( + self, product_qty=100, set_time=False, percent_time=False + ): + fully_productive_time = self.env["mrp.workcenter.productivity.loss"].search( + [("loss_type", "=", "performance")], limit=1 + ) + mo_form = Form(self.env["mrp.production"]) + mo_form.product_id = self.bom_2.product_id + mo_form.bom_id = self.bom_2 + mo_form.product_qty = product_qty + mo = mo_form.save() + self.env["stock.quant"]._update_available_quantity( + self.product_4, self.stock_location, 200 + ) + self.env["stock.quant"]._update_available_quantity( + self.product_3, self.stock_location, 200 + ) + mo.date_start = Dt.now() + mo.action_confirm() + mo.action_assign() + mo.button_plan() + if set_time: + date_start = Dt.now() + date_end = date_start + relativedelta( + minutes=mo.workorder_ids[0].duration_expected * (percent_time / 100.0) + ) + mo.workorder_ids.write( + { + "time_ids": [ + Command.create( + { + "user_id": self.env.user.id, + "date_start": date_start, + "date_end": date_end, + "loss_id": fully_productive_time.id, + "workcenter_id": mo.workorder_ids[0].workcenter_id.id, + "description": fully_productive_time.name, + }, + ) + ] + } + ) + return mo + + def test_mrp_default_workorder_time(self): + self.stock_location = self.env.ref("stock.stock_location_stock") + mo = self._create_production_with_workorders(1) + self.assertEqual(len(mo), 1, "MO should have been created") + mo.button_mark_done() + self.assertEqual( + mo.workorder_ids[0].duration, mo.workorder_ids[0].duration_expected + ) + + mo2 = self._create_production_with_workorders( + 1, True, mo.company_id.minimum_order_time_threshold + ) + mo2.company_id.use_projected_time_work_orders = False + self.assertEqual(len(mo2), 1, "MO should have been created") + mo2.button_mark_done() + self.assertNotEqual( + mo2.workorder_ids[0].duration, mo2.workorder_ids[0].duration_expected + ) + + mo3 = self._create_production_with_workorders( + 1, True, mo.company_id.minimum_order_time_threshold + ) + mo3.company_id.use_projected_time_work_orders = True + mo3.company_id.minimum_order_time_threshold = 20 + self.assertEqual(len(mo3), 1, "MO should have been created") + mo3.button_mark_done() + self.assertEqual( + mo3.workorder_ids[0].duration, mo3.workorder_ids[0].duration_expected + ) + + mo4 = self._create_production_with_workorders( + 1, True, mo.company_id.minimum_order_time_threshold + 1 + ) + mo4.company_id.use_projected_time_work_orders = True + mo4.company_id.minimum_order_time_threshold = 20 + self.assertEqual(len(mo4), 1, "MO should have been created") + mo4.button_mark_done() + self.assertNotEqual( + mo4.workorder_ids[0].duration, mo4.workorder_ids[0].duration_expected + ) + + mo5 = self._create_production_with_workorders( + 1, True, mo.company_id.maximum_order_time_threshold + ) + mo5.company_id.use_projected_time_work_orders = True + mo5.company_id.minimum_order_time_threshold = 20 + self.assertEqual(len(mo5), 1, "MO should have been created") + mo5.button_mark_done() + self.assertNotEqual( + mo5.workorder_ids[0].duration, mo5.workorder_ids[0].duration_expected + ) + + mo6 = self._create_production_with_workorders( + 1, True, mo.company_id.maximum_order_time_threshold + 1 + ) + mo6.company_id.use_projected_time_work_orders = True + mo6.company_id.minimum_order_time_threshold = 20 + self.assertEqual(len(mo6), 1, "MO should have been created") + mo6.button_mark_done() + self.assertNotEqual( + mo6.workorder_ids[0].duration, mo6.workorder_ids[0].duration_expected + ) diff --git a/mrp_default_workorder_time/views/res_config_settings_view.xml b/mrp_default_workorder_time/views/res_config_settings_view.xml new file mode 100644 index 00000000000..cfaabf93118 --- /dev/null +++ b/mrp_default_workorder_time/views/res_config_settings_view.xml @@ -0,0 +1,36 @@ + + + + res.config.settings.view.form.inherit.mrp + res.config.settings + + + + + +
+
+ Minimum % +
+
+ Maximum % +
+
+
+
+
+
+