diff --git a/product_configurator_mrp/README.rst b/product_configurator_mrp/README.rst new file mode 100644 index 000000000..43f470e7d --- /dev/null +++ b/product_configurator_mrp/README.rst @@ -0,0 +1,88 @@ +================================== +Product Configurator Manufacturing +================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f57ae9cbefa8b335475e030e097ae2d2e530a627f774b11a501fb3231af06fe4 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-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%2Fproduct--configurator-lightgray.png?logo=github + :target: https://github.com/OCA/product-configurator/tree/17.0/product_configurator_mrp + :alt: OCA/product-configurator +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/product-configurator-17-0/product-configurator-17-0-product_configurator_mrp + :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/product-configurator&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Product Configurator wizard available on Manufacturing Orders. + +**Table of contents** + +.. contents:: + :local: + +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 +------- + +* Pledra + +Contributors +------------ + +- ``Aion Tech ``\ \_\_\_\_: + + - Simone Rubino simone.rubino@aion-tech.it + +- Murtaza Mithaiwala mmithaiwala@opensourceintegrators.com + +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-PCatinean| image:: https://github.com/PCatinean.png?size=40px + :target: https://github.com/PCatinean + :alt: PCatinean + +Current `maintainer `__: + +|maintainer-PCatinean| + +This module is part of the `OCA/product-configurator `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_configurator_mrp/__init__.py b/product_configurator_mrp/__init__.py new file mode 100644 index 000000000..5c81ea7a8 --- /dev/null +++ b/product_configurator_mrp/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models +from . import wizard diff --git a/product_configurator_mrp/__manifest__.py b/product_configurator_mrp/__manifest__.py new file mode 100644 index 000000000..2ac34e8b4 --- /dev/null +++ b/product_configurator_mrp/__manifest__.py @@ -0,0 +1,33 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Product Configurator Manufacturing", + "version": "17.0.1.0.0", + "category": "Manufacturing", + "summary": "BOM Support for configurable products", + "author": "Pledra, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/product-configurator", + "depends": ["mrp_account", "product_configurator"], + "data": [ + "data/menu_product.xml", + "views/mrp_view.xml", + "security/configurator_security.xml", + "security/ir.model.access.csv", + ], + "assets": { + "web.assets_backend": [ + "/product_configurator_mrp/static/src/js/list_controller.js", + "/product_configurator_mrp/static/src/js/kanban_controller.js", + "/product_configurator_mrp/static/src/js/form_controller.js", + "/product_configurator_mrp/static/src/scss/mrp_config.scss", + "/product_configurator_mrp/static/src/xml/mrp_production_views.xml", + ], + }, + "demo": ["demo/product_template.xml"], + "installable": True, + "auto_install": False, + "development_status": "Beta", + "maintainers": ["PCatinean"], +} diff --git a/product_configurator_mrp/data/menu_product.xml b/product_configurator_mrp/data/menu_product.xml new file mode 100644 index 000000000..2df11dbfa --- /dev/null +++ b/product_configurator_mrp/data/menu_product.xml @@ -0,0 +1,14 @@ + + + + {"search_default_consumable": 1, "default_type": "product", "search_default_filter_standard_products": 1} + + + {"search_default_filter_standard_products": 1} + + + diff --git a/product_configurator_mrp/demo/product_template.xml b/product_configurator_mrp/demo/product_template.xml new file mode 100644 index 000000000..f3d53415c --- /dev/null +++ b/product_configurator_mrp/demo/product_template.xml @@ -0,0 +1,103 @@ + + + + product + + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + + product + + diff --git a/product_configurator_mrp/i18n/de.po b/product_configurator_mrp/i18n/de.po new file mode 100644 index 000000000..aee40fea6 --- /dev/null +++ b/product_configurator_mrp/i18n/de.po @@ -0,0 +1,290 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_configurator_mrp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 9.0c\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-26 10:02+0000\n" +"PO-Revision-Date: 2016-11-26 10:02+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__value_ids +msgid "Attribute Values" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__attribute_line_ids +msgid "Attributes" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom +msgid "Bill of Material" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line +msgid "Bill of Material Line" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__bom_line_ids +msgid "BoM Lines" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__config_session_id +msgid "Config Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__config_set_id +msgid "Config Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__config_ok +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__config_ok +msgid "Configurable" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_tmpl_id +msgid "Configurable Template" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__name +msgid "Configuration" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_session_id +msgid "Configuration Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__name +msgid "Configuration Session Number" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__config_set_id +msgid "Configuration Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.ui.menu,name:product_configurator_mrp.product_menu_mrp_bom_line_config_set +msgid "Configuration Sets" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step_name +msgid "Configuration Step" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step +msgid "Configuration Step ID" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step_ids +msgid "Configuration Steps" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__configuration_ids +msgid "Configurations" +msgstr "" + +#. module: product_configurator_mrp +#. openerp-web +#: code:addons/product_configurator_mrp/static/src/xml/mrp_production_views.xml:0 +#, python-format +msgid "Configure" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__create_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__create_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__create_uid +msgid "Created by" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__create_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__create_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__create_date +msgid "Created on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__currency_id +msgid "Currency" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__custom_value_ids +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__custom_value_ids +#: model_terms:ir.ui.view,arch_db:product_configurator_mrp.mrp_production_form_view_config +msgid "Custom Values" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__display_name +msgid "Display Name" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__id +msgid "ID" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__write_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__write_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__write_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__write_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__order_id +msgid "Manufacturing Order" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line_configuration +msgid "Mrp Bom Line Configuration" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line_configuration_set +msgid "Mrp Bom Line Configuration Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_preset_id +msgid "Preset" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__price +msgid "Price" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.actions.act_window,name:product_configurator_mrp.action_mrp_bom_line_config_set +#: model:ir.ui.menu,name:product_configurator_mrp.menu_mrp_bom_line_config_set +msgid "Product Attribute Sets" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_product_config_session +msgid "Product Config Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_product_configurator_mrp +msgid "Product Configurator MRP" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_img +msgid "Product Img" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_id +msgid "Product Variant" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: product_configurator_mrp +#: model:res.groups,name:product_configurator_mrp.group_product_configurator_mrp +msgid "Products & BOMS" +msgstr "" + +#. module: product_configurator_mrp +#: model_terms:ir.ui.view,arch_db:product_configurator_mrp.mrp_production_form_view_config +msgid "Reconfigure" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,help:product_configurator_mrp.field_product_configurator_mrp__product_id +msgid "Set only when re-configuring a existing variant" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__state +msgid "State" +msgstr "" + +#. module: product_configurator_mrp +#: code:addons/product_configurator_mrp/wizard/product_configurator_mrp.py:0 +#, python-format +msgid "" +"There is no BOM associated with selected product. Please inform to " +"administrator/manager. [Product: %s]" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__user_id +msgid "User" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__value_ids +msgid "Value" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__weight +msgid "Weight" +msgstr "" + +#~ msgid "Product Template" +#~ msgstr "Produktvorlage" diff --git a/product_configurator_mrp/i18n/product_configurator_mrp.pot b/product_configurator_mrp/i18n/product_configurator_mrp.pot new file mode 100644 index 000000000..4743fd44e --- /dev/null +++ b/product_configurator_mrp/i18n/product_configurator_mrp.pot @@ -0,0 +1,286 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_configurator_mrp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.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: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__value_ids +msgid "Attribute Values" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__attribute_line_ids +msgid "Attributes" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom +msgid "Bill of Material" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line +msgid "Bill of Material Line" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__bom_line_ids +msgid "BoM Lines" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__config_session_id +msgid "Config Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__config_set_id +msgid "Config Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__config_ok +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__config_ok +msgid "Configurable" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_tmpl_id +msgid "Configurable Template" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__name +msgid "Configuration" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_session_id +msgid "Configuration Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__name +msgid "Configuration Session Number" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__config_set_id +msgid "Configuration Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.ui.menu,name:product_configurator_mrp.product_menu_mrp_bom_line_config_set +msgid "Configuration Sets" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step_name +msgid "Configuration Step" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step +msgid "Configuration Step ID" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__config_step_ids +msgid "Configuration Steps" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__configuration_ids +msgid "Configurations" +msgstr "" + +#. module: product_configurator_mrp +#. openerp-web +#: code:addons/product_configurator_mrp/static/src/xml/mrp_production_views.xml:0 +#: code:addons/product_configurator_mrp/static/src/xml/mrp_production_views.xml:0 +#: code:addons/product_configurator_mrp/static/src/xml/mrp_production_views.xml:0 +#, python-format +msgid "Configure" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__create_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__create_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__create_uid +msgid "Created by" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__create_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__create_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__create_date +msgid "Created on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__currency_id +msgid "Currency" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__custom_value_ids +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__custom_value_ids +#: model_terms:ir.ui.view,arch_db:product_configurator_mrp.mrp_production_form_view_config +msgid "Custom Values" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session__display_name +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__display_name +msgid "Display Name" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session__id +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__id +msgid "ID" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_production____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_config_session____last_update +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__write_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__write_uid +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration__write_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_mrp_bom_line_configuration_set__write_date +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__order_id +msgid "Manufacturing Order" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line_configuration +msgid "Mrp Bom Line Configuration" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_bom_line_configuration_set +msgid "Mrp Bom Line Configuration Set" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_preset_id +msgid "Preset" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__price +msgid "Price" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.actions.act_window,name:product_configurator_mrp.action_mrp_bom_line_config_set +#: model:ir.ui.menu,name:product_configurator_mrp.menu_mrp_bom_line_config_set +msgid "Product Attribute Sets" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_product_config_session +msgid "Product Config Session" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_product_configurator_mrp +msgid "Product Configurator MRP" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_img +msgid "Product Img" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__product_id +msgid "Product Variant" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model,name:product_configurator_mrp.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: product_configurator_mrp +#: model:res.groups,name:product_configurator_mrp.group_product_configurator_mrp +msgid "Products & BOMS" +msgstr "" + +#. module: product_configurator_mrp +#: model_terms:ir.ui.view,arch_db:product_configurator_mrp.mrp_production_form_view_config +msgid "Reconfigure" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,help:product_configurator_mrp.field_product_configurator_mrp__product_id +msgid "Set only when re-configuring a existing variant" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__state +msgid "State" +msgstr "" + +#. module: product_configurator_mrp +#: code:addons/product_configurator_mrp/wizard/product_configurator_mrp.py:0 +#, python-format +msgid "" +"There is no BOM associated with selected product. Please inform to " +"administrator/manager. [Product: %s]" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__user_id +msgid "User" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__value_ids +msgid "Value" +msgstr "" + +#. module: product_configurator_mrp +#: model:ir.model.fields,field_description:product_configurator_mrp.field_product_configurator_mrp__weight +msgid "Weight" +msgstr "" diff --git a/product_configurator_mrp/models/__init__.py b/product_configurator_mrp/models/__init__.py new file mode 100644 index 000000000..b3714dbfa --- /dev/null +++ b/product_configurator_mrp/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import mrp +from . import product_config diff --git a/product_configurator_mrp/models/mrp.py b/product_configurator_mrp/models/mrp.py new file mode 100644 index 000000000..3947082e4 --- /dev/null +++ b/product_configurator_mrp/models/mrp.py @@ -0,0 +1,172 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, exceptions, fields, models + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + config_ok = fields.Boolean( + related="product_id.config_ok", + store=True, + string="Configurable", + readonly=True, + ) + config_session_id = fields.Many2one( + comodel_name="product.config.session", string="Config Session" + ) + custom_value_ids = fields.One2many( + comodel_name="product.config.session.custom.value", + inverse_name="cfg_session_id", + related="config_session_id.custom_value_ids", + string="Custom Values", + ) + + @api.model + def action_config_start(self): + """Return action to start configuration wizard""" + configurator_obj = self.env["product.configurator.mrp"] + ctx = dict( + self.env.context, + wizard_id=None, + wizard_model="product.configurator.mrp", + allow_preset_selection=True, + ) + return configurator_obj.with_context(**ctx).get_wizard_action() + + def reconfigure_product(self): + """Creates and launches a product configurator wizard with a linked + template and variant in order to re-configure a existing product. It is + esetially a shortcut to pre-fill configuration data of a variant""" + wizard_model = "product.configurator.mrp" + extra_vals = {"order_id": self.id, "product_id": self.product_id.id} + self = self.with_context(default_order_id=self.id) + return self.product_id.product_tmpl_id.create_config_wizard( + model_name=wizard_model, extra_vals=extra_vals + ) + + +class MrpBom(models.Model): + _inherit = "mrp.bom" + + config_ok = fields.Boolean( + related="product_tmpl_id.config_ok", + store=True, + string="Configurable", + readonly=True, + ) + scaffolding_bom = fields.Boolean( + string="Scaffolding BoM", + help="When checked, this BoM will serve as the main BoM used by the configurator to " + "create the product variant BoM’s. Only one BoM per product can be set as a Scaffolding BoM. " + "If no scaffolding BoM exists, the configurator will then look for a BoM that doesn’t have a " + "Product Variant to use.", + ) + existing_scaffolding_bom = fields.Boolean( + string="Existing Scaffolding BoM", + compute="_compute_existing_scaffolding_bom", + store=True, + ) + + @api.model + def default_get(self, val_list): + result = super().default_get(val_list) + if result.get("product_tmpl_id"): + product_tmpl_id = self.env["product.template"].browse( + result.get("product_tmpl_id") + ) + result["company_id"] = ( + product_tmpl_id and product_tmpl_id.company_id.id or False + ) + return result + + @api.constrains("product_tmpl_id", "scaffolding_bom") + def _check_product_tmpl_scaffolding_bom(self): + """Constraint ensures only one scaffolding BoM exists per product template""" + for rec in self: + if ( + self.search_count( + [ + ("scaffolding_bom", "=", True), + ("product_tmpl_id", "=", rec.product_tmpl_id.id), + ] + ) + > 1 + ): + raise exceptions.ValidationError( + _( + "You can only have one unarchived Scaffolding BOM for a configurable product." + ) + ) + + @api.depends("scaffolding_bom", "active", "product_tmpl_id") + def _compute_existing_scaffolding_bom(self): + for rec in self: + domain = [ + ("scaffolding_bom", "=", True), + ("active", "=", True), + ("product_tmpl_id", "=", rec.product_tmpl_id.id), + ("product_id", "=", False), + ] + + # Only add the id condition if the record has an actual id (i.e., not a new record) + if rec.id: + domain.append(("id", "!=", rec.id)) + + if self.search_count(domain) >= 1: + rec.existing_scaffolding_bom = True + else: + rec.existing_scaffolding_bom = False + + @api.onchange("product_id") + def onchange_scaffolding_bom_product_id(self): + """onchange method to automatically set 'scaffolding_bom' + based on 'product_id'.""" + if self.product_id: + self.scaffolding_bom = False + else: + self.scaffolding_bom = True + + +class MrpBomLine(models.Model): + _inherit = "mrp.bom.line" + + config_set_id = fields.Many2one( + comodel_name="mrp.bom.line.configuration.set", + string="Configuration Set", + ) + + +class MrpBomLineConfigurationSet(models.Model): + _name = "mrp.bom.line.configuration.set" + _description = "Mrp Bom Line Configuration Set" + + name = fields.Char(string="Configuration", required=True) + configuration_ids = fields.One2many( + comodel_name="mrp.bom.line.configuration", + inverse_name="config_set_id", + string="Configurations", + ) + bom_line_ids = fields.One2many( + comodel_name="mrp.bom.line", + inverse_name="config_set_id", + string="BoM Lines", + readonly=True, + ) + + +class MrpBomLineConfiguration(models.Model): + _name = "mrp.bom.line.configuration" + _description = "Mrp Bom Line Configuration" + + config_set_id = fields.Many2one( + comodel_name="mrp.bom.line.configuration.set", + ondelete="cascade", + required=True, + ) + value_ids = fields.Many2many( + string="Attribute Values", + comodel_name="product.attribute.value", + required=True, + ) diff --git a/product_configurator_mrp/models/product_config.py b/product_configurator_mrp/models/product_config.py new file mode 100644 index 000000000..524e815ca --- /dev/null +++ b/product_configurator_mrp/models/product_config.py @@ -0,0 +1,160 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ProductConfigSession(models.Model): + _inherit = "product.config.session" + + def create_get_bom(self, variant, product_tmpl_id=None, values=None): + # default_type is set as 'product' when the user navigates + # through menu item "Products". This conflicts + # with the type for mrp.bom when mrpBom.onchange() is executed. + ctx = self.env.context.copy() + if ctx.get("default_type"): + ctx.pop("default_type") + self.env.context = ctx + + if values is None: + values = {} + if product_tmpl_id is None or variant.product_tmpl_id != product_tmpl_id: + product_tmpl_id = variant.product_tmpl_id + + mrpBom = self.env["mrp.bom"] + mrpBomLine = self.env["mrp.bom.line"] + attr_products = variant.product_template_attribute_value_ids.mapped( + "product_attribute_value_id.product_id" + ) + attr_values = variant.product_template_attribute_value_ids.mapped( + "product_attribute_value_id" + ) + existing_bom = self.env["mrp.bom"].search( + [ + ("product_tmpl_id", "=", product_tmpl_id.id), + ("product_id", "=", variant.id), + ] + ) + if existing_bom: + return existing_bom[:1] + + parent_bom = self.env["mrp.bom"].search( + [ + ("product_tmpl_id", "=", product_tmpl_id.id), + ("product_id", "=", False), + ("scaffolding_bom", "=", True), + ], + order="sequence asc", + limit=1, + ) + if not parent_bom: + parent_bom = self.env["mrp.bom"].search( + [ + ("product_tmpl_id", "=", product_tmpl_id.id), + ("product_id", "=", False), + ], + order="sequence asc", + limit=1, + ) + bom_type = parent_bom and parent_bom.type or "normal" + bom_lines = [] + if not parent_bom: + # If not Bom, then Cycle through attributes to add their + # related products to the bom lines. + for product in attr_products: + bom_line_vals = {"product_id": product.id, "product_qty": 1} + specs = self.get_onchange_specifications(model="mrp.bom.line") + for key, val in specs.items(): + if val is None: + specs[key] = {} + updates = mrpBomLine.onchange( + bom_line_vals, ["product_id", "product_qty"], specs + ) + values = updates.get("value", {}) + values = self.get_vals_to_write(values=values, model="mrp.bom.line") + values.update(bom_line_vals) + bom_lines.append((0, 0, values)) + else: + # If parent BOM is used, then look through Config Sets + # on parent product's bom to add the products to the bom lines. + for parent_bom_line in parent_bom.bom_line_ids: + if parent_bom_line.config_set_id: + for config in parent_bom_line.config_set_id.configuration_ids: + # Add bom lines if config values are part of attr_values + if set(config.value_ids.ids).issubset(set(attr_values.ids)): + if parent_bom_line.bom_id.id == parent_bom.id: + parent_bom_line_vals = { + "product_id": parent_bom_line.product_id.id, + "product_qty": parent_bom_line.product_qty, + } + specs = self.get_onchange_specifications( + model="mrp.bom.line" + ) + for key, val in specs.items(): + if val is None: + specs[key] = {} + updates = mrpBomLine.onchange( + parent_bom_line_vals, + ["product_id", "product_qty"], + specs, + ) + values = updates.get("value", {}) + values = self.get_vals_to_write( + values=values, model="mrp.bom.line" + ) + values.update(parent_bom_line_vals) + bom_lines.append((0, 0, parent_bom_line_vals)) + else: + parent_bom_line_vals = { + "product_id": parent_bom_line.product_id.id, + "product_qty": parent_bom_line.product_qty, + } + specs = self.get_onchange_specifications(model="mrp.bom.line") + for key, val in specs.items(): + if val is None: + specs[key] = {} + updates = mrpBomLine.onchange( + parent_bom_line_vals, ["product_id", "product_qty"], specs + ) + values = updates.get("value", {}) + values = self.get_vals_to_write(values=values, model="mrp.bom.line") + values.update(parent_bom_line_vals) + bom_lines.append((0, 0, values)) + if bom_lines: + bom_values = { + "product_tmpl_id": self.product_tmpl_id.id, + "product_id": variant.id, + "type": bom_type, + "bom_line_ids": bom_lines, + } + specs = self.get_onchange_specifications(model="mrp.bom") + for key, val in specs.items(): + if val is None: + specs[key] = {} + updates = mrpBom.onchange( + bom_values, + [ + "product_id", + "product_configurator_sale_mrproduct_tmpl_id", + "bom_line_ids", + ], + specs, + ) + values = updates.get("value", {}) + values = self.get_vals_to_write(values=values, model="mrp.bom") + values.update(bom_values) + mrp_bom_id = mrpBom.sudo().create(values) + if mrp_bom_id and parent_bom: + if mrp_bom_id.company_id and not parent_bom.company_id: + mrp_bom_id.company_id = False + for operation_line in parent_bom.operation_ids: + operation_line.copy(default={"bom_id": mrp_bom_id.id}) + return mrp_bom_id + return False + + def create_get_variant(self, value_ids=None, custom_vals=None): + variant = super().create_get_variant( + value_ids=value_ids, custom_vals=custom_vals + ) + self.create_get_bom(variant=variant, product_tmpl_id=self.product_tmpl_id) + return variant diff --git a/product_configurator_mrp/pyproject.toml b/product_configurator_mrp/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/product_configurator_mrp/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/product_configurator_mrp/readme/CONTRIBUTORS.md b/product_configurator_mrp/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..0d82b8c89 --- /dev/null +++ b/product_configurator_mrp/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ + - `Aion Tech `____: + + * Simone Rubino + + - Murtaza Mithaiwala diff --git a/product_configurator_mrp/readme/DESCRIPTION.md b/product_configurator_mrp/readme/DESCRIPTION.md new file mode 100644 index 000000000..81abc2d53 --- /dev/null +++ b/product_configurator_mrp/readme/DESCRIPTION.md @@ -0,0 +1 @@ +Product Configurator wizard available on Manufacturing Orders. diff --git a/product_configurator_mrp/security/configurator_security.xml b/product_configurator_mrp/security/configurator_security.xml new file mode 100644 index 000000000..7d2d3a4c0 --- /dev/null +++ b/product_configurator_mrp/security/configurator_security.xml @@ -0,0 +1,13 @@ + + + + Products & BOMS + + + + + + diff --git a/product_configurator_mrp/security/ir.model.access.csv b/product_configurator_mrp/security/ir.model.access.csv new file mode 100644 index 000000000..89e00886d --- /dev/null +++ b/product_configurator_mrp/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_mrp_bom_line_configuration_set,access_mrp_bom_line_configuration_set,model_mrp_bom_line_configuration_set,product_configurator.group_product_configurator_manager,1,1,1,1 +access_mrp_bom_line_configuration,access_mrp_bom_line_configuration,model_mrp_bom_line_configuration,product_configurator.group_product_configurator_manager,1,1,1,1 +access_product_configurator_mrp,product_configurator_mrp,model_product_configurator_mrp,product_configurator.group_product_configurator_manager,1,1,1,1 diff --git a/product_configurator_mrp/static/description/icon.png b/product_configurator_mrp/static/description/icon.png new file mode 100644 index 000000000..d5d307c64 Binary files /dev/null and b/product_configurator_mrp/static/description/icon.png differ diff --git a/product_configurator_mrp/static/description/index.html b/product_configurator_mrp/static/description/index.html new file mode 100644 index 000000000..2131e3e17 --- /dev/null +++ b/product_configurator_mrp/static/description/index.html @@ -0,0 +1,427 @@ + + + + + + +Product Configurator Manufacturing + + + +
+

Product Configurator Manufacturing

+ + +

Beta License: AGPL-3 OCA/product-configurator Translate me on Weblate Try me on Runboat

+

Product Configurator wizard available on Manufacturing Orders.

+

Table of contents

+ +
+

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

+
    +
  • Pledra
  • +
+
+
+

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:

+

PCatinean

+

This module is part of the OCA/product-configurator project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/product_configurator_mrp/static/src/js/form_controller.js b/product_configurator_mrp/static/src/js/form_controller.js new file mode 100644 index 000000000..c0be68ead --- /dev/null +++ b/product_configurator_mrp/static/src/js/form_controller.js @@ -0,0 +1,34 @@ +/** @odoo-module **/ + +import {_t} from "@web/core/l10n/translation"; +import {registry} from "@web/core/registry"; +import {useService} from "@web/core/utils/hooks"; +import {formView} from "@web/views/form/form_view"; +import {FormController} from "@web/views/form/form_controller"; + +export class ProductConfiguratorFormController extends FormController { + setup() { + super.setup(); + this.action = useService("action"); + this.rpc = useService("rpc"); + this.orm = useService("orm"); + } + + async _onConfigure() { + let action = await this.orm.call("mrp.production", "action_config_start", []); + this.action.doAction(action); + } +} +ProductConfiguratorFormController.components = { + ...FormController.components, +}; + +export const ProductConfiguratorFormView = { + ...formView, + Controller: ProductConfiguratorFormController, + buttonTemplate: "product_configurator_mrp.FormButtons", +}; + +registry + .category("views") + .add("product_configurator_mrp_form", ProductConfiguratorFormView); diff --git a/product_configurator_mrp/static/src/js/kanban_controller.js b/product_configurator_mrp/static/src/js/kanban_controller.js new file mode 100644 index 000000000..ba2511a93 --- /dev/null +++ b/product_configurator_mrp/static/src/js/kanban_controller.js @@ -0,0 +1,33 @@ +/** @odoo-module **/ + +import {_t} from "@web/core/l10n/translation"; +import {registry} from "@web/core/registry"; +import {useService} from "@web/core/utils/hooks"; +import {kanbanView} from "@web/views/kanban/kanban_view"; +import {KanbanController} from "@web/views/kanban/kanban_controller"; + +export class ProductConfiguratorKanbanController extends KanbanController { + setup() { + super.setup(); + this.action = useService("action"); + this.rpc = useService("rpc"); + this.orm = useService("orm"); + } + + async _onConfigure() { + let action = await this.orm.call("mrp.production", "action_config_start", []); + this.action.doAction(action); + } +} +ProductConfiguratorKanbanController.components = { + ...KanbanController.components, +}; + +export const ProductConfiguratorKanbanView = { + ...kanbanView, + Controller: ProductConfiguratorKanbanController, + buttonTemplate: "product_configurator_mrp.KanbanButtons", +}; +registry + .category("views") + .add("product_configurator_mrp_kanban", ProductConfiguratorKanbanView); diff --git a/product_configurator_mrp/static/src/js/list_controller.js b/product_configurator_mrp/static/src/js/list_controller.js new file mode 100644 index 000000000..17a3bb92e --- /dev/null +++ b/product_configurator_mrp/static/src/js/list_controller.js @@ -0,0 +1,35 @@ +/** @odoo-module **/ + +import {_t} from "@web/core/l10n/translation"; +import {registry} from "@web/core/registry"; +import {listView} from "@web/views/list/list_view"; +import {ListController} from "@web/views/list/list_controller"; +import {useService} from "@web/core/utils/hooks"; + +export class ProductConfiguratorController extends ListController { + setup() { + super.setup(); + this.action = useService("action"); + this.rpc = useService("rpc"); + this.orm = useService("orm"); + } + + async _onConfigure() { + let action = await this.orm.call("mrp.production", "action_config_start", []); + this.action.doAction(action); + } +} + +ProductConfiguratorController.components = { + ...ListController.components, +}; + +export const ProductConfiguratorListView = { + ...listView, + Controller: ProductConfiguratorController, + buttonTemplate: "product_configurator_mrp.ListButtons", +}; + +registry + .category("views") + .add("product_configurator_mrp_tree", ProductConfiguratorListView); diff --git a/product_configurator_mrp/static/src/scss/mrp_config.scss b/product_configurator_mrp/static/src/scss/mrp_config.scss new file mode 100644 index 000000000..7bf54a56a --- /dev/null +++ b/product_configurator_mrp/static/src/scss/mrp_config.scss @@ -0,0 +1,9 @@ +.o_list_button_add_config { + display: none; +} +.o-kanban-button-new_config { + display: none; +} +.o_form_button_create_config { + display: none; +} diff --git a/product_configurator_mrp/static/src/xml/mrp_production_views.xml b/product_configurator_mrp/static/src/xml/mrp_production_views.xml new file mode 100644 index 000000000..aef0a3c23 --- /dev/null +++ b/product_configurator_mrp/static/src/xml/mrp_production_views.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/product_configurator_mrp/tests/__init__.py b/product_configurator_mrp/tests/__init__.py new file mode 100644 index 000000000..56a908793 --- /dev/null +++ b/product_configurator_mrp/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# from . import test_mrp diff --git a/product_configurator_mrp/tests/test_mrp.py b/product_configurator_mrp/tests/test_mrp.py new file mode 100644 index 000000000..e25c1a3c2 --- /dev/null +++ b/product_configurator_mrp/tests/test_mrp.py @@ -0,0 +1,126 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from datetime import datetime + +from odoo.addons.product_configurator.tests.test_product_configurator_test_cases import ( + ProductConfiguratorTestCases, +) + + +class TestMrp(ProductConfiguratorTestCases): + def setUp(self): + super().setUp() + self.mrpBomConfigSet = self.env["mrp.bom.line.configuration.set"] + self.mrpBomConfig = self.env["mrp.bom.line.configuration"] + self.mrpBom = self.env["mrp.bom"] + self.mrpBomLine = self.env["mrp.bom.line"] + self.mrpRoutingWorkcenter = self.env["mrp.routing.workcenter"] + self.productProduct = self.env["product.product"] + self.productTemplate = self.env["product.template"] + self.mrpProduction = self.env["mrp.production"] + self.product_id = self.env.ref("product.product_product_3") + self.workcenter_id = self.env.ref("mrp.mrp_workcenter_3") + + # create bom + self.bom_id = self.mrpBom.create( + { + "product_tmpl_id": self.product_id.product_tmpl_id.id, + "product_qty": 1.00, + "type": "normal", + "ready_to_produce": "all_available", + } + ) + # create bom line + self.bom_line_id = self.mrpBomLine.create( + { + "bom_id": self.bom_id.id, + "product_id": self.product_id.id, + "product_qty": 1.00, + } + ) + # create BOM operations line + self.mrpRoutingWorkcenter.create( + { + "bom_id": self.bom_id.id, + "name": "Operation 1", + "workcenter_id": self.workcenter_id.id, + } + ) + + def test_00_skip_bom_line(self): + checkVal = self.mrpBomLine._skip_bom_line(product=self.product_id) + self.assertFalse( + checkVal, + "Error: If value exists\ + Method: _skip_bom_line()", + ) + self.bom_line_id.bom_id.config_ok = True + self.mrp_config_step = self.mrpBomConfigSet.create( + { + "name": "TestConfigSet", + } + ) + self.bom_line_id.write({"config_set_id": self.mrp_config_step.id}) + # create bom_line_config + self.mrp_bom_config = self.mrpBomConfig.create( + { + "config_set_id": self.mrp_config_step.id, + "value_ids": [ + ( + 6, + 0, + [ + self.value_gasoline.id, + self.value_218i.id, + self.value_220i.id, + self.value_red.id, + ], + ) + ], + } + ) + self.product_id.write( + {"attribute_value_ids": [(6, 0, self.mrp_bom_config.value_ids.ids)]} + ) + self.mrpProduction.create( + { + "product_id": self.product_id.id, + "product_qty": 1.00, + "product_uom_id": 1.00, + "bom_id": self.bom_id.id, + "date_planned_start": datetime.now(), + } + ) + self.mrpBomLine._skip_bom_line(product=self.product_id) + self.assertFalse( + checkVal, + "Error: If value exists\ + Method: _skip_bom_line()", + ) + + def test_01_action_config_start(self): + mrpProduction = self.mrpProduction.create( + { + "product_id": self.product_id.id, + "product_qty": 1.00, + "product_uom_id": 1.00, + "bom_id": self.bom_id.id, + "date_planned_start": datetime.now(), + } + ) + context = dict( + self.env.context, + default_order_id=mrpProduction.id, + wizard_model="product.configurator.mrp", + ) + mrpProduction.action_config_start() + self.ProductConfWizard = self.env["product.configurator.mrp"].with_context( + **context + ) + self._configure_product_nxt_step() + # self.assertEqual( + # vals['res_id'], + # mrpProduction.product_id.id, + # 'Not Equal' + # ) diff --git a/product_configurator_mrp/views/mrp_view.xml b/product_configurator_mrp/views/mrp_view.xml new file mode 100644 index 000000000..3b125f8c4 --- /dev/null +++ b/product_configurator_mrp/views/mrp_view.xml @@ -0,0 +1,193 @@ + + + + + product.config.mrp.form.view + mrp.production + + + + product_configurator_mrp_form + + + oe_title col-lg-10 col-md-9 col-sm-9 col-xs-12 pull-left + + +
+ +
+
+ + + + + + + + + + + +
+
+ + + product.config.mrp.tree.view + mrp.production + + + + product_configurator_mrp_tree + + + + + + product.config.mrp.kanban.view + mrp.production + + + + product_configurator_mrp_kanban + + + + + + {"search_default_todo": True, "default_company_id": allowed_company_ids[0], "custom_create_variant": True} + + + + product.config.mrp.bom.tree.view + mrp.bom + + + + + + + + + + + product.config.mrp.bom.form.view + mrp.bom + + + + + + + + + "config_ok" + True + + + + parent.type not in ('normal', 'phantom') + parent.config_ok + + + + + + + + + + + + + + + + + mrp.bom.line.configuration.set.form.view + mrp.bom.line.configuration.set + +
+ + + + + + + + + + + + + + +
+
+
+ + + mrp.bom.line.configuration.set.tree.view + mrp.bom.line.configuration.set + + + + + + + + + Product Attribute Sets + mrp.bom.line.configuration.set + tree,form + + + + + + +
diff --git a/product_configurator_mrp/wizard/__init__.py b/product_configurator_mrp/wizard/__init__.py new file mode 100644 index 000000000..47b38a648 --- /dev/null +++ b/product_configurator_mrp/wizard/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import product_configurator_mrp diff --git a/product_configurator_mrp/wizard/product_configurator_mrp.py b/product_configurator_mrp/wizard/product_configurator_mrp.py new file mode 100644 index 000000000..167aad464 --- /dev/null +++ b/product_configurator_mrp/wizard/product_configurator_mrp.py @@ -0,0 +1,104 @@ +# Copyright (C) 2021 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.safe_eval import safe_eval + + +class ProductConfiguratorMrp(models.TransientModel): + _name = "product.configurator.mrp" + _inherit = "product.configurator" + _description = "Product Configurator MRP" + + order_id = fields.Many2one( + comodel_name="mrp.production", string="Manufacturing Order" + ) + + domain_attr_ids = fields.Many2many( + "product.attribute.value", + "domain_attrs_mrp_configurator_rel", + "wiz_id", + "attribute_id", + string="Domain", + ) + + domain_attr_2_ids = fields.Many2many( + "product.attribute.value", + "domain_attrs_mrp_configurator_2_rel", + "wiz_id", + "attribute_id", + string="Domain 2", + ) + + def get_mrp_production_action(self): + mrp_action = self.env.ref("mrp.mrp_production_action").read() + if mrp_action: + mrp_action = mrp_action[0] + context = safe_eval( + mrp_action["context"], self.env.context.copy(), nocopy=True + ) + context.update(self.env.context) + mrp_action.update( + { + "view_mode": "form", + "context": context, + "views": [(False, "form")], + } + ) + else: + mrp_action = { + "type": "ir.actions.act_window", + "res_model": "mrp.production", + "name": "Manufacturing Order", + "view_mode": "form", + "context": self.env.context, + "views": [(False, "form")], + } + return mrp_action + + def _get_order_vals(self, product_id): + """Hook to allow custom line values to be put on the newly + created or edited lines.""" + product = self.env["product.product"].browse(product_id) + bom = self.config_session_id.create_get_bom( + variant=product, + ) + line_vals = { + "bom_id": bom.id, + "product_uom_id": product.uom_id.id, + "config_session_id": self.config_session_id.id, + } + return line_vals + + def action_config_done(self): + """Parse values and execute final code before closing the wizard""" + res = super().action_config_done() + if res.get("res_model") == self._name: + return res + model_name = "mrp.production" + line_vals = self._get_order_vals(res["res_id"]) + # mrpProduction = self.env[model_name] + cfg_session = self.config_session_id + # specs = cfg_session.get_onchange_specifications(model=model_name) + # updates = mrpProduction.onchange(line_vals, ["bom_id"], specs) + # values = updates.get("value", {}) + # values = cfg_session.get_vals_to_write(values=values, model=model_name) + # values.update(line_vals) + if not line_vals.get("bom_id"): + raise ValidationError( + _( + "There is no BOM associated with selected product. " + "Please inform to administrator/manager. [Product: %s]" + % (self.env["product.product"].browse(res["res_id"]).display_name) + ) + ) + + if self.order_id: + self.order_id.write(line_vals) + mrp_order = self.order_id + else: + mrp_order = self.order_id.create(line_vals) + mrp_action = self.get_mrp_production_action() + mrp_action.update({"res_id": mrp_order.id}) + return mrp_action