diff --git a/mrp_multi_level/README.rst b/mrp_multi_level/README.rst new file mode 100644 index 000000000..88e19e763 --- /dev/null +++ b/mrp_multi_level/README.rst @@ -0,0 +1,271 @@ +=============== +MRP Multi Level +=============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:afddaf576893642eae579ee762efefb3c3ecc9f84445b23b43ab6fc448975fce + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github + :target: https://github.com/OCA/manufacture/tree/18.0/mrp_multi_level + :alt: OCA/manufacture +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/manufacture-18-0/manufacture-18-0-mrp_multi_level + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to calculate, based in known inventory, demand, +and supply, and based on parameters set at product variant level, the +new procurements for each product. + +To do this, the calculation starts at top level of the bill of material +and explodes this down to the lowest level. + +Key Features +------------ + +- MRP parameters set by product variant MRP area pairs. +- Cron job to calculate the MRP demand. +- Manually calculate the MRP demand. +- Confirm the calculated MRP demand and create PO's, or MO's. +- Able to see the products for which action is needed throught Planned + Orders. +- Integration with `Stock Demand + Estimates `__ + system. Note: You need to install `mrp_multi_level_estimate + module `__. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +MRP Areas +~~~~~~~~~ + +- Go to *Manufacturing > Configuration > MRP Areas* and define or edit + any existing area. You can specify the working hours for every area. + +Product MRP Area Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Go to *Manufacturing > Products > Product MRP Area Parameters* and + set the MRP parameters for a given product and area. + +Usage +===== + +To manually run the MRP scheduler: + +1. Go to *Manufacturing > Planning > Run MRP Multi Level*. +2. On the wizard click *Run MRP*. + +To launch replenishment orders (moves, purchases, production orders...): + +1. Go to *Manufacturing > Planning > MRP Inventory*. +2. Filter with *To procure*. +3. Select multiple records and click on *Action > Procure* or click the + right hand side gears in any record. +4. On the wizard, check everything is ok and click *Execute*. + +Changelog +========= + +13.0.1.5.0 (2020-04-09) +----------------------- + +**Features** + +- Show *Run MRP Multi Level* menu only to a specific new security group + *Run MRP Manually*. + (`#492 `__) + +13.0.1.4.0 (2020-03-26) +----------------------- + + - Add menu entry for planned orders + - Add button to navigate from planned orders to linked manufacturing + orders + - Add action to convert planned orders to fixed + - When changing the due date in a planned order the release date is + recomputed + +13.0.1.3.0 (2020-03-02) +----------------------- + +- [IMP] Minor changes" + (`#470 `__). + + - Planned Order release and due date become required. + - Add button to Product MRP Area to update MOQ from Supplier Info. + - Link Manufacturing Orders with Planned Orders. + - Allow Mrp Inventory Procure Wizard to be used from other models. + - Make MRP Inventory creation more extensible. + - Main Supplier computation (v13 requires explicit False + definitions) + +13.0.1.2.0 (2020-02-20) +----------------------- + +- [IMP] Minor changes + (`#468 `__). + + - Planned Orders become fixed on manual creation by default + - Released Quantity becomes readonly + - Add product reference if Planned Order name is not defined on bom + explosion + +13.0.1.1.0 (2020-02-21) +----------------------- + +- [FIX] Minor changes + (`#469 `__). + + - Fix Main supplier computation in multi company + - Drop Triplicated field in search view + +- [IMP] Minor changes + (`#463 `__). + + - Show supply method on MRP Inventory + - Allow no-MRP users to look into Products + +13.0.1.0.0 (2019-12-18) +----------------------- + +- [MIG] Migration to v13. + +12.0.1.0.0 (2019-08-05) +----------------------- + +- [MIG] Migration to v12: + + - Estimates as a forecasting mechanism is moved to a new module + (mrp_multi_level_estimate). + +11.0.3.0.0 (2019-05-22) +----------------------- + +- [REW/IMP] Rework to include Planned Orders. + (`#365 `__). +- [IMP] Able to procure from a different location than the area's + location. + +11.0.2.2.0 (2019-05-02) +----------------------- + +- [IMP] Able to run MRP only for selected areas. + (`#360 `__). + +11.0.2.1.0 (2019-04-02) +----------------------- + +- [IMP] Implement *Nbr. Days* functionality to be able to group demand + when generating supply proposals. + (`#345 `__). + +11.0.2.0.0 (2018-11-20) +----------------------- + +- [REW] Refactor MRP Area. + (`#322 `__): + + - MRP product concept dropped in favor of *Product MRP Area + Parameters*. This allow to set different MRP parameters for the + same product in different areas. + - Menu items reordering. + +11.0.1.1.0 (2018-08-30) +----------------------- + +- [FIX] Consider *Qty Multiple* on product to propose the quantity to + procure. (`#297 `__) + +11.0.1.0.1 (2018-08-03) +----------------------- + +- [FIX] User and system locales doesn't break MRP calculation. + (`#290 `__) +- [FIX] Working Hours are now defined only at Warehouse level and + displayed as a related on MRP Areas. + (`#290 `__) + +11.0.1.0.0 (2018-07-09) +----------------------- + +- Start of the history. + +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 +------- + +* Ucamco +* ForgeFlow + +Contributors +------------ + +- Wim Audenaert +- Jordi Ballester +- Lois Rilo +- Héctor Villarreal +- Christopher Ormaza +- Joan Sisquella +- Alexandre Fayolle + +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/manufacture `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mrp_multi_level/__init__.py b/mrp_multi_level/__init__.py new file mode 100644 index 000000000..aee8895e7 --- /dev/null +++ b/mrp_multi_level/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/mrp_multi_level/__manifest__.py b/mrp_multi_level/__manifest__.py new file mode 100644 index 000000000..2b2464da6 --- /dev/null +++ b/mrp_multi_level/__manifest__.py @@ -0,0 +1,45 @@ +# Copyright 2016 Ucamco - Wim Audenaert +# Copyright 2016-21 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "MRP Multi Level", + "version": "18.0.1.0.0", + "development_status": "Production/Stable", + "license": "LGPL-3", + "author": "Ucamco, ForgeFlow, Odoo Community Association (OCA)", + "maintainers": ["JordiBForgeFlow", "LoisRForgeFlow"], + "summary": "Adds an MRP Scheduler", + "website": "https://github.com/OCA/manufacture", + "category": "Manufacturing", + "depends": ["mrp", "purchase_stock", "mrp_warehouse_calendar"], + "data": [ + "security/mrp_multi_level_security.xml", + "security/ir.model.access.csv", + "data/system_parameter.xml", + "views/mrp_area_views.xml", + "views/product_product_views.xml", + "views/product_template_views.xml", + "views/product_mrp_area_views.xml", + "views/stock_location_views.xml", + "wizards/mrp_inventory_procure_views.xml", + "views/mrp_inventory_views.xml", + "views/mrp_planned_order_views.xml", + "wizards/mrp_multi_level_views.xml", + "views/mrp_move_views.xml", + "views/mrp_menuitem.xml", + "data/mrp_multi_level_cron.xml", + "data/mrp_area_data.xml", + ], + "demo": [ + "demo/product_category_demo.xml", + "demo/product_product_demo.xml", + "demo/res_partner_demo.xml", + "demo/product_supplierinfo_demo.xml", + "demo/product_mrp_area_demo.xml", + "demo/mrp_bom_demo.xml", + "demo/initial_on_hand_demo.xml", + ], + "installable": True, + "application": True, +} diff --git a/mrp_multi_level/data/mrp_area_data.xml b/mrp_multi_level/data/mrp_area_data.xml new file mode 100644 index 000000000..9486ed4d3 --- /dev/null +++ b/mrp_multi_level/data/mrp_area_data.xml @@ -0,0 +1,8 @@ + + + + WH/Stock + + + + diff --git a/mrp_multi_level/data/mrp_multi_level_cron.xml b/mrp_multi_level/data/mrp_multi_level_cron.xml new file mode 100644 index 000000000..a03f02bd4 --- /dev/null +++ b/mrp_multi_level/data/mrp_multi_level_cron.xml @@ -0,0 +1,12 @@ + + + + Multi Level MRP + + + 1 + days + code + model.run_mrp_multi_level() + + diff --git a/mrp_multi_level/data/system_parameter.xml b/mrp_multi_level/data/system_parameter.xml new file mode 100644 index 000000000..0ab7543a3 --- /dev/null +++ b/mrp_multi_level/data/system_parameter.xml @@ -0,0 +1,7 @@ + + + + mrp_multi_level.llc_calculation_recursion_limit + 1000 + + diff --git a/mrp_multi_level/demo/initial_on_hand_demo.xml b/mrp_multi_level/demo/initial_on_hand_demo.xml new file mode 100644 index 000000000..20f5e5b6d --- /dev/null +++ b/mrp_multi_level/demo/initial_on_hand_demo.xml @@ -0,0 +1,43 @@ + + + + + + 10 + + + + + + 20 + + + + + + 15 + + + + + + diff --git a/mrp_multi_level/demo/mrp_bom_demo.xml b/mrp_multi_level/demo/mrp_bom_demo.xml new file mode 100644 index 000000000..296ae2ec7 --- /dev/null +++ b/mrp_multi_level/demo/mrp_bom_demo.xml @@ -0,0 +1,178 @@ + + + + + + + 5 + 2 + + + + 2 + + 5 + + + + + 3 + + 5 + + + + + + + 5 + 1 + + + + 2 + + 5 + + + + + 3 + + 5 + + + + + + + + 5 + 3 + + + + 2 + + 5 + + + + + 2 + + 5 + + + + + + + + 5 + + + + 1 + + 1 + + + + + + 1 + + 2 + + + + + + 1 + + 3 + + + + + + 1 + + 4 + + + + + + + + 5 + 1 + + + + 3 + + 5 + + + + + 2 + + 5 + + + + + + + 5 + 3 + + + + 3 + + 5 + + + + + + + phantom + 5 + 3 + + + + 1 + + 5 + + + + + 3 + + 5 + + + diff --git a/mrp_multi_level/demo/product_category_demo.xml b/mrp_multi_level/demo/product_category_demo.xml new file mode 100644 index 000000000..3af16dc4d --- /dev/null +++ b/mrp_multi_level/demo/product_category_demo.xml @@ -0,0 +1,6 @@ + + + + MRP + + diff --git a/mrp_multi_level/demo/product_mrp_area_demo.xml b/mrp_multi_level/demo/product_mrp_area_demo.xml new file mode 100644 index 000000000..531a46bc5 --- /dev/null +++ b/mrp_multi_level/demo/product_mrp_area_demo.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mrp_multi_level/demo/product_product_demo.xml b/mrp_multi_level/demo/product_product_demo.xml new file mode 100644 index 000000000..b7ad6bf6d --- /dev/null +++ b/mrp_multi_level/demo/product_product_demo.xml @@ -0,0 +1,176 @@ + + + + FP-1 + + + + + + + + FP-2 + + + + + + + + FP-3 + + + + + + + + FP-4 + + + + + + + + + + + + SF-1 + + + + + + + + SF-2 + + + + + + + + SF-3 + + + + + + + + + PP-1 + + + + + + + + PP-2 + + + + + + + + + PP-3 + + + + + + + + + PP-4 + + + + + + + + + AV-11 steel + + + + + + + + AV-12 aluminium + + + + + + + + AV-21 white + + + + + + + + AV-22 black + + + + + + + diff --git a/mrp_multi_level/demo/product_supplierinfo_demo.xml b/mrp_multi_level/demo/product_supplierinfo_demo.xml new file mode 100644 index 000000000..59c643866 --- /dev/null +++ b/mrp_multi_level/demo/product_supplierinfo_demo.xml @@ -0,0 +1,61 @@ + + + + + + 4 + 0 + 100 + + + + + 4 + 0 + 100 + + + + + 4 + 0 + 100 + + + + + 4 + 0 + 100 + + + + + 4 + 0 + 100 + + + + + 2 + 0 + 100 + + + + + + 2 + 0 + 10 + + + + + + 3 + 0 + 80 + + diff --git a/mrp_multi_level/demo/res_partner_demo.xml b/mrp_multi_level/demo/res_partner_demo.xml new file mode 100644 index 000000000..c336a8c18 --- /dev/null +++ b/mrp_multi_level/demo/res_partner_demo.xml @@ -0,0 +1,8 @@ + + + + Lazer Tech + 1 + + + diff --git a/mrp_multi_level/docs/mrp_multi_level_test_run.ods b/mrp_multi_level/docs/mrp_multi_level_test_run.ods new file mode 100644 index 000000000..e41f28115 Binary files /dev/null and b/mrp_multi_level/docs/mrp_multi_level_test_run.ods differ diff --git a/mrp_multi_level/i18n/de.po b/mrp_multi_level/i18n/de.po new file mode 100644 index 000000000..40c75f21e --- /dev/null +++ b/mrp_multi_level/i18n/de.po @@ -0,0 +1,1164 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_multi_level +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-06-28 14:42+0000\n" +"Last-Translator: Maria Sparenberg \n" +"Language-Team: none\n" +"Language: de\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 3.6.1\n" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_11_product_template +msgid "AV-11 steel" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_12_product_template +msgid "AV-12 aluminium" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_21_product_template +msgid "AV-21 white" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_22_product_template +msgid "AV-22 black" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_action +msgid "Action" +msgstr "Aktion" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__active +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__active +msgid "Active" +msgstr "Aktiv" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__approved +msgid "Approved" +msgstr "Genehmigt" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Archived" +msgstr "Archiviert" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__assigned +msgid "Assigned" +msgstr "Zugewiesen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_inventory_id +msgid "Associated MRP Inventory" +msgstr "Zugehöriger MRP Bestand" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__bom_id +msgid "Bom" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__buy +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__buy +msgid "Buy" +msgstr "Einkaufen" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Cancel" +msgstr "Abbrechen" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_change_mrp_procure_qty +msgid "Change procure quantity in MRP" +msgstr "Beschaffungsmenge in der Fertigung ändern" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__company_id +msgid "Company" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__confirmed +msgid "Confirmed" +msgstr "Bestätigt" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Create Procurement" +msgstr "Beschaffung erzeugen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_uid +msgid "Created by" +msgstr "Erstellt von" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_date +msgid "Created on" +msgstr "Erstellt am" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_date +msgid "Current Date" +msgstr "Aktuelles Datum" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_qty +msgid "Current Qty" +msgstr "Aktuelle Menge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date" +msgstr "Datum" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__due_date +msgid "Date in which the supply must have been completed." +msgstr "Das ist das Fälligkeitsdatum, zu dem der Auftrag erledigt sein muss." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#, fuzzy +msgid "Date to Procure" +msgstr "Beschaffungsdatum (nach Tagen)" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__demand_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__d +msgid "Demand" +msgstr "Nachfrage" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__name +msgid "Description" +msgstr "Beschreibung" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Details" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__display_name +msgid "Display Name" +msgstr "Anzeigename" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__distribution_lead_time +msgid "Distribution Lead Time" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__draft +msgid "Draft" +msgstr "Entwurf" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__due_date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Due Date" +msgstr "Fälligkeitsdatum" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_exclude +msgid "Exclude from MRP" +msgstr "von der Ressourcenplanung ausschließen" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Execute" +msgstr "Ausführen" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_1_product_template +msgid "FP-1" +msgstr "FP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_2_product_template +msgid "FP-2" +msgstr "FP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_3_product_template +msgid "FP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_4_product_template +msgid "FP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__fixed +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Fixed" +msgstr "Fest" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__fc +msgid "Forecast" +msgstr "Vorhersage" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__final_on_hand_qty +msgid "Forecasted Inventory" +msgstr "Vorhergesagter Bestand" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, fuzzy +msgid "Get from main supplier" +msgstr "Hauptlieferant" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Group By..." +msgstr "Gruppiere nach..." + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "Grouped Demand of %(product_name)s for %(delta_days)d Days" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__id +msgid "ID" +msgstr "ID" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Identifies that this product has been verified to be valid for the MRP." +msgstr "" +"Dieses Produkt wurde als für die Fertigungsressourcenplanung gültig " +"verifiziert." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "If empty, all areas will be computed." +msgstr "Wenn das Feld leer ist, werden alle Bereiche berechnet." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Incoming Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_inspection_delay +msgid "Inspection Delay" +msgstr "Inspektionsverzögerung" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_location +msgid "Inventory Locations" +msgstr "Lagerorte" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__item_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Items" +msgstr "Positionen" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__phantom +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__phantom +msgid "Kit" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_uid +msgid "Last Updated by" +msgstr "Zuletzt aktualisiert von" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_date +msgid "Last Updated on" +msgstr "Zuletzt aktualisiert am" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_lead_time +msgid "Lead Time" +msgstr "Durchlaufzeit" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_id +msgid "Location" +msgstr "Lagerort" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__llc +msgid "Low Level Code" +msgstr "Dispositionsstufe" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_form +msgid "MOs" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mrp +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_mrp +msgid "MRP" +msgstr "Ressourcenplanung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_applicable +msgid "MRP Applicable" +msgstr "Ressourcenplanung anwendbar" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_area_action +#: model:ir.model,name:mrp_multi_level.model_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "MRP Area" +msgstr "Bereich" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_stock_location__mrp_area_count +msgid "MRP Area Parameter Count" +msgstr "Anzahl der Bereich-Parameter" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_ids +msgid "MRP Area parameters" +msgstr "Bereich-Parameter" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_areas +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_template_only_form_view_mrp +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_location_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_product_product_form +msgid "MRP Areas" +msgstr "Bereiche" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "MRP Areas to run" +msgstr "Auszuführende Bereiche" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_date +msgid "MRP Date" +msgstr "Datum (MRP)" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_inventory_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_inventory +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_graph +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_pivot +msgid "MRP Inventory" +msgstr "Bestand" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure_item +#, fuzzy +msgid "MRP Inventory procure item" +msgstr "mrp.inventory.procure.item" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_move +#, fuzzy +msgid "MRP Move" +msgstr "Lagerbewegungen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_move_down_ids +msgid "MRP Move DOWN" +msgstr "nach unten verschieben" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_move_action +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "MRP Moves" +msgstr "Lagerbewegungen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_qty +msgid "MRP Quantity" +msgstr "Menge (MRP)" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory +msgid "MRP inventory projections" +msgstr "Bestandsvorhersagen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__main_supplier_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplier_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Main Supplier" +msgstr "Hauptlieferant" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure +msgid "Make Procurements from MRP inventory projections" +msgstr "Beschaffungen aus den Bestandsvorhersagen (MRP) erstellen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__production_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mo +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__manufacture +msgid "Manufacturing Order" +msgstr "Fertigungsauftrag" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_production_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__manufacturing_order_ids +msgid "Manufacturing Orders" +msgstr "Fertigungsaufträge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_maximum_order_qty +msgid "Maximum Order Qty" +msgstr "Maximale Auftragsmenge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_order_qty +msgid "Minimum Order Qty" +msgstr "Minimale Auftragsmenge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mo_count +msgid "Mo Count" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mv +msgid "Move" +msgstr "Lagerbewegung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_area_id +msgid "Mrp Area" +msgstr "Bereich" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__mrp_inventory_id +msgid "Mrp Inventory" +msgstr "Bestand (MRP)" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_move_ids +msgid "Mrp Move" +msgstr "Lagerbewegungen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_planner_id +msgid "Mrp Planner" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.mrp_multi_level_cron_ir_actions_server +#: model:ir.model,name:mrp_multi_level.model_mrp_multi_level +msgid "Multi Level MRP" +msgstr "Mehrstufige MRP" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "My products" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__name +msgid "Name" +msgstr "Bezeichnung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "Nbr. Days" +msgstr "# Tage" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "No MRP product found" +msgstr "Kein Produkt für MRP gefunden" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__none +msgid "None" +msgstr "Keines" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "" +"Number of days to group demand for this product during the MRP run, in order " +"to determine the quantity to order." +msgstr "" +"Anzahl der Tage zur Gruppierung von Nachfragen für das Produkt während eines " +"MRP-Laufs, um die zu beschaffende Menge festzulegen." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_order_number +msgid "Order Number" +msgstr "Auftragsnummer" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__order_release_date +msgid "Order Release Date" +msgstr "Auftragsfreigabe-Datum" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__order_release_date +#, fuzzy +msgid "Order release date planned by MRP." +msgstr "Auftragsfreigabe-Datum" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_origin +msgid "Origin" +msgstr "Ursprung" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Outgoing Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_1_product_template +msgid "PP-1" +msgstr "PP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_2_product_template +msgid "PP-2" +msgstr "PP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_3_product_template +msgid "PP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_4_product_template +msgid "PP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__parent_product_id +msgid "Parent Product" +msgstr "Übergeordnetes Produkt" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__partially_available +msgid "Partially Available" +msgstr "Teilweise verfügbar" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Planned Availability" +msgstr "Geplante Verfügbarkeit" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__date_planned +msgid "Planned Date" +msgstr "Geplantes Datum" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_planned_order +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__planned_order_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_production__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__planned_order_ids +msgid "Planned Order" +msgstr "Geplanter Auftrag" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/mrp_inventory.py:0 +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_planned_order_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_planned_order +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, python-format +msgid "Planned Orders" +msgstr "Geplante Aufträge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__planned_order_up_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_move_view_form +#, fuzzy +msgid "Planned Orders UP" +msgstr "Einkaufsbestellungen" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure_planned_order +msgid "Procure" +msgstr "Beschaffen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "Procure Location" +msgstr "Beschaffungslagerort" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Procurement Request" +msgstr "Beschaffungsanfrage" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__manufacture +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__manufacture +msgid "Produce" +msgstr "Produzieren" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_template +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Product" +msgstr "Produkt" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_mrp_area_id +msgid "Product MRP Area" +msgstr "Produkt - Bereich" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.product_mrp_area_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_product_mrp_area_parameters +msgid "Product MRP Area Parameters" +msgstr "Produkt-Bereich-Parameter" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Product MRP Area parameters" +msgstr "Produkt-Bereich-Parameter" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Product Parameters" +msgstr "Produkt-Parameter" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_tmpl_id +msgid "Product Template" +msgstr "Produktvorlage" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__uom_id +msgid "Product UoM" +msgstr "Produkt ME" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_production +#, fuzzy +msgid "Production Order" +msgstr "Produkt-Parameter" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull_push +msgid "Pull & Push" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull +msgid "Pull From" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_order_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__po +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__buy +msgid "Purchase Order" +msgstr "Einkaufsbestellung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_line_id +msgid "Purchase Order Line" +msgstr "Bestellpositionen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__purchase_order_line_ids +msgid "Purchase Orders" +msgstr "Einkaufsbestellungen" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__push +msgid "Push To" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_qty_multiple +msgid "Qty Multiple" +msgstr "Mengenfaktor" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__qty_released +msgid "Qty Released" +msgstr "Freigegebene Menge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__qty +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_qty +msgid "Quantity" +msgstr "Menge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__qty_available +msgid "Quantity Available" +msgstr "Verfügbare Menge" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_inventory_procure.py:0 +#, python-format +msgid "Quantity must be positive." +msgstr "Die Menge muss größer als 0 sein." + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__ready +msgid "Ready" +msgstr "Bereit" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Release Date" +msgstr "Freigabe-Datum" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.action_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP" +msgstr "Ressourcenplanung (MRP) ausführen" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_mrp_multi_level_run +#, fuzzy +msgid "Run MRP Manually" +msgstr "Mehrstufige Ressourcenplanung (MRP) ausführen" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP Multi Level" +msgstr "Mehrstufige Ressourcenplanung (MRP) ausführen" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_1_product_template +msgid "SF-1" +msgstr "SF-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_2_product_template +msgid "SF-2" +msgstr "SF-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_3_product_template +msgid "SF-3" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_stock +#, python-format +msgid "Safety Stock" +msgstr "Sicherheitsbestand" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Selection..." +msgstr "Auswahl..." + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__sent +msgid "Sent" +msgstr "Gesendet" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "" +"Set this if you need to procure from a different locationthan area's " +"location." +msgstr "" +"Setzen Sie hier einen Lagerort, wenn die Beschaffung von einem anderen " +"Lagerort stattfinden soll als im Bereich angegeben." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__origin +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__origin +msgid "Source Document" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__initial_on_hand_qty +msgid "Starting Inventory" +msgstr "Anfangsbestand" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__state +msgid "State" +msgstr "Status" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__stock_move_id +msgid "Stock Move" +msgstr "Lagerbewegung" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_rule +#, fuzzy +msgid "Stock Rule" +msgstr "Lagerbewegung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplierinfo_id +msgid "Supplier Info" +msgstr "Lieferanten-Information" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__s +msgid "Supply" +msgstr "Liefermenge" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_bom_id +msgid "Supply BoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_method +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Supply Method" +msgstr "Liefermethode" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__company_id +msgid "The company is automatically set from your user preferences." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.constraint,message:mrp_multi_level.constraint_product_mrp_area_product_mrp_area_uniq +msgid "The product/MRP Area parameters combination must be unique." +msgstr "Die Kombination der Produkt-/Bereich-Parameter muss einzigartig sein." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Theoretical inventory level if all planned orders were released." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__to_approve +msgid "To Approve" +msgstr "Genehmigen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__to_procure +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "To Procure" +msgstr "Beschaffen" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.action_server_planned_order_toggle_fixed +msgid "Toggle Fixed" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_transit_delay +msgid "Transit Delay" +msgstr "Umbuchungsverzögerung" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_type +msgid "Type" +msgstr "Typ" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__none +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__none +msgid "Undefined" +msgstr "Nicht definiert" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__uom_id +msgid "Unit of Measure" +msgstr "Mengeneinheit" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "" +"Use this assistant to procure for this product and date.\n" +" According to the product configuration,\n" +" this may trigger a draft purchase order, a " +"manufacturing\n" +" order or a transfer picking." +msgstr "" +"Verwenden Sie diesen Assistenten zur Beschaffung des Produktes und des " +"Datums.\n" +"Abhängig von der Produktkonfiguration wird entweder eine Einkaufsbestellung, " +"ein Fertigungsauftrag oder ein Lieferschein im Entwurf erstellt." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Verified for MRP" +msgstr "für MRP verifiziert" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__waiting +msgid "Waiting" +msgstr "Wartend" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__warehouse_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__warehouse_id +msgid "Warehouse" +msgstr "Lager" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__wiz_id +msgid "Wizard" +msgstr "Assistent" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__calendar_id +msgid "Working Hours" +msgstr "Arbeitsstunden" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/product_mrp_area.py:0 +#, python-format +msgid "You cannot use a negative number." +msgstr "Es darf keine negative Zahl angegeben werden." + +#~ msgid "Last Modified on" +#~ msgstr "Zuletzt geändert am" + +#~ msgid "" +#~ "Requirements for a particular MRP area are combined for the purposes of " +#~ "procurement by the MRP." +#~ msgstr "" +#~ "Nachfragen für einen bestimmten MRP-Bereich werden zum Zweck der " +#~ "Beschaffung gruppiert." + +#~ msgid "or" +#~ msgstr "oder" + +#~ msgid "Theoretical inventory level if all planned orderswere released." +#~ msgstr "" +#~ "Dies ist der theoretische Lagerbestand, wenn alle geplanten Aufträge " +#~ "freigegeben werden." + +#~ msgid "To procure" +#~ msgstr "Beschaffen" + +#~ msgid "Date to Procure (By Month)" +#~ msgstr "Beschaffungsdatum (nach Monaten)" + +#~ msgid "Date to Procure (By Week)" +#~ msgstr "Beschaffungsdatum (nach Wochen)" + +#~ msgid "Transfer" +#~ msgstr "Umbuchen" + +#~ msgid "mrp.area" +#~ msgstr "mrp.area" + +#~ msgid "mrp.move" +#~ msgstr "mrp.move" + +#~ msgid "mrp.multi.level" +#~ msgstr "mrp.multi.level" + +#~ msgid "" +#~ "Average delay in days to produce this product. In the case of multi-level " +#~ "BOM, the manufacturing lead times of the components will be added." +#~ msgstr "" +#~ "Durchschnittliche Dauer für die Produktion des Produktes. Im Fall einer " +#~ "mehrstufigen Stückliste wird die Fertigungsdurchlaufzeit der Komponenten " +#~ "addiert." + +#~ msgid "MRP Action Date" +#~ msgstr "Aktionsdatum" + +#~ msgid "MRP Move UP" +#~ msgstr "nach oben verschieben" + +#~ msgid "Minimum Stock" +#~ msgstr "Mindestbestand" + +#~ msgid "Processed" +#~ msgstr "Bearbeitet" + +#~ msgid "" +#~ "Current quantity of products.\n" +#~ "In a context with a single Stock Location, this includes goods stored at " +#~ "this Location, or any of its children.\n" +#~ "In a context with a single Warehouse, this includes goods stored in the " +#~ "Stock Location of this Warehouse, or any of its children.\n" +#~ "stored in the Stock Location of the Warehouse of this Shop, or any of its " +#~ "children.\n" +#~ "Otherwise, this includes goods stored in any Stock Location with " +#~ "'internal' type." +#~ msgstr "" +#~ "Aktuelle Menge der Produkte\n" +#~ "Im Kontext eines einzelnen Lagerortes enthält der Wert die Waren, die auf " +#~ "diesem Lagerort und all seiner Unterlagerorte liegen.\n" +#~ "Im Kontext eines einzelnen Lagers enthält der Wert die Waren, die auf dem " +#~ "Lagerort dieses Lagers und all seiner Unterlagerorte liegen.\n" +#~ "Ansonsten enthält der Wert alle Waren von alĺen 'internen' Lagerorten." + +#~ msgid "MRP Product" +#~ msgstr "Produkt" + +#~ msgid "MRP Product data" +#~ msgstr "Produktdaten" + +#~ msgid "MRP Products" +#~ msgstr "Produkte" + +#~ msgid "MRP Qty Available" +#~ msgstr "Verfügbare Menge (MRP)" + +#~ msgid "MRP Verified" +#~ msgstr "für MRP verifiziert" + +#~ msgid "Manufacture Actions" +#~ msgstr "Fertigungsaktionen" + +#~ msgid "Moves" +#~ msgstr "Lagerbewegungen" + +#~ msgid "Nbr Actions" +#~ msgstr "# Aktionen" + +#~ msgid "Nbr Actions 4 Weeks" +#~ msgstr "# Aktionen (4 Wochen)" + +#~ msgid "Purchase Actions" +#~ msgstr "Einkaufsaktionen" + +#~ msgid "Search Product" +#~ msgstr "Produkt suchen" + +#~ msgid "With Actions" +#~ msgstr "Mit Aktionen" + +#~ msgid "With Actions in Coming 4 Weeks" +#~ msgstr "Mit Aktionen in den kommenden 4 Wochen" + +#~ msgid "With Moves" +#~ msgstr "Mit Lagerbewegungen" + +#~ msgid "mrp.product" +#~ msgstr "mrp.product" diff --git a/mrp_multi_level/i18n/es.po b/mrp_multi_level/i18n/es.po new file mode 100644 index 000000000..2cfa84faf --- /dev/null +++ b/mrp_multi_level/i18n/es.po @@ -0,0 +1,1108 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_multi_level +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-07-20 11:12+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_11_product_template +msgid "AV-11 steel" +msgstr "AV-11 acero" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_12_product_template +msgid "AV-12 aluminium" +msgstr "AV-12 aluminio" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_21_product_template +msgid "AV-21 white" +msgstr "AV-21 blanco" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_22_product_template +msgid "AV-22 black" +msgstr "AV-22 negro" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_action +msgid "Action" +msgstr "Acción" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__active +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__active +msgid "Active" +msgstr "Activo" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__approved +msgid "Approved" +msgstr "Aprobado" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Archived" +msgstr "Archivado" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__assigned +msgid "Assigned" +msgstr "Asignado" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_inventory_id +msgid "Associated MRP Inventory" +msgstr "Inventario MRP asociado" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__bom_id +msgid "Bom" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__buy +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__buy +msgid "Buy" +msgstr "Comprar" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Cancel" +msgstr "Cancelar" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_change_mrp_procure_qty +msgid "Change procure quantity in MRP" +msgstr "Cambiar la cantidad de reaprovisionamiento de MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__company_id +msgid "Company" +msgstr "Compañía" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__confirmed +msgid "Confirmed" +msgstr "Confirmado" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Create Procurement" +msgstr "Crear Aprovisionamiento" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_date +msgid "Current Date" +msgstr "Fecha actual" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_qty +msgid "Current Qty" +msgstr "Ctd. actual" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date" +msgstr "Fecha" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__due_date +msgid "Date in which the supply must have been completed." +msgstr "Fecha en la que debe haberse completado el suministro." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date to Procure" +msgstr "Fecha de adquisición" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__demand_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__d +msgid "Demand" +msgstr "Demanda" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__name +msgid "Description" +msgstr "Descripción" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Details" +msgstr "Detalles" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__display_name +msgid "Display Name" +msgstr "Nombre de Visualización" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__distribution_lead_time +msgid "Distribution Lead Time" +msgstr "Plazo de distribución" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__draft +msgid "Draft" +msgstr "Borrador" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__due_date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Due Date" +msgstr "Fecha de vencimiento" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_exclude +msgid "Exclude from MRP" +msgstr "Excluir del MRP" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Execute" +msgstr "Ejecutar" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_1_product_template +msgid "FP-1" +msgstr "FP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_2_product_template +msgid "FP-2" +msgstr "FP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_3_product_template +msgid "FP-3" +msgstr "FP-3" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_4_product_template +msgid "FP-4" +msgstr "FP-4" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__fixed +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Fixed" +msgstr "Fijado" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__fc +msgid "Forecast" +msgstr "Previsión" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__final_on_hand_qty +msgid "Forecasted Inventory" +msgstr "Previsión de stock" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Get from main supplier" +msgstr "Obtener del proveedor principal" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Group By..." +msgstr "Agrupar por..." + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "Grouped Demand of %(product_name)s for %(delta_days)d Days" +msgstr "Demanda Agrupada de %(product_name)s para %(delta_days)d Dias" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__id +msgid "ID" +msgstr "ID" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Identifies that this product has been verified to be valid for the MRP." +msgstr "" +"Identifica que se ha verificado que este producto es válido para el MRP." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "If empty, all areas will be computed." +msgstr "Si está vacío, se calcularán todas las áreas." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Incoming Moves" +msgstr "Movimientos entrantes" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_inspection_delay +msgid "Inspection Delay" +msgstr "Retraso en la inspección" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_location +msgid "Inventory Locations" +msgstr "Localización de inventarios" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__item_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Items" +msgstr "Artículos" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__phantom +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__phantom +msgid "Kit" +msgstr "Paquete" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_date +msgid "Last Updated on" +msgstr "Última Actualización en" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_lead_time +msgid "Lead Time" +msgstr "Plazo de Entrega" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_id +msgid "Location" +msgstr "Ubicación" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__llc +msgid "Low Level Code" +msgstr "Código de bajo nivel" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_form +msgid "MOs" +msgstr "MOs" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mrp +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_mrp +msgid "MRP" +msgstr "MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_applicable +msgid "MRP Applicable" +msgstr "Aplicable a MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_area_action +#: model:ir.model,name:mrp_multi_level.model_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "MRP Area" +msgstr "Area MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_stock_location__mrp_area_count +msgid "MRP Area Parameter Count" +msgstr "Recuento de parámetros del área MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_ids +msgid "MRP Area parameters" +msgstr "Parámetros área MRP" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_areas +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_template_only_form_view_mrp +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_location_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_product_product_form +msgid "MRP Areas" +msgstr "Areas MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "MRP Areas to run" +msgstr "Áreas MRP a ejecutar" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_date +msgid "MRP Date" +msgstr "Fecha MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_inventory_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_inventory +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_graph +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_pivot +msgid "MRP Inventory" +msgstr "Inventario MRP" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure_item +msgid "MRP Inventory procure item" +msgstr "MRP Artículo de aprovisionamiento de inventario" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_move +msgid "MRP Move" +msgstr "Movimiento MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_move_down_ids +msgid "MRP Move DOWN" +msgstr "Movimiento Abajo MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_move_action +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "MRP Moves" +msgstr "Movimientos MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_qty +msgid "MRP Quantity" +msgstr "Ctd. MRP" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory +msgid "MRP inventory projections" +msgstr "Proyección de Stock MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__main_supplier_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplier_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Main Supplier" +msgstr "Proveedor Principal" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure +msgid "Make Procurements from MRP inventory projections" +msgstr "Crear Aprovisionamiento desde Proyecciones de Stock MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__production_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mo +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__manufacture +msgid "Manufacturing Order" +msgstr "Order de Fabricación" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_production_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__manufacturing_order_ids +msgid "Manufacturing Orders" +msgstr "Órdenes de Fabricación" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_maximum_order_qty +msgid "Maximum Order Qty" +msgstr "Ctd. Máxima de Pedido" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_order_qty +msgid "Minimum Order Qty" +msgstr "Ctd. Mínima de Pedido" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mo_count +msgid "Mo Count" +msgstr "Conteo Mo" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mv +msgid "Move" +msgstr "Movimiento" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_area_id +msgid "Mrp Area" +msgstr "Área MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__mrp_inventory_id +msgid "Mrp Inventory" +msgstr "Stock MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_move_ids +msgid "Mrp Move" +msgstr "Movimiento Mrp" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_planner_id +msgid "Mrp Planner" +msgstr "Planificador Mrp" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.mrp_multi_level_cron_ir_actions_server +#: model:ir.model,name:mrp_multi_level.model_mrp_multi_level +msgid "Multi Level MRP" +msgstr "MRP Multi Nivel" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "My products" +msgstr "Mis productos" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__name +msgid "Name" +msgstr "Nombre" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "Nbr. Days" +msgstr "Núm. Días" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "No MRP product found" +msgstr "No se encontró producto MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__none +msgid "None" +msgstr "Ninguno/a" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "" +"Number of days to group demand for this product during the MRP run, in order " +"to determine the quantity to order." +msgstr "" +"Número de días para agrupar la demanda de este producto durante la ejecución " +"del MRP, con el fin de determinar la cantidad a pedir." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_order_number +msgid "Order Number" +msgstr "Número de Pedido" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__order_release_date +msgid "Order Release Date" +msgstr "Fecha de Lanzamiento de Orden" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Order release date planned by MRP." +msgstr "Fecha de publicación del pedido prevista por MRP." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_origin +msgid "Origin" +msgstr "Origen" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Outgoing Moves" +msgstr "Movimientos de salida" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_1_product_template +msgid "PP-1" +msgstr "PP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_2_product_template +msgid "PP-2" +msgstr "PP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_3_product_template +msgid "PP-3" +msgstr "PP-3" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_4_product_template +msgid "PP-4" +msgstr "PP-4" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__parent_product_id +msgid "Parent Product" +msgstr "Producto Padre" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__partially_available +msgid "Partially Available" +msgstr "Parcialmente Disponible" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Planned Availability" +msgstr "Disponibilidad planificada" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__date_planned +msgid "Planned Date" +msgstr "Fecha Planificada" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_planned_order +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__planned_order_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_production__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__planned_order_ids +msgid "Planned Order" +msgstr "Orden prevista" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/mrp_inventory.py:0 +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_planned_order_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_planned_order +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, python-format +msgid "Planned Orders" +msgstr "Órdenes Planificadas" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__planned_order_up_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_move_view_form +msgid "Planned Orders UP" +msgstr "Órdenes planificadas ARRIBA" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure_planned_order +msgid "Procure" +msgstr "Abastecer" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "Procure Location" +msgstr "Procurar ubicación" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Procurement Request" +msgstr "Solicitud de Abastecimiento" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__manufacture +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__manufacture +msgid "Produce" +msgstr "Producir" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_template +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Product" +msgstr "Producto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_mrp_area_id +msgid "Product MRP Area" +msgstr "Área MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.product_mrp_area_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_product_mrp_area_parameters +msgid "Product MRP Area Parameters" +msgstr "Parámetros del área MRP de productos" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Product MRP Area parameters" +msgstr "Parámetros del área MRP de productos" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Product Parameters" +msgstr "Parámetros del producto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_tmpl_id +msgid "Product Template" +msgstr "Producto Modelo" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__uom_id +msgid "Product UoM" +msgstr "UdM del Producto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_product +msgid "Product Variant" +msgstr "Variante de Producto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_production +msgid "Production Order" +msgstr "Orden de producción" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull_push +msgid "Pull & Push" +msgstr "Tira y Empuja" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull +msgid "Pull From" +msgstr "Tirar desde" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_order_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__po +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__buy +msgid "Purchase Order" +msgstr "Orden de Compra" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_line_id +msgid "Purchase Order Line" +msgstr "Línea de Orden de Compra" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__purchase_order_line_ids +msgid "Purchase Orders" +msgstr "Órdenes de Compra" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__push +msgid "Push To" +msgstr "Empujar a" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_qty_multiple +msgid "Qty Multiple" +msgstr "Múltiplo de Cantidad" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__qty_released +msgid "Qty Released" +msgstr "Cantidad liberada" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__qty +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_qty +msgid "Quantity" +msgstr "Cantidad" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__qty_available +msgid "Quantity Available" +msgstr "Cantidad disponible" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_inventory_procure.py:0 +#, python-format +msgid "Quantity must be positive." +msgstr "La cantidad debe ser positiva." + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_quant +msgid "Quants" +msgstr "Cantidades" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__ready +msgid "Ready" +msgstr "Listo" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Release Date" +msgstr "Fecha de publicación" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.action_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP" +msgstr "Ejecutar MRP" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_mrp_multi_level_run +msgid "Run MRP Manually" +msgstr "Ejecución manual de MRP" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP Multi Level" +msgstr "Ejecutar MRP Multi Nivel" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_1_product_template +msgid "SF-1" +msgstr "SF-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_2_product_template +msgid "SF-2" +msgstr "SF-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_3_product_template +msgid "SF-3" +msgstr "SF-3" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_stock +#, python-format +msgid "Safety Stock" +msgstr "Existencias de seguridad" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Selection..." +msgstr "Selección..." + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__sent +msgid "Sent" +msgstr "Enviado" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "" +"Set this if you need to procure from a different locationthan area's " +"location." +msgstr "" +"Establézcalo si necesita abastecerse en una ubicación diferente a la del " +"área." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__origin +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__origin +msgid "Source Document" +msgstr "Documento de origen" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__initial_on_hand_qty +msgid "Starting Inventory" +msgstr "Stock Inicial" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__state +msgid "State" +msgstr "Estado" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__stock_move_id +msgid "Stock Move" +msgstr "Movimiento de Stock" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_rule +msgid "Stock Rule" +msgstr "Regla de valores" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplierinfo_id +msgid "Supplier Info" +msgstr "Información de Proveedor" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__s +msgid "Supply" +msgstr "Suministro" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_bom_id +msgid "Supply BoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_method +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Supply Method" +msgstr "Método de Suministro" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__company_id +msgid "The company is automatically set from your user preferences." +msgstr "" +"La empresa se establece automáticamente a partir de sus preferencias de " +"usuario." + +#. module: mrp_multi_level +#: model:ir.model.constraint,message:mrp_multi_level.constraint_product_mrp_area_product_mrp_area_uniq +msgid "The product/MRP Area parameters combination must be unique." +msgstr "La combinación de parámetros producto/Área MRP debe ser única." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Theoretical inventory level if all planned orders were released." +msgstr "" +"Nivel de inventario teórico si se liberaran todos los pedidos previstos." + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__to_approve +msgid "To Approve" +msgstr "Por Aprobar" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__to_procure +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "To Procure" +msgstr "para procurar" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.action_server_planned_order_toggle_fixed +msgid "Toggle Fixed" +msgstr "Conmutar Fijo" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_transit_delay +msgid "Transit Delay" +msgstr "Retraso de Tránsito" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_type +msgid "Type" +msgstr "Tipo" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__none +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__none +msgid "Undefined" +msgstr "Indefinido" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__uom_id +msgid "Unit of Measure" +msgstr "Unidad de Medida" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "" +"Use this assistant to procure for this product and date.\n" +" According to the product configuration,\n" +" this may trigger a draft purchase order, a " +"manufacturing\n" +" order or a transfer picking." +msgstr "" +"Utilice este asistente para aprovisionarse para este producto y fecha.\n" +" Según la configuración del " +"producto,\n" +" puede desencadenar un borrador " +"de pedido, una orden de\n" +" fabricación o un picking de " +"transferencia." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Verified for MRP" +msgstr "Verificado para MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__waiting +msgid "Waiting" +msgstr "Esperando" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__warehouse_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__warehouse_id +msgid "Warehouse" +msgstr "Almacén" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__wiz_id +msgid "Wizard" +msgstr "Asistente" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__calendar_id +msgid "Working Hours" +msgstr "Horario de Trabajo" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/product_mrp_area.py:0 +#, python-format +msgid "You cannot use a negative number." +msgstr "No puede utilizar un número negativo." + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación en" + +#~ msgid "" +#~ "Requirements for a particular MRP area are combined for the purposes of " +#~ "procurement by the MRP." +#~ msgstr "" +#~ "Las necesidades de un área concreta del MRP se combinan a efectos de " +#~ "adquisición por parte del MRP." + +#~ msgid "or" +#~ msgstr "o" + +#~ msgid "Date to Procure (By Month)" +#~ msgstr "Fecha para reaprovisionar (por mes)" + +#~ msgid "Date to Procure (By Week)" +#~ msgstr "Fecha para reaprovisionar (por semana)" + +#~ msgid "Transfer" +#~ msgstr "Transfer" + +#~ msgid "MRP Action Date" +#~ msgstr "Fecha de acción MRP" + +#~ msgid "MRP Move UP" +#~ msgstr "Movimiento Arriba MRP" + +#~ msgid "Minimum Stock" +#~ msgstr "Stock Mínimo" + +#~ msgid "Processed" +#~ msgstr "Procesado" + +#~ msgid "MRP Product" +#~ msgstr "Producto MRP" + +#~ msgid "MRP Product data" +#~ msgstr "Datos Producto MRP" + +#~ msgid "MRP Products" +#~ msgstr "Productos MRP" + +#~ msgid "MRP Qty Available" +#~ msgstr "Ctd. Disponible MRP" + +#~ msgid "MRP Verified" +#~ msgstr "Verificado para MRP" + +#~ msgid "Manufacture Actions" +#~ msgstr "Acciones de Fabricación" + +#~ msgid "Moves" +#~ msgstr "Movimientos" + +#~ msgid "Purchase Actions" +#~ msgstr "Acciones de Compra" + +#~ msgid "Search Product" +#~ msgstr "Buscar Producto" + +#~ msgid "With Actions" +#~ msgstr "Con Acciones" + +#~ msgid "With Actions in Coming 4 Weeks" +#~ msgstr "Con Acciones en las Próximas 4 Semanas" + +#~ msgid "With Moves" +#~ msgstr "Con Movimientos" diff --git a/mrp_multi_level/i18n/hr.po b/mrp_multi_level/i18n/hr.po new file mode 100644 index 000000000..e3c221c83 --- /dev/null +++ b/mrp_multi_level/i18n/hr.po @@ -0,0 +1,1024 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_multi_level +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-12-04 14:04+0000\n" +"Last-Translator: Bole \n" +"Language-Team: none\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.9.1\n" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_11_product_template +msgid "AV-11 steel" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_12_product_template +msgid "AV-12 aluminium" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_21_product_template +msgid "AV-21 white" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_22_product_template +msgid "AV-22 black" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_action +msgid "Action" +msgstr "Akcija" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__active +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__active +msgid "Active" +msgstr "Aktivan" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__approved +msgid "Approved" +msgstr "Odobreno" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Archived" +msgstr "Arhivirano" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__assigned +msgid "Assigned" +msgstr "Dodijeljeno" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_inventory_id +msgid "Associated MRP Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__bom_id +msgid "Bom" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__buy +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__buy +msgid "Buy" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Cancel" +msgstr "" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_change_mrp_procure_qty +msgid "Change procure quantity in MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__company_id +msgid "Company" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__confirmed +msgid "Confirmed" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Create Procurement" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_uid +msgid "Created by" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_date +msgid "Created on" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_date +msgid "Current Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_qty +msgid "Current Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__due_date +msgid "Date in which the supply must have been completed." +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date to Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__demand_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__d +msgid "Demand" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__name +msgid "Description" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Details" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__display_name +msgid "Display Name" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__distribution_lead_time +msgid "Distribution Lead Time" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__draft +msgid "Draft" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__due_date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Due Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_exclude +msgid "Exclude from MRP" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Execute" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_1_product_template +msgid "FP-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_2_product_template +msgid "FP-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_3_product_template +msgid "FP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_4_product_template +msgid "FP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__fixed +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Fixed" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__fc +msgid "Forecast" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__final_on_hand_qty +msgid "Forecasted Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Get from main supplier" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Group By..." +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "Grouped Demand of %(product_name)s for %(delta_days)d Days" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__id +msgid "ID" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Identifies that this product has been verified to be valid for the MRP." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "If empty, all areas will be computed." +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Incoming Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_inspection_delay +msgid "Inspection Delay" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__item_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Items" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__phantom +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__phantom +msgid "Kit" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_date +msgid "Last Updated on" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_lead_time +msgid "Lead Time" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_id +msgid "Location" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__llc +msgid "Low Level Code" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_form +msgid "MOs" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mrp +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_mrp +msgid "MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_applicable +msgid "MRP Applicable" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_area_action +#: model:ir.model,name:mrp_multi_level.model_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "MRP Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_stock_location__mrp_area_count +msgid "MRP Area Parameter Count" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_ids +msgid "MRP Area parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_areas +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_template_only_form_view_mrp +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_location_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_product_product_form +msgid "MRP Areas" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "MRP Areas to run" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_date +msgid "MRP Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_inventory_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_inventory +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_graph +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_pivot +msgid "MRP Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure_item +msgid "MRP Inventory procure item" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_move +msgid "MRP Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_move_down_ids +msgid "MRP Move DOWN" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_move_action +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "MRP Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_qty +msgid "MRP Quantity" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory +msgid "MRP inventory projections" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__main_supplier_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplier_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Main Supplier" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure +msgid "Make Procurements from MRP inventory projections" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__production_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mo +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__manufacture +msgid "Manufacturing Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_production_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__manufacturing_order_ids +msgid "Manufacturing Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_maximum_order_qty +msgid "Maximum Order Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_order_qty +msgid "Minimum Order Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mo_count +msgid "Mo Count" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mv +msgid "Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_area_id +msgid "Mrp Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__mrp_inventory_id +msgid "Mrp Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_move_ids +msgid "Mrp Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_planner_id +msgid "Mrp Planner" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.mrp_multi_level_cron_ir_actions_server +#: model:ir.model,name:mrp_multi_level.model_mrp_multi_level +msgid "Multi Level MRP" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "My products" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__name +msgid "Name" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "Nbr. Days" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "No MRP product found" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__none +msgid "None" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "" +"Number of days to group demand for this product during the MRP run, in order " +"to determine the quantity to order." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_order_number +msgid "Order Number" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__order_release_date +msgid "Order Release Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Order release date planned by MRP." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_origin +msgid "Origin" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Outgoing Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_1_product_template +msgid "PP-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_2_product_template +msgid "PP-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_3_product_template +msgid "PP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_4_product_template +msgid "PP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__parent_product_id +msgid "Parent Product" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__partially_available +msgid "Partially Available" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Planned Availability" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__date_planned +msgid "Planned Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_planned_order +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__planned_order_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_production__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__planned_order_ids +msgid "Planned Order" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/mrp_inventory.py:0 +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_planned_order_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_planned_order +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, python-format +msgid "Planned Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__planned_order_up_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_move_view_form +msgid "Planned Orders UP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure_planned_order +msgid "Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "Procure Location" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Procurement Request" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__manufacture +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__manufacture +msgid "Produce" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_template +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Product" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_mrp_area_id +msgid "Product MRP Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.product_mrp_area_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_product_mrp_area_parameters +msgid "Product MRP Area Parameters" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Product MRP Area parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Product Parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_tmpl_id +msgid "Product Template" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__uom_id +msgid "Product UoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull_push +msgid "Pull & Push" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull +msgid "Pull From" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_order_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__po +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__buy +msgid "Purchase Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_line_id +msgid "Purchase Order Line" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__purchase_order_line_ids +msgid "Purchase Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__push +msgid "Push To" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_qty_multiple +msgid "Qty Multiple" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__qty_released +msgid "Qty Released" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__qty +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_qty +msgid "Quantity" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__qty_available +msgid "Quantity Available" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_inventory_procure.py:0 +#, python-format +msgid "Quantity must be positive." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__ready +msgid "Ready" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Release Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.action_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_mrp_multi_level_run +msgid "Run MRP Manually" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP Multi Level" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_1_product_template +msgid "SF-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_2_product_template +msgid "SF-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_3_product_template +msgid "SF-3" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_stock +#, python-format +msgid "Safety Stock" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Selection..." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__sent +msgid "Sent" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "" +"Set this if you need to procure from a different locationthan area's " +"location." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__origin +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__origin +msgid "Source Document" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__initial_on_hand_qty +msgid "Starting Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__state +msgid "State" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__stock_move_id +msgid "Stock Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_rule +msgid "Stock Rule" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplierinfo_id +msgid "Supplier Info" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__s +msgid "Supply" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_bom_id +msgid "Supply BoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_method +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Supply Method" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__company_id +msgid "The company is automatically set from your user preferences." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.constraint,message:mrp_multi_level.constraint_product_mrp_area_product_mrp_area_uniq +msgid "The product/MRP Area parameters combination must be unique." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Theoretical inventory level if all planned orders were released." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__to_approve +msgid "To Approve" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__to_procure +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "To Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.action_server_planned_order_toggle_fixed +msgid "Toggle Fixed" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_transit_delay +msgid "Transit Delay" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_type +msgid "Type" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__none +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__none +msgid "Undefined" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__uom_id +msgid "Unit of Measure" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "" +"Use this assistant to procure for this product and date.\n" +" According to the product configuration,\n" +" this may trigger a draft purchase order, a " +"manufacturing\n" +" order or a transfer picking." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Verified for MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__waiting +msgid "Waiting" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__warehouse_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__warehouse_id +msgid "Warehouse" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__wiz_id +msgid "Wizard" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__calendar_id +msgid "Working Hours" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/product_mrp_area.py:0 +#, python-format +msgid "You cannot use a negative number." +msgstr "" diff --git a/mrp_multi_level/i18n/it.po b/mrp_multi_level/i18n/it.po new file mode 100644 index 000000000..7dcf668b9 --- /dev/null +++ b/mrp_multi_level/i18n/it.po @@ -0,0 +1,1045 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_multi_level +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-11-11 14:06+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.6.2\n" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_11_product_template +msgid "AV-11 steel" +msgstr "AV-11 acciaio" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_12_product_template +msgid "AV-12 aluminium" +msgstr "AV-12 alluminio" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_21_product_template +msgid "AV-21 white" +msgstr "AV-21 bianco" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_22_product_template +msgid "AV-22 black" +msgstr "AV-22 nero" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_action +msgid "Action" +msgstr "Azione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__active +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__active +msgid "Active" +msgstr "Attivo" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__approved +msgid "Approved" +msgstr "Approvato" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Archived" +msgstr "In archivio" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__assigned +msgid "Assigned" +msgstr "Assegnato" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_inventory_id +msgid "Associated MRP Inventory" +msgstr "Magazzino MRP associato" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__bom_id +msgid "Bom" +msgstr "DiBa" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__buy +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__buy +msgid "Buy" +msgstr "Acquista" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Cancel" +msgstr "Annulla" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_change_mrp_procure_qty +msgid "Change procure quantity in MRP" +msgstr "Modifica quantità approvvigionamento nell'MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__company_id +msgid "Company" +msgstr "Azienda" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__confirmed +msgid "Confirmed" +msgstr "Confermato" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Create Procurement" +msgstr "Crea approvvigionamento" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_date +msgid "Current Date" +msgstr "Datta attuale" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_qty +msgid "Current Qty" +msgstr "Q.tà attuale" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date" +msgstr "Data" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__due_date +msgid "Date in which the supply must have been completed." +msgstr "Data alla quale la fornitura deve essere completata." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date to Procure" +msgstr "Data a approvvigionare" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__demand_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__d +msgid "Demand" +msgstr "Domanda" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__name +msgid "Description" +msgstr "Descrizione" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Details" +msgstr "Dettagli" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__distribution_lead_time +msgid "Distribution Lead Time" +msgstr "Tempo attesa distribuzione" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__draft +msgid "Draft" +msgstr "Bozza" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__due_date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Due Date" +msgstr "Scadenza" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_exclude +msgid "Exclude from MRP" +msgstr "Esclude da MRP" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Execute" +msgstr "Esegui" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_1_product_template +msgid "FP-1" +msgstr "FP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_2_product_template +msgid "FP-2" +msgstr "FP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_3_product_template +msgid "FP-3" +msgstr "FP-3" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_4_product_template +msgid "FP-4" +msgstr "FP-4" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__fixed +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Fixed" +msgstr "Fisso" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__fc +msgid "Forecast" +msgstr "Previsione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__final_on_hand_qty +msgid "Forecasted Inventory" +msgstr "Giacenge previste" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Get from main supplier" +msgstr "Ottieni dal fornitore principale" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Group By..." +msgstr "Raggruppa per..." + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "Grouped Demand of %(product_name)s for %(delta_days)d Days" +msgstr "Richiesta raggruppata di %(product_name)s per %(delta_days)d giorni" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__id +msgid "ID" +msgstr "ID" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Identifies that this product has been verified to be valid for the MRP." +msgstr "Identifica il prodotto come verificato valido per l'MRP." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "If empty, all areas will be computed." +msgstr "Se vuoto, tutte le aree verranno calcolate." + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Incoming Moves" +msgstr "Movimenti di ingresso" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_inspection_delay +msgid "Inspection Delay" +msgstr "Ritardo ispezione" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_location +msgid "Inventory Locations" +msgstr "Ubicazioni di inventario" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__item_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Items" +msgstr "Elementi" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__phantom +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__phantom +msgid "Kit" +msgstr "Confezione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_lead_time +msgid "Lead Time" +msgstr "Tempo di attesa" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_id +msgid "Location" +msgstr "Ubicazione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__llc +msgid "Low Level Code" +msgstr "Codice livello basso" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_form +msgid "MOs" +msgstr "OP" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mrp +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_mrp +msgid "MRP" +msgstr "MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_applicable +msgid "MRP Applicable" +msgstr "MRP applicabile" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_area_action +#: model:ir.model,name:mrp_multi_level.model_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "MRP Area" +msgstr "Area MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_stock_location__mrp_area_count +msgid "MRP Area Parameter Count" +msgstr "Contegio parametri area MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_ids +msgid "MRP Area parameters" +msgstr "Parametri area MRP" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_areas +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_template_only_form_view_mrp +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_location_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_product_product_form +msgid "MRP Areas" +msgstr "Aree MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "MRP Areas to run" +msgstr "Aree MRP da eseguire" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_date +msgid "MRP Date" +msgstr "Data MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_inventory_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_inventory +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_graph +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_pivot +msgid "MRP Inventory" +msgstr "Magazzino MRP" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure_item +msgid "MRP Inventory procure item" +msgstr "Elemento approvvigionamento di magazzino MRP" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_move +msgid "MRP Move" +msgstr "Movimento MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_move_down_ids +msgid "MRP Move DOWN" +msgstr "Abbassa movimento MRP" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_move_action +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "MRP Moves" +msgstr "Movimenti MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_qty +msgid "MRP Quantity" +msgstr "Quantità MRP" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory +msgid "MRP inventory projections" +msgstr "Proiezioni magazzino MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__main_supplier_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplier_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Main Supplier" +msgstr "Fornitore principale" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure +msgid "Make Procurements from MRP inventory projections" +msgstr "Eseguire approvvigionamenti per le proiezioni inventario MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__production_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mo +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__manufacture +msgid "Manufacturing Order" +msgstr "Ordine di produzione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_production_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__manufacturing_order_ids +msgid "Manufacturing Orders" +msgstr "Ordini di produzione" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_maximum_order_qty +msgid "Maximum Order Qty" +msgstr "Quantità massima ordine" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_order_qty +msgid "Minimum Order Qty" +msgstr "Quantità minima ordine" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mo_count +msgid "Mo Count" +msgstr "Conteggio OP" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mv +msgid "Move" +msgstr "Movimento" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_area_id +msgid "Mrp Area" +msgstr "Area MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__mrp_inventory_id +msgid "Mrp Inventory" +msgstr "Magazzino MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_move_ids +msgid "Mrp Move" +msgstr "Movimento MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_planner_id +msgid "Mrp Planner" +msgstr "Pianificatore MRP" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.mrp_multi_level_cron_ir_actions_server +#: model:ir.model,name:mrp_multi_level.model_mrp_multi_level +msgid "Multi Level MRP" +msgstr "MRP multi livello" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "My products" +msgstr "Prodotti miei" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__name +msgid "Name" +msgstr "Nome" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "Nbr. Days" +msgstr "Nr. giorni" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "No MRP product found" +msgstr "Nessun prodotto MRP trovato" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__none +msgid "None" +msgstr "Nessuno" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "" +"Number of days to group demand for this product during the MRP run, in order " +"to determine the quantity to order." +msgstr "" +"Numero di giorni della domanda da raggruppare per questo prodotto " +"nell'esecuzione dell'MRP, per definire la quantità da ordinare." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_order_number +msgid "Order Number" +msgstr "Numero ordine" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__order_release_date +msgid "Order Release Date" +msgstr "Data rilascio ordine" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Order release date planned by MRP." +msgstr "Data rilascio ordine pianificata dall'MRP." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_origin +msgid "Origin" +msgstr "Origine" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Outgoing Moves" +msgstr "Movimenti di uscita" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_1_product_template +msgid "PP-1" +msgstr "PP-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_2_product_template +msgid "PP-2" +msgstr "PP-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_3_product_template +msgid "PP-3" +msgstr "PP-3" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_4_product_template +msgid "PP-4" +msgstr "PP-4" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__parent_product_id +msgid "Parent Product" +msgstr "Prodotto padre" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__partially_available +msgid "Partially Available" +msgstr "Parzialmente disponibile" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Planned Availability" +msgstr "Disponibilità pianificata" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__date_planned +msgid "Planned Date" +msgstr "Data pianificata" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_planned_order +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__planned_order_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_production__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__planned_order_ids +msgid "Planned Order" +msgstr "Ordine pianificato" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/mrp_inventory.py:0 +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_planned_order_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_planned_order +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, python-format +msgid "Planned Orders" +msgstr "Ordini pianificati" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__planned_order_up_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_move_view_form +msgid "Planned Orders UP" +msgstr "Alza ordini pianificati" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure_planned_order +msgid "Procure" +msgstr "Approvvigiona" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "Procure Location" +msgstr "Ubicazione di approvvigionamento" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Procurement Request" +msgstr "Richiesta approvvigionamento" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__manufacture +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__manufacture +msgid "Produce" +msgstr "Produzione" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_template +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Product" +msgstr "Prodotto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_mrp_area_id +msgid "Product MRP Area" +msgstr "Area MRP prodotto" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.product_mrp_area_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_product_mrp_area_parameters +msgid "Product MRP Area Parameters" +msgstr "Parametri area MRP prodotto" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Product MRP Area parameters" +msgstr "Parametri area MRP prodotto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Product Parameters" +msgstr "Parametri prodotto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_tmpl_id +msgid "Product Template" +msgstr "Modello prodotto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__uom_id +msgid "Product UoM" +msgstr "UdM prodotto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_product +msgid "Product Variant" +msgstr "Variante prodotto" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_production +msgid "Production Order" +msgstr "Ordine di produzione" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull_push +msgid "Pull & Push" +msgstr "Pull & Push" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull +msgid "Pull From" +msgstr "Modello richiesta" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_order_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__po +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__buy +msgid "Purchase Order" +msgstr "Ordine di acquisto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_line_id +msgid "Purchase Order Line" +msgstr "Riga ordine di acquisto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__purchase_order_line_ids +msgid "Purchase Orders" +msgstr "Ordini di acquisto" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__push +msgid "Push To" +msgstr "Invia a" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_qty_multiple +msgid "Qty Multiple" +msgstr "Multiplo q.tà" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__qty_released +msgid "Qty Released" +msgstr "Ata. rilasciata" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__qty +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_qty +msgid "Quantity" +msgstr "Quantità" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__qty_available +msgid "Quantity Available" +msgstr "Quantità disponibile" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_inventory_procure.py:0 +#, python-format +msgid "Quantity must be positive." +msgstr "La quantità deve essere positiva." + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_quant +msgid "Quants" +msgstr "Quanti" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__ready +msgid "Ready" +msgstr "Pronto" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Release Date" +msgstr "Data rilascio" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.action_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP" +msgstr "Esegui MRP" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_mrp_multi_level_run +msgid "Run MRP Manually" +msgstr "Esegui manualmente MRP" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP Multi Level" +msgstr "Esegui MRP multi livello" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_1_product_template +msgid "SF-1" +msgstr "SF-1" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_2_product_template +msgid "SF-2" +msgstr "SF-2" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_3_product_template +msgid "SF-3" +msgstr "SF-3" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_stock +#, python-format +msgid "Safety Stock" +msgstr "Giacenza di sicurezza" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Selection..." +msgstr "Selezione..." + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__sent +msgid "Sent" +msgstr "Inviato" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "" +"Set this if you need to procure from a different locationthan area's " +"location." +msgstr "" +"Da impostare se è necessario approvvigionare da un'ubicazione diversa da " +"quella dell'area." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__origin +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__origin +msgid "Source Document" +msgstr "Documento di origine" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__initial_on_hand_qty +msgid "Starting Inventory" +msgstr "Inizio inventario" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__state +msgid "State" +msgstr "Stato" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__stock_move_id +msgid "Stock Move" +msgstr "Movimento di magazzino" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_rule +msgid "Stock Rule" +msgstr "Regola di giacenza" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplierinfo_id +msgid "Supplier Info" +msgstr "Informazioni fornitore" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__s +msgid "Supply" +msgstr "Fornitura" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_bom_id +msgid "Supply BoM" +msgstr "DiBa fornitura" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_method +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Supply Method" +msgstr "Metodo fornitura" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__company_id +msgid "The company is automatically set from your user preferences." +msgstr "L'azienda è impostata automaticamente in base alle preferenze utente." + +#. module: mrp_multi_level +#: model:ir.model.constraint,message:mrp_multi_level.constraint_product_mrp_area_product_mrp_area_uniq +msgid "The product/MRP Area parameters combination must be unique." +msgstr "La combinazione dei parametri prodotto/Area MRP deve essere univoca." + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Theoretical inventory level if all planned orders were released." +msgstr "" +"Livello teorico giacenze se tutti gli ordini pianificati venissero " +"rilasciati." + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__to_approve +msgid "To Approve" +msgstr "Da approvare" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__to_procure +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "To Procure" +msgstr "Da approvvigionare" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.action_server_planned_order_toggle_fixed +msgid "Toggle Fixed" +msgstr "Modifica bloccata" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_transit_delay +msgid "Transit Delay" +msgstr "Ritardo di transito" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_type +msgid "Type" +msgstr "Tipo" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__none +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__none +msgid "Undefined" +msgstr "Non definito" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__uom_id +msgid "Unit of Measure" +msgstr "Unità di misura" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "" +"Use this assistant to procure for this product and date.\n" +" According to the product configuration,\n" +" this may trigger a draft purchase order, a " +"manufacturing\n" +" order or a transfer picking." +msgstr "" +"Utilizzare questo assistente per approvvigionare questo prodotto a questa " +"data.\n" +" In funzione della configurazione prodotto,\n" +" questo genererà una bozza di ordine di acquisto, un " +"ordine\n" +" di produzione o un prelievo di trasferimento." + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Verified for MRP" +msgstr "Verificato per l'MRP" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__waiting +msgid "Waiting" +msgstr "In attesa" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__warehouse_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__warehouse_id +msgid "Warehouse" +msgstr "Magazzino" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__wiz_id +msgid "Wizard" +msgstr "Procedura guidata" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__calendar_id +msgid "Working Hours" +msgstr "Orario lavorativo" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/product_mrp_area.py:0 +#, python-format +msgid "You cannot use a negative number." +msgstr "non si può usare un numero negativo." + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "" +#~ "Requirements for a particular MRP area are combined for the purposes of " +#~ "procurement by the MRP." +#~ msgstr "" +#~ "Richieste di una area MRP particolare sono combinate allo scopo di " +#~ "approvvigionamento dall'MRP." diff --git a/mrp_multi_level/i18n/mrp_multi_level.pot b/mrp_multi_level/i18n/mrp_multi_level.pot new file mode 100644 index 000000000..65713585f --- /dev/null +++ b/mrp_multi_level/i18n/mrp_multi_level.pot @@ -0,0 +1,1024 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mrp_multi_level +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_11_product_template +msgid "AV-11 steel" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_12_product_template +msgid "AV-12 aluminium" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_21_product_template +msgid "AV-21 white" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_av_22_product_template +msgid "AV-22 black" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_action +msgid "Action" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__active +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__active +msgid "Active" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__approved +msgid "Approved" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Archived" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__assigned +msgid "Assigned" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_inventory_id +msgid "Associated MRP Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__bom_id +msgid "Bom" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__buy +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__buy +msgid "Buy" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Cancel" +msgstr "" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_change_mrp_procure_qty +msgid "Change procure quantity in MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__company_id +msgid "Company" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__confirmed +msgid "Confirmed" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Create Procurement" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_uid +msgid "Created by" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__create_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__create_date +msgid "Created on" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_date +msgid "Current Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__current_qty +msgid "Current Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__due_date +msgid "Date in which the supply must have been completed." +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Date to Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__demand_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__d +msgid "Demand" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__name +msgid "Description" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_tree +msgid "Details" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__display_name +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__display_name +msgid "Display Name" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__distribution_lead_time +msgid "Distribution Lead Time" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__draft +msgid "Draft" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__due_date +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Due Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_exclude +msgid "Exclude from MRP" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Execute" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_1_product_template +msgid "FP-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_2_product_template +msgid "FP-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_3_product_template +msgid "FP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_fp_4_product_template +msgid "FP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__fixed +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Fixed" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__fc +msgid "Forecast" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__final_on_hand_qty +msgid "Forecasted Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Get from main supplier" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Group By..." +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "Grouped Demand of %(product_name)s for %(delta_days)d Days" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__id +msgid "ID" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "" +"Identifies that this product has been verified to be valid for the MRP." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "If empty, all areas will be computed." +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Incoming Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_inspection_delay +msgid "Inspection Delay" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__item_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Items" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__phantom +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__phantom +msgid "Kit" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_uid +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__write_date +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__write_date +msgid "Last Updated on" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_lead_time +msgid "Lead Time" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__location_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_id +msgid "Location" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__llc +msgid "Low Level Code" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_form +msgid "MOs" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mrp +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_mrp +msgid "MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_applicable +msgid "MRP Applicable" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_area_action +#: model:ir.model,name:mrp_multi_level.model_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "MRP Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_count +#: model:ir.model.fields,field_description:mrp_multi_level.field_stock_location__mrp_area_count +msgid "MRP Area Parameter Count" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__mrp_area_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_template__mrp_area_ids +msgid "MRP Area parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_areas +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_template_only_form_view_mrp +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_location_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_product_product_form +msgid "MRP Areas" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_multi_level__mrp_area_ids +msgid "MRP Areas to run" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_date +msgid "MRP Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_inventory_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_inventory +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_graph +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_pivot +msgid "MRP Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure_item +msgid "MRP Inventory procure item" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_move +msgid "MRP Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_move_down_ids +msgid "MRP Move DOWN" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_move_action +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "MRP Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_qty +msgid "MRP Quantity" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory +msgid "MRP inventory projections" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__main_supplier_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplier_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Main Supplier" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_inventory_procure +msgid "Make Procurements from MRP inventory projections" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__production_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mo +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__manufacture +msgid "Manufacturing Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_production_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__manufacturing_order_ids +msgid "Manufacturing Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_maximum_order_qty +msgid "Maximum Order Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_order_qty +msgid "Minimum Order Qty" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mo_count +msgid "Mo Count" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__mv +msgid "Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_area_id +msgid "Mrp Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__mrp_inventory_id +msgid "Mrp Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_move_ids +msgid "Mrp Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_planner_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_planner_id +msgid "Mrp Planner" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.mrp_multi_level_cron_ir_actions_server +#: model:ir.model,name:mrp_multi_level.model_mrp_multi_level +msgid "Multi Level MRP" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "My products" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__name +msgid "Name" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "Nbr. Days" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#, python-format +msgid "No MRP product found" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__none +msgid "None" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__mrp_nbr_days +msgid "" +"Number of days to group demand for this product during the MRP run, in order" +" to determine the quantity to order." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_order_number +msgid "Order Number" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__order_release_date +msgid "Order Release Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Order release date planned by MRP." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_origin +msgid "Origin" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +msgid "Outgoing Moves" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_1_product_template +msgid "PP-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_2_product_template +msgid "PP-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_3_product_template +msgid "PP-3" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_pp_4_product_template +msgid "PP-4" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__parent_product_id +msgid "Parent Product" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__partially_available +msgid "Partially Available" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Planned Availability" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__date_planned +msgid "Planned Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_planned_order +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__planned_order_ids +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_production__planned_order_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__planned_order_ids +msgid "Planned Order" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/mrp_inventory.py:0 +#: model:ir.actions.act_window,name:mrp_multi_level.mrp_planned_order_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_planned_order +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#, python-format +msgid "Planned Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__planned_order_up_ids +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_move_view_form +msgid "Planned Orders UP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure +#: model:ir.actions.act_window,name:mrp_multi_level.act_mrp_inventory_procure_planned_order +msgid "Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "Procure Location" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "Procurement Request" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__manufacture +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__manufacture +msgid "Produce" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_template +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Product" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_mrp_area +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__product_mrp_area_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__product_mrp_area_id +msgid "Product MRP Area" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.product_mrp_area_action +#: model:ir.ui.menu,name:mrp_multi_level.menu_product_mrp_area_parameters +msgid "Product MRP Area Parameters" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_form +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.product_mrp_area_search +msgid "Product MRP Area parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__product_mrp_area_id +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_planned_order_view_search +msgid "Product Parameters" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__product_tmpl_id +msgid "Product Template" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__uom_id +msgid "Product UoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull_push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull_push +msgid "Pull & Push" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__pull +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__pull +msgid "Pull From" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_order_id +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_origin__po +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__buy +msgid "Purchase Order" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__purchase_line_id +msgid "Purchase Order Line" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_product__purchase_order_line_ids +msgid "Purchase Orders" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_planned_order__mrp_action__push +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__push +msgid "Push To" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_qty_multiple +msgid "Qty Multiple" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__qty_released +msgid "Qty Released" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__qty +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__mrp_qty +msgid "Quantity" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__qty_available +msgid "Quantity Available" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_inventory_procure.py:0 +#, python-format +msgid "Quantity must be positive." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__ready +msgid "Ready" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__order_release_date +msgid "Release Date" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.act_window,name:mrp_multi_level.action_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:res.groups,name:mrp_multi_level.group_mrp_multi_level_run +msgid "Run MRP Manually" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.ui.menu,name:mrp_multi_level.menu_mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_run_mrp_multi_level_wizard +msgid "Run MRP Multi Level" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_1_product_template +msgid "SF-1" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_2_product_template +msgid "SF-2" +msgstr "" + +#. module: mrp_multi_level +#: model:product.template,name:mrp_multi_level.product_product_sf_3_product_template +msgid "SF-3" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: code:addons/mrp_multi_level/wizards/mrp_multi_level.py:0 +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_minimum_stock +#, python-format +msgid "Safety Stock" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Selection..." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__sent +msgid "Sent" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__location_proc_id +msgid "" +"Set this if you need to procure from a different locationthan area's " +"location." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__origin +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_planned_order__origin +msgid "Source Document" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__initial_on_hand_qty +msgid "Starting Inventory" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__state +msgid "State" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__stock_move_id +msgid "Stock Move" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model,name:mrp_multi_level.model_stock_rule +msgid "Stock Rule" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__main_supplierinfo_id +msgid "Supplier Info" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_qty +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__mrp_type__s +msgid "Supply" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_bom_id +msgid "Supply BoM" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__supply_method +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__supply_method +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "Supply Method" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_area__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_move__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_planned_order__company_id +#: model:ir.model.fields,help:mrp_multi_level.field_product_mrp_area__company_id +msgid "The company is automatically set from your user preferences." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.constraint,message:mrp_multi_level.constraint_product_mrp_area_product_mrp_area_uniq +msgid "The product/MRP Area parameters combination must be unique." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,help:mrp_multi_level.field_mrp_inventory__running_availability +msgid "Theoretical inventory level if all planned orders were released." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__to_approve +msgid "To Approve" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory__to_procure +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.mrp_inventory_search +msgid "To Procure" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.actions.server,name:mrp_multi_level.action_server_planned_order_toggle_fixed +msgid "Toggle Fixed" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_transit_delay +msgid "Transit Delay" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_move__mrp_type +msgid "Type" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_inventory_procure_item__supply_method__none +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__product_mrp_area__supply_method__none +msgid "Undefined" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__uom_id +msgid "Unit of Measure" +msgstr "" + +#. module: mrp_multi_level +#: model_terms:ir.ui.view,arch_db:mrp_multi_level.view_mrp_inventory_procure_wizard +msgid "" +"Use this assistant to procure for this product and date.\n" +" According to the product configuration,\n" +" this may trigger a draft purchase order, a manufacturing\n" +" order or a transfer picking." +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_product_mrp_area__mrp_verified +msgid "Verified for MRP" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields.selection,name:mrp_multi_level.selection__mrp_move__state__waiting +msgid "Waiting" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__warehouse_id +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__warehouse_id +msgid "Warehouse" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_inventory_procure_item__wiz_id +msgid "Wizard" +msgstr "" + +#. module: mrp_multi_level +#: model:ir.model.fields,field_description:mrp_multi_level.field_mrp_area__calendar_id +msgid "Working Hours" +msgstr "" + +#. module: mrp_multi_level +#. odoo-python +#: code:addons/mrp_multi_level/models/product_mrp_area.py:0 +#, python-format +msgid "You cannot use a negative number." +msgstr "" diff --git a/mrp_multi_level/models/__init__.py b/mrp_multi_level/models/__init__.py new file mode 100644 index 000000000..708a1ebdb --- /dev/null +++ b/mrp_multi_level/models/__init__.py @@ -0,0 +1,11 @@ +from . import mrp_area +from . import stock_location +from . import product_product +from . import product_template +from . import mrp_move +from . import mrp_planned_order +from . import mrp_inventory +from . import product_mrp_area +from . import stock_rule +from . import mrp_production +from . import stock_quant diff --git a/mrp_multi_level/models/mrp_area.py b/mrp_multi_level/models/mrp_area.py new file mode 100644 index 000000000..63ebcc1f9 --- /dev/null +++ b/mrp_multi_level/models/mrp_area.py @@ -0,0 +1,42 @@ +# © 2016 Ucamco - Wim Audenaert +# Copyright 2016-21 ForgeFlow S.L. (https://www.forgeflow.com) +# - Jordi Ballester Alomar +# - Lois Rilo Antelo +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class MrpArea(models.Model): + _name = "mrp.area" + _description = "MRP Area" + + name = fields.Char(required=True) + warehouse_id = fields.Many2one( + comodel_name="stock.warehouse", string="Warehouse", required=True + ) + company_id = fields.Many2one( + comodel_name="res.company", related="warehouse_id.company_id", store=True + ) + location_id = fields.Many2one( + comodel_name="stock.location", string="Location", required=True + ) + active = fields.Boolean(default=True) + calendar_id = fields.Many2one( + comodel_name="resource.calendar", + string="Working Hours", + related="warehouse_id.calendar_id", + ) + + @api.model + def _datetime_to_date_tz(self, dt_to_convert=None): + """Coverts a datetime to date considering the timezone of MRP Area. + If no datetime is provided, it returns today's date in the timezone.""" + return fields.Date.context_today( + self.with_context(tz=self.calendar_id.tz), + timestamp=dt_to_convert, + ) + + def _get_locations(self): + self.ensure_one() + return self.location_id diff --git a/mrp_multi_level/models/mrp_inventory.py b/mrp_multi_level/models/mrp_inventory.py new file mode 100644 index 000000000..bf5fb5b46 --- /dev/null +++ b/mrp_multi_level/models/mrp_inventory.py @@ -0,0 +1,135 @@ +# © 2016 Ucamco - Wim Audenaert +# Copyright 2016-21 ForgeFlow S.L. (https://www.forgeflow.com) +# - Jordi Ballester Alomar +# - Lois Rilo Antelo +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import date, timedelta + +from odoo import _, api, fields, models + + +class MrpInventory(models.Model): + _name = "mrp.inventory" + _order = "product_mrp_area_id, date" + _description = "MRP inventory projections" + _rec_name = "product_mrp_area_id" + + # TODO: name to pass to procurements? + # TODO: compute procurement_date to pass to the wizard? not needed for + # PO at least. Check for MO and moves + + mrp_area_id = fields.Many2one( + comodel_name="mrp.area", + string="MRP Area", + related="product_mrp_area_id.mrp_area_id", + store=True, + ) + product_mrp_area_id = fields.Many2one( + comodel_name="product.mrp.area", + string="Product Parameters", + index=True, + required=True, + ondelete="cascade", + ) + company_id = fields.Many2one( + comodel_name="res.company", + related="product_mrp_area_id.mrp_area_id.warehouse_id.company_id", + store=True, + ) + product_id = fields.Many2one( + comodel_name="product.product", + related="product_mrp_area_id.product_id", + store=True, + ) + uom_id = fields.Many2one( + comodel_name="uom.uom", string="Product UoM", compute="_compute_uom_id" + ) + date = fields.Date() + demand_qty = fields.Float(string="Demand") + supply_qty = fields.Float(string="Supply") + initial_on_hand_qty = fields.Float(string="Starting Inventory", aggregator="avg") + final_on_hand_qty = fields.Float(string="Forecasted Inventory", aggregator="avg") + to_procure = fields.Float(compute="_compute_to_procure", store=True) + running_availability = fields.Float( + string="Planned Availability", + aggregator="avg", + help="Theoretical inventory level if all planned orders were released.", + ) + order_release_date = fields.Date(compute="_compute_order_release_date", store=True) + planned_order_ids = fields.One2many( + comodel_name="mrp.planned.order", inverse_name="mrp_inventory_id", readonly=True + ) + supply_method = fields.Selection( + string="Supply Method", + related="product_mrp_area_id.supply_method", + readonly=True, + store=True, + ) + main_supplier_id = fields.Many2one( + string="Main Supplier", + related="product_mrp_area_id.main_supplier_id", + readonly=True, + store=True, + ) + mrp_planner_id = fields.Many2one( + related="product_mrp_area_id.mrp_planner_id", + readonly=True, + store=True, + ) + + def _compute_uom_id(self): + for rec in self: + rec.uom_id = rec.product_mrp_area_id.product_id.uom_id + + @api.depends("planned_order_ids", "planned_order_ids.qty_released") + def _compute_to_procure(self): + for rec in self: + rec.to_procure = ( + 0.0 + if rec.supply_method == "phantom" + else sum(rec.planned_order_ids.mapped("mrp_qty")) + - sum(rec.planned_order_ids.mapped("qty_released")) + ) + + @api.depends( + "product_mrp_area_id", + "product_mrp_area_id.main_supplierinfo_id", + "product_mrp_area_id.mrp_lead_time", + "product_mrp_area_id.mrp_area_id.calendar_id", + ) + def _compute_order_release_date(self): + today = date.today() + for rec in self.filtered(lambda r: r.date): + delay = rec.product_mrp_area_id.mrp_lead_time + if delay and rec.mrp_area_id.calendar_id: + dt_date = fields.Datetime.to_datetime(rec.date) + # dt_date is at the beginning of the day (00:00), + # so we can subtract the delay straight forward. + order_release_date = rec.mrp_area_id.calendar_id.plan_days( + -delay, dt_date + ).date() + elif delay: + order_release_date = fields.Date.from_string(rec.date) - timedelta( + days=delay + ) + else: + order_release_date = rec.date + if order_release_date < today: + order_release_date = today + rec.order_release_date = order_release_date + + def action_open_planned_orders(self): + planned_order_ids = [] + for rec in self: + planned_order_ids += rec.planned_order_ids.ids + + domain = [("id", "in", planned_order_ids)] + + return { + "name": _("Planned Orders"), + "type": "ir.actions.act_window", + "res_model": "mrp.planned.order", + "view_mode": "list,form", + "domain": domain, + } diff --git a/mrp_multi_level/models/mrp_move.py b/mrp_multi_level/models/mrp_move.py new file mode 100644 index 000000000..29906c0e8 --- /dev/null +++ b/mrp_multi_level/models/mrp_move.py @@ -0,0 +1,95 @@ +# © 2016 Ucamco - Wim Audenaert +# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class MrpMove(models.Model): + _name = "mrp.move" + _description = "MRP Move" + _order = "product_mrp_area_id, mrp_date, mrp_type desc, id" + + # TODO: too many indexes... + + product_mrp_area_id = fields.Many2one( + comodel_name="product.mrp.area", + string="Product MRP Area", + index=True, + required=True, + ondelete="cascade", + ) + mrp_area_id = fields.Many2one( + comodel_name="mrp.area", + related="product_mrp_area_id.mrp_area_id", + string="MRP Area", + store=True, + index=True, + ) + company_id = fields.Many2one( + comodel_name="res.company", + related="product_mrp_area_id.mrp_area_id.warehouse_id.company_id", + store=True, + ) + product_id = fields.Many2one( + comodel_name="product.product", + related="product_mrp_area_id.product_id", + store=True, + ) + + current_date = fields.Date() + current_qty = fields.Float() + mrp_date = fields.Date(string="MRP Date") + planned_order_up_ids = fields.Many2many( + comodel_name="mrp.planned.order", + relation="mrp_move_planned_order_rel", + column1="move_down_id", + column2="order_id", + string="Planned Orders UP", + ) + mrp_order_number = fields.Char(string="Order Number") + mrp_origin = fields.Selection( + selection=[ + ("mo", "Manufacturing Order"), + ("po", "Purchase Order"), + ("mv", "Move"), + ("fc", "Forecast"), + ("mrp", "MRP"), + ], + string="Origin", + ) + mrp_qty = fields.Float(string="MRP Quantity") + mrp_type = fields.Selection( + selection=[("s", "Supply"), ("d", "Demand")], string="Type" + ) + name = fields.Char(string="Description") + origin = fields.Char(string="Source Document") + parent_product_id = fields.Many2one( + comodel_name="product.product", string="Parent Product", index=True + ) + production_id = fields.Many2one( + comodel_name="mrp.production", string="Manufacturing Order", index=True + ) + purchase_line_id = fields.Many2one( + comodel_name="purchase.order.line", string="Purchase Order Line", index=True + ) + purchase_order_id = fields.Many2one( + comodel_name="purchase.order", string="Purchase Order", index=True + ) + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("assigned", "Assigned"), + ("confirmed", "Confirmed"), + ("waiting", "Waiting"), + ("partially_available", "Partially Available"), + ("ready", "Ready"), + ("sent", "Sent"), + ("to approve", "To Approve"), + ("approved", "Approved"), + ], + ) + stock_move_id = fields.Many2one( + comodel_name="stock.move", string="Stock Move", index=True + ) + bom_id = fields.Many2one("mrp.bom") diff --git a/mrp_multi_level/models/mrp_planned_order.py b/mrp_multi_level/models/mrp_planned_order.py new file mode 100644 index 000000000..e29e54854 --- /dev/null +++ b/mrp_multi_level/models/mrp_planned_order.py @@ -0,0 +1,115 @@ +# Copyright 2019 ForgeFlow S.L. (https://www.forgeflow.com) +# - Lois Rilo Antelo +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from datetime import timedelta + +from odoo import api, fields, models + + +class MrpPlannedOrder(models.Model): + _name = "mrp.planned.order" + _description = "Planned Order" + _order = "due_date, id" + + name = fields.Char(string="Description") + origin = fields.Char(string="Source Document") + product_mrp_area_id = fields.Many2one( + comodel_name="product.mrp.area", + string="Product MRP Area", + index=True, + required=True, + ondelete="cascade", + ) + mrp_area_id = fields.Many2one( + comodel_name="mrp.area", + related="product_mrp_area_id.mrp_area_id", + string="MRP Area", + store=True, + index=True, + readonly=True, + ) + company_id = fields.Many2one( + comodel_name="res.company", + related="product_mrp_area_id.mrp_area_id.warehouse_id.company_id", + store=True, + ) + product_id = fields.Many2one( + comodel_name="product.product", + related="product_mrp_area_id.product_id", + store=True, + readonly=True, + ) + order_release_date = fields.Date( + string="Release Date", help="Order release date planned by MRP.", required=True + ) + due_date = fields.Date( + help="Date in which the supply must have been completed.", + required=True, + ) + qty_released = fields.Float(readonly=True) + fixed = fields.Boolean(default=True) + mrp_qty = fields.Float(string="Quantity") + mrp_move_down_ids = fields.Many2many( + comodel_name="mrp.move", + relation="mrp_move_planned_order_rel", + column1="order_id", + column2="move_down_id", + string="MRP Move DOWN", + ) + mrp_action = fields.Selection( + selection=[ + ("manufacture", "Manufacturing Order"), + ("phantom", "Kit"), + ("buy", "Purchase Order"), + ("pull", "Pull From"), + ("push", "Push To"), + ("pull_push", "Pull & Push"), + ("none", "None"), + ], + string="Action", + ) + mrp_inventory_id = fields.Many2one( + string="Associated MRP Inventory", + comodel_name="mrp.inventory", + ondelete="set null", + ) + mrp_production_ids = fields.One2many( + "mrp.production", "planned_order_id", string="Manufacturing Orders" + ) + mo_count = fields.Integer(compute="_compute_mrp_production_count") + mrp_planner_id = fields.Many2one( + related="product_mrp_area_id.mrp_planner_id", + readonly=True, + store=True, + ) + + def _compute_mrp_production_count(self): + for rec in self: + rec.mo_count = len(rec.mrp_production_ids) + + @api.onchange("due_date") + def _onchange_due_date(self): + if self.due_date: + if self.product_mrp_area_id.mrp_lead_time: + calendar = self.mrp_area_id.calendar_id + if calendar: + dt = fields.Datetime.from_string(self.due_date) + res = calendar.plan_days( + -1 * (self.product_mrp_area_id.mrp_lead_time + 1), dt + ) + self.order_release_date = res.date() + else: + self.order_release_date = fields.Date.from_string( + self.due_date + ) - timedelta(days=self.product_mrp_area_id.mrp_lead_time) + + def action_toggle_fixed(self): + for rec in self: + rec.fixed = not rec.fixed + + def action_open_linked_mrp_production(self): + action = self.env.ref("mrp.mrp_production_action") + result = action.read()[0] + result["context"] = {} + result["domain"] = f"[('id','in',{self.mrp_production_ids.ids})]" + return result diff --git a/mrp_multi_level/models/mrp_production.py b/mrp_multi_level/models/mrp_production.py new file mode 100644 index 000000000..97128d226 --- /dev/null +++ b/mrp_multi_level/models/mrp_production.py @@ -0,0 +1,15 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# - Héctor Villarreal +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import fields, models + + +class MrpProduction(models.Model): + """Manufacturing Orders""" + + _inherit = "mrp.production" + + planned_order_id = fields.Many2one( + comodel_name="mrp.planned.order", + index=True, + ) diff --git a/mrp_multi_level/models/product_mrp_area.py b/mrp_multi_level/models/product_mrp_area.py new file mode 100644 index 000000000..c980199f5 --- /dev/null +++ b/mrp_multi_level/models/product_mrp_area.py @@ -0,0 +1,312 @@ +# Copyright 2016 Ucamco - Wim Audenaert +# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) +# - Jordi Ballester Alomar +# - Lois Rilo Antelo +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from math import ceil + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class ProductMRPArea(models.Model): + _name = "product.mrp.area" + _description = "Product MRP Area" + + active = fields.Boolean(default=True) + mrp_area_id = fields.Many2one(comodel_name="mrp.area", required=True) + company_id = fields.Many2one( + comodel_name="res.company", + related="mrp_area_id.warehouse_id.company_id", + store=True, + ) + product_id = fields.Many2one( + comodel_name="product.product", + required=True, + string="Product", + ondelete="cascade", + ) + product_tmpl_id = fields.Many2one( + comodel_name="product.template", + readonly=True, + related="product_id.product_tmpl_id", + store=True, + ) + location_id = fields.Many2one(related="mrp_area_id.location_id") + location_proc_id = fields.Many2one( + string="Procure Location", + comodel_name="stock.location", + domain="[('location_id', 'child_of', location_id)]", + help="Set this if you need to procure from a different location" + "than area's location.", + ) + # TODO: applicable and exclude... redundant?? + mrp_applicable = fields.Boolean(string="MRP Applicable") + mrp_exclude = fields.Boolean(string="Exclude from MRP") + mrp_inspection_delay = fields.Integer(string="Inspection Delay") + mrp_maximum_order_qty = fields.Float(string="Maximum Order Qty", default=0.0) + mrp_minimum_order_qty = fields.Float(string="Minimum Order Qty", default=0.0) + mrp_minimum_stock = fields.Float(string="Safety Stock") + mrp_nbr_days = fields.Integer( + string="Nbr. Days", + default=0, + help="Number of days to group demand for this product during the " + "MRP run, in order to determine the quantity to order.", + ) + mrp_qty_multiple = fields.Float(string="Qty Multiple", default=1.00) + mrp_transit_delay = fields.Integer(string="Transit Delay", default=0) + mrp_verified = fields.Boolean( + string="Verified for MRP", + help="Identifies that this product has been verified " + "to be valid for the MRP.", + ) + mrp_lead_time = fields.Float(string="Lead Time", compute="_compute_mrp_lead_time") + distribution_lead_time = fields.Float() + main_supplier_id = fields.Many2one( + comodel_name="res.partner", + string="Main Supplier", + compute="_compute_main_supplier", + store=True, + index=True, + ) + main_supplierinfo_id = fields.Many2one( + comodel_name="product.supplierinfo", + string="Supplier Info", + compute="_compute_main_supplier", + store=True, + ) + supply_method = fields.Selection( + selection=[ + ("buy", "Buy"), + ("none", "Undefined"), + ("manufacture", "Produce"), + ("phantom", "Kit"), + ("pull", "Pull From"), + ("push", "Push To"), + ("pull_push", "Pull & Push"), + ], + compute="_compute_supply_method", + ) + supply_bom_id = fields.Many2one( + comodel_name="mrp.bom", + string="Supply BoM", + compute="_compute_supply_method", + ) + qty_available = fields.Float( + string="Quantity Available", compute="_compute_qty_available" + ) + mrp_move_ids = fields.One2many( + comodel_name="mrp.move", inverse_name="product_mrp_area_id", readonly=True + ) + planned_order_ids = fields.One2many( + comodel_name="mrp.planned.order", + inverse_name="product_mrp_area_id", + readonly=True, + ) + mrp_planner_id = fields.Many2one("res.users") + + _sql_constraints = [ + ( + "product_mrp_area_uniq", + "unique(product_id, mrp_area_id)", + "The product/MRP Area parameters combination must be unique.", + ) + ] + + @api.constrains( + "mrp_minimum_order_qty", + "mrp_maximum_order_qty", + "mrp_qty_multiple", + "mrp_minimum_stock", + "mrp_nbr_days", + ) + def _check_negatives(self): + values = self.read( + [ + "mrp_minimum_order_qty", + "mrp_maximum_order_qty", + "mrp_qty_multiple", + "mrp_minimum_stock", + "mrp_nbr_days", + ] + ) + for rec in values: + if any(v < 0 for v in rec.values()): + raise ValidationError(_("You cannot use a negative number.")) + + def _compute_display_name(self): + for area in self: + area.display_name = ( + f"[{area.mrp_area_id.name}] {area.product_id.display_name}" + ) + + @api.model + def _search_display_name(self, operator, value): + domain = super()._search_display_name(operator, value) + if operator in ("ilike", "like", "=", "=like", "=ilike"): + domain = [ + "|", + "|", + ("product_id.name", operator, value), + ("product_id.default_code", operator, value), + ("mrp_area_id.name", operator, value), + ] + return domain + return domain + + def _compute_mrp_lead_time(self): + produced = self.filtered(lambda r: r.supply_method == "manufacture") + purchased = self.filtered(lambda r: r.supply_method == "buy") + distributed = self.filtered( + lambda r: r.supply_method in ("pull", "push", "pull_push") + ) + for rec in produced: + rec.mrp_lead_time = sum(rec.product_id.mapped("bom_ids.produce_delay")) + for rec in purchased: + rec.mrp_lead_time = rec.main_supplierinfo_id.delay + for rec in distributed: + rec.mrp_lead_time = rec.distribution_lead_time + for rec in self - produced - purchased - distributed: + rec.mrp_lead_time = 0 + + def _compute_qty_available(self): + for rec in self: + rec.qty_available = rec.product_id.with_context( + location=rec._get_locations().ids + ).qty_available + + def _get_rule(self): + self.ensure_one() + group_obj = self.env["procurement.group"] + proc_loc = self.location_proc_id or self.location_id + values = { + "warehouse_id": self.mrp_area_id.warehouse_id, + "company_id": self.company_id, + } + rule = group_obj._get_rule(self.product_id, proc_loc, values) + if not rule: + return False + # Keep getting the rule for the product and the source location until the + # action is "buy" or "manufacture". Or until the action is "Pull From" or + # "Pull & Push" and the supply method is "Take from Stock". + while rule.action not in ("buy", "manufacture") and rule.procure_method in ( + "make_to_order", + "mts_else_mto", + ): + new_rule = group_obj._get_rule( + self.product_id, rule.location_src_id, values + ) + if not new_rule: + break + rule = new_rule + return rule + + def _compute_supply_method(self): + boms_by_product = self.env["mrp.bom"]._bom_find(self.mapped("product_id")) + for rec in self: + rule = rec._get_rule() + bom = boms_by_product.get(rec.product_id, self.env["mrp.bom"]) + if bom.type == "phantom": + rec.supply_method = "phantom" + rec.supply_bom_id = bom + elif not rule: + rec.supply_method = "none" + rec.supply_bom_id = False + elif rule.action == "manufacture": + rec.supply_method = rule.action + rec.supply_bom_id = bom + else: + rec.supply_method = rule.action + rec.supply_bom_id = False + + @api.depends( + "mrp_area_id", "supply_method", "product_id.route_ids", "product_id.seller_ids" + ) + def _compute_main_supplier(self): + """Simplified and similar to procurement.rule logic.""" + for rec in self.filtered(lambda r: r.supply_method == "buy"): + suppliers = rec.product_id.seller_ids.filtered( + lambda r, rec=rec: (not r.product_id or r.product_id == rec.product_id) + and (not r.company_id or r.company_id == rec.company_id) + ).sorted(lambda s: (s.sequence, -s.min_qty, s.price, s.id)) + if not suppliers: + rec.main_supplierinfo_id = False + rec.main_supplier_id = False + continue + rec.main_supplierinfo_id = suppliers[0] + rec.main_supplier_id = suppliers[0].partner_id + for rec in self.filtered(lambda r: r.supply_method != "buy"): + rec.main_supplierinfo_id = False + rec.main_supplier_id = False + + def _adjust_qty_to_order(self, qty_to_order): + self.ensure_one() + if ( + not self.mrp_maximum_order_qty + and not self.mrp_minimum_order_qty + and self.mrp_qty_multiple == 1.0 + ): + return qty_to_order + if qty_to_order < self.mrp_minimum_order_qty: + return self.mrp_minimum_order_qty + if self.mrp_qty_multiple: + multiplier = ceil(qty_to_order / self.mrp_qty_multiple) + qty_to_order = multiplier * self.mrp_qty_multiple + if self.mrp_maximum_order_qty and qty_to_order > self.mrp_maximum_order_qty: + return self.mrp_maximum_order_qty + return qty_to_order + + def update_min_qty_from_main_supplier(self): + for rec in self.filtered( + lambda r: r.main_supplierinfo_id and r.supply_method == "buy" + ): + rec.mrp_minimum_order_qty = rec.main_supplierinfo_id.min_qty + + def _in_stock_moves_domain(self): + self.ensure_one() + locations = self._get_locations() + return [ + ("product_id", "=", self.product_id.id), + ("state", "not in", ["done", "cancel"]), + ("product_qty", ">", 0.00), + "!", + ("location_id", "child_of", locations.ids), + ("location_dest_id", "child_of", locations.ids), + ] + + def _out_stock_moves_domain(self): + self.ensure_one() + locations = self._get_locations() + return [ + ("product_id", "=", self.product_id.id), + ("state", "not in", ["done", "cancel"]), + ("product_qty", ">", 0.00), + ("location_id", "child_of", locations.ids), + "!", + ("location_dest_id", "child_of", locations.ids), + ] + + def action_view_stock_moves(self, domain): + self.ensure_one() + action = self.env.ref("stock.stock_move_action").read()[0] + action["domain"] = domain + action["context"] = {} + return action + + def action_view_incoming_stock_moves(self): + return self.action_view_stock_moves(self._in_stock_moves_domain()) + + def action_view_outgoing_stock_moves(self): + return self.action_view_stock_moves(self._out_stock_moves_domain()) + + def _to_be_exploded(self): + self.ensure_one() + return self.supply_method in ["manufacture", "phantom"] + + def _get_locations(self): + self.ensure_one() + return self.mrp_area_id._get_locations() + + def _should_create_planned_order(self): + self.ensure_one() + return True diff --git a/mrp_multi_level/models/product_product.py b/mrp_multi_level/models/product_product.py new file mode 100644 index 000000000..4fc38e94f --- /dev/null +++ b/mrp_multi_level/models/product_product.py @@ -0,0 +1,71 @@ +# Copyright 2016 Ucamco - Wim Audenaert +# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +import ast + +from odoo import fields, models + + +class Product(models.Model): + _inherit = "product.product" + + llc = fields.Integer(string="Low Level Code", default=0, index=True) + manufacturing_order_ids = fields.One2many( + comodel_name="mrp.production", + inverse_name="product_id", + string="Manufacturing Orders", + domain=[("state", "=", "draft")], + ) + purchase_order_line_ids = fields.One2many( + comodel_name="purchase.order.line", + inverse_name="product_id", + string="Purchase Orders", + ) + mrp_area_ids = fields.One2many( + comodel_name="product.mrp.area", + inverse_name="product_id", + string="MRP Area parameters", + ) + mrp_area_count = fields.Integer( + string="MRP Area Parameter Count", + readonly=True, + compute="_compute_mrp_area_count", + ) + + def _compute_mrp_area_count(self): + for rec in self: + rec.mrp_area_count = len(rec.mrp_area_ids) + + def write(self, values): + res = super().write(values) + if values.get("active") is False: + parameters = ( + self.env["product.mrp.area"] + .sudo() + .search([("product_id", "in", self.ids)]) + ) + parameters.write({"active": False}) + return res + + def action_view_mrp_area_parameters(self): + self.ensure_one() + result = self.env["ir.actions.actions"]._for_xml_id( + "mrp_multi_level.product_mrp_area_action" + ) + ctx = ast.literal_eval(result.get("context")) + if not ctx: + ctx = {} + mrp_areas = self.env["mrp.area"].search([]) + if len(mrp_areas) == 1: + ctx.update({"default_mrp_area_id": mrp_areas[0].id}) + area_ids = self.mrp_area_ids.ids + ctx.update({"default_product_id": self.id}) + if self.mrp_area_count != 1: + result["domain"] = [("id", "in", area_ids)] + else: + res = self.env.ref("mrp_multi_level.product_mrp_area_form", False) + result["views"] = [(res and res.id or False, "form")] + result["res_id"] = area_ids[0] + result["context"] = ctx + return result diff --git a/mrp_multi_level/models/product_template.py b/mrp_multi_level/models/product_template.py new file mode 100644 index 000000000..8719c294c --- /dev/null +++ b/mrp_multi_level/models/product_template.py @@ -0,0 +1,49 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +import ast + +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + mrp_area_ids = fields.One2many( + comodel_name="product.mrp.area", + inverse_name="product_tmpl_id", + string="MRP Area parameters", + ) + mrp_area_count = fields.Integer( + string="MRP Area Parameter Count", + readonly=True, + compute="_compute_mrp_area_count", + ) + + def _compute_mrp_area_count(self): + for rec in self: + rec.mrp_area_count = len(rec.mrp_area_ids) + + def action_view_mrp_area_parameters(self): + self.ensure_one() + result = self.env["ir.actions.actions"]._for_xml_id( + "mrp_multi_level.product_mrp_area_action" + ) + ctx = ast.literal_eval(result.get("context")) + mrp_areas = self.env["mrp.area"].search([]) + if "context" not in result: + result["context"] = {} + if len(mrp_areas) == 1: + ctx.update({"default_mrp_area_id": mrp_areas[0].id}) + mrp_area_ids = self.with_context(active_test=False).mrp_area_ids.ids + if len(self.product_variant_ids) == 1: + variant = self.product_variant_ids[0] + ctx.update({"default_product_id": variant.id}) + if len(mrp_area_ids) != 1: + result["domain"] = [("id", "in", mrp_area_ids)] + else: + res = self.env.ref("mrp_multi_level.product_mrp_area_form", False) + result["views"] = [(res and res.id or False, "form")] + result["res_id"] = mrp_area_ids[0] + result["context"] = ctx + return result diff --git a/mrp_multi_level/models/stock_location.py b/mrp_multi_level/models/stock_location.py new file mode 100644 index 000000000..210fd5cf8 --- /dev/null +++ b/mrp_multi_level/models/stock_location.py @@ -0,0 +1,41 @@ +# © 2016 Ucamco - Wim Audenaert +# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) +# - Jordi Ballester Alomar +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +import ast + +from odoo import fields, models + + +class StockLocation(models.Model): + _inherit = "stock.location" + + mrp_area_count = fields.Integer( + string="MRP Area Parameter Count", + readonly=True, + compute="_compute_mrp_area_count", + ) + + def _compute_mrp_area_count(self): + for rec in self: + areas = self.env["mrp.area"].search([("location_id", "=", rec.id)]) + rec.mrp_area_count = len(areas) + + def action_view_mrp_area_location(self): + self.ensure_one() + result = self.env["ir.actions.actions"]._for_xml_id( + "mrp_multi_level.mrp_area_action" + ) + ctx = ast.literal_eval(result.get("context")) + if not ctx: + ctx = {} + mrp_areas = self.env["mrp.area"].search([("location_id", "=", self.id)]) + if self.mrp_area_count != 1: + result["domain"] = [("id", "in", mrp_areas.ids)] + else: + ctx.update({"default_mrp_area_id": mrp_areas[0].id}) + res = self.env.ref("mrp_multi_level.mrp_area_form", False) + result["views"] = [(res and res.id or False, "form")] + result["res_id"] = mrp_areas[0].id + result["context"] = ctx + return result diff --git a/mrp_multi_level/models/stock_quant.py b/mrp_multi_level/models/stock_quant.py new file mode 100644 index 000000000..b2cf844ea --- /dev/null +++ b/mrp_multi_level/models/stock_quant.py @@ -0,0 +1,16 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# - Joan Sisquella Andrés +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import api, models + + +class StockQuant(models.Model): + _inherit = "stock.quant" + + @api.model + def _get_inventory_fields_write(self): + """ + Adding field product_uom_id, inventory_quantity + """ + fields = super()._get_inventory_fields_write() + return fields + ["product_uom_id", "inventory_quantity"] diff --git a/mrp_multi_level/models/stock_rule.py b/mrp_multi_level/models/stock_rule.py new file mode 100644 index 000000000..9abb680df --- /dev/null +++ b/mrp_multi_level/models/stock_rule.py @@ -0,0 +1,35 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# - Héctor Villarreal +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _prepare_mo_vals( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + bom, + ): + res = super()._prepare_mo_vals( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + bom, + ) + if "planned_order_id" in values: + res["planned_order_id"] = values["planned_order_id"] + return res diff --git a/mrp_multi_level/pyproject.toml b/mrp_multi_level/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/mrp_multi_level/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mrp_multi_level/readme/CONFIGURE.md b/mrp_multi_level/readme/CONFIGURE.md new file mode 100644 index 000000000..7821abfc0 --- /dev/null +++ b/mrp_multi_level/readme/CONFIGURE.md @@ -0,0 +1,9 @@ +### MRP Areas + +- Go to *Manufacturing \> Configuration \> MRP Areas* and define or edit + any existing area. You can specify the working hours for every area. + +### Product MRP Area Parameters + +- Go to *Manufacturing \> Products \> Product MRP Area Parameters* + and set the MRP parameters for a given product and area. diff --git a/mrp_multi_level/readme/CONTRIBUTORS.md b/mrp_multi_level/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..56d1ef122 --- /dev/null +++ b/mrp_multi_level/readme/CONTRIBUTORS.md @@ -0,0 +1,7 @@ +- Wim Audenaert \<\> +- Jordi Ballester \<\> +- Lois Rilo \<\> +- Héctor Villarreal \<\> +- Christopher Ormaza \<\> +- Joan Sisquella \<\> +- Alexandre Fayolle \<\> diff --git a/mrp_multi_level/readme/DESCRIPTION.md b/mrp_multi_level/readme/DESCRIPTION.md new file mode 100644 index 000000000..7daa1c71d --- /dev/null +++ b/mrp_multi_level/readme/DESCRIPTION.md @@ -0,0 +1,19 @@ +This module allows you to calculate, based in known inventory, demand, +and supply, and based on parameters set at product variant level, the +new procurements for each product. + +To do this, the calculation starts at top level of the bill of material +and explodes this down to the lowest level. + +## Key Features + +- MRP parameters set by product variant MRP area pairs. +- Cron job to calculate the MRP demand. +- Manually calculate the MRP demand. +- Confirm the calculated MRP demand and create PO's, or MO's. +- Able to see the products for which action is needed throught Planned + Orders. +- Integration with [Stock Demand + Estimates](https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_demand_estimate) + system. Note: You need to install [mrp_multi_level_estimate + module](https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level_estimate). diff --git a/mrp_multi_level/readme/HISTORY.md b/mrp_multi_level/readme/HISTORY.md new file mode 100644 index 000000000..e132a3ab2 --- /dev/null +++ b/mrp_multi_level/readme/HISTORY.md @@ -0,0 +1,101 @@ +## 13.0.1.5.0 (2020-04-09) + +**Features** + +- Show *Run MRP Multi Level* menu only to a specific new security group + *Run MRP Manually*. + ([\#492](https://github.com/OCA/manufacture/issues/492)) + +## 13.0.1.4.0 (2020-03-26) + +> - Add menu entry for planned orders +> - Add button to navigate from planned orders to linked manufacturing +> orders +> - Add action to convert planned orders to fixed +> - When changing the due date in a planned order the release date is +> recomputed + +## 13.0.1.3.0 (2020-03-02) + +- \[IMP\] Minor changes" + ([\#470](https://github.com/OCA/manufacture/pull/470)). + - Planned Order release and due date become required. + - Add button to Product MRP Area to update MOQ from Supplier Info. + - Link Manufacturing Orders with Planned Orders. + - Allow Mrp Inventory Procure Wizard to be used from other models. + - Make MRP Inventory creation more extensible. + - Main Supplier computation (v13 requires explicit False definitions) + +## 13.0.1.2.0 (2020-02-20) + +- \[IMP\] Minor changes + ([\#468](https://github.com/OCA/manufacture/pull/468)). + - Planned Orders become fixed on manual creation by default + - Released Quantity becomes readonly + - Add product reference if Planned Order name is not defined on bom + explosion + +## 13.0.1.1.0 (2020-02-21) + +- \[FIX\] Minor changes + ([\#469](https://github.com/OCA/manufacture/pull/469)). + - Fix Main supplier computation in multi company + - Drop Triplicated field in search view +- \[IMP\] Minor changes + ([\#463](https://github.com/OCA/manufacture/pull/463)). + - Show supply method on MRP Inventory + - Allow no-MRP users to look into Products + +## 13.0.1.0.0 (2019-12-18) + +- \[MIG\] Migration to v13. + +## 12.0.1.0.0 (2019-08-05) + +- \[MIG\] Migration to v12: + - Estimates as a forecasting mechanism is moved to a new module + (mrp_multi_level_estimate). + +## 11.0.3.0.0 (2019-05-22) + +- \[REW/IMP\] Rework to include Planned Orders. + ([\#365](https://github.com/OCA/manufacture/pull/365)). +- \[IMP\] Able to procure from a different location than the area's + location. + +## 11.0.2.2.0 (2019-05-02) + +- \[IMP\] Able to run MRP only for selected areas. + ([\#360](https://github.com/OCA/manufacture/pull/360)). + +## 11.0.2.1.0 (2019-04-02) + +- \[IMP\] Implement *Nbr. Days* functionality to be able to group demand + when generating supply proposals. + ([\#345](https://github.com/OCA/manufacture/pull/345)). + +## 11.0.2.0.0 (2018-11-20) + +- \[REW\] Refactor MRP Area. + ([\#322](https://github.com/OCA/manufacture/pull/322)): + - MRP product concept dropped in favor of *Product MRP Area + Parameters*. This allow to set different MRP parameters for the same + product in different areas. + - Menu items reordering. + +## 11.0.1.1.0 (2018-08-30) + +- \[FIX\] Consider *Qty Multiple* on product to propose the quantity to + procure. ([\#297](https://github.com/OCA/manufacture/pull/297)) + +## 11.0.1.0.1 (2018-08-03) + +- \[FIX\] User and system locales doesn't break MRP calculation. + ([\#290](https://github.com/OCA/manufacture/pull/290)) +- \[FIX\] Working Hours are now defined only at Warehouse level and + displayed as a related on MRP Areas. + ([\#290](https://github.com/OCA/manufacture/pull/290)) + +## 11.0.1.0.0 (2018-07-09) + +- Start of the history. diff --git a/mrp_multi_level/readme/USAGE.md b/mrp_multi_level/readme/USAGE.md new file mode 100644 index 000000000..9b8fe0b7f --- /dev/null +++ b/mrp_multi_level/readme/USAGE.md @@ -0,0 +1,12 @@ +To manually run the MRP scheduler: + +1. Go to *Manufacturing \> Planning \> Run MRP Multi Level*. +2. On the wizard click *Run MRP*. + +To launch replenishment orders (moves, purchases, production orders...): + +1. Go to *Manufacturing \> Planning \> MRP Inventory*. +2. Filter with *To procure*. +3. Select multiple records and click on *Action \> Procure* or click + the right hand side gears in any record. +4. On the wizard, check everything is ok and click *Execute*. diff --git a/mrp_multi_level/security/ir.model.access.csv b/mrp_multi_level/security/ir.model.access.csv new file mode 100644 index 000000000..16f465c66 --- /dev/null +++ b/mrp_multi_level/security/ir.model.access.csv @@ -0,0 +1,16 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_mrp_inventory_user,mrp.inventory user,model_mrp_inventory,mrp.group_mrp_user,1,0,0,0 +access_mrp_inventory_manager,mrp.inventory manager,model_mrp_inventory,mrp.group_mrp_manager,1,1,1,1 +access_mrp_move_user,mrp.move user,model_mrp_move,mrp.group_mrp_user,1,0,0,0 +access_mrp_move_manager,mrp.move manager,model_mrp_move,mrp.group_mrp_manager,1,1,1,1 +access_mrp_area_user,mrp.area user,model_mrp_area,mrp.group_mrp_user,1,0,0,0 +access_mrp_area_manager,mrp.area manager,model_mrp_area,mrp.group_mrp_manager,1,1,1,1 +access_product_mrp_area_user,product.mrp.area user,model_product_mrp_area,mrp.group_mrp_user,1,1,1,0 +access_product_mrp_area_manager,product.mrp.area manager,model_product_mrp_area,mrp.group_mrp_manager,1,1,1,1 +access_product_mrp_area_read,product.mrp.area read,model_product_mrp_area,base.group_user,1,0,0,0 +access_mrp_planned_order_user,mrp.planned.order user,model_mrp_planned_order,mrp.group_mrp_user,1,0,0,0 +access_mrp_planned_order_manager,mrp.planned.order manager,model_mrp_planned_order,mrp.group_mrp_manager,1,1,1,1 +access_mrp_multi_level_user,mrp.multi.level user,model_mrp_multi_level,mrp.group_mrp_user,1,0,0,0 +access_mrp_multi_level_manager,mrp.multi.level manager,model_mrp_multi_level,mrp.group_mrp_manager,1,1,1,1 +access_mrp_inventory_procure_user,mrp.inventory.procure user,model_mrp_inventory_procure,mrp.group_mrp_user,1,1,1,1 +access_mrp_inventory_procure_item_user,mrp.inventory.procure.item user,model_mrp_inventory_procure_item,mrp.group_mrp_user,1,1,1,1 diff --git a/mrp_multi_level/security/mrp_multi_level_security.xml b/mrp_multi_level/security/mrp_multi_level_security.xml new file mode 100644 index 000000000..8fa95f687 --- /dev/null +++ b/mrp_multi_level/security/mrp_multi_level_security.xml @@ -0,0 +1,57 @@ + + + + Change procure quantity in MRP + + + + + Run MRP Manually + + + + + + MRP Area multi-company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + Product MRP Area multi-company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + MRP Inventory multi-company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + MRP Move multi-company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + MRP Planned Order multi-company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + diff --git a/mrp_multi_level/static/description/icon.png b/mrp_multi_level/static/description/icon.png new file mode 100644 index 000000000..b1cef6c4c Binary files /dev/null and b/mrp_multi_level/static/description/icon.png differ diff --git a/mrp_multi_level/static/description/index.html b/mrp_multi_level/static/description/index.html new file mode 100644 index 000000000..8a044585c --- /dev/null +++ b/mrp_multi_level/static/description/index.html @@ -0,0 +1,631 @@ + + + + + +MRP Multi Level + + + +
+

MRP Multi Level

+ + +

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

+

This module allows you to calculate, based in known inventory, demand, +and supply, and based on parameters set at product variant level, the +new procurements for each product.

+

To do this, the calculation starts at top level of the bill of material +and explodes this down to the lowest level.

+
+

Key Features

+
    +
  • MRP parameters set by product variant MRP area pairs.
  • +
  • Cron job to calculate the MRP demand.
  • +
  • Manually calculate the MRP demand.
  • +
  • Confirm the calculated MRP demand and create PO’s, or MO’s.
  • +
  • Able to see the products for which action is needed throught Planned +Orders.
  • +
  • Integration with Stock Demand +Estimates +system. Note: You need to install mrp_multi_level_estimate +module.
  • +
+

Table of contents

+ +
+

Configuration

+
+

MRP Areas

+
    +
  • Go to Manufacturing > Configuration > MRP Areas and define or edit +any existing area. You can specify the working hours for every area.
  • +
+
+
+

Product MRP Area Parameters

+
    +
  • Go to Manufacturing > Products > Product MRP Area Parameters and +set the MRP parameters for a given product and area.
  • +
+
+
+
+

Usage

+

To manually run the MRP scheduler:

+
    +
  1. Go to Manufacturing > Planning > Run MRP Multi Level.
  2. +
  3. On the wizard click Run MRP.
  4. +
+

To launch replenishment orders (moves, purchases, production orders…):

+
    +
  1. Go to Manufacturing > Planning > MRP Inventory.
  2. +
  3. Filter with To procure.
  4. +
  5. Select multiple records and click on Action > Procure or click the +right hand side gears in any record.
  6. +
  7. On the wizard, check everything is ok and click Execute.
  8. +
+
+ +
+
+

13.0.1.5.0 (2020-04-09)

+

Features

+
    +
  • Show Run MRP Multi Level menu only to a specific new security group +Run MRP Manually. +(#492)
  • +
+
+
+

13.0.1.4.0 (2020-03-26)

+
+
    +
  • Add menu entry for planned orders
  • +
  • Add button to navigate from planned orders to linked manufacturing +orders
  • +
  • Add action to convert planned orders to fixed
  • +
  • When changing the due date in a planned order the release date is +recomputed
  • +
+
+
+
+

13.0.1.3.0 (2020-03-02)

+
    +
  • [IMP] Minor changes” +(#470).
      +
    • Planned Order release and due date become required.
    • +
    • Add button to Product MRP Area to update MOQ from Supplier Info.
    • +
    • Link Manufacturing Orders with Planned Orders.
    • +
    • Allow Mrp Inventory Procure Wizard to be used from other models.
    • +
    • Make MRP Inventory creation more extensible.
    • +
    • Main Supplier computation (v13 requires explicit False +definitions)
    • +
    +
  • +
+
+
+

13.0.1.2.0 (2020-02-20)

+
    +
  • [IMP] Minor changes +(#468).
      +
    • Planned Orders become fixed on manual creation by default
    • +
    • Released Quantity becomes readonly
    • +
    • Add product reference if Planned Order name is not defined on bom +explosion
    • +
    +
  • +
+
+
+

13.0.1.1.0 (2020-02-21)

+
    +
  • [FIX] Minor changes +(#469).
      +
    • Fix Main supplier computation in multi company
    • +
    • Drop Triplicated field in search view
    • +
    +
  • +
  • [IMP] Minor changes +(#463).
      +
    • Show supply method on MRP Inventory
    • +
    • Allow no-MRP users to look into Products
    • +
    +
  • +
+
+
+

13.0.1.0.0 (2019-12-18)

+
    +
  • [MIG] Migration to v13.
  • +
+
+
+

12.0.1.0.0 (2019-08-05)

+
    +
  • [MIG] Migration to v12:
      +
    • Estimates as a forecasting mechanism is moved to a new module +(mrp_multi_level_estimate).
    • +
    +
  • +
+
+
+

11.0.3.0.0 (2019-05-22)

+
    +
  • [REW/IMP] Rework to include Planned Orders. +(#365).
  • +
  • [IMP] Able to procure from a different location than the area’s +location.
  • +
+
+
+

11.0.2.2.0 (2019-05-02)

+
    +
  • [IMP] Able to run MRP only for selected areas. +(#360).
  • +
+
+
+

11.0.2.1.0 (2019-04-02)

+
    +
  • [IMP] Implement Nbr. Days functionality to be able to group demand +when generating supply proposals. +(#345).
  • +
+
+
+

11.0.2.0.0 (2018-11-20)

+
    +
  • [REW] Refactor MRP Area. +(#322):
      +
    • MRP product concept dropped in favor of Product MRP Area +Parameters. This allow to set different MRP parameters for the +same product in different areas.
    • +
    • Menu items reordering.
    • +
    +
  • +
+
+
+

11.0.1.1.0 (2018-08-30)

+
    +
  • [FIX] Consider Qty Multiple on product to propose the quantity to +procure. (#297)
  • +
+
+
+

11.0.1.0.1 (2018-08-03)

+
    +
  • [FIX] User and system locales doesn’t break MRP calculation. +(#290)
  • +
  • [FIX] Working Hours are now defined only at Warehouse level and +displayed as a related on MRP Areas. +(#290)
  • +
+
+
+

11.0.1.0.0 (2018-07-09)

+
    +
  • Start of the history.
  • +
+
+

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

+
    +
  • Ucamco
  • +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainers:

+

JordiBForgeFlow LoisRForgeFlow

+

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

+

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

+
+
+ + diff --git a/mrp_multi_level/static/src/img/icon.png b/mrp_multi_level/static/src/img/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/mrp_multi_level/static/src/img/icon.png differ diff --git a/mrp_multi_level/tests/__init__.py b/mrp_multi_level/tests/__init__.py new file mode 100644 index 000000000..c27acfad0 --- /dev/null +++ b/mrp_multi_level/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mrp_multi_level diff --git a/mrp_multi_level/tests/common.py b/mrp_multi_level/tests/common.py new file mode 100644 index 000000000..cbac87082 --- /dev/null +++ b/mrp_multi_level/tests/common.py @@ -0,0 +1,656 @@ +# Copyright 2018-19 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.tests import Form +from odoo.tests.common import TransactionCase + + +class TestMrpMultiLevelCommon(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.mo_obj = cls.env["mrp.production"] + cls.po_obj = cls.env["purchase.order"] + cls.product_obj = cls.env["product.product"] + cls.loc_obj = cls.env["stock.location"] + cls.quant_obj = cls.env["stock.quant"] + cls.mrp_area_obj = cls.env["mrp.area"] + cls.product_mrp_area_obj = cls.env["product.mrp.area"] + cls.partner_obj = cls.env["res.partner"] + cls.res_users = cls.env["res.users"] + cls.stock_picking_obj = cls.env["stock.picking"] + cls.mrp_multi_level_wiz = cls.env["mrp.multi.level"] + cls.mrp_inventory_procure_wiz = cls.env["mrp.inventory.procure"] + cls.mrp_inventory_obj = cls.env["mrp.inventory"] + cls.mrp_move_obj = cls.env["mrp.move"] + cls.planned_order_obj = cls.env["mrp.planned.order"] + cls.lot_obj = cls.env["stock.lot"] + cls.mrp_bom_obj = cls.env["mrp.bom"] + + cls.fp_1 = cls.env.ref("mrp_multi_level.product_product_fp_1") + cls.fp_2 = cls.env.ref("mrp_multi_level.product_product_fp_2") + cls.fp_3 = cls.env.ref("mrp_multi_level.product_product_fp_3") + cls.fp_4 = cls.env.ref("mrp_multi_level.product_product_fp_4") + cls.sf_1 = cls.env.ref("mrp_multi_level.product_product_sf_1") + cls.sf_2 = cls.env.ref("mrp_multi_level.product_product_sf_2") + cls.sf_3 = cls.env.ref("mrp_multi_level.product_product_sf_3") + cls.pp_1 = cls.env.ref("mrp_multi_level.product_product_pp_1") + cls.pp_2 = cls.env.ref("mrp_multi_level.product_product_pp_2") + cls.pp_3 = cls.env.ref("mrp_multi_level.product_product_pp_3") + cls.pp_4 = cls.env.ref("mrp_multi_level.product_product_pp_4") + cls.product_4b = cls.env.ref("product.product_product_4b") + cls.product_4c = cls.env.ref("product.product_product_4c") + cls.av_11 = cls.env.ref("mrp_multi_level.product_product_av_11") + cls.av_12 = cls.env.ref("mrp_multi_level.product_product_av_12") + cls.av_21 = cls.env.ref("mrp_multi_level.product_product_av_21") + cls.av_22 = cls.env.ref("mrp_multi_level.product_product_av_22") + cls.company = cls.env.ref("base.main_company") + cls.mrp_area = cls.env.ref("mrp_multi_level.mrp_area_stock_wh0") + cls.vendor = cls.env.ref("mrp_multi_level.res_partner_lazer_tech") + cls.wh = cls.env.ref("stock.warehouse0") + cls.stock_location = cls.wh.lot_stock_id + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + cls.calendar = cls.env.ref("resource.resource_calendar_std") + # Add calendar to WH: + cls.wh.calendar_id = cls.calendar + + # Partner: + vendor1 = cls.partner_obj.create({"name": "Vendor 1"}) + + # Create user: + group_mrp_manager = cls.env.ref("mrp.group_mrp_manager") + group_user = cls.env.ref("base.group_user") + group_stock_manager = cls.env.ref("stock.group_stock_manager") + cls.mrp_manager = cls._create_user( + "Test User", + [group_mrp_manager, group_user, group_stock_manager], + cls.company, + ) + + # Create secondary location and MRP Area: + cls.sec_loc = cls.loc_obj.create( + { + "name": "Test location", + "usage": "internal", + "location_id": cls.wh.view_location_id.id, + } + ) + cls.secondary_area = cls.mrp_area_obj.create( + {"name": "Test", "warehouse_id": cls.wh.id, "location_id": cls.sec_loc.id} + ) + # Create an area for design special cases and test them, different + # cases will be expected to not share products, this way each case + # can be isolated. + cls.cases_loc = cls.loc_obj.create( + { + "name": "Special Cases location", + "usage": "internal", + "location_id": cls.wh.view_location_id.id, + } + ) + cls.cases_area = cls.mrp_area_obj.create( + { + "name": "Special Cases Tests", + "warehouse_id": cls.wh.id, + "location_id": cls.cases_loc.id, + } + ) + + # Create products: + route_buy = cls.env.ref("purchase_stock.route_warehouse0_buy").id + cls.prod_test = cls.product_obj.create( + { + "name": "Test Top Seller", + "is_storable": True, + "list_price": 150.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 20.0})], + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.prod_test.id, "mrp_area_id": cls.mrp_area.id} + ) + # Parameters in secondary area with nbr_days set. + cls.product_mrp_area_obj.create( + { + "product_id": cls.prod_test.id, + "mrp_area_id": cls.secondary_area.id, + "mrp_nbr_days": 7, + } + ) + cls.prod_min = cls.product_obj.create( + { + "name": "Product with minimum order qty", + "is_storable": True, + "list_price": 50.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 10.0})], + } + ) + cls.product_mrp_area_obj.create( + { + "product_id": cls.prod_min.id, + "mrp_area_id": cls.mrp_area.id, + "mrp_minimum_order_qty": 50.0, + "mrp_maximum_order_qty": 0.0, + "mrp_qty_multiple": 1.0, + } + ) + + cls.prod_max = cls.product_obj.create( + { + "name": "Product with maximum order qty", + "is_storable": True, + "list_price": 50.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 10.0})], + } + ) + cls.product_mrp_area_obj.create( + { + "product_id": cls.prod_max.id, + "mrp_area_id": cls.mrp_area.id, + "mrp_minimum_order_qty": 50.0, + "mrp_maximum_order_qty": 100.0, + "mrp_qty_multiple": 1.0, + } + ) + cls.prod_multiple = cls.product_obj.create( + { + "name": "Product with qty multiple", + "is_storable": True, + "list_price": 50.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 10.0})], + } + ) + cls.product_mrp_area_obj.create( + { + "product_id": cls.prod_multiple.id, + "mrp_area_id": cls.mrp_area.id, + "mrp_minimum_order_qty": 50.0, + "mrp_maximum_order_qty": 500.0, + "mrp_qty_multiple": 25.0, + } + ) + # Create more products to test special corner case scenarios: + cls.product_scenario_1 = cls.product_obj.create( + { + "name": "Product Special Scenario 1", + "is_storable": True, + "list_price": 100.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 20.0})], + } + ) + cls.product_mrp_area_obj.create( + { + "product_id": cls.product_scenario_1.id, + "mrp_area_id": cls.cases_area.id, + "mrp_nbr_days": 7, + "mrp_qty_multiple": 5.0, + } + ) + # Another product: + cls.product_tz = cls.product_obj.create( + { + "name": "Product Timezone", + "is_storable": True, + "list_price": 100.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 20.0})], + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.product_tz.id, "mrp_area_id": cls.cases_area.id} + ) + # Product to test special case with Purchase Uom: + cls.prod_uom_test = cls.product_obj.create( + { + "name": "Product Uom Test", + "is_storable": True, + "uom_id": cls.env.ref("uom.product_uom_unit").id, + "uom_po_id": cls.env.ref("uom.product_uom_dozen").id, + "list_price": 150.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 20.0})], + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.prod_uom_test.id, "mrp_area_id": cls.mrp_area.id} + ) + # Product to test lots + cls.product_lots = cls.product_obj.create( + { + "name": "Product Tracked by Lots", + "is_storable": True, + "tracking": "lot", + "uom_id": cls.env.ref("uom.product_uom_unit").id, + "list_price": 100.0, + "route_ids": [(6, 0, [route_buy])], + "seller_ids": [(0, 0, {"partner_id": vendor1.id, "price": 25.0})], + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.product_lots.id, "mrp_area_id": cls.mrp_area.id} + ) + cls.lot_1 = cls.lot_obj.create( + { + "product_id": cls.product_lots.id, + "name": "Lot 1", + "company_id": cls.company.id, + } + ) + cls.lot_2 = cls.lot_obj.create( + { + "product_id": cls.product_lots.id, + "name": "Lot 2", + "company_id": cls.company.id, + } + ) + cls.quant_obj.sudo().create( + { + "product_id": cls.product_lots.id, + "lot_id": cls.lot_1.id, + "quantity": 100.0, + "location_id": cls.stock_location.id, + } + ) + cls.quant_obj.sudo().create( + { + "product_id": cls.product_lots.id, + "lot_id": cls.lot_2.id, + "quantity": 110.0, + "location_id": cls.stock_location.id, + } + ) + + # Product MRP Parameter to test supply method computation + cls.env.ref("stock.route_warehouse0_mto").active = True + cls.env["stock.rule"].create( + { + "name": "WH2: Main Area → Secondary Area (MTO)", + "action": "pull", + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "location_src_id": cls.env.ref("stock.stock_location_stock").id, + "location_dest_id": cls.sec_loc.id, + "route_id": cls.env.ref("stock.route_warehouse0_mto").id, + "procure_method": "mts_else_mto", + } + ) + cls.product_mrp_area_obj.create( + {"product_id": cls.fp_4.id, "mrp_area_id": cls.secondary_area.id} + ) + + # Create pickings for Scenario 1: + dt_base = cls.calendar.plan_days(3 + 1, datetime.today()) + cls._create_picking_in( + cls.product_scenario_1, 87, dt_base, location=cls.cases_loc + ) + dt_bit_later = dt_base + timedelta(hours=1) + cls._create_picking_out( + cls.product_scenario_1, 124, dt_bit_later, location=cls.cases_loc + ) + dt_base_2 = cls.calendar.plan_days(3 + 1, datetime.today()) + cls._create_picking_out( + cls.product_scenario_1, 90, dt_base_2, location=cls.cases_loc + ) + + dt_next_group = cls.calendar.plan_days(10 + 1, datetime.today()) + cls._create_picking_out( + cls.product_scenario_1, 18, dt_next_group, location=cls.cases_loc + ) + + # product_4b will use the template bom (sequence 5) + # (11, 22) = ("steel", "black") + # create variant bom for product_4c (sequence 1) + # (12, 21) = ("aluminum", "white") + cls.mrp_bom_obj.create( + { + "product_tmpl_id": cls.product_4c.product_tmpl_id.id, + "product_id": cls.product_4c.id, + "type": "normal", + "sequence": 1, + "bom_line_ids": [ + ( + 0, + 0, + { + "product_id": cls.av_12.id, + "product_qty": 1.0, + }, + ), + ( + 0, + 0, + { + "product_id": cls.av_21.id, + "product_qty": 1.0, + }, + ), + ], + } + ) + + # Create test picking for FP-1, FP-2, Desk(steel, black), Desk(aluminum, white) + res = cls.calendar.plan_days(7 + 1, datetime.today().replace(hour=0)) + date_move = res.date() + cls.picking_1 = cls.stock_picking_obj.create( + { + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + "scheduled_date": date_move, + "move_ids": [ + ( + 0, + 0, + { + "name": "Test move fp-1", + "product_id": cls.fp_1.id, + "date": date_move, + "product_uom": cls.fp_1.uom_id.id, + "product_uom_qty": 100, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move fp-2", + "product_id": cls.fp_2.id, + "date": date_move, + "product_uom": cls.fp_2.uom_id.id, + "product_uom_qty": 15, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move fp-3", + "product_id": cls.fp_3.id, + "date": date_move, + "product_uom": cls.fp_3.uom_id.id, + "product_uom_qty": 5, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move product-4b", + "product_id": cls.product_4b.id, + "date": date_move, + "product_uom": cls.product_4b.uom_id.id, + "product_uom_qty": 150, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move product-4c", + "product_id": cls.product_4c.id, + "date": date_move, + "product_uom": cls.product_4c.uom_id.id, + "product_uom_qty": 56, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ], + } + ) + cls.picking_1.action_confirm() + + # Create test picking for procure qty adjustment tests: + cls.picking_2 = cls.stock_picking_obj.create( + { + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + "scheduled_date": date_move, + "move_ids": [ + ( + 0, + 0, + { + "name": "Test move prod_min", + "product_id": cls.prod_min.id, + "date": date_move, + "product_uom": cls.prod_min.uom_id.id, + "product_uom_qty": 16, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move prod_max", + "product_id": cls.prod_max.id, + "date": date_move, + "product_uom": cls.prod_max.uom_id.id, + "product_uom_qty": 140, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ( + 0, + 0, + { + "name": "Test move prod_multiple", + "product_id": cls.prod_multiple.id, + "date": date_move, + "product_uom": cls.prod_multiple.uom_id.id, + "product_uom_qty": 112, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, + }, + ), + ], + } + ) + cls.picking_2.action_confirm() + + # Create Test PO: + date_po = cls.calendar.plan_days(1 + 1, datetime.today().replace(hour=0)).date() + cls.po = cls.po_obj.create( + { + "name": "Test PO-001", + "partner_id": cls.vendor.id, + "order_line": [ + ( + 0, + 0, + { + "name": "Test PP-2 line", + "product_id": cls.pp_2.id, + "date_planned": date_po, + "product_qty": 5.0, + "product_uom": cls.pp_2.uom_id.id, + "price_unit": 25.0, + }, + ) + ], + } + ) + # Create Test PO for special case Puchase uom: + # Remember that prod_uom_test had a UoM of units but it is purchased in dozens. + # For this reason buying 1 quantity of it, means to have 12 units in stock. + date_po = cls.calendar.plan_days(1 + 1, datetime.today().replace(hour=0)).date() + cls.po_uom = cls.po_obj.create( + { + "name": "Test PO-002", + "partner_id": cls.vendor.id, + "order_line": [ + ( + 0, + 0, + { + "name": "Product Uom Test line", + "product_id": cls.prod_uom_test.id, + "date_planned": date_po, + "product_qty": 1.0, + "product_uom": cls.prod_uom_test.uom_po_id.id, + "price_unit": 25.0, + }, + ) + ], + } + ) + + # Create test MO: + date_mo = cls.calendar.plan_days(9 + 1, datetime.today().replace(hour=0)).date() + bom_fp_2 = cls.env.ref("mrp_multi_level.mrp_bom_fp_2") + cls.mo = cls._create_mo(cls.fp_2, bom_fp_2, date_mo, qty=12.0) + + # Dates: + today = datetime.today().replace(hour=0) + cls.date_3 = cls.calendar.plan_days(3 + 1, today).date() + cls.date_5 = cls.calendar.plan_days(5 + 1, today).date() + cls.date_6 = cls.calendar.plan_days(6 + 1, today).date() + cls.date_7 = cls.calendar.plan_days(7 + 1, today).date() + cls.date_8 = cls.calendar.plan_days(8 + 1, today).date() + cls.date_9 = cls.calendar.plan_days(9 + 1, today).date() + cls.date_10 = cls.calendar.plan_days(10 + 1, today).date() + cls.date_20 = cls.calendar.plan_days(20 + 1, today).date() + cls.date_22 = cls.calendar.plan_days(22 + 1, today).date() + + # Create movements in secondary area: + cls.create_demand_sec_loc(cls.date_8, 80.0) + cls.create_demand_sec_loc(cls.date_9, 50.0) + cls.create_demand_sec_loc(cls.date_10, 70.0) + cls.create_demand_sec_loc(cls.date_20, 46.0) + cls.create_demand_sec_loc(cls.date_22, 33.0) + + # Create pickings: + cls._create_picking_out(cls.product_lots, 25, today) + + cls.mrp_multi_level_wiz.create({}).run_mrp_multi_level() + + @classmethod + def create_demand_sec_loc(cls, date_move, qty): + return cls.stock_picking_obj.create( + { + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": cls.sec_loc.id, + "location_dest_id": cls.customer_location.id, + "scheduled_date": date_move, + "move_ids": [ + ( + 0, + 0, + { + "name": "Test move", + "product_id": cls.prod_test.id, + "date": date_move, + "product_uom": cls.prod_test.uom_id.id, + "product_uom_qty": qty, + "location_id": cls.sec_loc.id, + "location_dest_id": cls.customer_location.id, + }, + ) + ], + } + ) + + @classmethod + def _create_user(cls, login, groups, company): + user = cls.res_users.create( + { + "name": login, + "login": login, + "password": "demo", + "email": "example@yourcompany.com", + "company_id": company.id, + "groups_id": [(6, 0, [group.id for group in groups])], + } + ) + return user + + @classmethod + def _create_picking_in(cls, product, qty, date_move, location=None): + if not location: + location = cls.stock_location + picking = cls.stock_picking_obj.create( + { + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "location_id": cls.supplier_location.id, + "location_dest_id": location.id, + "scheduled_date": date_move, + "move_ids": [ + ( + 0, + 0, + { + "name": "Test Move", + "product_id": product.id, + "date": date_move, + "product_uom": product.uom_id.id, + "product_uom_qty": qty, + "location_id": cls.supplier_location.id, + "location_dest_id": location.id, + }, + ) + ], + } + ) + picking.action_confirm() + return picking + + @classmethod + def _create_picking_out(cls, product, qty, date_move, location=None): + if not location: + location = cls.stock_location + picking = cls.stock_picking_obj.create( + { + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": location.id, + "location_dest_id": cls.customer_location.id, + "scheduled_date": date_move, + "move_ids": [ + ( + 0, + 0, + { + "name": "Test Move", + "product_id": product.id, + "date": date_move, + "product_uom": product.uom_id.id, + "product_uom_qty": qty, + "location_id": location.id, + "location_dest_id": cls.customer_location.id, + }, + ) + ], + } + ) + picking.action_confirm() + return picking + + @classmethod + def _create_mo(cls, product, bom, date, qty=10.0): + mo_form = Form(cls.mo_obj) + mo_form.product_id = product + mo_form.bom_id = bom + mo_form.product_qty = qty + mo_form.date_start = date + mo = mo_form.save() + # Confirm the MO to generate stock moves: + mo.action_confirm() + return mo diff --git a/mrp_multi_level/tests/test_mrp_multi_level.py b/mrp_multi_level/tests/test_mrp_multi_level.py new file mode 100644 index 000000000..4dd4d8e51 --- /dev/null +++ b/mrp_multi_level/tests/test_mrp_multi_level.py @@ -0,0 +1,930 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import date, datetime, timedelta + +from odoo import fields + +from .common import TestMrpMultiLevelCommon + + +class TestMrpMultiLevel(TestMrpMultiLevelCommon): + def test_01_mrp_levels(self): + """Tests computation of MRP levels.""" + self.assertEqual(self.fp_1.llc, 0) + self.assertEqual(self.fp_2.llc, 0) + self.assertEqual(self.sf_1.llc, 1) + self.assertEqual(self.sf_2.llc, 1) + self.assertEqual(self.pp_1.llc, 2) + self.assertEqual(self.pp_2.llc, 2) + + def test_02_product_mrp_area(self): + """Tests that mrp products are generated correctly.""" + product_mrp_area = self.product_mrp_area_obj.search( + [("product_id", "=", self.pp_1.id)] + ) + self.assertEqual(product_mrp_area.supply_method, "buy") + self.assertEqual(product_mrp_area.main_supplier_id, self.vendor) + self.assertEqual(product_mrp_area.qty_available, 10.0) + product_mrp_area = self.product_mrp_area_obj.search( + [("product_id", "=", self.sf_1.id)] + ) + self.assertEqual(product_mrp_area.supply_method, "manufacture") + self.assertFalse(product_mrp_area.main_supplier_id) + self.assertFalse(product_mrp_area.main_supplierinfo_id) + # Archiving the product should archive parameters: + self.assertTrue(product_mrp_area.active) + self.sf_1.active = False + self.assertFalse(product_mrp_area.active) + + def test_03_mrp_moves(self): + """Tests for mrp moves generated.""" + moves = self.mrp_move_obj.search([("product_id", "=", self.pp_1.id)]) + self.assertEqual(len(moves), 3) + self.assertNotIn("s", moves.mapped("mrp_type")) + for move in moves: + self.assertTrue(move.planned_order_up_ids) + if move.planned_order_up_ids.product_mrp_area_id.product_id == self.fp_1: + # Demand coming from FP-1 + self.assertEqual(move.planned_order_up_ids.mrp_action, "manufacture") + self.assertEqual(move.mrp_qty, -200.0) + elif move.planned_order_up_ids.product_mrp_area_id.product_id == self.sf_1: + # Demand coming from FP-2 -> SF-1 + self.assertEqual(move.planned_order_up_ids.mrp_action, "manufacture") + if move.mrp_date == self.date_5: + self.assertEqual(move.mrp_qty, -90.0) + elif move.mrp_date == self.date_8: + self.assertEqual(move.mrp_qty, -72.0) + # Check actions: + planned_orders = self.planned_order_obj.search( + [("product_id", "=", self.pp_1.id)] + ) + self.assertEqual(len(planned_orders), 3) + for plan in planned_orders: + self.assertEqual(plan.mrp_action, "buy") + # Check PP-2 PO being accounted: + po_move = self.mrp_move_obj.search( + [("product_id", "=", self.pp_2.id), ("mrp_type", "=", "s")] + ) + self.assertEqual(len(po_move), 1) + self.assertEqual(po_move.purchase_order_id, self.po) + self.assertEqual(po_move.purchase_line_id, self.po.order_line) + + def test_04_mrp_multi_level(self): + """Tests MRP inventories created.""" + # FP-1 + fp_1_inventory_lines = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.fp_1.id)] + ) + self.assertEqual(len(fp_1_inventory_lines), 1) + self.assertEqual(fp_1_inventory_lines.date, self.date_7) + self.assertEqual(fp_1_inventory_lines.demand_qty, 100.0) + self.assertEqual(fp_1_inventory_lines.to_procure, 100.0) + # FP-2 + fp_2_line_1 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.fp_2.id), + ("date", "=", self.date_7), + ] + ) + self.assertEqual(len(fp_2_line_1), 1) + self.assertEqual(fp_2_line_1.demand_qty, 15.0) + self.assertEqual(fp_2_line_1.to_procure, 15.0) + fp_2_line_2 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.fp_2.id), + ("date", "=", self.date_10), + ] + ) + self.assertEqual(len(fp_2_line_2), 1) + self.assertEqual(fp_2_line_2.demand_qty, 0.0) + self.assertEqual(fp_2_line_2.to_procure, 0.0) + self.assertEqual(fp_2_line_2.supply_qty, 12.0) + + # SF-1 + sf_1_line_1 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.sf_1.id), + ("date", "=", self.date_6), + ] + ) + self.assertEqual(len(sf_1_line_1), 1) + self.assertEqual(sf_1_line_1.demand_qty, 30.0) + self.assertEqual(sf_1_line_1.to_procure, 30.0) + sf_1_line_2 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.sf_1.id), + ("date", "=", self.date_9), + ] + ) + self.assertEqual(len(sf_1_line_2), 1) + self.assertEqual(sf_1_line_2.demand_qty, 24.0) + self.assertEqual(sf_1_line_2.to_procure, 24.0) + # SF-2 + sf_2_line_1 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.sf_2.id), + ("date", "=", self.date_6), + ] + ) + self.assertEqual(len(sf_2_line_1), 1) + self.assertEqual(sf_2_line_1.demand_qty, 45.0) + self.assertEqual(sf_2_line_1.to_procure, 30.0) + sf_2_line_2 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.sf_2.id), + ("date", "=", self.date_9), + ] + ) + self.assertEqual(len(sf_2_line_2), 1) + self.assertEqual(sf_2_line_2.demand_qty, 36.0) + self.assertEqual(sf_2_line_2.to_procure, 36.0) + + # PP-1 + pp_1_line_1 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_1.id), + ("date", "=", self.date_5), + ] + ) + self.assertEqual(len(pp_1_line_1), 1) + self.assertEqual(pp_1_line_1.demand_qty, 290.0) + self.assertEqual(pp_1_line_1.to_procure, 280.0) + pp_1_line_2 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_1.id), + ("date", "=", self.date_8), + ] + ) + self.assertEqual(len(pp_1_line_2), 1) + self.assertEqual(pp_1_line_2.demand_qty, 72.0) + self.assertEqual(pp_1_line_2.to_procure, 72.0) + # PP-2 + pp_2_line_1 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_2.id), + ("date", "=", self.date_3), + ] + ) + self.assertEqual(len(pp_2_line_1), 1) + self.assertEqual(pp_2_line_1.demand_qty, 90.0) + # 90.0 demand - 20.0 on hand - 5.0 on PO = 65.0 + self.assertEqual(pp_2_line_1.to_procure, 65.0) + pp_2_line_2 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_2.id), + ("date", "=", self.date_5), + ] + ) + self.assertEqual(len(pp_2_line_2), 1) + self.assertEqual(pp_2_line_2.demand_qty, 360.0) + self.assertEqual(pp_2_line_2.to_procure, 360.0) + pp_2_line_3 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_2.id), + ("date", "=", self.date_6), + ] + ) + self.assertEqual(len(pp_2_line_3), 1) + self.assertEqual(pp_2_line_3.demand_qty, 108.0) + self.assertEqual(pp_2_line_3.to_procure, 108.0) + pp_2_line_4 = self.mrp_inventory_obj.search( + [ + ("product_mrp_area_id.product_id", "=", self.pp_2.id), + ("date", "=", self.date_8), + ] + ) + self.assertEqual(len(pp_2_line_4), 1) + self.assertEqual(pp_2_line_4.demand_qty, 48.0) + self.assertEqual(pp_2_line_4.to_procure, 48.0) + + def test_05_planned_availability(self): + """Test planned availability computation.""" + # Running availability for PP-1: + invs = self.mrp_inventory_obj.search( + [("product_id", "=", self.pp_1.id)], order="date" + ) + self.assertEqual(len(invs), 2) + expected = [0.0, 0.0] # No grouping, lot size nor safety stock. + self.assertEqual(invs.mapped("running_availability"), expected) + + def test_06_procure_mo(self): + """Test procurement wizard with MOs.""" + mos = self.mo_obj.search([("product_id", "=", self.fp_1.id)]) + self.assertFalse(mos) + mrp_inv = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.fp_1.id)] + ) + self.mrp_inventory_procure_wiz.with_context( + active_model="mrp.inventory", + active_ids=mrp_inv.ids, + active_id=mrp_inv.id, + ).create({}).make_procurement() + mos = self.mo_obj.search([("product_id", "=", self.fp_1.id)]) + self.assertTrue(mos) + self.assertEqual(mos.product_qty, 100.0) + mo_date_start = fields.Date.to_date(mos.date_start) + self.assertEqual(mo_date_start, self.date_5) + + def test_07_adjust_qty_to_order(self): + """Test the adjustments made to the qty to procure when minimum, + maximum order quantities and quantity multiple are set.""" + # minimum order quantity: + mrp_inv_min = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.prod_min.id)] + ) + self.assertEqual(mrp_inv_min.to_procure, 50.0) + # maximum order quantity: + mrp_inv_max = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.prod_max.id)] + ) + self.assertEqual(mrp_inv_max.to_procure, 150) + plans = self.planned_order_obj.search([("product_id", "=", self.prod_max.id)]) + self.assertEqual(len(plans), 2) + self.assertIn(100.0, plans.mapped("mrp_qty")) + self.assertIn(50.0, plans.mapped("mrp_qty")) + # quantity multiple: + mrp_inv_multiple = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.prod_multiple.id)] + ) + self.assertEqual(mrp_inv_multiple.to_procure, 125) + + def test_08_group_demand(self): + """Test demand grouping functionality, `nbr_days`.""" + pickings = self.stock_picking_obj.search( + [ + ("product_id", "=", self.prod_test.id), + ("location_id", "=", self.sec_loc.id), + ] + ) + self.assertEqual(len(pickings), 5) + moves = self.mrp_move_obj.search( + [ + ("product_id", "=", self.prod_test.id), + ("mrp_area_id", "=", self.secondary_area.id), + ] + ) + supply_plans = self.planned_order_obj.search( + [ + ("product_id", "=", self.prod_test.id), + ("mrp_area_id", "=", self.secondary_area.id), + ] + ) + moves_demand = moves.filtered(lambda m: m.mrp_type == "d") + self.assertEqual(len(moves_demand), 5) + # two groups expected: + # 1. days 8, 9 and 10. + # 2. days 20, and 22. + self.assertEqual(len(supply_plans), 2) + quantities = supply_plans.mapped("mrp_qty") + week_1_expected = sum(moves_demand[0:3].mapped("mrp_qty")) + self.assertIn(abs(week_1_expected), quantities) + week_2_expected = sum(moves_demand[3:].mapped("mrp_qty")) + self.assertIn(abs(week_2_expected), quantities) + + def test_09_isolated_mrp_area_run(self): + """Test running MRP for just one area.""" + self.mrp_multi_level_wiz.with_user(self.mrp_manager).create( + {"mrp_area_ids": [(6, 0, self.secondary_area.ids)]} + ).run_mrp_multi_level() + this = self.mrp_inventory_obj.search( + [("mrp_area_id", "=", self.secondary_area.id)], limit=1 + ) + self.assertTrue(this) + # Only recently exectued areas should have been created by test user: + self.assertEqual(this.create_uid, self.mrp_manager) + prev = self.mrp_inventory_obj.search( + [("mrp_area_id", "!=", self.secondary_area.id)], limit=1 + ) + self.assertNotEqual(this.create_uid, prev.create_uid) + + def test_10_special_scenario_1(self): + """When grouping demand supply and demand are in the same day but + supply goes first.""" + moves = self.mrp_move_obj.search( + [("product_id", "=", self.product_scenario_1.id)] + ) + self.assertEqual(len(moves), 4) + mrp_invs = self.mrp_inventory_obj.search( + [("product_id", "=", self.product_scenario_1.id)] + ) + self.assertEqual(len(mrp_invs), 2) + # Net needs = 124 + 90 - 87 = 127 -> 130 (because of qty multiple) + self.assertEqual(mrp_invs[0].to_procure, 130) + # Net needs = 18, available on-hand = 3 -> 15 + self.assertEqual(mrp_invs[1].to_procure, 15) + + def test_11_bom_line_attribute_value_skip(self): + """Check for the correct demand on components of a product with + multiple variants""" + product_4b_demand = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.product_4b.id)] + ) + self.assertTrue(product_4b_demand) + self.assertEqual(product_4b_demand.to_procure, 100) + product_4c_demand = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.product_4c.id)] + ) + self.assertTrue(product_4c_demand) + self.assertEqual(product_4c_demand.to_procure, 1) + # Testing variant BoM + # Supply of one unit for AV-12 or AV-21 + av_12_supply = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.av_12.id)] + ) + self.assertEqual(av_12_supply.to_procure, 1.0) + av_21_supply = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.av_21.id)] + ) + self.assertEqual(av_21_supply.to_procure, 1.0) + # Testing template BoM + # Supply of 150 units for AV-11 and AV-22 + av_11_supply = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.av_11.id)] + ) + self.assertEqual(av_11_supply.to_procure, 100.0) + av_22_supply = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.av_22.id)] + ) + self.assertTrue(av_22_supply.to_procure, 100.0) + + def test_12_timezone_handling(self): + self.calendar.tz = "Australia/Sydney" # Oct-Apr/Apr-Oct: UTC+11/UTC+10 + date_move = datetime(2090, 4, 19, 20, 00) # Apr 20 6/7 am in Sidney + sidney_date = date(2090, 4, 20) + self._create_picking_in( + self.product_tz, 10.0, date_move, location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", self.product_tz.id), + ] + ) + self.assertEqual(len(inventory), 1) + self.assertEqual(inventory.date, sidney_date) + + def test_13_timezone_not_set(self): + self.wh.calendar_id = False + date_move = datetime(2090, 4, 19, 20, 00) + self._create_picking_in( + self.product_tz, 10.0, date_move, location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", self.product_tz.id), + ] + ) + self.assertEqual(len(inventory), 1) + self.assertEqual(inventory.date, date_move.date()) + + def test_14_units_case(self): + """When a product has a different purchase unit of measure than + the general unit of measure and the supply is coming from an RFQ""" + prod_uom_test_inventory_lines = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.prod_uom_test.id)] + ) + self.assertEqual(len(prod_uom_test_inventory_lines), 1) + self.assertEqual(prod_uom_test_inventory_lines.supply_qty, 12.0) + # Supply qty has to be 12 has a dozen of units are in a RFQ. + + def test_15_phantom_comp_planning(self): + """ + Phantom components will not appear in MRP Inventory or Planned Orders. + MRP Parameter will have 'phantom' supply method. + """ + # SF-3 + sf_3_line_1 = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.sf_3.id)] + ) + self.assertEqual(len(sf_3_line_1), 0) + sf_3_planned_order_1 = self.planned_order_obj.search( + [("product_mrp_area_id.product_id", "=", self.sf_3.id)] + ) + self.assertEqual(sf_3_planned_order_1.mrp_action, "phantom") + self.assertEqual(sf_3_planned_order_1.mrp_qty, 10.0) + # PP-3 + pp_3_line_1 = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_3.id)] + ) + self.assertEqual(len(pp_3_line_1), 1) + self.assertEqual(pp_3_line_1.demand_qty, 20.0) + pp_3_planned_orders = self.planned_order_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_3.id)] + ) + self.assertEqual(len(pp_3_planned_orders), 2) + # PP-4 + pp_4_line_1 = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_4.id)] + ) + self.assertEqual(len(pp_4_line_1), 1) + self.assertEqual(pp_4_line_1.demand_qty, 30.0) + pp_4_planned_orders = self.planned_order_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_4.id)] + ) + self.assertEqual(len(pp_4_planned_orders), 1) + + def test_16_supply_method(self): + """Test supply method computation.""" + self.fp_4.route_ids = [(5, 0, 0)] + product_mrp_area = self.product_mrp_area_obj.search( + [("product_id", "=", self.fp_4.id)] + ) + self.assertEqual(product_mrp_area.supply_method, "none") + self.fp_4.route_ids = [(4, self.env.ref("stock.route_warehouse0_mto").id)] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "pull") + self.fp_4.route_ids = [(4, self.env.ref("mrp.route_warehouse0_manufacture").id)] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "manufacture") + # because of the issue discussed here https://github.com/odoo/odoo/pull/188846 + # we need to apply routes explicitly in the proper order (by sequence) + self.fp_4.route_ids = [ + ( + 6, + 0, + ( + self.env.ref("stock.route_warehouse0_mto") + + self.env.ref("purchase_stock.route_warehouse0_buy") + + self.env.ref("mrp.route_warehouse0_manufacture") + ).ids, + ) + ] + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "buy") + kit_bom = self.mrp_bom_obj.create( + { + "product_tmpl_id": self.fp_4.product_tmpl_id.id, + "product_id": self.fp_4.id, + "type": "phantom", + } + ) + product_mrp_area._compute_supply_method() + self.assertEqual(product_mrp_area.supply_method, "phantom") + self.assertEqual(product_mrp_area.supply_bom_id, kit_bom) + + def test_17_priorize_safety_stock(self): + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + "mrp_applicable": True, # needed? + } + ) + self._create_picking_out( + product, 6.0, now + timedelta(days=3), location=self.cases_loc + ) + self._create_picking_in( + product, 10.0, now + timedelta(days=7), location=self.cases_loc + ) + self._create_picking_out( + product, 12.0, now + timedelta(days=14), location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", product.id), + ] + ) + expected = [ + { + "date": now.date(), + "demand_qty": 0.0, + "final_on_hand_qty": 5.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 10.0, + }, + { + "date": now.date() + timedelta(days=3), + "demand_qty": 6.0, + "final_on_hand_qty": -1.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 6.0, + }, + { + "date": now.date() + timedelta(days=7), + "demand_qty": 0.0, + "final_on_hand_qty": 9.0, + "initial_on_hand_qty": -1.0, + "running_availability": 25.0, + "supply_qty": 10.0, + "to_procure": 0.0, + }, + { + "date": now.date() + timedelta(days=14), + "demand_qty": 12.0, + "final_on_hand_qty": -3.0, + "initial_on_hand_qty": 9.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 2.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_18_on_hand_with_lots(self): + """Check that on-hand is correctly computed when tracking by lots.""" + lots_line_1 = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.product_lots.id)] + ) + self.assertEqual(len(lots_line_1), 1) + self.assertEqual(lots_line_1.initial_on_hand_qty, 210) + self.assertEqual(lots_line_1.final_on_hand_qty, 185) + + def test_19_prioritize_safety_stock_grouped_1(self): + """Test grouped demand MRP but with a short nbr days. + Safety stock should be ordered.""" + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + "mrp_nbr_days": 2, + } + ) + self._create_picking_out( + product, 6.0, now + timedelta(days=3), location=self.cases_loc + ) + self._create_picking_in( + product, 10.0, now + timedelta(days=7), location=self.cases_loc + ) + self._create_picking_out( + product, 12.0, now + timedelta(days=14), location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", product.id), + ] + ) + expected = [ + { + "date": now.date(), + "demand_qty": 0.0, + "final_on_hand_qty": 5.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 10.0, + }, + { + "date": now.date() + timedelta(days=3), + "demand_qty": 6.0, + "final_on_hand_qty": -1.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 6.0, + }, + { + "date": now.date() + timedelta(days=7), + "demand_qty": 0.0, + "final_on_hand_qty": 9.0, + "initial_on_hand_qty": -1.0, + "running_availability": 25.0, + "supply_qty": 10.0, + "to_procure": 0.0, + }, + { + "date": now.date() + timedelta(days=14), + "demand_qty": 12.0, + "final_on_hand_qty": -3.0, + "initial_on_hand_qty": 9.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 2.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_20_prioritize_safety_stock_grouped_2(self): + """Test grouped demand MRP but with a longer nbr days. + Safety stock should be ordered.""" + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + "mrp_nbr_days": 7, + } + ) + self._create_picking_out( + product, 6.0, now + timedelta(days=3), location=self.cases_loc + ) + self._create_picking_in( + product, 10.0, now + timedelta(days=7), location=self.cases_loc + ) + self._create_picking_out( + product, 12.0, now + timedelta(days=12), location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", product.id), + ] + ) + expected = [ + { + "date": now.date(), + "demand_qty": 0.0, + "final_on_hand_qty": 5.0, + "initial_on_hand_qty": 5.0, + "running_availability": 21.0, + "supply_qty": 0.0, + "to_procure": 16.0, + }, + { + "date": now.date() + timedelta(days=3), + "demand_qty": 6.0, + "final_on_hand_qty": -1.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 0.0, + }, + { + "date": now.date() + timedelta(days=7), + "demand_qty": 0.0, + "final_on_hand_qty": 9.0, + "initial_on_hand_qty": -1.0, + "running_availability": 27.0, + "supply_qty": 10.0, + "to_procure": 2.0, + }, + { + "date": now.date() + timedelta(days=12), + "demand_qty": 12.0, + "final_on_hand_qty": -3.0, + "initial_on_hand_qty": 9.0, + "running_availability": 15.0, + "supply_qty": 0.0, + "to_procure": 0.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_21_prioritize_safety_stock_grouped_3(self): + """Test grouped demand MRP but with an existing incoming supply + Safety stock should NOT be ordered.""" + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + "mrp_nbr_days": 7, + } + ) + self._create_picking_in( + product, 30.0, now + timedelta(days=3), location=self.cases_loc + ) + self._create_picking_out( + product, 6.0, now + timedelta(days=7), location=self.cases_loc + ) + self._create_picking_out( + product, 12.0, now + timedelta(days=12), location=self.cases_loc + ) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [ + ("mrp_area_id", "=", self.cases_area.id), + ("product_id", "=", product.id), + ] + ) + expected = [ + { + "date": now.date() + timedelta(days=3), + "demand_qty": 0.0, + "initial_on_hand_qty": 5.0, + "final_on_hand_qty": 35.0, + "running_availability": 35.0, + "supply_qty": 30.0, + "to_procure": 0.0, + }, + { + "date": now.date() + timedelta(days=7), + "demand_qty": 6.0, + "initial_on_hand_qty": 35.0, + "final_on_hand_qty": 29.0, + "running_availability": 29.0, + "supply_qty": 0.0, + "to_procure": 0.0, + }, + { + "date": now.date() + timedelta(days=12), + "demand_qty": 12.0, + "initial_on_hand_qty": 29.0, + "final_on_hand_qty": 17.0, + "running_availability": 17.0, + "supply_qty": 0.0, + "to_procure": 0.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_22_prioritize_safety_stock_with_mrp_moves_today(self): + """Test MRP but with moves today. Safety stock should not be ordered.""" + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + } + ) + self._create_picking_out(product, 10.0, now, location=self.cases_loc) + self._create_picking_in(product, 20.0, now, location=self.cases_loc) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [("mrp_area_id", "=", self.cases_area.id), ("product_id", "=", product.id)] + ) + expected = [ + { + "date": now.date(), + "demand_qty": 10.0, + "final_on_hand_qty": 15.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 20.0, + "to_procure": 0.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_23_prioritize_safety_stock_with_mrp_moves_today_grouped(self): + """Test grouped demand MRP but with moves today. Safety stock should not be + ordered. + """ + now = datetime.now() + product = self.prod_test # has Buy route + product.seller_ids[0].delay = 2 # set a purchase lead time + self.quant_obj._update_available_quantity(product, self.cases_loc, 5) + self.product_mrp_area_obj.create( + { + "product_id": product.id, + "mrp_area_id": self.cases_area.id, + "mrp_minimum_stock": 15, + "mrp_nbr_days": 2, + } + ) + self._create_picking_out(product, 10.0, now, location=self.cases_loc) + self._create_picking_in(product, 20.0, now, location=self.cases_loc) + self.mrp_multi_level_wiz.create( + {"mrp_area_ids": [(6, 0, self.cases_area.ids)]} + ).run_mrp_multi_level() + inventory = self.mrp_inventory_obj.search( + [("mrp_area_id", "=", self.cases_area.id), ("product_id", "=", product.id)] + ) + expected = [ + { + "date": now.date(), + "demand_qty": 10.0, + "final_on_hand_qty": 15.0, + "initial_on_hand_qty": 5.0, + "running_availability": 15.0, + "supply_qty": 20.0, + "to_procure": 0.0, + }, + ] + self.assertEqual(len(expected), len(inventory)) + for test_vals, inv in zip(expected, inventory, strict=True): + for key in test_vals: + self.assertEqual( + test_vals[key], + inv[key], + f"unexpected value for {key}: {inv[key]} " + f"(expected {test_vals[key]} on {inv.date})", + ) + + def test_24_phantom_comp_on_hand(self): + """ + A phantom product with positive qty_available (which is computed from the + availability of its components) should not satisfy demand, because this leads + to double counting qty_available of its component products. + """ + quant = self.quant_obj.sudo().create( + { + "product_id": self.pp_3.id, + "inventory_quantity": 10.0, + "location_id": self.stock_location.id, + } + ) + quant.action_apply_inventory() + quant = self.quant_obj.sudo().create( + { + "product_id": self.pp_4.id, + "inventory_quantity": 30.0, + "location_id": self.stock_location.id, + } + ) + quant.action_apply_inventory() + self.assertEqual(self.sf_3.qty_available, 10.0) + self.mrp_multi_level_wiz.create({}).run_mrp_multi_level() + # PP-3 + pp_3_line_1 = self.mrp_inventory_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_3.id)] + ) + self.assertEqual(len(pp_3_line_1), 1) + self.assertEqual(pp_3_line_1.demand_qty, 20.0) + self.assertEqual(pp_3_line_1.to_procure, 10.0) + pp_3_planned_orders = self.planned_order_obj.search( + [("product_mrp_area_id.product_id", "=", self.pp_3.id)] + ) + self.assertEqual(len(pp_3_planned_orders), 1) + self.assertEqual(pp_3_planned_orders.mrp_qty, 10) + sf3_planned_orders = self.env["mrp.planned.order"].search( + [("product_id", "=", self.sf_3.id)] + ) + self.assertEqual(len(sf3_planned_orders), 1) + # Trying to procure a kit planned order will have no effect. + procure_wizard = ( + self.env["mrp.inventory.procure"] + .with_context( + active_model="mrp.planned.order", active_ids=sf3_planned_orders.ids + ) + .create({}) + ) + self.assertEqual(len(procure_wizard.item_ids), 0) diff --git a/mrp_multi_level/views/mrp_area_views.xml b/mrp_multi_level/views/mrp_area_views.xml new file mode 100644 index 000000000..994a13a00 --- /dev/null +++ b/mrp_multi_level/views/mrp_area_views.xml @@ -0,0 +1,60 @@ + + + + mrp.area.list + mrp.area + list + + + + + + + + + + + + mrp.area.form + mrp.area + form + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + mrp.planned.order.pivot + mrp.planned.order + + + + + + + + + + + mrp.planned.order.search + mrp.planned.order + + + + + + + + + + + + + + + + + + Planned Orders + mrp.planned.order + ir.actions.act_window + list,form,pivot + {'search_default_fixed': 1} + + + + Toggle Fixed + + + code + records.action_toggle_fixed() + + + Procure + mrp.inventory.procure + form + new + + +
diff --git a/mrp_multi_level/views/product_mrp_area_views.xml b/mrp_multi_level/views/product_mrp_area_views.xml new file mode 100644 index 000000000..f9d016697 --- /dev/null +++ b/mrp_multi_level/views/product_mrp_area_views.xml @@ -0,0 +1,183 @@ + + + + product.mrp.area.list + product.mrp.area + list + + + + + + + + + + + + + + + + + + + + + + product.mrp.area.form + product.mrp.area + form + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + product.mrp.area.search + product.mrp.area + search + + + + + + + + + + + + + Product MRP Area Parameters + product.mrp.area + ir.actions.act_window + list,form + + + +
diff --git a/mrp_multi_level/views/product_product_views.xml b/mrp_multi_level/views/product_product_views.xml new file mode 100644 index 000000000..da018d344 --- /dev/null +++ b/mrp_multi_level/views/product_product_views.xml @@ -0,0 +1,22 @@ + + + + view.product.mrp.area.product.form + product.product + + form + +
+ +
+
+
+
diff --git a/mrp_multi_level/views/product_template_views.xml b/mrp_multi_level/views/product_template_views.xml new file mode 100644 index 000000000..40fd43882 --- /dev/null +++ b/mrp_multi_level/views/product_template_views.xml @@ -0,0 +1,21 @@ + + + + product.template.product.form.mrp + product.template + + +
+ +
+
+
+
diff --git a/mrp_multi_level/views/stock_location_views.xml b/mrp_multi_level/views/stock_location_views.xml new file mode 100644 index 000000000..a94632d75 --- /dev/null +++ b/mrp_multi_level/views/stock_location_views.xml @@ -0,0 +1,20 @@ + + + + stock.location.form + stock.location + + + + + + + + diff --git a/mrp_multi_level/wizards/__init__.py b/mrp_multi_level/wizards/__init__.py new file mode 100644 index 000000000..6e1a7350a --- /dev/null +++ b/mrp_multi_level/wizards/__init__.py @@ -0,0 +1,2 @@ +from . import mrp_multi_level +from . import mrp_inventory_procure diff --git a/mrp_multi_level/wizards/mrp_inventory_procure.py b/mrp_multi_level/wizards/mrp_inventory_procure.py new file mode 100644 index 000000000..951b4d2bf --- /dev/null +++ b/mrp_multi_level/wizards/mrp_inventory_procure.py @@ -0,0 +1,151 @@ +# Copyright 2018-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 UserError, ValidationError + + +class MrpInventoryProcure(models.TransientModel): + _name = "mrp.inventory.procure" + _description = "Make Procurements from MRP inventory projections" + + item_ids = fields.One2many( + comodel_name="mrp.inventory.procure.item", inverse_name="wiz_id", string="Items" + ) + + @api.model + def _prepare_item(self, planned_order): + return { + "planned_order_id": planned_order.id, + "qty": planned_order.mrp_qty - planned_order.qty_released, + "uom_id": planned_order.mrp_inventory_id.uom_id.id, + "date_planned": planned_order.due_date, + "mrp_inventory_id": planned_order.mrp_inventory_id.id, + "product_id": planned_order.product_id.id, + "warehouse_id": planned_order.mrp_area_id.warehouse_id.id, + "location_id": planned_order.product_mrp_area_id.location_proc_id.id + or planned_order.mrp_area_id.location_id.id, + "supply_method": planned_order.product_mrp_area_id.supply_method, + } + + @api.model + def fields_view_get( + self, view_id=None, view_type="form", toolbar=False, submenu=False + ): + if self.user_has_groups("mrp_multi_level.group_change_mrp_procure_qty"): + view_id = self.env.ref( + "mrp_multi_level.view_mrp_inventory_procure_wizard" + ).id + else: + view_id = self.env.ref( + "mrp_multi_level.view_mrp_inventory_procure_without_security" + ).id + return super().fields_view_get( + view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu + ) + + @api.model + def default_get(self, fields): + res = super().default_get(fields) + active_ids = self.env.context["active_ids"] or [] + active_model = self.env.context["active_model"] + if not active_ids or "item_ids" not in fields: + return res + items = item_obj = self.env["mrp.inventory.procure.item"] + if active_model == "mrp.inventory": + mrp_inventory_obj = self.env[active_model] + for line in mrp_inventory_obj.browse(active_ids).mapped( + "planned_order_ids" + ): + if line.qty_released < line.mrp_qty: + items += item_obj.create(self._prepare_item(line)) + elif active_model == "mrp.planned.order": + mrp_planned_order_obj = self.env[active_model] + for line in mrp_planned_order_obj.browse(active_ids): + if line.mrp_action == "phantom": + continue + if line.qty_released < line.mrp_qty: + items += item_obj.create(self._prepare_item(line)) + if items: + res["item_ids"] = [(6, 0, items.ids)] + return res + + def make_procurement(self): + self.ensure_one() + errors = [] + pg = self.env["procurement.group"] + procurements = [] + for item in self.item_ids: + if not item.qty: + raise ValidationError(_("Quantity must be positive.")) + values = item._prepare_procurement_values() + procurements.append( + pg.Procurement( + item.product_id, + item.qty, + item.uom_id, + item.location_id, + "MRP: " + (item.planned_order_id.name or self.env.user.login), + "MRP: " + (item.planned_order_id.origin or self.env.user.login), + item.mrp_inventory_id.company_id, + values, + ) + ) + # Run procurements + try: + pg.run(procurements) + for item in self.item_ids: + item.planned_order_id.qty_released += item.qty + except UserError as error: + errors.append(error.name) + if errors: + raise UserError("\n".join(errors)) + return {"type": "ir.actions.act_window_close"} + + +class MrpInventoryProcureItem(models.TransientModel): + _name = "mrp.inventory.procure.item" + _description = "MRP Inventory procure item" + + wiz_id = fields.Many2one( + comodel_name="mrp.inventory.procure", + string="Wizard", + ondelete="cascade", + readonly=True, + ) + qty = fields.Float(string="Quantity") + uom_id = fields.Many2one(string="Unit of Measure", comodel_name="uom.uom") + date_planned = fields.Date(string="Planned Date", required=True) + mrp_inventory_id = fields.Many2one( + string="Mrp Inventory", comodel_name="mrp.inventory" + ) + planned_order_id = fields.Many2one(comodel_name="mrp.planned.order") + product_id = fields.Many2one(string="Product", comodel_name="product.product") + warehouse_id = fields.Many2one(string="Warehouse", comodel_name="stock.warehouse") + location_id = fields.Many2one(string="Location", comodel_name="stock.location") + supply_method = fields.Selection( + selection=[ + ("buy", "Buy"), + ("none", "Undefined"), + ("manufacture", "Produce"), + ("pull", "Pull From"), + ("push", "Push To"), + ("pull_push", "Pull & Push"), + ], + readonly=True, + ) + + def _prepare_procurement_values(self, group=False): + return { + "date_planned": self.date_planned, + "warehouse_id": self.warehouse_id, + "group_id": group, + "planned_order_id": self.planned_order_id.id, + } + + @api.onchange("uom_id") + def onchange_uom_id(self): + for rec in self: + rec.qty = rec.mrp_inventory_id.uom_id._compute_quantity( + rec.mrp_inventory_id.to_procure, rec.uom_id + ) diff --git a/mrp_multi_level/wizards/mrp_inventory_procure_views.xml b/mrp_multi_level/wizards/mrp_inventory_procure_views.xml new file mode 100644 index 000000000..a55124c23 --- /dev/null +++ b/mrp_multi_level/wizards/mrp_inventory_procure_views.xml @@ -0,0 +1,67 @@ + + + + + mrp.inventory.procure.form + mrp.inventory.procure + +
+

+ Use this assistant to procure for this product and date. + According to the product configuration, + this may trigger a draft purchase order, a manufacturing + order or a transfer picking. +

+ + + + + + + + + + + + + +
+
+ +
+
+ + + mrp.inventory.procure.form - readonly qty + mrp.inventory.procure + + primary + + + 1 + + + + + Procure + mrp.inventory.procure + form + new + + +
diff --git a/mrp_multi_level/wizards/mrp_multi_level.py b/mrp_multi_level/wizards/mrp_multi_level.py new file mode 100644 index 000000000..a39d12e5a --- /dev/null +++ b/mrp_multi_level/wizards/mrp_multi_level.py @@ -0,0 +1,924 @@ +# Copyright 2016 Ucamco - Wim Audenaert +# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) +# - Jordi Ballester Alomar +# - Lois Rilo +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +import logging +from datetime import date, timedelta + +from odoo import _, api, exceptions, fields, models +from odoo.tools import float_is_zero, mute_logger + +logger = logging.getLogger(__name__) + + +class MultiLevelMrp(models.TransientModel): + _name = "mrp.multi.level" + _description = "Multi Level MRP" + + mrp_area_ids = fields.Many2many( + comodel_name="mrp.area", + string="MRP Areas to run", + help="If empty, all areas will be computed.", + ) + + @api.model + def _prepare_mrp_move_data_from_stock_move( + self, product_mrp_area, move, direction="in" + ): + area = product_mrp_area.mrp_area_id + if direction == "out": + mrp_type = "d" + product_qty = -move.product_qty + else: + mrp_type = "s" + product_qty = move.product_qty + po = po_line = None + mo = origin = order_number = order_origin = parent_product_id = None + if move.purchase_line_id: + po = move.purchase_line_id.order_id + order_number = po.name + order_origin = po.origin + origin = "po" + po = move.purchase_line_id.order_id.id + po_line = move.purchase_line_id.id + elif move.production_id or move.raw_material_production_id: + production = move.production_id or move.raw_material_production_id + order_number = production.name + order_origin = production.origin + origin = "mo" + mo = production.id + elif move.move_dest_ids: + for move_dest_id in move.move_dest_ids.filtered("production_id"): + production = move_dest_id.production_id + order_number = production.name + order_origin = production.origin + origin = "mo" + mo = move_dest_id.production_id.id + parent_product_id = ( + move_dest_id.production_id.product_id or move_dest_id.product_id + ).id + if not order_number: + source = (move.picking_id or move).origin + order_number = source or (move.picking_id or move).name + origin = "mv" + # The date to display is based on the timezone of the warehouse. + today_tz = area._datetime_to_date_tz() + move_date_tz = area._datetime_to_date_tz(move.date) + if move_date_tz > today_tz: + mrp_date = move_date_tz + else: + mrp_date = today_tz + return { + "product_id": move.product_id.id, + "product_mrp_area_id": product_mrp_area.id, + "production_id": mo, + "purchase_order_id": po, + "purchase_line_id": po_line, + "stock_move_id": move.id, + "mrp_qty": product_qty, + "current_qty": product_qty, + "mrp_date": mrp_date, + "current_date": move.date, + "mrp_type": mrp_type, + "mrp_origin": origin or "", + "mrp_order_number": order_number, + "parent_product_id": parent_product_id, + "name": order_number, + "origin": order_origin, + "state": move.state, + } + + @api.model + def _prepare_planned_order_data( + self, product_mrp_area, qty, mrp_date_supply, mrp_action_date, name, values + ): + return { + "product_mrp_area_id": product_mrp_area.id, + "mrp_qty": qty, + "due_date": mrp_date_supply, + "order_release_date": mrp_action_date, + "mrp_action": product_mrp_area.supply_method, + "qty_released": 0.0, + "name": "Planned supply for: " + name, + "origin": values.get("origin") or name, + "fixed": False, + } + + @api.model + def _prepare_mrp_move_data_bom_explosion( + self, + product, + bomline, + qty, + mrp_date_demand_2, + bom, + name, + planned_order, + values=None, + ): + product_mrp_area = self._get_product_mrp_area_from_product_and_area( + bomline.product_id, product.mrp_area_id + ) + if not product_mrp_area: + raise exceptions.Warning(_("No MRP product found")) + factor = ( + product.product_id.uom_id._compute_quantity( + qty, bomline.bom_id.product_uom_id + ) + / bomline.bom_id.product_qty + ) + line_quantity = factor * bomline.product_qty + return { + "mrp_area_id": product_mrp_area.mrp_area_id.id, + "product_id": bomline.product_id.id, + "product_mrp_area_id": product_mrp_area.id, + "production_id": None, + "purchase_order_id": None, + "purchase_line_id": None, + "stock_move_id": None, + "mrp_qty": -line_quantity, # TODO: review with UoM + "current_qty": None, + "mrp_date": mrp_date_demand_2, + "current_date": None, + "mrp_type": "d", + "mrp_origin": "mrp", + "mrp_order_number": None, + "parent_product_id": bom.product_id.id, + "name": ( + "Demand Bom Explosion: %s" + % (name or product.product_id.default_code or product.product_id.name) + ).replace( + "Demand Bom Explosion: Demand Bom Explosion: ", "Demand Bom Explosion: " + ), + "origin": planned_order.origin if planned_order else values.get("origin"), + "bom_id": bom.id, + } + + @api.model + def _get_action_and_supply_dates(self, product_mrp_area, mrp_date): + if not isinstance(mrp_date, date): + mrp_date = fields.Date.from_string(mrp_date) + + if mrp_date < date.today(): + mrp_date_supply = date.today() + else: + mrp_date_supply = mrp_date + + calendar = product_mrp_area.mrp_area_id.calendar_id + if calendar and product_mrp_area.mrp_lead_time: + date_str = fields.Date.to_string(mrp_date) + dt = fields.Datetime.from_string(date_str) + # dt is at the beginning of the day (00:00) + res = calendar.plan_days(-1 * product_mrp_area.mrp_lead_time, dt) + mrp_action_date = res.date() + else: + mrp_action_date = mrp_date - timedelta(days=product_mrp_area.mrp_lead_time) + return mrp_action_date, mrp_date_supply + + @api.model + def _get_bom_to_explode(self, product_mrp_area_id): + return product_mrp_area_id.supply_bom_id + + @api.model + def explode_action( + self, product_mrp_area_id, mrp_action_date, name, qty, action, values=None + ): + """Explode requirements.""" + mrp_date_demand = mrp_action_date + if mrp_date_demand < date.today(): + mrp_date_demand = date.today() + bom = self._get_bom_to_explode(product_mrp_area_id) + if not bom: + return False + pd = self.env["decimal.precision"].precision_get("Product Unit of Measure") + for bomline in bom.bom_line_ids: + if ( + float_is_zero(bomline.product_qty, precision_digits=pd) + or bomline.product_id.type != "consu" + ): + continue + if self.with_context(mrp_explosion=True)._exclude_from_mrp( + bomline.product_id, product_mrp_area_id.mrp_area_id + ): + # Stop explosion. + continue + if bomline._skip_bom_line(product_mrp_area_id.product_id): + continue + # TODO: review: mrp_transit_delay, mrp_inspection_delay + mrp_date_demand_2 = mrp_date_demand - timedelta( + days=( + product_mrp_area_id.mrp_transit_delay + + product_mrp_area_id.mrp_inspection_delay + ) + ) + move_data = self._prepare_mrp_move_data_bom_explosion( + product_mrp_area_id, + bomline, + qty, + mrp_date_demand_2, + bom, + name, + action, + values, + ) + mrpmove_id2 = self.env["mrp.move"].create(move_data) + if hasattr(action, "mrp_move_down_ids"): + action.mrp_move_down_ids = [(4, mrpmove_id2.id)] + return True + + @api.model + def create_action(self, product_mrp_area_id, mrp_date, mrp_qty, name, values=None): + if not values: + values = {} + if not isinstance(mrp_date, date): + mrp_date = fields.Date.from_string(mrp_date) + action_date, date_supply = self._get_action_and_supply_dates( + product_mrp_area_id, mrp_date + ) + return self.create_planned_order( + product_mrp_area_id, mrp_qty, name, date_supply, action_date, values=values + ) + + @api.model + def create_planned_order( + self, + product_mrp_area_id, + mrp_qty, + name, + mrp_date_supply, + mrp_action_date, + values=None, + ): + self = self.with_context(auditlog_disabled=True) + if self._exclude_from_mrp( + product_mrp_area_id.product_id, product_mrp_area_id.mrp_area_id + ): + values["qty_ordered"] = 0.0 + return values + + qty_ordered = values.get("qty_ordered", 0.0) if values else 0.0 + qty_to_order = mrp_qty + while qty_ordered < mrp_qty: + qty = product_mrp_area_id._adjust_qty_to_order(qty_to_order) + qty_to_order -= qty + order_data = self._prepare_planned_order_data( + product_mrp_area_id, qty, mrp_date_supply, mrp_action_date, name, values + ) + planned_order = False + if product_mrp_area_id._should_create_planned_order(): + planned_order = self.env["mrp.planned.order"].create(order_data) + qty_ordered = qty_ordered + qty + + if product_mrp_area_id._to_be_exploded(): + self.explode_action( + product_mrp_area_id, + mrp_action_date, + name, + qty, + planned_order, + values, + ) + + values["qty_ordered"] = qty_ordered + log_msg = "[{}] {}: qty_ordered = {}".format( + product_mrp_area_id.mrp_area_id.name, + product_mrp_area_id.product_id.default_code + or product_mrp_area_id.product_id.name, + qty_ordered, + ) + logger.debug(log_msg) + return values + + @api.model + def _mrp_cleanup(self, mrp_areas): + logger.info("Start MRP Cleanup") + domain = [] + if mrp_areas: + domain += [("mrp_area_id", "in", mrp_areas.ids)] + with mute_logger("odoo.models.unlink"): + self.env["mrp.move"].search(domain).unlink() + self.env["mrp.planned.order"].search( + domain + [("fixed", "=", False)] + ).unlink() + self.env["mrp.inventory"].search(domain).unlink() + logger.info("End MRP Cleanup") + return True + + def _domain_bom_lines_by_llc(self, llc, product_templates): + return [ + ("product_id.llc", "=", llc), + ("bom_id.product_tmpl_id", "in", product_templates.ids), + ("bom_id.active", "=", True), + ] + + def _get_bom_lines_by_llc(self, llc, product_templates): + return self.env["mrp.bom.line"].search( + self._domain_bom_lines_by_llc(llc, product_templates) + ) + + @api.model + def _low_level_code_calculation(self): + logger.info("Start low level code calculation") + counter = 999999 + llc = 0 + llc_recursion_limit = ( + int( + self.env["ir.config_parameter"] + .sudo() + .get_param("mrp_multi_level.llc_calculation_recursion_limit") + ) + or 1000 + ) + self.env["product.product"].search([]).write({"llc": llc}) + products = self.env["product.product"].search([("llc", "=", llc)]) + if products: + counter = len(products) + log_msg = f"Low level code 0 finished - Nbr. products: {counter}" + logger.info(log_msg) + + while counter: + llc += 1 + products = self.env["product.product"].search([("llc", "=", llc - 1)]) + p_templates = products.mapped("product_tmpl_id") + bom_lines = self._get_bom_lines_by_llc(llc - 1, p_templates) + products = bom_lines.mapped("product_id") + products.write({"llc": llc}) + counter = self.env["product.product"].search_count([("llc", "=", llc)]) + log_msg = f"Low level code {llc} finished - Nbr. products: {counter}" + logger.info(log_msg) + if llc > llc_recursion_limit: + logger.error("Recursion limit reached during LLC calculation.") + break + + mrp_lowest_llc = llc + logger.info("End low level code calculation") + return mrp_lowest_llc + + @api.model + def _adjust_mrp_applicable(self, mrp_areas): + """This method is meant to modify the products that are applicable + to MRP Multi level calculation + """ + return True + + @api.model + def _calculate_mrp_applicable(self, mrp_areas): + logger.info("Start Calculate MRP Applicable") + domain = [] + if mrp_areas: + domain += [("mrp_area_id", "in", mrp_areas.ids)] + self.env["product.mrp.area"].search(domain).write({"mrp_applicable": False}) + domain += [ + ("product_id.type", "=", "consu"), + ("product_id.is_storable", "=", True), + ] + self.env["product.mrp.area"].search(domain).write({"mrp_applicable": True}) + self._adjust_mrp_applicable(mrp_areas) + count_domain = [("mrp_applicable", "=", True)] + if mrp_areas: + count_domain += [("mrp_area_id", "in", mrp_areas.ids)] + counter = self.env["product.mrp.area"].search_count(count_domain) + log_msg = f"End Calculate MRP Applicable: {counter}" + logger.info(log_msg) + return True + + @api.model + def _init_mrp_move_from_forecast(self, product_mrp_area): + """This method is meant to be inherited to add a forecast mechanism.""" + return True + + @api.model + def _init_mrp_move_from_stock_move(self, product_mrp_area): + move_obj = self.env["stock.move"] + mrp_move_obj = self.env["mrp.move"] + in_domain = product_mrp_area._in_stock_moves_domain() + in_moves = move_obj.search(in_domain) + out_domain = product_mrp_area._out_stock_moves_domain() + out_moves = move_obj.search(out_domain) + move_vals = [] + if in_moves: + for move in in_moves: + move_data = self._prepare_mrp_move_data_from_stock_move( + product_mrp_area, move, direction="in" + ) + if move_data: + move_vals.append(move_data) + if out_moves: + for move in out_moves: + move_data = self._prepare_mrp_move_data_from_stock_move( + product_mrp_area, move, direction="out" + ) + if move_data: + move_vals.append(move_data) + mrp_move_obj.create(move_vals) + return True + + @api.model + def _prepare_mrp_move_data_from_purchase_order(self, poline, product_mrp_area): + mrp_date = date.today() + if fields.Date.from_string(poline.date_planned) > date.today(): + mrp_date = fields.Date.from_string(poline.date_planned) + return { + "product_id": poline.product_id.id, + "product_mrp_area_id": product_mrp_area.id, + "production_id": None, + "purchase_order_id": poline.order_id.id, + "purchase_line_id": poline.id, + "stock_move_id": None, + "mrp_qty": poline.product_uom_qty, + "current_qty": poline.product_uom_qty, + "mrp_date": mrp_date, + "current_date": poline.date_planned, + "mrp_type": "s", + "mrp_origin": "po", + "mrp_order_number": poline.order_id.name, + "parent_product_id": None, + "name": poline.order_id.name, + "state": poline.order_id.state, + } + + @api.model + def _init_mrp_move_from_purchase_order(self, product_mrp_area): + location_ids = product_mrp_area._get_locations() + picking_types = self.env["stock.picking.type"].search( + [("default_location_dest_id", "child_of", location_ids.ids)] + ) + picking_type_ids = [ptype.id for ptype in picking_types] + orders = self.env["purchase.order"].search( + [ + ("picking_type_id", "in", picking_type_ids), + ("state", "in", ["draft", "sent", "to approve"]), + ] + ) + po_lines = self.env["purchase.order.line"].search( + [ + ("order_id", "in", orders.ids), + ("product_qty", ">", 0.0), + ("product_id", "=", product_mrp_area.product_id.id), + ] + ) + + mrp_move_vals = [] + for line in po_lines: + mrp_move_data = self._prepare_mrp_move_data_from_purchase_order( + line, product_mrp_area + ) + mrp_move_vals.append(mrp_move_data) + if mrp_move_vals: + self.env["mrp.move"].create(mrp_move_vals) + + @api.model + def _get_product_mrp_area_from_product_and_area(self, product, mrp_area): + return self.env["product.mrp.area"].search( + [("product_id", "=", product.id), ("mrp_area_id", "=", mrp_area.id)], + limit=1, + ) + + @api.model + def _init_mrp_move(self, product_mrp_area): + self._init_mrp_move_from_forecast(product_mrp_area) + self._init_mrp_move_from_stock_move(product_mrp_area) + self._init_mrp_move_from_purchase_order(product_mrp_area) + + @api.model + def _exclude_from_mrp(self, product, mrp_area): + """To extend with various logic where needed.""" + product_mrp_area = self.env["product.mrp.area"].search( + [("product_id", "=", product.id), ("mrp_area_id", "=", mrp_area.id)], + limit=1, + ) + if not product_mrp_area: + return True + return product_mrp_area.mrp_exclude + + @api.model + def _mrp_initialisation(self, mrp_areas): + logger.info("Start MRP initialisation") + if not mrp_areas: + mrp_areas = self.env["mrp.area"].search([]) + product_mrp_areas = self.env["product.mrp.area"].search( + [("mrp_area_id", "in", mrp_areas.ids), ("mrp_applicable", "=", True)] + ) + init_counter = 0 + for mrp_area in mrp_areas: + for product_mrp_area in product_mrp_areas.filtered( + lambda a, mrp_area=mrp_area: a.mrp_area_id == mrp_area + ): + if self._exclude_from_mrp(product_mrp_area.product_id, mrp_area): + continue + init_counter += 1 + log_msg = f"MRP Init: {init_counter} - {product_mrp_area.display_name} " + logger.info(log_msg) + self._init_mrp_move(product_mrp_area) + logger.info("End MRP initialisation") + + def _get_qty_to_order(self, product_mrp_area, date, move_qty, onhand): + """Compute the qty to order at a given date, for a product MRP area, given an + mrp.move quantity and an onhand quantity. + + This method is an extension point, allowing a new module to change the way this + quantity should be computed. + """ + # The default rule is to resupply to rebuild the safety stock + return product_mrp_area.mrp_minimum_stock - onhand - move_qty + + @api.model + def _init_mrp_move_grouped_demand(self, product_mrp_area): + last_date = None + last_qty = 0.00 + onhand = ( + 0.0 + if product_mrp_area.supply_method == "phantom" + else product_mrp_area.qty_available + ) + grouping_delta = product_mrp_area.mrp_nbr_days + demand_origin = [] + + if ( + product_mrp_area.mrp_move_ids + and onhand < product_mrp_area.mrp_minimum_stock + ): + last_date = self._get_safety_stock_target_date(product_mrp_area) + demand_origin.append("Safety Stock") + move = fields.first(product_mrp_area.mrp_move_ids) + if last_date and ( + fields.Date.from_string(move.mrp_date) + >= last_date + timedelta(days=grouping_delta) + ): + name = _("Safety Stock") + origin = ",".join(list({x for x in demand_origin if x})) + qtytoorder = self._get_qty_to_order( + product_mrp_area, last_date, 0, onhand + ) + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=last_date, + mrp_qty=qtytoorder, + name=name, + values=dict(origin=origin), + ) + qty_ordered = cm.get("qty_ordered", 0.0) + onhand = onhand + qty_ordered + last_date = None + last_qty = 0.00 + demand_origin = [] + + for move in product_mrp_area.mrp_move_ids: + if self._exclude_move(move): + continue + if ( + last_date + and ( + fields.Date.from_string(move.mrp_date) + >= last_date + timedelta(days=grouping_delta) + ) + and ( + (onhand + last_qty + move.mrp_qty) + < product_mrp_area.mrp_minimum_stock + or (onhand + last_qty) < product_mrp_area.mrp_minimum_stock + ) + ): + name = _( + "Grouped Demand of %(product_name)s for %(delta_days)d Days" + ) % dict( + product_name=product_mrp_area.product_id.display_name, + delta_days=grouping_delta, + ) + origin = ",".join(list({x for x in demand_origin if x})) + qtytoorder = self._get_qty_to_order( + product_mrp_area, last_date, last_qty, onhand + ) + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=last_date, + mrp_qty=qtytoorder, + name=name, + values=dict(origin=origin), + ) + qty_ordered = cm.get("qty_ordered", 0.0) + onhand = onhand + last_qty + qty_ordered + last_date = None + last_qty = 0.00 + demand_origin = [] + if ( + onhand + last_qty + move.mrp_qty + ) < product_mrp_area.mrp_minimum_stock or ( + onhand + last_qty + ) < product_mrp_area.mrp_minimum_stock: + if not last_date: + last_date = fields.Date.from_string(move.mrp_date) + last_qty = move.mrp_qty + else: + last_qty += move.mrp_qty + else: + last_date = fields.Date.from_string(move.mrp_date) + onhand += move.mrp_qty + if move.mrp_type == "d": + demand_origin.append(move.origin or move.name) + + if last_date and last_qty != 0.00: + name = _( + "Grouped Demand of %(product_name)s for %(delta_days)d Days" + ) % dict( + product_name=product_mrp_area.product_id.display_name, + delta_days=grouping_delta, + ) + origin = ",".join(list({x for x in demand_origin if x})) + qtytoorder = self._get_qty_to_order( + product_mrp_area, last_date, last_qty, onhand + ) + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=last_date, + mrp_qty=qtytoorder, + name=name, + values=dict(origin=origin), + ) + qty_ordered = cm.get("qty_ordered", 0.0) + onhand += qty_ordered + last_qty -= qty_ordered + + if (onhand + last_qty) < product_mrp_area.mrp_minimum_stock: + mrp_date = self._get_safety_stock_target_date(product_mrp_area) + qtytoorder = self._get_qty_to_order(product_mrp_area, mrp_date, 0, onhand) + name = _("Safety Stock") + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=mrp_date, + mrp_qty=qtytoorder, + name=name, + values=dict(origin=name), + ) + qty_ordered = cm["qty_ordered"] + onhand += qty_ordered + + def _get_safety_stock_target_date(self, product_mrp_area): + """Get the date at which the safety stock rebuild should be targeted + + This method is an extension point for modules who need to cusomize that date.""" + return date.today() + + @api.model + def _init_mrp_move_non_grouped_demand(self, product_mrp_area): + onhand = ( + 0.0 + if product_mrp_area.supply_method == "phantom" + else product_mrp_area.qty_available + ) + for move in product_mrp_area.mrp_move_ids: + if self._exclude_move(move): + continue + # This works because mrp moves are ordered by: + # product_mrp_area_id, mrp_date, mrp_type desc, id + if onhand + move.mrp_qty < product_mrp_area.mrp_minimum_stock: + qtytoorder = self._get_qty_to_order( + product_mrp_area, + self._get_safety_stock_target_date(product_mrp_area), + 0, + onhand, + ) + name = _("Safety Stock") + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=self._get_safety_stock_target_date(product_mrp_area), + mrp_qty=qtytoorder, + name=name, + values=dict(origin=name), + ) + qty_ordered = cm["qty_ordered"] + onhand += qty_ordered + + qtytoorder = self._get_qty_to_order( + product_mrp_area, move.mrp_date, move.mrp_qty, onhand + ) + if qtytoorder > 0.0: + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=move.mrp_date, + mrp_qty=qtytoorder, + name=move.name or "", + values=dict(origin=move.origin or ""), + ) + qty_ordered = cm["qty_ordered"] + onhand += move.mrp_qty + qty_ordered + else: + onhand += move.mrp_qty + if onhand < product_mrp_area.mrp_minimum_stock: + mrp_date = self._get_safety_stock_target_date(product_mrp_area) + qtytoorder = self._get_qty_to_order(product_mrp_area, mrp_date, 0, onhand) + name = _("Safety Stock") + cm = self.create_action( + product_mrp_area_id=product_mrp_area, + mrp_date=mrp_date, + mrp_qty=qtytoorder, + name=name, + values=dict(origin=name), + ) + qty_ordered = cm["qty_ordered"] + onhand += qty_ordered + + @api.model + def _exclude_move(self, move): + """Improve extensibility being able to exclude special moves.""" + return False + + def _get_mrp_initialization_groups_of_params(self, mrp_lowest_llc, mrp_areas): + product_mrp_area_obj = self.env["product.mrp.area"] + groups = {} + for mrp_area in mrp_areas: + llc = 0 + while mrp_lowest_llc > llc: + groups[mrp_area, llc] = product_mrp_area_obj.search( + [("product_id.llc", "=", llc), ("mrp_area_id", "=", mrp_area.id)] + ) + llc += 1 + return groups + + @api.model + def _mrp_calculation(self, mrp_lowest_llc, mrp_areas): + logger.info("Start MRP calculation") + if not mrp_areas: + mrp_areas = self.env["mrp.area"].search([]) + keyed_groups = self._get_mrp_initialization_groups_of_params( + mrp_lowest_llc, mrp_areas + ) + for (mrp_area, llc), product_mrp_areas in keyed_groups.items(): + counter = 0 + for product_mrp_area in product_mrp_areas: + if product_mrp_area.mrp_nbr_days == 0: + self._init_mrp_move_non_grouped_demand(product_mrp_area) + else: + self._init_mrp_move_grouped_demand(product_mrp_area) + counter += 1 + + log_msg = ( + f"MRP Calculation LLC {llc} at {mrp_area.name} Finished " + "- Nbr. products: {counter}" + ) + logger.info(log_msg) + + logger.info("End MRP calculation") + + @api.model + def _get_demand_groups(self, product_mrp_area): + query = """ + SELECT mrp_date, sum(mrp_qty) + FROM mrp_move + WHERE product_mrp_area_id = %(mrp_product)s + AND mrp_type = 'd' + GROUP BY mrp_date + """ + params = {"mrp_product": product_mrp_area.id} + return query, params + + @api.model + def _get_supply_groups(self, product_mrp_area): + query = """ + SELECT mrp_date, sum(mrp_qty) + FROM mrp_move + WHERE product_mrp_area_id = %(mrp_product)s + AND mrp_type = 's' + GROUP BY mrp_date + """ + params = {"mrp_product": product_mrp_area.id} + return query, params + + @api.model + def _get_planned_order_groups(self, product_mrp_area): + query = """ + SELECT due_date, sum(mrp_qty) + FROM mrp_planned_order + WHERE product_mrp_area_id = %(mrp_product)s + GROUP BY due_date + """ + params = {"mrp_product": product_mrp_area.id} + return query, params + + @api.model + def _prepare_mrp_inventory_data( + self, + product_mrp_area, + mdt, + on_hand_qty, + running_availability, + demand_qty_by_date, + supply_qty_by_date, + planned_qty_by_date, + ): + """Return dict to create mrp.inventory records on MRP Multi Level Scheduler""" + mrp_inventory_data = {"product_mrp_area_id": product_mrp_area.id, "date": mdt} + demand_qty = demand_qty_by_date.get(mdt, 0.0) + mrp_inventory_data["demand_qty"] = abs(demand_qty) + supply_qty = supply_qty_by_date.get(mdt, 0.0) + mrp_inventory_data["supply_qty"] = abs(supply_qty) + mrp_inventory_data["initial_on_hand_qty"] = on_hand_qty + if product_mrp_area.supply_method != "phantom": + on_hand_qty += supply_qty + demand_qty + mrp_inventory_data["final_on_hand_qty"] = on_hand_qty + # Consider that MRP plan is followed exactly: + running_availability += ( + supply_qty + demand_qty + planned_qty_by_date.get(mdt, 0.0) + ) + mrp_inventory_data["running_availability"] = running_availability + return mrp_inventory_data, running_availability, on_hand_qty + + @api.model + def _init_mrp_inventory(self, product_mrp_area): + mrp_move_obj = self.env["mrp.move"] + planned_order_obj = self.env["mrp.planned.order"] + # Read Demand + demand_qty_by_date = {} + query, params = self._get_demand_groups(product_mrp_area) + self.env.cr.execute(query, params) + for mrp_date, qty in self.env.cr.fetchall(): + demand_qty_by_date[mrp_date] = qty + # Read Supply + supply_qty_by_date = {} + query, params = self._get_supply_groups(product_mrp_area) + self.env.cr.execute(query, params) + for mrp_date, qty in self.env.cr.fetchall(): + supply_qty_by_date[mrp_date] = qty + # Read planned orders: + planned_qty_by_date = {} + query, params = self._get_planned_order_groups(product_mrp_area) + self.env.cr.execute(query, params) + for mrp_date, qty in self.env.cr.fetchall(): + planned_qty_by_date[mrp_date] = qty + # Dates + moves_dates = mrp_move_obj.search( + [("product_mrp_area_id", "=", product_mrp_area.id)], order="mrp_date" + ).mapped("mrp_date") + action_dates = planned_order_obj.search( + [("product_mrp_area_id", "=", product_mrp_area.id)], order="due_date" + ).mapped("due_date") + mrp_dates = set(moves_dates + action_dates) + on_hand_qty = ( + 0.0 + if product_mrp_area.supply_method == "phantom" + else product_mrp_area.qty_available + ) + running_availability = on_hand_qty + mrp_inventory_vals = [] + for mdt in sorted(mrp_dates): + ( + mrp_inventory_data, + running_availability, + on_hand_qty, + ) = self._prepare_mrp_inventory_data( + product_mrp_area, + mdt, + on_hand_qty, + running_availability, + demand_qty_by_date, + supply_qty_by_date, + planned_qty_by_date, + ) + mrp_inventory_vals.append(mrp_inventory_data) + if mrp_inventory_vals: + mrp_invs = self.env["mrp.inventory"].create(mrp_inventory_vals) + planned_orders = planned_order_obj.search( + [("product_mrp_area_id", "=", product_mrp_area.id)] + ) + # attach planned orders to inventory + for po in planned_orders: + invs = mrp_invs.filtered(lambda i, po=po: i.date == po.due_date) + if invs: + po.mrp_inventory_id = invs[0] + + def should_build_time_phased_inventory(self, product_mrp_area): + return not ( + self._exclude_from_mrp( + product_mrp_area.product_id, product_mrp_area.mrp_area_id + ) + or product_mrp_area.supply_method == "phantom" + ) + + @api.model + def _mrp_final_process(self, mrp_areas): + logger.info("Start MRP final process") + domain = [("product_id.llc", "<", 9999)] + if mrp_areas: + domain += [("mrp_area_id", "in", mrp_areas.ids)] + product_mrp_area_ids = self.env["product.mrp.area"].search(domain) + + for product_mrp_area in product_mrp_area_ids: + # Build the time-phased inventory + if not self.should_build_time_phased_inventory(product_mrp_area): + continue + self._init_mrp_inventory(product_mrp_area) + logger.info("End MRP final process") + + def run_mrp_multi_level(self): + self._mrp_cleanup(self.mrp_area_ids) + mrp_lowest_llc = self._low_level_code_calculation() + self._calculate_mrp_applicable(self.mrp_area_ids) + self._mrp_initialisation(self.mrp_area_ids) + self._mrp_calculation(mrp_lowest_llc, self.mrp_area_ids) + self._mrp_final_process(self.mrp_area_ids) + # Open MRP inventory screen to show result if manually run: + # Done as sudo to allow non-admin users to read the action. + action = self.env.ref("mrp_multi_level.mrp_inventory_action") + result = action.sudo().read()[0] + return result diff --git a/mrp_multi_level/wizards/mrp_multi_level_views.xml b/mrp_multi_level/wizards/mrp_multi_level_views.xml new file mode 100644 index 000000000..064b3077f --- /dev/null +++ b/mrp_multi_level/wizards/mrp_multi_level_views.xml @@ -0,0 +1,35 @@ + + + + Run MRP + mrp.multi.level + +
+ + + +
+
+
+
+
+ + + Run MRP + mrp.multi.level + form + new + + +