diff --git a/ddmrp_product_replace/README.rst b/ddmrp_product_replace/README.rst new file mode 100644 index 000000000..0524dcc5a --- /dev/null +++ b/ddmrp_product_replace/README.rst @@ -0,0 +1,125 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +===================== +DDMRP Product Replace +===================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f09b719afa62bdd5ac4e164c3f124ba9c6f3e725d83275fb5c32a16e46ff64f8 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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%2Fddmrp-lightgray.png?logo=github + :target: https://github.com/OCA/ddmrp/tree/19.0/ddmrp_product_replace + :alt: OCA/ddmrp +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/ddmrp-19-0/ddmrp-19-0-ddmrp_product_replace + :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/ddmrp&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Provides a tool for product replacement. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Go to *Inventory > Configuration > DDMRP > Product Replacement Tool*. + +Then you can fill the wizard options to complete the replacement. There +are two modes of operation: *Create a new buffer for the replacing +product* and *Replace product in existing buffers*. + +Known issues / Roadmap +====================== + +- Option to create new buffer and make old ones inactive. +- Consider Demand estimates in the replacement. + +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 +------------ + +- Lois Rilo + +- Jordi Ballester + +- Akim Juillerat + +- `Trobz `__: + + - Khoi Vo + +Other credits +------------- + +The initial development of this module has been financially supported +by: + +- Aleph Objects, Inc. + +The migration of this module from 13.0 to 14.0 was financially supported +by Camptocamp + +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-JordiBForgeFlow| image:: https://github.com/JordiBForgeFlow.png?size=40px + :target: https://github.com/JordiBForgeFlow + :alt: JordiBForgeFlow +.. |maintainer-LoisRForgeFlow| image:: https://github.com/LoisRForgeFlow.png?size=40px + :target: https://github.com/LoisRForgeFlow + :alt: LoisRForgeFlow + +Current `maintainers `__: + +|maintainer-JordiBForgeFlow| |maintainer-LoisRForgeFlow| + +This module is part of the `OCA/ddmrp `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/ddmrp_product_replace/__init__.py b/ddmrp_product_replace/__init__.py new file mode 100644 index 000000000..aee8895e7 --- /dev/null +++ b/ddmrp_product_replace/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/ddmrp_product_replace/__manifest__.py b/ddmrp_product_replace/__manifest__.py new file mode 100644 index 000000000..eee54c659 --- /dev/null +++ b/ddmrp_product_replace/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2017-21 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "DDMRP Product Replace", + "summary": "Provides a assisting tool for product replacement.", + "version": "19.0.1.0.0", + "development_status": "Beta", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "maintainers": ["JordiBForgeFlow", "LoisRForgeFlow"], + "website": "https://github.com/OCA/ddmrp", + "category": "Warehouse Management", + "depends": ["ddmrp_chatter"], + "data": [ + "security/ir.model.access.csv", + "wizards/ddmrp_product_replace_view.xml", + "wizards/make_procurement_buffer_view.xml", + "views/stock_buffer_view.xml", + ], + "license": "LGPL-3", + "installable": True, +} diff --git a/ddmrp_product_replace/i18n/ddmrp_product_replace.pot b/ddmrp_product_replace/i18n/ddmrp_product_replace.pot new file mode 100644 index 000000000..d5688f6e3 --- /dev/null +++ b/ddmrp_product_replace/i18n/ddmrp_product_replace.pot @@ -0,0 +1,368 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ddmrp_product_replace +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.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: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "" +"\n" +" When there are more than one product replaced, only the buffer(s) of the primary product in\n" +" this list will be used to create the buffer(s) and/or product(s) for replacement." +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "" +"" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_make_procurement_buffer_wizard +msgid "" +"" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "or" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__buffer_ids +msgid "Affected Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffered product must be considered as demand." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffers Replaced" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Cancel" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old Product Demand" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old product moves as demand for new product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "Considered As Demand" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_packaging +msgid "Copy Packaging" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_putaway +msgid "Copy Put Away Strategy" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_route +msgid "Copy Routes" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__new +msgid "Create New Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__new_buffer +msgid "Create a new buffer for the replacing product." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_uid +msgid "Created by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_date +msgid "Created on" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_ddmrp_product_replace +msgid "DDMRP Product Replace" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__display_name +msgid "Display Name" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__has_replaced_buffers +msgid "Has Replaced Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__id +msgid "ID" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "" +"If you tick this option, the buffer will consider the incoming and on-hand " +"of all products it replaces and this will impact its NFP." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "Include Incoming & On-Hands of replaced products" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__is_already_replaced +msgid "Is Already Replaced" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_date +msgid "Last Updated on" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_make_procurement_buffer +msgid "Make Procurements from Stock Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__mode +msgid "Mode" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__multi_product +msgid "Multi Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_default_code +msgid "New Product Internal Ref." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_name +msgid "New Product Name" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "New Stock Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "No affected buffers found." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__primary_old_product_id +msgid "Primary Replaced Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Product Replacement" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.actions.act_window,name:ddmrp_product_replace.action_ddmrp_product_replace_wizard +#: model:ir.ui.menu,name:ddmrp_product_replace.menu_ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Product Replacement Tool" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Product that is going to replace the other one." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Product to be replaced." +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replace Buffer" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__use_existing +msgid "Replace product in existing buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__replaced_by_alert_text +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_alert_text +msgid "Replaced By Alert Text" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Replaced Products" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "Replaced by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_count +msgid "Replacement For Count" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__is_replacement_product +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_search +msgid "Replacement Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replacement for" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_ids +msgid "Replaces" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Replacing Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replaced Products" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replacing Product" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "" +"Some of the affected buffers have a different product than the replaced " +"ones." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Some of the buffers have already been replaced." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/make_procurement_buffer.py:0 +msgid "Some products are being replaced:" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_buffer +msgid "Stock Buffer" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Substitute Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "" +"The product in this buffer is replaced by the product of selected buffer. When you replace another buffer:\n" +" - Past Demand of the replacement buffer will include the past demand of this product\n" +" - Several buffers can be replaced in chained and coexist at the same time: A replaces B that replaces C, then A aggregates both B and C where B only aggregates C" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__is_replacement_product +msgid "The product of this buffer is replacing another product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "" +"This field is used for a correct product replacement within a DDMRP buffer." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "This product is replaced by %s." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__existing +msgid "Use Existing Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__use_existing +msgid "Use Existing/New Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Validate" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "You cannot create recursive \"Replaced by\" chains." +msgstr "" diff --git a/ddmrp_product_replace/i18n/es.po b/ddmrp_product_replace/i18n/es.po new file mode 100644 index 000000000..5b9981e4c --- /dev/null +++ b/ddmrp_product_replace/i18n/es.po @@ -0,0 +1,404 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ddmrp_product_replace +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-17 21:35+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: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "" +"\n" +" When there are more than one product replaced, " +"only the buffer(s) of the primary product in\n" +" this list will be used to create the buffer(s) " +"and/or product(s) for replacement." +msgstr "" +"\n" +" Cuando hay más de un producto reemplazado, sólo " +"el búfer(es) del producto primario en\n" +" esta lista se utilizará para crear el búfer (s) " +"y / o producto (s) para el reemplazo." + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "" +"" +msgstr "" +"" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_make_procurement_buffer_wizard +msgid "" +"" +msgstr "" +"" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "or" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__buffer_ids +msgid "Affected Buffers" +msgstr "Búferes afectados" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffered product must be considered as demand." +msgstr "El producto tamponado debe considerarse como demanda." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffers Replaced" +msgstr "Búferes sustituidos" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old Product Demand" +msgstr "Considerar la Demanda de Productos Antiguos" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old product moves as demand for new product" +msgstr "Considerar que el producto antiguo se desplaza como demanda del nuevo" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "Considered As Demand" +msgstr "Considerada como Demanda" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_packaging +msgid "Copy Packaging" +msgstr "Embalaje de Copias" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_putaway +msgid "Copy Put Away Strategy" +msgstr "Estrategia de retirada de copias" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_route +msgid "Copy Routes" +msgstr "Copiar Rutas" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__new +msgid "Create New Product" +msgstr "Crear un Nuevo Producto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__new_buffer +msgid "Create a new buffer for the replacing product." +msgstr "Crear una nueva memoria intermedia para el producto de sustitución." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_ddmrp_product_replace +msgid "DDMRP Product Replace" +msgstr "Sustitución del Producto DDMRP" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__has_replaced_buffers +msgid "Has Replaced Buffers" +msgstr "Ha Sustituido a Los Búferes" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "" +"If you tick this option, the buffer will consider the incoming and on-hand " +"of all products it replaces and this will impact its NFP." +msgstr "" +"Si marca esta opción, el buffer tendrá en cuenta las entradas y salidas de " +"todos los productos que sustituya y esto repercutirá en su PFN." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "Include Incoming & On-Hands of replaced products" +msgstr "Incluir productos entrantes y disponibles de productos reemplazados" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__is_already_replaced +msgid "Is Already Replaced" +msgstr "Ya ha sido Sustituido" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_uid +msgid "Last Updated by" +msgstr "Última Actualzacíón por" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_make_procurement_buffer +msgid "Make Procurements from Stock Buffers" +msgstr "Crear Abastecimientos desde Búfer de Inventario" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__mode +msgid "Mode" +msgstr "Modo" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__multi_product +msgid "Multi Product" +msgstr "Multi Producto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_default_code +msgid "New Product Internal Ref." +msgstr "Nuevo Producto Ref. Interna." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_name +msgid "New Product Name" +msgstr "Nuevo Nombre de Producto" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "New Stock Buffers" +msgstr "Nuevos Topes de Existencias" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "No affected buffers found." +msgstr "No se ha encontrado ningún búfer afectado." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__primary_old_product_id +msgid "Primary Replaced Product" +msgstr "Producto Primario Sustituido" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Product Replacement" +msgstr "Sustitución de Productos" + +#. module: ddmrp_product_replace +#: model:ir.actions.act_window,name:ddmrp_product_replace.action_ddmrp_product_replace_wizard +#: model:ir.ui.menu,name:ddmrp_product_replace.menu_ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Product Replacement Tool" +msgstr "Herramienta de Sustitución de Productos" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Product that is going to replace the other one." +msgstr "Producto que va a sustituir al otro." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Product to be replaced." +msgstr "Producto que debe sustituirse." + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replace Buffer" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__use_existing +msgid "Replace product in existing buffers" +msgstr "Sustituir el producto en los topes existentes" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__replaced_by_alert_text +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_alert_text +msgid "Replaced By Alert Text" +msgstr "Sustituido por Texto de Alerta" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Replaced Products" +msgstr "Productos Sustituidos" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "Replaced by" +msgstr "Sustituido por" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_count +msgid "Replacement For Count" +msgstr "Sustitución para el Conteo" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__is_replacement_product +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_search +msgid "Replacement Product" +msgstr "Producto de Sustitución" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replacement for" +msgstr "Sustitución para" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_ids +msgid "Replaces" +msgstr "Sustituye" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Replacing Product" +msgstr "Sustitución del Producto" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replaced Products" +msgstr "Seleccionar Productos Sustituidos" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replacing Product" +msgstr "Seleccione el Producto Sustitutivo" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "" +"Some of the affected buffers have a different product than the replaced ones." +msgstr "" +"Algunos de los búferes afectados tienen un producto diferente al de los " +"sustituidos." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Some of the buffers have already been replaced." +msgstr "Algunos de los topes ya han sido sustituidos." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/make_procurement_buffer.py:0 +msgid "Some products are being replaced:" +msgstr "Algunos productos están siendo sustituidos:" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_buffer +msgid "Stock Buffer" +msgstr "Búfer de Inventario" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de Existencias" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Substitute Product" +msgstr "Productos Sustitutivos" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "" +"The product in this buffer is replaced by the product of selected buffer. " +"When you replace another buffer:\n" +" - Past Demand of the replacement buffer will include the past demand of " +"this product\n" +" - Several buffers can be replaced in chained and coexist at the same time: " +"A replaces B that replaces C, then A aggregates both B and C where B only " +"aggregates C" +msgstr "" +"El producto de este búfer se sustituye por el producto del búfer " +"seleccionado. Cuando se reemplaza otro búfer:\n" +" - La demanda pasada del búfer de sustitución incluirá la demanda pasada de " +"este producto\n" +" - Varios búferes pueden ser reemplazados en cadena y coexistir al mismo " +"tiempo: A sustituye a B que sustituye a C, entonces A agrega tanto B como C " +"donde B sólo agrega C" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__is_replacement_product +msgid "The product of this buffer is replacing another product" +msgstr "El producto de este búfer sustituye a otro producto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "" +"This field is used for a correct product replacement within a DDMRP buffer." +msgstr "" +"Este campo se utiliza para una correcta sustitución del producto dentro de " +"un búfer DDMRP." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "This product is replaced by %s." +msgstr "Este producto se sustituye por %s." + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__existing +msgid "Use Existing Product" +msgstr "Utilizar el Producto Existente" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__use_existing +msgid "Use Existing/New Product" +msgstr "Utilizar Producto Existente/Nuevo" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Validate" +msgstr "Validado" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "You cannot create recursive \"Replaced by\" chains." +msgstr "No se pueden crear cadenas \"Sustituido por\" recursivas." + +#~ msgid "Last Modified on" +#~ msgstr "Última Actualización el" + +#~ msgid "or" +#~ msgstr "o" diff --git a/ddmrp_product_replace/i18n/it.po b/ddmrp_product_replace/i18n/it.po new file mode 100644 index 000000000..22a302e82 --- /dev/null +++ b/ddmrp_product_replace/i18n/it.po @@ -0,0 +1,405 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ddmrp_product_replace +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2026-02-16 15:09+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 5.15.2\n" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "" +"\n" +" When there are more than one product replaced, " +"only the buffer(s) of the primary product in\n" +" this list will be used to create the buffer(s) " +"and/or product(s) for replacement." +msgstr "" +"\n" +" Quando c'è più di un prodotto sostituito, solo " +"il buffer del prodotto primario in\n" +" questa lista verrà utilizzato per creare il " +"buffer e/o il prodotto per la sostituzione." + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "" +"" +msgstr "" +"" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_make_procurement_buffer_wizard +msgid "" +"" +msgstr "" +"" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "or" +msgstr "o" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__buffer_ids +msgid "Affected Buffers" +msgstr "Buffer coinvolti" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffered product must be considered as demand." +msgstr "I prodotti nei buffer devono essere considerati come fabbisogno." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffers Replaced" +msgstr "Buffer sostituiti" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Cancel" +msgstr "Annulla" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old Product Demand" +msgstr "Considerare vecchio fabbisogno prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old product moves as demand for new product" +msgstr "" +"Considerare i vecchi movimenti prodotto come fabbisogno per nuovi prodotti" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "Considered As Demand" +msgstr "Considerato come fabbisogno" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_packaging +msgid "Copy Packaging" +msgstr "Copia imballaggio" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_putaway +msgid "Copy Put Away Strategy" +msgstr "Copia strategia inoltro" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_route +msgid "Copy Routes" +msgstr "Copia rotte" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__new +msgid "Create New Product" +msgstr "Crea nuovo prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__new_buffer +msgid "Create a new buffer for the replacing product." +msgstr "Creare un nuovo buffer per il prodotto da sostituire." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_ddmrp_product_replace +msgid "DDMRP Product Replace" +msgstr "Sostituzione prodotto DDMRP" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__has_replaced_buffers +msgid "Has Replaced Buffers" +msgstr "Ha buffer sostituiti" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__id +msgid "ID" +msgstr "ID" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "" +"If you tick this option, the buffer will consider the incoming and on-hand " +"of all products it replaces and this will impact its NFP." +msgstr "" +"Se si seleziona questa opzione, il buffer considererà gli ingressi e le " +"disponibilità di tutti i prodotti che sostituisce e questo impatterà il suo " +"NFP." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "Include Incoming & On-Hands of replaced products" +msgstr "Includere ingressi e disponibilità dei prodotti sostituiti" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__is_already_replaced +msgid "Is Already Replaced" +msgstr "Già sostituito" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_make_procurement_buffer +msgid "Make Procurements from Stock Buffers" +msgstr "Esegue approvvigionamenti dai buffer di materiale" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__mode +msgid "Mode" +msgstr "Modo" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__multi_product +msgid "Multi Product" +msgstr "Multi prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_default_code +msgid "New Product Internal Ref." +msgstr "Rif. interno nuovo prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_name +msgid "New Product Name" +msgstr "Nome nuovo prodotto" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "New Stock Buffers" +msgstr "Nuovi buffer di materiale" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "No affected buffers found." +msgstr "Nessun buffer coinvolto." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__primary_old_product_id +msgid "Primary Replaced Product" +msgstr "Prodotto sostituito primario" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Product Replacement" +msgstr "Sostituzione prodotto" + +#. module: ddmrp_product_replace +#: model:ir.actions.act_window,name:ddmrp_product_replace.action_ddmrp_product_replace_wizard +#: model:ir.ui.menu,name:ddmrp_product_replace.menu_ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Product Replacement Tool" +msgstr "Strumento sostituzione prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Product that is going to replace the other one." +msgstr "Prodotto che sta sostituendo l'altro." + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Product to be replaced." +msgstr "Prodotto da sostituire." + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replace Buffer" +msgstr "Sostituisci buffer" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__use_existing +msgid "Replace product in existing buffers" +msgstr "Sostituisce prodotto nei buffer esistenti" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__replaced_by_alert_text +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_alert_text +msgid "Replaced By Alert Text" +msgstr "Sostituito da testo allerta" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Replaced Products" +msgstr "Prodotti sostituiti" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "Replaced by" +msgstr "Sostituito da" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_count +msgid "Replacement For Count" +msgstr "Sostituzione per conteggio" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__is_replacement_product +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_search +msgid "Replacement Product" +msgstr "Prodotto sostitutivo" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replacement for" +msgstr "Sostituzione per" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_ids +msgid "Replaces" +msgstr "Sostituisce" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Replacing Product" +msgstr "Sostituzione prodotto" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replaced Products" +msgstr "Selezionare prodotti sostituiti" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replacing Product" +msgstr "Selezionare prodotto sostituto" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "" +"Some of the affected buffers have a different product than the replaced ones." +msgstr "" +"Alcuni dei buffer coinvolti hanno un prodotto diverso da quello sostituito." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Some of the buffers have already been replaced." +msgstr "Alcuni dei prodotti sono già stati sostituiti." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/make_procurement_buffer.py:0 +msgid "Some products are being replaced:" +msgstr "Alcuni prodotti verranno sostituiti:" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_buffer +msgid "Stock Buffer" +msgstr "Buffer di materiale" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_move +msgid "Stock Move" +msgstr "Movimento di magazzino" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Substitute Product" +msgstr "Prodotto sostitutivo" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "" +"The product in this buffer is replaced by the product of selected buffer. " +"When you replace another buffer:\n" +" - Past Demand of the replacement buffer will include the past demand of " +"this product\n" +" - Several buffers can be replaced in chained and coexist at the same time: " +"A replaces B that replaces C, then A aggregates both B and C where B only " +"aggregates C" +msgstr "" +"il prodotto in questo buffer è sostituito dal prodotto del buffer " +"selezionato. Quando si sostituisce un altro buffer:\n" +" - il fabbisogno passato del buffer sostituito includerà il fabbisogno " +"passato di questo prodotto\n" +" - diversi buffer possono essere sostituiti in sequenza e coesistere allo " +"stesso tempo: A sostituisce B che sostituisce C, quindi A aggrega sia B che " +"C dove B aggrega solo C" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__is_replacement_product +msgid "The product of this buffer is replacing another product" +msgstr "Il prodotto di questo buffer sta sostituendo un altro prodotto" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "" +"This field is used for a correct product replacement within a DDMRP buffer." +msgstr "" +"Questo campo è utilizzato per una sostituzione corretta all'interno di un " +"buffer DDMRP." + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "This product is replaced by %s." +msgstr "Questo prodotto è sostituito da %s." + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__existing +msgid "Use Existing Product" +msgstr "Usa prodotto esistente" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__use_existing +msgid "Use Existing/New Product" +msgstr "Utilizza prodotto esistente/nuovo" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Validate" +msgstr "Valida" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "You cannot create recursive \"Replaced by\" chains." +msgstr "Non si possono creare catene \"sostituito da\" ricorsive." + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "or" +#~ msgstr "o" diff --git a/ddmrp_product_replace/i18n/pt_BR.po b/ddmrp_product_replace/i18n/pt_BR.po new file mode 100644 index 000000000..a2d506f09 --- /dev/null +++ b/ddmrp_product_replace/i18n/pt_BR.po @@ -0,0 +1,377 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ddmrp_product_replace +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-05-29 15:36+0000\n" +"Last-Translator: Rodrigo Macedo " +"\n" +"Language-Team: none\n" +"Language: pt_BR\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: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "" +"\n" +" When there are more than one product replaced, " +"only the buffer(s) of the primary product in\n" +" this list will be used to create the buffer(s) " +"and/or product(s) for replacement." +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "" +"" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_make_procurement_buffer_wizard +msgid "" +"" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "or" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__buffer_ids +msgid "Affected Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffered product must be considered as demand." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "Buffers Replaced" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Cancel" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old Product Demand" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__consider_past_demand +msgid "Consider Old product moves as demand for new product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "Considered As Demand" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_packaging +msgid "Copy Packaging" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_putaway +msgid "Copy Put Away Strategy" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__copy_route +msgid "Copy Routes" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__new +msgid "Create New Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__new_buffer +msgid "Create a new buffer for the replacing product." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_uid +msgid "Created by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__create_date +msgid "Created on" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_ddmrp_product_replace +msgid "DDMRP Product Replace" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__display_name +msgid "Display Name" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__has_replaced_buffers +msgid "Has Replaced Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__id +msgid "ID" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "" +"If you tick this option, the buffer will consider the incoming and on-hand " +"of all products it replaces and this will impact its NFP." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__use_replacement_for_buffer_status +msgid "Include Incoming & On-Hands of replaced products" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__is_already_replaced +msgid "Is Already Replaced" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__write_date +msgid "Last Updated on" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_make_procurement_buffer +msgid "Make Procurements from Stock Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__mode +msgid "Mode" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__multi_product +msgid "Multi Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_default_code +msgid "New Product Internal Ref." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_name +msgid "New Product Name" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "New Stock Buffers" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "No affected buffers found." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__primary_old_product_id +msgid "Primary Replaced Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Product Replacement" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.actions.act_window,name:ddmrp_product_replace.action_ddmrp_product_replace_wizard +#: model:ir.ui.menu,name:ddmrp_product_replace.menu_ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Product Replacement Tool" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Product that is going to replace the other one." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Product to be replaced." +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replace Buffer" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__mode__use_existing +msgid "Replace product in existing buffers" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_make_procurement_buffer__replaced_by_alert_text +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_alert_text +msgid "Replaced By Alert Text" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__old_product_ids +msgid "Replaced Products" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "Replaced by" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_count +msgid "Replacement For Count" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__is_replacement_product +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_search +msgid "Replacement Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.stock_buffer_view_form +msgid "Replacement for" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_stock_buffer__replacement_for_ids +msgid "Replaces" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Replacing Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replaced Products" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Select Replacing Product" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "" +"Some of the affected buffers have a different product than the replaced ones." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/ddmrp_product_replace.py:0 +msgid "Some of the buffers have already been replaced." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/wizards/make_procurement_buffer.py:0 +msgid "Some products are being replaced:" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_buffer +msgid "Stock Buffer" +msgstr "Buffer de estoque" + +#. module: ddmrp_product_replace +#: model:ir.model,name:ddmrp_product_replace.model_stock_move +msgid "Stock Move" +msgstr "Movimento de estoque" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__new_product_id +msgid "Substitute Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__replaced_by_id +msgid "" +"The product in this buffer is replaced by the product of selected buffer. " +"When you replace another buffer:\n" +" - Past Demand of the replacement buffer will include the past demand of " +"this product\n" +" - Several buffers can be replaced in chained and coexist at the same time: " +"A replaces B that replaces C, then A aggregates both B and C where B only " +"aggregates C" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__is_replacement_product +msgid "The product of this buffer is replacing another product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,help:ddmrp_product_replace.field_stock_buffer__demand_product_ids +msgid "" +"This field is used for a correct product replacement within a DDMRP buffer." +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "This product is replaced by %s." +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields.selection,name:ddmrp_product_replace.selection__ddmrp_product_replace__use_existing__existing +msgid "Use Existing Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model:ir.model.fields,field_description:ddmrp_product_replace.field_ddmrp_product_replace__use_existing +msgid "Use Existing/New Product" +msgstr "" + +#. module: ddmrp_product_replace +#: model_terms:ir.ui.view,arch_db:ddmrp_product_replace.view_ddmrp_adjustment_sheet_wizard_form +msgid "Validate" +msgstr "" + +#. module: ddmrp_product_replace +#. odoo-python +#: code:addons/ddmrp_product_replace/models/stock_buffer.py:0 +msgid "You cannot create recursive \"Replaced by\" chains." +msgstr "" diff --git a/ddmrp_product_replace/models/__init__.py b/ddmrp_product_replace/models/__init__.py new file mode 100644 index 000000000..911aa93ea --- /dev/null +++ b/ddmrp_product_replace/models/__init__.py @@ -0,0 +1,2 @@ +from . import stock_buffer +from . import stock_move diff --git a/ddmrp_product_replace/models/stock_buffer.py b/ddmrp_product_replace/models/stock_buffer.py new file mode 100644 index 000000000..f27e184af --- /dev/null +++ b/ddmrp_product_replace/models/stock_buffer.py @@ -0,0 +1,187 @@ +# Copyright 2019-21 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models +from odoo.exceptions import ValidationError + + +class StockBuffer(models.Model): + _inherit = "stock.buffer" + + replaced_by_id = fields.Many2one( + comodel_name="stock.buffer", + string="Replaced by", + help="The product in this buffer is replaced by the product of selected " + "buffer. When you replace another buffer:\n - Past Demand of the " + "replacement buffer will include the past demand of this product\n" + " - Several buffers can be replaced in chained and coexist at the " + "same time: A replaces B that replaces C, then A aggregates both B" + " and C where B only aggregates C", + tracking=True, + readonly=True, + ) + replaced_by_alert_text = fields.Char( + compute="_compute_replaced_by_alert_text", + ) + replacement_for_ids = fields.One2many( + string="Replaces", + comodel_name="stock.buffer", + inverse_name="replaced_by_id", + ) + replacement_for_count = fields.Integer( + compute="_compute_replacement_for_count", + ) + is_replacement_product = fields.Boolean( + string="Replacement Product", + compute="_compute_is_replacement_product", + store=True, + help="The product of this buffer is replacing another product", + ) + demand_product_ids = fields.Many2many( + comodel_name="product.product", + string="Considered As Demand", + help="This field is used for a correct product replacement within a " + "DDMRP buffer.", + copy=False, + ) + use_replacement_for_buffer_status = fields.Boolean( + string="Include Incoming & On-Hands of replaced products", + compute="_compute_use_replacement_for_buffer_status", + store=True, + readonly=False, + copy=False, + help="If you tick this option, the buffer will consider the incoming " + "and on-hand of all products it replaces and this will impact its " + "NFP.", + ) + + @api.constrains("replaced_by_id") + def _check_replaced_by_id(self): + if self._has_cycle(field_name="replaced_by_id"): + raise ValidationError( + self.env._('You cannot create recursive "Replaced by" chains.') + ) + + @api.constrains("demand_product_ids") + def _check_demand_product_ids(self): + for rec in self: + if rec.demand_product_ids and rec.product_id not in rec.demand_product_ids: + raise ValidationError( + self.env._("Buffered product must be considered as demand.") + ) + + def _compute_replaced_by_alert_text(self): + for rec in self: + if rec.replaced_by_id: + rec.replaced_by_alert_text = self.env._( + "This product is replaced by %s.", + rec.replaced_by_id.product_id.display_name, + ) + else: + rec.replaced_by_alert_text = "" + + def _compute_replacement_for_count(self): + for rec in self: + rec.replacement_for_count = len(rec.replacement_for_ids) + + @api.depends("replaced_by_id", "replacement_for_ids", "replacement_for_ids.active") + def _compute_is_replacement_product(self): + for rec in self: + rec.is_replacement_product = ( + rec.replacement_for_ids and not rec.replaced_by_id + ) + + @api.depends("item_type") + def _compute_use_replacement_for_buffer_status(self): + for rec in self: + rec.use_replacement_for_buffer_status = rec.item_type in [ + "manufactured", + "purchased", + ] + + @api.depends("item_type") + def _compute_procure_recommended_qty(self): + replaced = self.filtered( + lambda r: r.replaced_by_id and r.item_type in ["manufactured", "purchased"] + ) + res = super(StockBuffer, self - replaced)._compute_procure_recommended_qty() + for rec in replaced: + rec.procure_recommended_qty = 0.0 + return res + + def _past_moves_domain(self, date_from, date_to, locations): + if not self.demand_product_ids: + return super()._past_moves_domain(date_from, date_to, locations) + domain = super()._past_moves_domain(date_from, date_to, locations) + index_replace = False + for n, clause in enumerate(domain): + if isinstance(clause, tuple) and clause[0] == "product_id": + index_replace = n + if isinstance(index_replace, int): + domain[index_replace] = ("product_id", "in", self.demand_product_ids.ids) + return domain + + @api.model + def _recursive_replacement_for_ids(self, buffers): + """Returns the list of buffers being replaced recursively.""" + res = self.env["stock.buffer"] + for rec in buffers: + if rec.replacement_for_ids: + res += self._recursive_replacement_for_ids(rec.replacement_for_ids) + res += rec + return res + + def _calc_product_available_qty(self): + res = super()._calc_product_available_qty() + for rec in self: + if not (rec.use_replacement_for_buffer_status and rec.replacement_for_ids): + continue + for buffer in rec.replacement_for_ids: + # Update 'incoming_total_qty' + replacements_incoming_qty = buffer.product_uom._compute_quantity( + buffer.incoming_total_qty, + rec.product_uom, + round=False, + ) + rec.incoming_total_qty += replacements_incoming_qty + # Update 'product_location_qty_available_not_res' + replacements_qty_not_res = buffer.product_uom._compute_quantity( + buffer.product_location_qty_available_not_res, + rec.product_uom, + round=False, + ) + rec.product_location_qty_available_not_res += replacements_qty_not_res + return res + + def _search_stock_moves_incoming_domain(self, outside_dlt=False): + domain = super()._search_stock_moves_incoming_domain(outside_dlt=outside_dlt) + if not (self.use_replacement_for_buffer_status and self.replacement_for_ids): + return domain + index_replace = False + for n, clause in enumerate(domain): + if isinstance(clause, tuple) and clause[0] == "product_id": + index_replace = n + if isinstance(index_replace, int): + domain[index_replace] = ( + "product_id", + "in", + (self + self._recursive_replacement_for_ids(self.replacement_for_ids)) + .mapped("product_id") + .ids, + ) + return domain + + def _search_stock_moves_qualified_demand_domain(self): + domain = super()._search_stock_moves_qualified_demand_domain() + if not self.demand_product_ids: + return domain + domain = [x for x in domain if x[0] != "product_id"] + [ + ("product_id", "in", self.demand_product_ids.ids) + ] + return domain + + def action_view_buffers_replaced(self): + result = self.env["ir.actions.actions"]._for_xml_id("ddmrp.action_stock_buffer") + result["name"] = self.env._("Buffers Replaced") + result["domain"] = [("id", "in", self.replacement_for_ids.ids)] + return result diff --git a/ddmrp_product_replace/models/stock_move.py b/ddmrp_product_replace/models/stock_move.py new file mode 100644 index 000000000..fdb0e3ef0 --- /dev/null +++ b/ddmrp_product_replace/models/stock_move.py @@ -0,0 +1,22 @@ +# Copyright 2021 ForgeFlow S.L. (http://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class StockMove(models.Model): + _inherit = "stock.move" + + def _find_buffers_to_update_nfp(self): + out_buffers, in_buffers = super()._find_buffers_to_update_nfp() + new_out_buffers = out_buffers + while new_out_buffers: + new_out_buffers = new_out_buffers.mapped("replaced_by_id") + out_buffers |= new_out_buffers + + new_in_buffers = in_buffers + while new_in_buffers: + new_in_buffers = new_in_buffers.mapped("replaced_by_id") + in_buffers |= new_in_buffers + + return out_buffers, in_buffers diff --git a/ddmrp_product_replace/pyproject.toml b/ddmrp_product_replace/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/ddmrp_product_replace/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/ddmrp_product_replace/readme/CONTRIBUTORS.md b/ddmrp_product_replace/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..e07faafa3 --- /dev/null +++ b/ddmrp_product_replace/readme/CONTRIBUTORS.md @@ -0,0 +1,8 @@ +- Lois Rilo \<\> + +- Jordi Ballester \<\> + +- Akim Juillerat \<\> + +- [Trobz](https://trobz.com): + - Khoi Vo \<\> diff --git a/ddmrp_product_replace/readme/CREDITS.md b/ddmrp_product_replace/readme/CREDITS.md new file mode 100644 index 000000000..f77962869 --- /dev/null +++ b/ddmrp_product_replace/readme/CREDITS.md @@ -0,0 +1,7 @@ +The initial development of this module has been financially supported +by: + +- Aleph Objects, Inc. + +The migration of this module from 13.0 to 14.0 was financially supported +by Camptocamp diff --git a/ddmrp_product_replace/readme/DESCRIPTION.md b/ddmrp_product_replace/readme/DESCRIPTION.md new file mode 100644 index 000000000..136e83fbc --- /dev/null +++ b/ddmrp_product_replace/readme/DESCRIPTION.md @@ -0,0 +1 @@ +Provides a tool for product replacement. diff --git a/ddmrp_product_replace/readme/ROADMAP.md b/ddmrp_product_replace/readme/ROADMAP.md new file mode 100644 index 000000000..57d278713 --- /dev/null +++ b/ddmrp_product_replace/readme/ROADMAP.md @@ -0,0 +1,2 @@ +- Option to create new buffer and make old ones inactive. +- Consider Demand estimates in the replacement. diff --git a/ddmrp_product_replace/readme/USAGE.md b/ddmrp_product_replace/readme/USAGE.md new file mode 100644 index 000000000..142968605 --- /dev/null +++ b/ddmrp_product_replace/readme/USAGE.md @@ -0,0 +1,5 @@ +Go to *Inventory \> Configuration \> DDMRP \> Product Replacement Tool*. + +Then you can fill the wizard options to complete the replacement. There +are two modes of operation: *Create a new buffer for the replacing +product* and *Replace product in existing buffers*. diff --git a/ddmrp_product_replace/security/ir.model.access.csv b/ddmrp_product_replace/security/ir.model.access.csv new file mode 100644 index 000000000..d32bc316f --- /dev/null +++ b/ddmrp_product_replace/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_ddmrp_product_replace,access_ddmrp_product_replace,model_ddmrp_product_replace,ddmrp.group_stock_buffer_maintainer,1,1,1,0 diff --git a/ddmrp_product_replace/static/description/icon.png b/ddmrp_product_replace/static/description/icon.png new file mode 100644 index 000000000..90c92e98d Binary files /dev/null and b/ddmrp_product_replace/static/description/icon.png differ diff --git a/ddmrp_product_replace/static/description/index.html b/ddmrp_product_replace/static/description/index.html new file mode 100644 index 000000000..18499e06d --- /dev/null +++ b/ddmrp_product_replace/static/description/index.html @@ -0,0 +1,464 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

DDMRP Product Replace

+ +

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

+

Provides a tool for product replacement.

+

Table of contents

+ +
+

Usage

+

Go to Inventory > Configuration > DDMRP > Product Replacement Tool.

+

Then you can fill the wizard options to complete the replacement. There +are two modes of operation: Create a new buffer for the replacing +product and Replace product in existing buffers.

+
+
+

Known issues / Roadmap

+
    +
  • Option to create new buffer and make old ones inactive.
  • +
  • Consider Demand estimates in the replacement.
  • +
+
+
+

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

+ +
+
+

Other credits

+

The initial development of this module has been financially supported +by:

+
    +
  • Aleph Objects, Inc.
  • +
+

The migration of this module from 13.0 to 14.0 was financially supported +by Camptocamp

+
+
+

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 maintainers:

+

JordiBForgeFlow LoisRForgeFlow

+

This module is part of the OCA/ddmrp project on GitHub.

+

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

+
+
+
+
+ + diff --git a/ddmrp_product_replace/tests/__init__.py b/ddmrp_product_replace/tests/__init__.py new file mode 100644 index 000000000..74c5eae89 --- /dev/null +++ b/ddmrp_product_replace/tests/__init__.py @@ -0,0 +1 @@ +from . import test_product_replace diff --git a/ddmrp_product_replace/tests/test_product_replace.py b/ddmrp_product_replace/tests/test_product_replace.py new file mode 100644 index 000000000..c4cb0b5e2 --- /dev/null +++ b/ddmrp_product_replace/tests/test_product_replace.py @@ -0,0 +1,146 @@ +# Copyright 2018 Camptocamp SA +# Copyright 2018-21 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import datetime, timedelta + +from odoo.addons.ddmrp.tests.common import TestDdmrpCommon + + +class TestDDMRPProductReplace(TestDdmrpCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.buffer = cls.buffer_rm01 + cls.old_product = cls.product_rm01 + cls.put_away_rule_obj = cls.env["stock.putaway.rule"] + cls.old_product.write( + { + "route_ids": [ + (6, 0, [cls.env.ref("mrp.route_warehouse0_manufacture").id]) + ], + } + ) + cls.old_product_putaway = cls.put_away_rule_obj.create( + { + "product_id": cls.old_product.id, + "location_in_id": cls.env.ref("stock.stock_location_stock").id, + "location_out_id": cls.location_shelf1.id, + } + ) + # Change adu method: + method = cls.env.ref("ddmrp.adu_calculation_method_past_120") + cls.buffer.adu_calculation_method = method + + def test_01_product_replace_use_existing(self): + date_move = datetime.today() - timedelta(days=30) + picking = self.create_picking_out(self.old_product, date_move, 60) + self._do_picking(picking, date_move) + self.buffer._calc_adu() + adu_previous = 60 / 120 + self.assertEqual(self.buffer.adu, adu_previous) + self.assertEqual(self.buffer.product_id, self.old_product) + self.assertEqual(len(self.buffer.demand_product_ids), 0) + + wiz = self.env["ddmrp.product.replace"].create( + { + "mode": "use_existing", + "old_product_ids": [(6, 0, self.buffer.product_id.ids)], + "use_existing": "new", + "new_product_name": "RM-01 Replacement", + "new_product_default_code": "ABCDE012345", + "copy_route": True, + "copy_putaway": True, + } + ) + self.assertEqual(wiz.buffer_ids, self.buffer) + new_product_id = wiz.button_validate().get("res_id") + new_product = self.env["product.product"].browse(new_product_id) + + self.assertEqual(new_product.name, "RM-01 Replacement") + self.assertEqual(new_product.default_code, "ABCDE012345") + self.assertEqual(new_product.route_ids, self.old_product.route_ids) + + new_product_putaway = self.put_away_rule_obj.search( + [("product_id", "=", new_product.id)] + ) + new_putaway_tuple = ( + new_product_putaway.location_in_id.id, + new_product_putaway.location_out_id.id, + ) + for putaway in self.old_product_putaway: + putaway_tuple = (putaway.location_in_id.id, putaway.location_out_id.id) + self.assertEqual(putaway_tuple, new_putaway_tuple) + + self.assertEqual(self.buffer.product_id, new_product) + self.assertIn(self.old_product, self.buffer.demand_product_ids) + self.buffer._calc_adu() + self.assertEqual(self.buffer.adu, adu_previous) + + def test_02_product_replace_new_buffer(self): + # Complete one delivery + date_move = datetime.today() - timedelta(days=30) + picking = self.create_picking_out(self.old_product, date_move, 60) + self._do_picking(picking, date_move) + # and confirm an incoming + self.create_picking_in(self.old_product, datetime.today(), 30) + self.buffer.cron_actions() + self.assertEqual(self.buffer.product_id, self.old_product) + self.assertEqual(len(self.buffer.demand_product_ids), 0) + old_onhand = self.buffer.product_location_qty_available_not_res + self.assertEqual(old_onhand, -60.0) + old_incoming_dlt_qty = self.buffer.incoming_dlt_qty + self.assertEqual(old_incoming_dlt_qty, 30.0) + old_incoming_qty = self.buffer.incoming_total_qty + self.assertEqual(old_incoming_qty, 30.0) + wiz = self.env["ddmrp.product.replace"].create( + { + "mode": "new_buffer", + "old_product_ids": [(6, 0, self.buffer.product_id.ids)], + "use_existing": "new", + "new_product_name": "RM-01 Replacement 2", + "new_product_default_code": "ABC000222", + "copy_route": True, + "copy_putaway": False, + } + ) + self.assertEqual(wiz.buffer_ids, self.buffer) + self.assertFalse(wiz.is_already_replaced) + res = wiz.button_validate() + new_buffer_ids = res.get("domain")[0][2] + model = res.get("res_model") + self.assertEqual(model, "stock.buffer") + new_buffer = self.bufferModel.browse(new_buffer_ids) + self.assertEqual(len(new_buffer), 1) + self.assertNotEqual(self.buffer.id, new_buffer.id) + # Check new product + new_product = new_buffer.product_id + self.assertEqual(new_product.name, "RM-01 Replacement 2") + self.assertEqual(new_product.default_code, "ABC000222") + self.assertEqual(new_product.route_ids, self.old_product.route_ids) + self.assertNotEqual(self.buffer.product_id, new_product) + # Check replacing fields in buffers: + self.assertEqual(self.buffer.replaced_by_id, new_buffer) + self.assertTrue(new_buffer.is_replacement_product) + self.assertTrue(new_buffer.use_replacement_for_buffer_status) + # Check buffer values: + self.buffer.cron_actions() + self.assertEqual(old_onhand, new_buffer.product_location_qty_available_not_res) + self.assertEqual(old_incoming_dlt_qty, new_buffer.incoming_dlt_qty) + self.assertEqual(old_incoming_qty, new_buffer.incoming_total_qty) + new_buffer.invalidate_recordset() + new_buffer.use_replacement_for_buffer_status = False + new_buffer.cron_actions() + self.assertNotEqual( + old_onhand, new_buffer.product_location_qty_available_not_res + ) + self.assertNotEqual(old_incoming_dlt_qty, new_buffer.incoming_dlt_qty) + self.assertNotEqual(old_incoming_qty, new_buffer.incoming_total_qty) + # Demand: + self.assertIn(self.old_product, new_buffer.demand_product_ids) + self.assertEqual(new_buffer.qualified_demand, 0) + self.create_picking_out(self.old_product, datetime.today(), 11) + self.buffer.cron_actions() + self.assertEqual(self.buffer.qualified_demand, 11) + new_buffer.cron_actions() + self.assertEqual(new_buffer.qualified_demand, 11) diff --git a/ddmrp_product_replace/views/stock_buffer_view.xml b/ddmrp_product_replace/views/stock_buffer_view.xml new file mode 100644 index 000000000..1894c5838 --- /dev/null +++ b/ddmrp_product_replace/views/stock_buffer_view.xml @@ -0,0 +1,98 @@ + + + + + stock.buffer.form - ddmrp_product_replace + stock.buffer + + + + + +
+ +
+ + + + + + + + + + + +
+
+ + stock.buffer.tree - ddmrp_product_replace + stock.buffer + + + + + + + + + + stock.buffer.search - ddmrp_product_replace + stock.buffer + + + + + + + + +
diff --git a/ddmrp_product_replace/wizards/__init__.py b/ddmrp_product_replace/wizards/__init__.py new file mode 100644 index 000000000..67932ed67 --- /dev/null +++ b/ddmrp_product_replace/wizards/__init__.py @@ -0,0 +1,2 @@ +from . import ddmrp_product_replace +from . import make_procurement_buffer diff --git a/ddmrp_product_replace/wizards/ddmrp_product_replace.py b/ddmrp_product_replace/wizards/ddmrp_product_replace.py new file mode 100644 index 000000000..93bfe620a --- /dev/null +++ b/ddmrp_product_replace/wizards/ddmrp_product_replace.py @@ -0,0 +1,223 @@ +# Copyright 2017-21 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models +from odoo.exceptions import ValidationError + + +class DdmrpProductReplace(models.TransientModel): + _name = "ddmrp.product.replace" + _description = "DDMRP Product Replace" + + old_product_ids = fields.Many2many( + comodel_name="product.product", + string="Replaced Products", + help="Product to be replaced.", + required=True, + ondelete="cascade", + ) + multi_product = fields.Boolean(compute="_compute_multi_product") + primary_old_product_id = fields.Many2one( + string="Primary Replaced Product", + comodel_name="product.product", + compute="_compute_primary_old_product_id", + store=True, + readonly=False, + domain="[('id', 'in', old_product_ids)]", + ) + buffer_ids = fields.Many2many( + comodel_name="stock.buffer", + string="Affected Buffers", + readonly=False, + compute="_compute_buffer_ids", + store=True, + ) + is_already_replaced = fields.Boolean( + compute="_compute_is_already_replaced", + ) + new_product_id = fields.Many2one( + comodel_name="product.product", + string="Substitute Product", + help="Product that is going to replace the other one.", + ) + mode = fields.Selection( + selection=[ + ("new_buffer", "Create a new buffer for the replacing product."), + ("use_existing", "Replace product in existing buffers"), + ], + default="new_buffer", + required=True, + ) + use_existing = fields.Selection( + string="Use Existing/New Product", + required=True, + selection=[("existing", "Use Existing Product"), ("new", "Create New Product")], + ) + new_product_name = fields.Char() + new_product_default_code = fields.Char(string="New Product Internal Ref.") + copy_route = fields.Boolean(string="Copy Routes") + copy_putaway = fields.Boolean(string="Copy Put Away Strategy") + copy_packaging = fields.Boolean() + consider_past_demand = fields.Boolean( + string="Consider Old Product Demand", + help="Consider Old product moves as demand for new product", + default=True, + ) + + @api.depends("old_product_ids") + def _compute_multi_product(self): + for rec in self: + rec.multi_product = len(rec.old_product_ids) > 1 + + @api.depends("old_product_ids") + def _compute_primary_old_product_id(self): + for rec in self: + rec.primary_old_product_id = rec.old_product_ids[:1]._origin + + @api.depends("old_product_ids") + def _compute_buffer_ids(self): + for rec in self: + rec.buffer_ids = self.env["stock.buffer"].search( + [("product_id", "in", rec.old_product_ids.ids)] + ) + + @api.depends("buffer_ids") + def _compute_is_already_replaced(self): + for rec in self: + rec.is_already_replaced = any(b.replaced_by_id for b in rec.buffer_ids) + + @api.constrains("buffer_ids") + def _check_buffer_ids(self): + for rec in self: + if rec.old_product_ids and any( + b.product_id not in rec.old_product_ids for b in rec.buffer_ids + ): + raise ValidationError( + self.env._( + "Some of the affected buffers have a different product than " + "the replaced ones." + ) + ) + + def _do_replacement_use_existing(self): + vals = { + "product_id": self.new_product_id.id, + } + if self.consider_past_demand: + vals["demand_product_ids"] = [ + (6, 0, (self.old_product_ids + self.new_product_id).ids) + ] + self.buffer_ids.write(vals) + return { + "name": self.env._("Replacing Product"), + "res_id": self.new_product_id.id, + "view_type": "form", + "view_mode": "form", + "res_model": "product.product", + "type": "ir.actions.act_window", + } + + def _get_new_buffer_default_value(self): + return dict( + product_id=self.new_product_id.id, + auto_procure=False, + demand_product_ids=False, + ) + + def _do_replacement_new_buffer(self): + primary_old = self.primary_old_product_id + new_buffers = self.env["stock.buffer"] + for replaced in self.buffer_ids.filtered(lambda b: b.product_id == primary_old): + default = self._get_new_buffer_default_value() + replacing = replaced.copy(default=default) + replaced.write({"replaced_by_id": replacing.id}) + new_buffers |= replacing + for replaced in self.buffer_ids.filtered(lambda b: b.product_id != primary_old): + # Do not create buffers for non-primary products. + # Instead assign one of the already created. + replacing = new_buffers.filtered( + lambda b: b.location_id == replaced.location_id # noqa: B023 + )[:1] + if not replacing: + replacing = new_buffers[0] + replaced.write({"replaced_by_id": replacing.id}) + if self.consider_past_demand: + for buffer in new_buffers: + recursive_buffers = buffer._recursive_replacement_for_ids( + buffer.replacement_for_ids + ) + buffer.write( + { + "demand_product_ids": [ + ( + 6, + 0, + ( + recursive_buffers.mapped("product_id") + + buffer.product_id + ).ids, + ) + ], + } + ) + new_buffers.cron_actions() + return { + "name": self.env._("New Stock Buffers"), + "domain": [("id", "in", new_buffers.ids)], + "view_mode": "list,form", + "res_model": "stock.buffer", + "type": "ir.actions.act_window", + } + + def button_validate(self): + self.ensure_one() + if self.is_already_replaced: + raise ValidationError( + self.env._("Some of the buffers have already been replaced.") + ) + if not self.buffer_ids: + raise ValidationError(self.env._("No affected buffers found.")) + # Only the first product is used as a template to create new products/buffers. + primary_old = self.primary_old_product_id + if self.use_existing == "new": + default = dict( + name=self.new_product_name, + default_code=self.new_product_default_code, + ) + if not self.copy_route: + default["route_ids"] = None + self.new_product_id = primary_old.copy(default=default) + elif self.use_existing == "existing": + if self.copy_route: + self.new_product_id.write( + {"route_ids": [(6, 0, primary_old.route_ids.ids)]} + ) + # Check if copy putaway strategies is True + if self.copy_putaway: + # Check if there exist putaway strategies for the from product + putaway_ids = self.env["stock.putaway.rule"].search( + [("product_id", "=", primary_old.id)] + ) + if putaway_ids: + # Copy putaway strategies + default_putaway = dict( + product_id=self.new_product_id.id, + ) + for pa in putaway_ids: + pa.copy(default=default_putaway) + if self.copy_packaging: + packs = self.env["product.packaging"].search( + [("product_id", "=", primary_old.id)] + ) + if packs: + default_packs = dict( + product_id=self.new_product_id.id, + ) + for pack in packs: + pack.copy(default=default_packs) + + if self.mode == "use_existing": + res = self._do_replacement_use_existing() + elif self.mode == "new_buffer": + res = self._do_replacement_new_buffer() + return res diff --git a/ddmrp_product_replace/wizards/ddmrp_product_replace_view.xml b/ddmrp_product_replace/wizards/ddmrp_product_replace_view.xml new file mode 100644 index 000000000..b095e0497 --- /dev/null +++ b/ddmrp_product_replace/wizards/ddmrp_product_replace_view.xml @@ -0,0 +1,84 @@ + + + + + ddmrp.product.replace.form + ddmrp.product.replace + +
+ + + + + +
+

+ When there are more than one product replaced, only the buffer(s) of the primary product in + this list will be used to create the buffer(s) and/or product(s) for replacement. +

+
+ + + + + + + + + + +
+ + + + + + + + + + +
+
+ +
+
+ + Product Replacement Tool + ddmrp.product.replace + + form + new + + +
diff --git a/ddmrp_product_replace/wizards/make_procurement_buffer.py b/ddmrp_product_replace/wizards/make_procurement_buffer.py new file mode 100644 index 000000000..4a82f740b --- /dev/null +++ b/ddmrp_product_replace/wizards/make_procurement_buffer.py @@ -0,0 +1,35 @@ +# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class MakeProcurementBuffer(models.TransientModel): + _inherit = "make.procurement.buffer" + + has_replaced_buffers = fields.Boolean( + compute="_compute_replaced_by_alert_text", + ) + replaced_by_alert_text = fields.Text( + compute="_compute_replaced_by_alert_text", + ) + + @api.depends("item_ids") + def _compute_replaced_by_alert_text(self): + for rec in self: + if any(r.buffer_id.replaced_by_id for r in rec.item_ids): + rec.has_replaced_buffers = True + alert_text = self.env._("Some products are being replaced:") + for item in rec.item_ids: + if item.buffer_id.replaced_by_id: + replacement = item.buffer_id.replaced_by_id + alert_text += ( + f"\n - {item.buffer_id.display_name} " + f"({item.buffer_id.product_id.display_name}) " + f"replaced by {replacement.display_name} " + f"({replacement.product_id.display_name})" + ) + rec.replaced_by_alert_text = alert_text + else: + rec.has_replaced_buffers = False + rec.replaced_by_alert_text = "" diff --git a/ddmrp_product_replace/wizards/make_procurement_buffer_view.xml b/ddmrp_product_replace/wizards/make_procurement_buffer_view.xml new file mode 100644 index 000000000..c73c60389 --- /dev/null +++ b/ddmrp_product_replace/wizards/make_procurement_buffer_view.xml @@ -0,0 +1,27 @@ + + + + Request Procurement + make.procurement.buffer + + + + + + + + diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..9fa131f52 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +# DO NOT MERGE — temporary pin until the ddmrp_chatter 19.0 MIG lands. +odoo-addon-ddmrp_chatter @ git+https://github.com/ledoent/ddmrp.git@19.0-mig-ddmrp_chatter#subdirectory=ddmrp_chatter