mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[12.0][MIG] mrp_multi_level:
* You can know integrate with different forecasting mechanisms. As a consequence integration with stock_demand_estimate is moved to a new module (mrp_multi_level_estimate). * As agreed by the authors, the module is re-licensed to LGPL-3.
This commit is contained in:
@@ -10,17 +10,17 @@ MRP Multi Level
|
|||||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||||
:target: https://odoo-community.org/page/development-status
|
:target: https://odoo-community.org/page/development-status
|
||||||
:alt: Beta
|
:alt: Beta
|
||||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
|
||||||
:alt: License: AGPL-3
|
:alt: License: LGPL-3
|
||||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
|
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
|
||||||
:target: https://github.com/OCA/manufacture/tree/11.0/mrp_multi_level
|
:target: https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level
|
||||||
:alt: OCA/manufacture
|
:alt: OCA/manufacture
|
||||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||||
:target: https://translation.odoo-community.org/projects/manufacture-11-0/manufacture-11-0-mrp_multi_level
|
:target: https://translation.odoo-community.org/projects/manufacture-12-0/manufacture-12-0-mrp_multi_level
|
||||||
:alt: Translate me on Weblate
|
:alt: Translate me on Weblate
|
||||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||||
:target: https://runbot.odoo-community.org/runbot/129/11.0
|
:target: https://runbot.odoo-community.org/runbot/129/12.0
|
||||||
:alt: Try me on Runbot
|
:alt: Try me on Runbot
|
||||||
|
|
||||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||||
@@ -36,11 +36,12 @@ Key Features
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* MRP parameters set by product variant MRP area pairs.
|
* MRP parameters set by product variant MRP area pairs.
|
||||||
* Integration with `Stock Demand Estimates <https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_demand_estimate>`_ system.
|
|
||||||
* Cron job to calculate the MRP demand.
|
* Cron job to calculate the MRP demand.
|
||||||
* Manually calculate the MRP demand.
|
* Manually calculate the MRP demand.
|
||||||
* Confirm the calculated MRP demand and create PO's, or MO's.
|
* 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.
|
* 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>`_.
|
||||||
|
|
||||||
**Table of contents**
|
**Table of contents**
|
||||||
|
|
||||||
@@ -81,6 +82,14 @@ To launch replenishment orders (moves, purchases, production orders...):
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
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)
|
11.0.3.0.0 (2019-05-22)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -138,7 +147,7 @@ Bug Tracker
|
|||||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/manufacture/issues>`_.
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/manufacture/issues>`_.
|
||||||
In case of trouble, please check there if your issue has already been reported.
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||||
`feedback <https://github.com/OCA/manufacture/issues/new?body=module:%20mrp_multi_level%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
`feedback <https://github.com/OCA/manufacture/issues/new?body=module:%20mrp_multi_level%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||||
|
|
||||||
Do not contact contributors directly about support or help with technical issues.
|
Do not contact contributors directly about support or help with technical issues.
|
||||||
|
|
||||||
@@ -182,6 +191,6 @@ Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|
|||||||
|
|
||||||
|maintainer-jbeficent| |maintainer-lreficent|
|
|maintainer-jbeficent| |maintainer-lreficent|
|
||||||
|
|
||||||
This module is part of the `OCA/manufacture <https://github.com/OCA/manufacture/tree/11.0/mrp_multi_level>`_ project on GitHub.
|
This module is part of the `OCA/manufacture <https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level>`_ project on GitHub.
|
||||||
|
|
||||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
# Copyright 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
# Copyright 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
||||||
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'MRP Multi Level',
|
'name': 'MRP Multi Level',
|
||||||
'version': '11.0.3.1.1',
|
'version': '12.0.1.0.0',
|
||||||
'development_status': 'Beta',
|
'development_status': 'Beta',
|
||||||
'license': 'AGPL-3',
|
'license': 'LGPL-3',
|
||||||
'author': 'Ucamco, '
|
'author': 'Ucamco, '
|
||||||
'Eficent, '
|
'Eficent, '
|
||||||
'Odoo Community Association (OCA)',
|
'Odoo Community Association (OCA)',
|
||||||
@@ -15,9 +16,7 @@
|
|||||||
'category': 'Manufacturing',
|
'category': 'Manufacturing',
|
||||||
'depends': [
|
'depends': [
|
||||||
'mrp',
|
'mrp',
|
||||||
'stock',
|
'purchase_stock',
|
||||||
'purchase',
|
|
||||||
'stock_demand_estimate',
|
|
||||||
'mrp_warehouse_calendar',
|
'mrp_warehouse_calendar',
|
||||||
],
|
],
|
||||||
'data': [
|
'data': [
|
||||||
|
|||||||
@@ -6,26 +6,26 @@
|
|||||||
</record>
|
</record>
|
||||||
<record id="stock_inventory_line_1" model="stock.inventory.line">
|
<record id="stock_inventory_line_1" model="stock.inventory.line">
|
||||||
<field name="product_id" ref="product_product_pp_1"/>
|
<field name="product_id" ref="product_product_pp_1"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
||||||
<field name="product_qty">10</field>
|
<field name="product_qty">10</field>
|
||||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="stock_inventory_line_2" model="stock.inventory.line">
|
<record id="stock_inventory_line_2" model="stock.inventory.line">
|
||||||
<field name="product_id" ref="product_product_pp_2"/>
|
<field name="product_id" ref="product_product_pp_2"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
||||||
<field name="product_qty">20</field>
|
<field name="product_qty">20</field>
|
||||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="stock_inventory_line_3" model="stock.inventory.line">
|
<record id="stock_inventory_line_3" model="stock.inventory.line">
|
||||||
<field name="product_id" ref="product_product_sf_2"/>
|
<field name="product_id" ref="product_product_sf_2"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
<field name="inventory_id" ref="stock_inventory_mrp_example"/>
|
||||||
<field name="product_qty">15</field>
|
<field name="product_qty">15</field>
|
||||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||||
</record>
|
</record>
|
||||||
<function model="stock.inventory" name="action_done">
|
<function model="stock.inventory" name="action_validate">
|
||||||
<function eval="[[('id', '=', ref('stock_inventory_mrp_example'))]]" model="stock.inventory" name="search"/>
|
<function eval="[[('id', '=', ref('stock_inventory_mrp_example'))]]" model="stock.inventory" name="search"/>
|
||||||
</function>
|
</function>
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
<record id="mrp_bom_fp_1" model="mrp.bom">
|
<record id="mrp_bom_fp_1" model="mrp.bom">
|
||||||
<field name="product_tmpl_id"
|
<field name="product_tmpl_id"
|
||||||
ref="product_product_fp_1_product_template"/>
|
ref="product_product_fp_1_product_template"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_fp_1_line_pp_1" model="mrp.bom.line">
|
<record id="mrp_bom_fp_1_line_pp_1" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_pp_1"/>
|
<field name="product_id" ref="product_product_pp_1"/>
|
||||||
<field name="product_qty">2</field>
|
<field name="product_qty">2</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_fp_1"/>
|
<field name="bom_id" ref="mrp_bom_fp_1"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_fp_1_line_pp_2" model="mrp.bom.line">
|
<record id="mrp_bom_fp_1_line_pp_2" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_pp_2"/>
|
<field name="product_id" ref="product_product_pp_2"/>
|
||||||
<field name="product_qty">3</field>
|
<field name="product_qty">3</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_fp_1"/>
|
<field name="bom_id" ref="mrp_bom_fp_1"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -26,20 +26,20 @@
|
|||||||
<record id="mrp_bom_fp_2" model="mrp.bom">
|
<record id="mrp_bom_fp_2" model="mrp.bom">
|
||||||
<field name="product_tmpl_id"
|
<field name="product_tmpl_id"
|
||||||
ref="product_product_fp_2_product_template"/>
|
ref="product_product_fp_2_product_template"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_fp_2_line_sf_1" model="mrp.bom.line">
|
<record id="mrp_bom_fp_2_line_sf_1" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_sf_1"/>
|
<field name="product_id" ref="product_product_sf_1"/>
|
||||||
<field name="product_qty">2</field>
|
<field name="product_qty">2</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_fp_2"/>
|
<field name="bom_id" ref="mrp_bom_fp_2"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_fp_2_line_sf_2" model="mrp.bom.line">
|
<record id="mrp_bom_fp_2_line_sf_2" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_sf_2"/>
|
<field name="product_id" ref="product_product_sf_2"/>
|
||||||
<field name="product_qty">3</field>
|
<field name="product_qty">3</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_fp_2"/>
|
<field name="bom_id" ref="mrp_bom_fp_2"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -47,20 +47,20 @@
|
|||||||
<record id="mrp_bom_sf_1" model="mrp.bom">
|
<record id="mrp_bom_sf_1" model="mrp.bom">
|
||||||
<field name="product_tmpl_id"
|
<field name="product_tmpl_id"
|
||||||
ref="product_product_sf_1_product_template"/>
|
ref="product_product_sf_1_product_template"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_sf_1_line_pp_1" model="mrp.bom.line">
|
<record id="mrp_bom_sf_1_line_pp_1" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_pp_1"/>
|
<field name="product_id" ref="product_product_pp_1"/>
|
||||||
<field name="product_qty">3</field>
|
<field name="product_qty">3</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_sf_1"/>
|
<field name="bom_id" ref="mrp_bom_sf_1"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_sf_1_line_pp_2" model="mrp.bom.line">
|
<record id="mrp_bom_sf_1_line_pp_2" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_pp_2"/>
|
<field name="product_id" ref="product_product_pp_2"/>
|
||||||
<field name="product_qty">2</field>
|
<field name="product_qty">2</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_sf_1"/>
|
<field name="bom_id" ref="mrp_bom_sf_1"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -68,13 +68,13 @@
|
|||||||
<record id="mrp_bom_sf_2" model="mrp.bom">
|
<record id="mrp_bom_sf_2" model="mrp.bom">
|
||||||
<field name="product_tmpl_id"
|
<field name="product_tmpl_id"
|
||||||
ref="product_product_sf_2_product_template"/>
|
ref="product_product_sf_2_product_template"/>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="mrp_bom_sf_2_line_pp_2" model="mrp.bom.line">
|
<record id="mrp_bom_sf_2_line_pp_2" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_pp_2"/>
|
<field name="product_id" ref="product_product_pp_2"/>
|
||||||
<field name="product_qty">3</field>
|
<field name="product_qty">3</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp_bom_sf_2"/>
|
<field name="bom_id" ref="mrp_bom_sf_2"/>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<field name="name">FP-1</field>
|
<field name="name">FP-1</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="produce_delay">2</field>
|
<field name="produce_delay">2</field>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
<field name="name">FP-2</field>
|
<field name="name">FP-2</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="produce_delay">1</field>
|
<field name="produce_delay">1</field>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
<field name="name">SF-1</field>
|
<field name="name">SF-1</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="produce_delay">1</field>
|
<field name="produce_delay">1</field>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
<field name="name">SF-2</field>
|
<field name="name">SF-2</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="produce_delay">3</field>
|
<field name="produce_delay">3</field>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('mrp.route_warehouse0_manufacture')])]"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -43,17 +43,17 @@
|
|||||||
<field name="name">PP-1</field>
|
<field name="name">PP-1</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('purchase.route_warehouse0_buy')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('purchase_stock.route_warehouse0_buy')])]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="product_product_pp_2" model="product.product">
|
<record id="product_product_pp_2" model="product.product">
|
||||||
<field name="name">PP-2</field>
|
<field name="name">PP-2</field>
|
||||||
<field name="categ_id" ref="product_category_mrp"/>
|
<field name="categ_id" ref="product_category_mrp"/>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="route_ids" eval="[(6, 0, [ref('purchase.route_warehouse0_buy')])]"/>
|
<field name="route_ids" eval="[(6, 0, [ref('purchase_stock.route_warehouse0_buy')])]"/>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2019 Eficent Business and IT Consulting Services, S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
import logging
|
import logging
|
||||||
from odoo import api, SUPERUSER_ID
|
from odoo import api, SUPERUSER_ID
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
# © 2016-19 Eficent Business and IT Consulting Services S.L.
|
# © 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||||
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class MrpArea(models.Model):
|
class MrpArea(models.Model):
|
||||||
_name = 'mrp.area'
|
_name = 'mrp.area'
|
||||||
|
_description = "MRP Area"
|
||||||
|
|
||||||
name = fields.Char(required=True)
|
name = fields.Char(required=True)
|
||||||
warehouse_id = fields.Many2one(
|
warehouse_id = fields.Many2one(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||||
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ class MrpInventory(models.Model):
|
|||||||
store=True,
|
store=True,
|
||||||
)
|
)
|
||||||
uom_id = fields.Many2one(
|
uom_id = fields.Many2one(
|
||||||
comodel_name='product.uom', string='Product UoM',
|
comodel_name='uom.uom', string='Product UoM',
|
||||||
compute='_compute_uom_id',
|
compute='_compute_uom_id',
|
||||||
)
|
)
|
||||||
date = fields.Date(string='Date')
|
date = fields.Date(string='Date')
|
||||||
@@ -84,9 +84,11 @@ class MrpInventory(models.Model):
|
|||||||
for rec in self.filtered(lambda r: r.date):
|
for rec in self.filtered(lambda r: r.date):
|
||||||
delay = rec.product_mrp_area_id.mrp_lead_time
|
delay = rec.product_mrp_area_id.mrp_lead_time
|
||||||
if delay and rec.mrp_area_id.calendar_id:
|
if delay and rec.mrp_area_id.calendar_id:
|
||||||
dt_date = fields.Datetime.from_string(rec.date)
|
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(
|
order_release_date = rec.mrp_area_id.calendar_id.plan_days(
|
||||||
-delay - 1, dt_date).date()
|
-delay, dt_date).date()
|
||||||
else:
|
else:
|
||||||
order_release_date = fields.Date.from_string(
|
order_release_date = fields.Date.from_string(
|
||||||
rec.date) - timedelta(days=delay)
|
rec.date) - timedelta(days=delay)
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
||||||
# © 2016-18 Eficent Business and IT Consulting Services S.L.
|
# © 2016-18 Eficent Business and IT Consulting Services S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import models, fields
|
from odoo import models, fields
|
||||||
|
|
||||||
|
|
||||||
class MrpMove(models.Model):
|
class MrpMove(models.Model):
|
||||||
_name = 'mrp.move'
|
_name = 'mrp.move'
|
||||||
|
_description = "MRP Move"
|
||||||
_order = 'product_mrp_area_id, mrp_date, mrp_type desc, id'
|
_order = 'product_mrp_area_id, mrp_date, mrp_type desc, id'
|
||||||
|
|
||||||
# TODO: too many indexes...
|
# TODO: too many indexes...
|
||||||
|
|
||||||
product_mrp_area_id = fields.Many2one(
|
product_mrp_area_id = fields.Many2one(
|
||||||
comodel_name="product.mrp.area",
|
comodel_name="product.mrp.area",
|
||||||
string="Product", index=True,
|
string="Product MRP Area",
|
||||||
|
index=True,
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
mrp_area_id = fields.Many2one(
|
mrp_area_id = fields.Many2one(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Copyright 2019 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2019 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import models, fields
|
from odoo import models, fields
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ class MrpPlannedOrder(models.Model):
|
|||||||
name = fields.Char(string="Description")
|
name = fields.Char(string="Description")
|
||||||
product_mrp_area_id = fields.Many2one(
|
product_mrp_area_id = fields.Many2one(
|
||||||
comodel_name="product.mrp.area",
|
comodel_name="product.mrp.area",
|
||||||
string="Product",
|
string="Product MRP Area",
|
||||||
index=True,
|
index=True,
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
@@ -52,7 +52,9 @@ class MrpPlannedOrder(models.Model):
|
|||||||
mrp_action = fields.Selection(
|
mrp_action = fields.Selection(
|
||||||
selection=[("manufacture", "Manufacturing Order"),
|
selection=[("manufacture", "Manufacturing Order"),
|
||||||
("buy", "Purchase Order"),
|
("buy", "Purchase Order"),
|
||||||
("move", "Transfer"),
|
('pull', 'Pull From'),
|
||||||
|
('push', 'Push To'),
|
||||||
|
('pull_push', 'Pull & Push'),
|
||||||
("none", "None")],
|
("none", "None")],
|
||||||
string="Action",
|
string="Action",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||||
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
# - Lois Rilo Antelo <lois.rilo@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
||||||
@@ -80,11 +80,12 @@ class ProductMRPArea(models.Model):
|
|||||||
selection=[('buy', 'Buy'),
|
selection=[('buy', 'Buy'),
|
||||||
('none', 'Undefined'),
|
('none', 'Undefined'),
|
||||||
('manufacture', 'Produce'),
|
('manufacture', 'Produce'),
|
||||||
('move', 'Transfer')],
|
('pull', 'Pull From'),
|
||||||
|
('push', 'Push To'),
|
||||||
|
('pull_push', 'Pull & Push')],
|
||||||
string='Supply Method',
|
string='Supply Method',
|
||||||
compute='_compute_supply_method',
|
compute='_compute_supply_method',
|
||||||
)
|
)
|
||||||
|
|
||||||
qty_available = fields.Float(
|
qty_available = fields.Float(
|
||||||
string="Quantity Available",
|
string="Quantity Available",
|
||||||
compute="_compute_qty_available",
|
compute="_compute_qty_available",
|
||||||
@@ -99,10 +100,7 @@ class ProductMRPArea(models.Model):
|
|||||||
inverse_name="product_mrp_area_id",
|
inverse_name="product_mrp_area_id",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
group_estimate_days = fields.Integer(
|
|
||||||
string="Group Days of Estimates",
|
|
||||||
default=1,
|
|
||||||
)
|
|
||||||
_sql_constraints = [
|
_sql_constraints = [
|
||||||
('product_mrp_area_uniq', 'unique(product_id, mrp_area_id)',
|
('product_mrp_area_uniq', 'unique(product_id, mrp_area_id)',
|
||||||
'The product/MRP Area parameters combination must be unique.'),
|
'The product/MRP Area parameters combination must be unique.'),
|
||||||
@@ -111,13 +109,12 @@ class ProductMRPArea(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
@api.constrains(
|
@api.constrains(
|
||||||
"mrp_minimum_order_qty", "mrp_maximum_order_qty", "mrp_qty_multiple",
|
"mrp_minimum_order_qty", "mrp_maximum_order_qty", "mrp_qty_multiple",
|
||||||
"mrp_minimum_stock", "mrp_nbr_days", "group_estimate_days",
|
"mrp_minimum_stock", "mrp_nbr_days",
|
||||||
)
|
)
|
||||||
def _check_negatives(self):
|
def _check_negatives(self):
|
||||||
values = self.read([
|
values = self.read([
|
||||||
"mrp_minimum_order_qty", "mrp_maximum_order_qty",
|
"mrp_minimum_order_qty", "mrp_maximum_order_qty",
|
||||||
"mrp_qty_multiple",
|
"mrp_qty_multiple", "mrp_minimum_stock", "mrp_nbr_days",
|
||||||
"mrp_minimum_stock", "mrp_nbr_days", "group_estimate_days",
|
|
||||||
])
|
])
|
||||||
for rec in values:
|
for rec in values:
|
||||||
if any(v < 0 for v in rec.values()):
|
if any(v < 0 for v in rec.values()):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Copyright 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
# Copyright 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
||||||
# Copyright 2016-18 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2016-18 Eficent Business and IT Consulting Services S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
import ast
|
import ast
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
import ast
|
import ast
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
|
||||||
# © 2016 Eficent Business and IT Consulting Services S.L.
|
# © 2016 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import fields, models
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ Key Features
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* MRP parameters set by product variant MRP area pairs.
|
* MRP parameters set by product variant MRP area pairs.
|
||||||
* Integration with `Stock Demand Estimates <https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_demand_estimate>`_ system.
|
|
||||||
* Cron job to calculate the MRP demand.
|
* Cron job to calculate the MRP demand.
|
||||||
* Manually calculate the MRP demand.
|
* Manually calculate the MRP demand.
|
||||||
* Confirm the calculated MRP demand and create PO's, or MO's.
|
* 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.
|
* 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>`_.
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
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)
|
11.0.3.0.0 (2019-05-22)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
<meta name="generator" content="Docutils 0.15.2: http://docutils.sourceforge.net/" />
|
||||||
<title>MRP Multi Level</title>
|
<title>MRP Multi Level</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ ul.auto-toc {
|
|||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/manufacture/tree/11.0/mrp_multi_level"><img alt="OCA/manufacture" src="https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/manufacture-11-0/manufacture-11-0-mrp_multi_level"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/129/11.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level"><img alt="OCA/manufacture" src="https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/manufacture-12-0/manufacture-12-0-mrp_multi_level"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/129/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||||
<p>This module allows you to calculate, based in known inventory, demand, and
|
<p>This module allows you to calculate, based in known inventory, demand, and
|
||||||
supply, and based on parameters set at product variant level, the new
|
supply, and based on parameters set at product variant level, the new
|
||||||
procurements for each product.</p>
|
procurements for each product.</p>
|
||||||
@@ -377,51 +377,53 @@ and explodes this down to the lowest level.</p>
|
|||||||
<h1>Key Features</h1>
|
<h1>Key Features</h1>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>MRP parameters set by product variant MRP area pairs.</li>
|
<li>MRP parameters set by product variant MRP area pairs.</li>
|
||||||
<li>Integration with <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_demand_estimate">Stock Demand Estimates</a> system.</li>
|
|
||||||
<li>Cron job to calculate the MRP demand.</li>
|
<li>Cron job to calculate the MRP demand.</li>
|
||||||
<li>Manually calculate the MRP demand.</li>
|
<li>Manually calculate the MRP demand.</li>
|
||||||
<li>Confirm the calculated MRP demand and create PO’s, or MO’s.</li>
|
<li>Confirm the calculated MRP demand and create PO’s, or MO’s.</li>
|
||||||
<li>Able to see the products for which action is needed throught Planned Orders.</li>
|
<li>Able to see the products for which action is needed throught Planned Orders.</li>
|
||||||
|
<li>Integration with <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_demand_estimate">Stock Demand Estimates</a> system.
|
||||||
|
Note: You need to install <a class="reference external" href="https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level_estimate">mrp_multi_level_estimate module</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><strong>Table of contents</strong></p>
|
<p><strong>Table of contents</strong></p>
|
||||||
<div class="contents local topic" id="contents">
|
<div class="contents local topic" id="contents">
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li><a class="reference internal" href="#configuration" id="id14">Configuration</a><ul>
|
<li><a class="reference internal" href="#configuration" id="id15">Configuration</a><ul>
|
||||||
<li><a class="reference internal" href="#mrp-areas" id="id15">MRP Areas</a></li>
|
<li><a class="reference internal" href="#mrp-areas" id="id16">MRP Areas</a></li>
|
||||||
<li><a class="reference internal" href="#product-mrp-area-parameters" id="id16">Product MRP Area Parameters</a></li>
|
<li><a class="reference internal" href="#product-mrp-area-parameters" id="id17">Product MRP Area Parameters</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference internal" href="#usage" id="id17">Usage</a></li>
|
<li><a class="reference internal" href="#usage" id="id18">Usage</a></li>
|
||||||
<li><a class="reference internal" href="#changelog" id="id18">Changelog</a><ul>
|
<li><a class="reference internal" href="#changelog" id="id19">Changelog</a><ul>
|
||||||
<li><a class="reference internal" href="#id1" id="id19">11.0.3.0.0 (2019-05-22)</a></li>
|
<li><a class="reference internal" href="#id1" id="id20">12.0.1.0.0 (2019-08-05)</a></li>
|
||||||
<li><a class="reference internal" href="#id3" id="id20">11.0.2.2.0 (2019-05-02)</a></li>
|
<li><a class="reference internal" href="#id2" id="id21">11.0.3.0.0 (2019-05-22)</a></li>
|
||||||
<li><a class="reference internal" href="#id5" id="id21">11.0.2.1.0 (2019-04-02)</a></li>
|
<li><a class="reference internal" href="#id4" id="id22">11.0.2.2.0 (2019-05-02)</a></li>
|
||||||
<li><a class="reference internal" href="#id7" id="id22">11.0.2.0.0 (2018-11-20)</a></li>
|
<li><a class="reference internal" href="#id6" id="id23">11.0.2.1.0 (2019-04-02)</a></li>
|
||||||
<li><a class="reference internal" href="#id9" id="id23">11.0.1.1.0 (2018-08-30)</a></li>
|
<li><a class="reference internal" href="#id8" id="id24">11.0.2.0.0 (2018-11-20)</a></li>
|
||||||
<li><a class="reference internal" href="#id11" id="id24">11.0.1.0.1 (2018-08-03)</a></li>
|
<li><a class="reference internal" href="#id10" id="id25">11.0.1.1.0 (2018-08-30)</a></li>
|
||||||
<li><a class="reference internal" href="#id13" id="id25">11.0.1.0.0 (2018-07-09)</a></li>
|
<li><a class="reference internal" href="#id12" id="id26">11.0.1.0.1 (2018-08-03)</a></li>
|
||||||
|
<li><a class="reference internal" href="#id14" id="id27">11.0.1.0.0 (2018-07-09)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference internal" href="#bug-tracker" id="id26">Bug Tracker</a></li>
|
<li><a class="reference internal" href="#bug-tracker" id="id28">Bug Tracker</a></li>
|
||||||
<li><a class="reference internal" href="#credits" id="id27">Credits</a><ul>
|
<li><a class="reference internal" href="#credits" id="id29">Credits</a><ul>
|
||||||
<li><a class="reference internal" href="#authors" id="id28">Authors</a></li>
|
<li><a class="reference internal" href="#authors" id="id30">Authors</a></li>
|
||||||
<li><a class="reference internal" href="#contributors" id="id29">Contributors</a></li>
|
<li><a class="reference internal" href="#contributors" id="id31">Contributors</a></li>
|
||||||
<li><a class="reference internal" href="#maintainers" id="id30">Maintainers</a></li>
|
<li><a class="reference internal" href="#maintainers" id="id32">Maintainers</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="configuration">
|
<div class="section" id="configuration">
|
||||||
<h2><a class="toc-backref" href="#id14">Configuration</a></h2>
|
<h2><a class="toc-backref" href="#id15">Configuration</a></h2>
|
||||||
<div class="section" id="mrp-areas">
|
<div class="section" id="mrp-areas">
|
||||||
<h3><a class="toc-backref" href="#id15">MRP Areas</a></h3>
|
<h3><a class="toc-backref" href="#id16">MRP Areas</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Go to <em>Manufacturing > Configuration > MRP Areas</em> and define or edit
|
<li>Go to <em>Manufacturing > Configuration > MRP Areas</em> and define or edit
|
||||||
any existing area. You can specify the working hours for every area.</li>
|
any existing area. You can specify the working hours for every area.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="product-mrp-area-parameters">
|
<div class="section" id="product-mrp-area-parameters">
|
||||||
<h3><a class="toc-backref" href="#id16">Product MRP Area Parameters</a></h3>
|
<h3><a class="toc-backref" href="#id17">Product MRP Area Parameters</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Go to <em>Manufacturing > Master Data > Product MRP Area Parameters</em> and set
|
<li>Go to <em>Manufacturing > Master Data > Product MRP Area Parameters</em> and set
|
||||||
the MRP parameters for a given product and area.</li>
|
the MRP parameters for a given product and area.</li>
|
||||||
@@ -429,7 +431,7 @@ the MRP parameters for a given product and area.</li>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="usage">
|
<div class="section" id="usage">
|
||||||
<h2><a class="toc-backref" href="#id17">Usage</a></h2>
|
<h2><a class="toc-backref" href="#id18">Usage</a></h2>
|
||||||
<p>To manually run the MRP scheduler:</p>
|
<p>To manually run the MRP scheduler:</p>
|
||||||
<ol class="arabic simple">
|
<ol class="arabic simple">
|
||||||
<li>Go to <em>Manufacturing > Operations > Run MRP Multi Level</em>.</li>
|
<li>Go to <em>Manufacturing > Operations > Run MRP Multi Level</em>.</li>
|
||||||
@@ -445,32 +447,42 @@ hand side gears in any record.</li>
|
|||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="changelog">
|
<div class="section" id="changelog">
|
||||||
<h2><a class="toc-backref" href="#id18">Changelog</a></h2>
|
<h2><a class="toc-backref" href="#id19">Changelog</a></h2>
|
||||||
<div class="section" id="id1">
|
<div class="section" id="id1">
|
||||||
<h3><a class="toc-backref" href="#id19">11.0.3.0.0 (2019-05-22)</a></h3>
|
<h3><a class="toc-backref" href="#id20">12.0.1.0.0 (2019-08-05)</a></h3>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>[MIG] Migration to v12:<ul>
|
||||||
|
<li>Estimates as a forecasting mechanism is moved to a new module
|
||||||
|
(mrp_multi_level_estimate).</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="id2">
|
||||||
|
<h3><a class="toc-backref" href="#id21">11.0.3.0.0 (2019-05-22)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[REW/IMP] Rework to include Planned Orders.
|
<li>[REW/IMP] Rework to include Planned Orders.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/365">#365</a>).</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/365">#365</a>).</li>
|
||||||
<li>[IMP] Able to procure from a different location than the area’s location.</li>
|
<li>[IMP] Able to procure from a different location than the area’s location.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id3">
|
<div class="section" id="id4">
|
||||||
<h3><a class="toc-backref" href="#id20">11.0.2.2.0 (2019-05-02)</a></h3>
|
<h3><a class="toc-backref" href="#id22">11.0.2.2.0 (2019-05-02)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[IMP] Able to run MRP only for selected areas.
|
<li>[IMP] Able to run MRP only for selected areas.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/360">#360</a>).</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/360">#360</a>).</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id5">
|
<div class="section" id="id6">
|
||||||
<h3><a class="toc-backref" href="#id21">11.0.2.1.0 (2019-04-02)</a></h3>
|
<h3><a class="toc-backref" href="#id23">11.0.2.1.0 (2019-04-02)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[IMP] Implement <em>Nbr. Days</em> functionality to be able to group demand when
|
<li>[IMP] Implement <em>Nbr. Days</em> functionality to be able to group demand when
|
||||||
generating supply proposals.
|
generating supply proposals.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/345">#345</a>).</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/345">#345</a>).</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id7">
|
<div class="section" id="id8">
|
||||||
<h3><a class="toc-backref" href="#id22">11.0.2.0.0 (2018-11-20)</a></h3>
|
<h3><a class="toc-backref" href="#id24">11.0.2.0.0 (2018-11-20)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[REW] Refactor MRP Area.
|
<li>[REW] Refactor MRP Area.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/322">#322</a>):<ul>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/322">#322</a>):<ul>
|
||||||
@@ -482,15 +494,15 @@ different areas.</li>
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id9">
|
<div class="section" id="id10">
|
||||||
<h3><a class="toc-backref" href="#id23">11.0.1.1.0 (2018-08-30)</a></h3>
|
<h3><a class="toc-backref" href="#id25">11.0.1.1.0 (2018-08-30)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[FIX] Consider <em>Qty Multiple</em> on product to propose the quantity to procure.
|
<li>[FIX] Consider <em>Qty Multiple</em> on product to propose the quantity to procure.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/297">#297</a>)</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/297">#297</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id11">
|
<div class="section" id="id12">
|
||||||
<h3><a class="toc-backref" href="#id24">11.0.1.0.1 (2018-08-03)</a></h3>
|
<h3><a class="toc-backref" href="#id26">11.0.1.0.1 (2018-08-03)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>[FIX] User and system locales doesn’t break MRP calculation.
|
<li>[FIX] User and system locales doesn’t break MRP calculation.
|
||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/290">#290</a>)</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/290">#290</a>)</li>
|
||||||
@@ -499,32 +511,32 @@ as a related on MRP Areas.
|
|||||||
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/290">#290</a>)</li>
|
(<a class="reference external" href="https://github.com/OCA/manufacture/pull/290">#290</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="id13">
|
<div class="section" id="id14">
|
||||||
<h3><a class="toc-backref" href="#id25">11.0.1.0.0 (2018-07-09)</a></h3>
|
<h3><a class="toc-backref" href="#id27">11.0.1.0.0 (2018-07-09)</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Start of the history.</li>
|
<li>Start of the history.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="bug-tracker">
|
<div class="section" id="bug-tracker">
|
||||||
<h2><a class="toc-backref" href="#id26">Bug Tracker</a></h2>
|
<h2><a class="toc-backref" href="#id28">Bug Tracker</a></h2>
|
||||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/manufacture/issues">GitHub Issues</a>.
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/manufacture/issues">GitHub Issues</a>.
|
||||||
In case of trouble, please check there if your issue has already been reported.
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||||
<a class="reference external" href="https://github.com/OCA/manufacture/issues/new?body=module:%20mrp_multi_level%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
<a class="reference external" href="https://github.com/OCA/manufacture/issues/new?body=module:%20mrp_multi_level%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="credits">
|
<div class="section" id="credits">
|
||||||
<h2><a class="toc-backref" href="#id27">Credits</a></h2>
|
<h2><a class="toc-backref" href="#id29">Credits</a></h2>
|
||||||
<div class="section" id="authors">
|
<div class="section" id="authors">
|
||||||
<h3><a class="toc-backref" href="#id28">Authors</a></h3>
|
<h3><a class="toc-backref" href="#id30">Authors</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Ucamco</li>
|
<li>Ucamco</li>
|
||||||
<li>Eficent</li>
|
<li>Eficent</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="contributors">
|
<div class="section" id="contributors">
|
||||||
<h3><a class="toc-backref" href="#id29">Contributors</a></h3>
|
<h3><a class="toc-backref" href="#id31">Contributors</a></h3>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Wim Audenaert <<a class="reference external" href="mailto:wim.audenaert@ucamco.com">wim.audenaert@ucamco.com</a>></li>
|
<li>Wim Audenaert <<a class="reference external" href="mailto:wim.audenaert@ucamco.com">wim.audenaert@ucamco.com</a>></li>
|
||||||
<li>Jordi Ballester <<a class="reference external" href="mailto:jordi.ballester@eficent.com">jordi.ballester@eficent.com</a>></li>
|
<li>Jordi Ballester <<a class="reference external" href="mailto:jordi.ballester@eficent.com">jordi.ballester@eficent.com</a>></li>
|
||||||
@@ -532,7 +544,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="maintainers">
|
<div class="section" id="maintainers">
|
||||||
<h3><a class="toc-backref" href="#id30">Maintainers</a></h3>
|
<h3><a class="toc-backref" href="#id32">Maintainers</a></h3>
|
||||||
<p>This module is maintained by the OCA.</p>
|
<p>This module is maintained by the OCA.</p>
|
||||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||||
@@ -540,7 +552,7 @@ mission is to support the collaborative development of Odoo features and
|
|||||||
promote its widespread use.</p>
|
promote its widespread use.</p>
|
||||||
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
|
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
|
||||||
<p><a class="reference external" href="https://github.com/jbeficent"><img alt="jbeficent" src="https://github.com/jbeficent.png?size=40px" /></a> <a class="reference external" href="https://github.com/lreficent"><img alt="lreficent" src="https://github.com/lreficent.png?size=40px" /></a></p>
|
<p><a class="reference external" href="https://github.com/jbeficent"><img alt="jbeficent" src="https://github.com/jbeficent.png?size=40px" /></a> <a class="reference external" href="https://github.com/lreficent"><img alt="lreficent" src="https://github.com/lreficent.png?size=40px" /></a></p>
|
||||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/manufacture/tree/11.0/mrp_multi_level">OCA/manufacture</a> project on GitHub.</p>
|
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/manufacture/tree/12.0/mrp_multi_level">OCA/manufacture</a> project on GitHub.</p>
|
||||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
from . import test_mrp_multi_level
|
from . import test_mrp_multi_level
|
||||||
|
|||||||
284
mrp_multi_level/tests/common.py
Normal file
284
mrp_multi_level/tests/common.py
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
||||||
|
# (http://www.eficent.com)
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from odoo.tests.common import SavepointCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestMrpMultiLevelCommon(SavepointCase):
|
||||||
|
|
||||||
|
@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.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.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.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.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.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.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 products:
|
||||||
|
route_buy = cls.env.ref('purchase_stock.route_warehouse0_buy').id
|
||||||
|
cls.prod_test = cls.product_obj.create({
|
||||||
|
'name': 'Test Top Seller',
|
||||||
|
'type': 'product',
|
||||||
|
'list_price': 150.0,
|
||||||
|
'produce_delay': 5.0,
|
||||||
|
'route_ids': [(6, 0, [route_buy])],
|
||||||
|
'seller_ids': [(0, 0, {'name': 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',
|
||||||
|
'type': 'product',
|
||||||
|
'list_price': 50.0,
|
||||||
|
'route_ids': [(6, 0, [route_buy])],
|
||||||
|
'seller_ids': [(0, 0, {'name': 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',
|
||||||
|
'type': 'product',
|
||||||
|
'list_price': 50.0,
|
||||||
|
'route_ids': [(6, 0, [route_buy])],
|
||||||
|
'seller_ids': [(0, 0, {'name': 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',
|
||||||
|
'type': 'product',
|
||||||
|
'list_price': 50.0,
|
||||||
|
'route_ids': [(6, 0, [route_buy])],
|
||||||
|
'seller_ids': [(0, 0, {'name': 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 test picking for FP-1 and FP-2:
|
||||||
|
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,
|
||||||
|
'move_lines': [
|
||||||
|
(0, 0, {
|
||||||
|
'name': 'Test move fp-1',
|
||||||
|
'product_id': cls.fp_1.id,
|
||||||
|
'date_expected': date_move,
|
||||||
|
'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_expected': date_move,
|
||||||
|
'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
|
||||||
|
})]
|
||||||
|
})
|
||||||
|
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,
|
||||||
|
'move_lines': [
|
||||||
|
(0, 0, {
|
||||||
|
'name': 'Test move prod_min',
|
||||||
|
'product_id': cls.prod_min.id,
|
||||||
|
'date_expected': date_move,
|
||||||
|
'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_expected': date_move,
|
||||||
|
'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_expected': date_move,
|
||||||
|
'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 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.mo_obj.create({
|
||||||
|
'product_id': cls.fp_2.id,
|
||||||
|
'bom_id': bom_fp_2.id,
|
||||||
|
'product_qty': 12.0,
|
||||||
|
'product_uom_id': cls.fp_2.uom_id.id,
|
||||||
|
'date_planned_start': date_mo,
|
||||||
|
})
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
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,
|
||||||
|
"move_lines": [
|
||||||
|
(0, 0, {
|
||||||
|
"name": "Test move",
|
||||||
|
"product_id": cls.prod_test.id,
|
||||||
|
"date_expected": date_move,
|
||||||
|
"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
|
||||||
@@ -1,303 +1,12 @@
|
|||||||
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# (http://www.eficent.com)
|
# (http://www.eficent.com)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from odoo.addons.mrp_multi_level.tests.common import TestMrpMultiLevelCommon
|
||||||
|
|
||||||
from odoo.tests.common import SavepointCase
|
|
||||||
from odoo import fields
|
from odoo import fields
|
||||||
from dateutil.rrule import WEEKLY
|
|
||||||
|
|
||||||
|
|
||||||
class TestMrpMultiLevel(SavepointCase):
|
class TestMrpMultiLevel(TestMrpMultiLevelCommon):
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
super(TestMrpMultiLevel, cls).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.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.estimate_obj = cls.env['stock.demand.estimate']
|
|
||||||
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.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.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.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.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.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 products:
|
|
||||||
route_buy = cls.env.ref('purchase.route_warehouse0_buy').id
|
|
||||||
cls.prod_test = cls.product_obj.create({
|
|
||||||
'name': 'Test Top Seller',
|
|
||||||
'type': 'product',
|
|
||||||
'list_price': 150.0,
|
|
||||||
'produce_delay': 5.0,
|
|
||||||
'route_ids': [(6, 0, [route_buy])],
|
|
||||||
'seller_ids': [(0, 0, {'name': 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',
|
|
||||||
'type': 'product',
|
|
||||||
'list_price': 50.0,
|
|
||||||
'route_ids': [(6, 0, [route_buy])],
|
|
||||||
'seller_ids': [(0, 0, {'name': 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',
|
|
||||||
'type': 'product',
|
|
||||||
'list_price': 50.0,
|
|
||||||
'route_ids': [(6, 0, [route_buy])],
|
|
||||||
'seller_ids': [(0, 0, {'name': 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',
|
|
||||||
'type': 'product',
|
|
||||||
'list_price': 50.0,
|
|
||||||
'route_ids': [(6, 0, [route_buy])],
|
|
||||||
'seller_ids': [(0, 0, {'name': 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 test picking for FP-1 and FP-2:
|
|
||||||
res = cls.calendar.plan_days(7+1, datetime.today())
|
|
||||||
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,
|
|
||||||
'move_lines': [
|
|
||||||
(0, 0, {
|
|
||||||
'name': 'Test move fp-1',
|
|
||||||
'product_id': cls.fp_1.id,
|
|
||||||
'date_expected': date_move,
|
|
||||||
'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_expected': date_move,
|
|
||||||
'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
|
|
||||||
})]
|
|
||||||
})
|
|
||||||
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,
|
|
||||||
'move_lines': [
|
|
||||||
(0, 0, {
|
|
||||||
'name': 'Test move prod_min',
|
|
||||||
'product_id': cls.prod_min.id,
|
|
||||||
'date_expected': date_move,
|
|
||||||
'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_expected': date_move,
|
|
||||||
'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_expected': date_move,
|
|
||||||
'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()).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 MO:
|
|
||||||
date_mo = cls.calendar.plan_days(9+1, datetime.today()).date()
|
|
||||||
bom_fp_2 = cls.env.ref('mrp_multi_level.mrp_bom_fp_2')
|
|
||||||
cls.mo = cls.mo_obj.create({
|
|
||||||
'product_id': cls.fp_2.id,
|
|
||||||
'bom_id': bom_fp_2.id,
|
|
||||||
'product_qty': 12.0,
|
|
||||||
'product_uom_id': cls.fp_2.uom_id.id,
|
|
||||||
'date_planned_start': date_mo,
|
|
||||||
})
|
|
||||||
|
|
||||||
# Dates (Strings):
|
|
||||||
today = datetime.today()
|
|
||||||
cls.date_3 = fields.Date.to_string(
|
|
||||||
cls.calendar.plan_days(3+1, datetime.today()).date())
|
|
||||||
cls.date_5 = fields.Date.to_string(
|
|
||||||
cls.calendar.plan_days(5+1, datetime.today()).date())
|
|
||||||
cls.date_6 = fields.Date.to_string(
|
|
||||||
cls.calendar.plan_days(6+1, datetime.today()).date())
|
|
||||||
cls.date_7 = fields.Date.to_string(
|
|
||||||
cls.calendar.plan_days(7+1, datetime.today()).date())
|
|
||||||
cls.date_8 = fields.Date.to_string((
|
|
||||||
cls.calendar.plan_days(8+1, datetime.today()).date()))
|
|
||||||
cls.date_9 = fields.Date.to_string((
|
|
||||||
cls.calendar.plan_days(9+1, datetime.today()).date()))
|
|
||||||
cls.date_10 = fields.Date.to_string(
|
|
||||||
cls.calendar.plan_days(10+1, datetime.today()).date())
|
|
||||||
|
|
||||||
# Create Date Ranges:
|
|
||||||
cls.dr_type = cls.env['date.range.type'].create({
|
|
||||||
'name': 'Weeks',
|
|
||||||
'company_id': False,
|
|
||||||
'allow_overlap': False,
|
|
||||||
})
|
|
||||||
generator = cls.env['date.range.generator'].create({
|
|
||||||
'date_start': today - timedelta(days=3),
|
|
||||||
'name_prefix': 'W-',
|
|
||||||
'type_id': cls.dr_type.id,
|
|
||||||
'duration_count': 1,
|
|
||||||
'unit_of_time': WEEKLY,
|
|
||||||
'count': 3})
|
|
||||||
generator.action_apply()
|
|
||||||
|
|
||||||
# Create Demand Estimates:
|
|
||||||
ranges = cls.env['date.range'].search(
|
|
||||||
[('type_id', '=', cls.dr_type.id)])
|
|
||||||
qty = 140.0
|
|
||||||
for dr in ranges:
|
|
||||||
qty += 70.0
|
|
||||||
cls._create_demand_estimate(
|
|
||||||
cls.prod_test, cls.stock_location, dr, qty)
|
|
||||||
cls._create_demand_estimate(
|
|
||||||
cls.prod_test, cls.sec_loc, dr, qty)
|
|
||||||
|
|
||||||
cls.mrp_multi_level_wiz.create({}).run_mrp_multi_level()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _create_demand_estimate(cls, product, location, date_range, qty):
|
|
||||||
cls.estimate_obj.create({
|
|
||||||
'product_id': product.id,
|
|
||||||
'location_id': location.id,
|
|
||||||
'product_uom': product.uom_id.id,
|
|
||||||
'product_uom_qty': qty,
|
|
||||||
'date_range_id': date_range.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
|
|
||||||
|
|
||||||
def test_01_mrp_levels(self):
|
def test_01_mrp_levels(self):
|
||||||
"""Tests computation of MRP levels."""
|
"""Tests computation of MRP levels."""
|
||||||
@@ -461,36 +170,7 @@ class TestMrpMultiLevel(SavepointCase):
|
|||||||
expected = [0.0, 0.0] # No grouping, lot size nor safety stock.
|
expected = [0.0, 0.0] # No grouping, lot size nor safety stock.
|
||||||
self.assertEqual(invs.mapped('running_availability'), expected)
|
self.assertEqual(invs.mapped('running_availability'), expected)
|
||||||
|
|
||||||
def test_06_demand_estimates(self):
|
def test_06_procure_mo(self):
|
||||||
"""Tests demand estimates integration."""
|
|
||||||
estimates = self.estimate_obj.search([
|
|
||||||
('product_id', '=', self.prod_test.id),
|
|
||||||
('location_id', '=', self.stock_location.id)])
|
|
||||||
self.assertEqual(len(estimates), 3)
|
|
||||||
moves = self.mrp_move_obj.search([
|
|
||||||
('product_id', '=', self.prod_test.id),
|
|
||||||
('mrp_area_id', '=', self.mrp_area.id),
|
|
||||||
])
|
|
||||||
# 3 weeks - 3 days in the past = 18 days of valid estimates:
|
|
||||||
moves_from_estimates = moves.filtered(lambda m: m.mrp_type == 'd')
|
|
||||||
self.assertEqual(len(moves_from_estimates), 18)
|
|
||||||
quantities = moves_from_estimates.mapped('mrp_qty')
|
|
||||||
self.assertIn(-30.0, quantities) # 210 a week => 30.0 dayly:
|
|
||||||
self.assertIn(-40.0, quantities) # 280 a week => 40.0 dayly:
|
|
||||||
self.assertIn(-50.0, quantities) # 350 a week => 50.0 dayly:
|
|
||||||
plans = self.planned_order_obj.search([
|
|
||||||
('product_id', '=', self.prod_test.id),
|
|
||||||
('mrp_area_id', '=', self.mrp_area.id),
|
|
||||||
])
|
|
||||||
action = list(set(plans.mapped("mrp_action")))
|
|
||||||
self.assertEqual(len(action), 1)
|
|
||||||
self.assertEqual(action[0], "buy")
|
|
||||||
self.assertEqual(len(plans), 18)
|
|
||||||
inventories = self.mrp_inventory_obj.search([
|
|
||||||
('mrp_area_id', '=', self.secondary_area.id)])
|
|
||||||
self.assertEqual(len(inventories), 18)
|
|
||||||
|
|
||||||
def test_07_procure_mo(self):
|
|
||||||
"""Test procurement wizard with MOs."""
|
"""Test procurement wizard with MOs."""
|
||||||
mos = self.mo_obj.search([
|
mos = self.mo_obj.search([
|
||||||
('product_id', '=', self.fp_1.id)])
|
('product_id', '=', self.fp_1.id)])
|
||||||
@@ -506,10 +186,10 @@ class TestMrpMultiLevel(SavepointCase):
|
|||||||
('product_id', '=', self.fp_1.id)])
|
('product_id', '=', self.fp_1.id)])
|
||||||
self.assertTrue(mos)
|
self.assertTrue(mos)
|
||||||
self.assertEqual(mos.product_qty, 100.0)
|
self.assertEqual(mos.product_qty, 100.0)
|
||||||
mo_date_start = mos.date_planned_start.split(' ')[0]
|
mo_date_start = fields.Date.to_date(mos.date_planned_start)
|
||||||
self.assertEqual(mo_date_start, self.date_5)
|
self.assertEqual(mo_date_start, self.date_5)
|
||||||
|
|
||||||
def test_08_adjust_qty_to_order(self):
|
def test_07_adjust_qty_to_order(self):
|
||||||
"""Test the adjustments made to the qty to procure when minimum,
|
"""Test the adjustments made to the qty to procure when minimum,
|
||||||
maximum order quantities and quantity multiple are set."""
|
maximum order quantities and quantity multiple are set."""
|
||||||
# minimum order quantity:
|
# minimum order quantity:
|
||||||
@@ -531,12 +211,12 @@ class TestMrpMultiLevel(SavepointCase):
|
|||||||
('product_mrp_area_id.product_id', '=', self.prod_multiple.id)])
|
('product_mrp_area_id.product_id', '=', self.prod_multiple.id)])
|
||||||
self.assertEqual(mrp_inv_multiple.to_procure, 125)
|
self.assertEqual(mrp_inv_multiple.to_procure, 125)
|
||||||
|
|
||||||
def test_09_group_demand(self):
|
def test_08_group_demand(self):
|
||||||
"""Test demand grouping functionality, `nbr_days`."""
|
"""Test demand grouping functionality, `nbr_days`."""
|
||||||
estimates = self.estimate_obj.search([
|
pickings = self.stock_picking_obj.search([
|
||||||
('product_id', '=', self.prod_test.id),
|
('product_id', '=', self.prod_test.id),
|
||||||
('location_id', '=', self.sec_loc.id)])
|
('location_id', '=', self.sec_loc.id)])
|
||||||
self.assertEqual(len(estimates), 3)
|
self.assertEqual(len(pickings), 5)
|
||||||
moves = self.mrp_move_obj.search([
|
moves = self.mrp_move_obj.search([
|
||||||
('product_id', '=', self.prod_test.id),
|
('product_id', '=', self.prod_test.id),
|
||||||
('mrp_area_id', '=', self.secondary_area.id),
|
('mrp_area_id', '=', self.secondary_area.id),
|
||||||
@@ -545,20 +225,19 @@ class TestMrpMultiLevel(SavepointCase):
|
|||||||
('product_id', '=', self.prod_test.id),
|
('product_id', '=', self.prod_test.id),
|
||||||
('mrp_area_id', '=', self.secondary_area.id),
|
('mrp_area_id', '=', self.secondary_area.id),
|
||||||
])
|
])
|
||||||
# 3 weeks - 3 days in the past = 18 days of valid estimates:
|
moves_demand = moves.filtered(lambda m: m.mrp_type == 'd')
|
||||||
moves_from_estimates = moves.filtered(lambda m: m.mrp_type == 'd')
|
self.assertEqual(len(moves_demand), 5)
|
||||||
self.assertEqual(len(moves_from_estimates), 18)
|
# two groups expected:
|
||||||
# 18 days of demand / 7 nbr_days = 2.57 => 3 supply moves expected.
|
# 1. days 8, 9 and 10.
|
||||||
self.assertEqual(len(supply_plans), 3)
|
# 2. days 20, and 22.
|
||||||
|
self.assertEqual(len(supply_plans), 2)
|
||||||
quantities = supply_plans.mapped('mrp_qty')
|
quantities = supply_plans.mapped('mrp_qty')
|
||||||
week_1_expected = sum(moves_from_estimates[0:7].mapped('mrp_qty'))
|
week_1_expected = sum(moves_demand[0:3].mapped('mrp_qty'))
|
||||||
self.assertIn(abs(week_1_expected), quantities)
|
self.assertIn(abs(week_1_expected), quantities)
|
||||||
week_2_expected = sum(moves_from_estimates[7:14].mapped('mrp_qty'))
|
week_2_expected = sum(moves_demand[3:].mapped('mrp_qty'))
|
||||||
self.assertIn(abs(week_2_expected), quantities)
|
self.assertIn(abs(week_2_expected), quantities)
|
||||||
week_3_expected = sum(moves_from_estimates[14:].mapped('mrp_qty'))
|
|
||||||
self.assertIn(abs(week_3_expected), quantities)
|
|
||||||
|
|
||||||
def test_10_isolated_mrp_area_run(self):
|
def test_09_isolated_mrp_area_run(self):
|
||||||
"""Test running MRP for just one area."""
|
"""Test running MRP for just one area."""
|
||||||
self.mrp_multi_level_wiz.sudo(self.mrp_manager).create({
|
self.mrp_multi_level_wiz.sudo(self.mrp_manager).create({
|
||||||
'mrp_area_ids': [(6, 0, self.secondary_area.ids)],
|
'mrp_area_ids': [(6, 0, self.secondary_area.ids)],
|
||||||
@@ -571,6 +250,3 @@ class TestMrpMultiLevel(SavepointCase):
|
|||||||
prev = self.mrp_inventory_obj.search([
|
prev = self.mrp_inventory_obj.search([
|
||||||
('mrp_area_id', '!=', self.secondary_area.id)], limit=1)
|
('mrp_area_id', '!=', self.secondary_area.id)], limit=1)
|
||||||
self.assertNotEqual(this.create_uid, prev.create_uid)
|
self.assertNotEqual(this.create_uid, prev.create_uid)
|
||||||
|
|
||||||
# TODO: test procure wizard: pos, multiple...
|
|
||||||
# TODO: test multiple destination IDS:...
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<field name="supply_qty"/>
|
<field name="supply_qty"/>
|
||||||
<field name="final_on_hand_qty"/>
|
<field name="final_on_hand_qty"/>
|
||||||
<field name="to_procure"/>
|
<field name="to_procure"/>
|
||||||
<field name="uom_id" groups="product.group_uom"/>
|
<field name="uom_id" groups="uom.group_uom"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<field name="mrp_area_id"/>
|
<field name="mrp_area_id"/>
|
||||||
<field name="product_id"/>
|
<field name="product_id"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="uom_id" groups="product.group_uom"/>
|
<field name="uom_id" groups="uom.group_uom"/>
|
||||||
<field name="initial_on_hand_qty"/>
|
<field name="initial_on_hand_qty"/>
|
||||||
<field name="demand_qty"/>
|
<field name="demand_qty"/>
|
||||||
<field name="supply_qty"/>
|
<field name="supply_qty"/>
|
||||||
@@ -94,15 +94,20 @@
|
|||||||
domain="[['to_procure','>',0.0]]"/>
|
domain="[['to_procure','>',0.0]]"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<group expand="0" string="Group By...">
|
<group expand="0" string="Group By...">
|
||||||
<filter string="Product"
|
<filter name="group_product"
|
||||||
|
string="Product"
|
||||||
context="{'group_by':'product_mrp_area_id'}"/>
|
context="{'group_by':'product_mrp_area_id'}"/>
|
||||||
<filter string="MRP Area"
|
<filter name="group_mrp_area"
|
||||||
|
string="MRP Area"
|
||||||
context="{'group_by':'mrp_area_id'}"/>
|
context="{'group_by':'mrp_area_id'}"/>
|
||||||
<filter string="Date to Procure (By Day)"
|
<filter name="group_release_date_day"
|
||||||
|
string="Date to Procure (By Day)"
|
||||||
context="{'group_by':'order_release_date:day'}"/>
|
context="{'group_by':'order_release_date:day'}"/>
|
||||||
<filter string="Date to Procure (By Week)"
|
<filter name="group_release_date_week"
|
||||||
|
string="Date to Procure (By Week)"
|
||||||
context="{'group_by':'order_release_date:week'}"/>
|
context="{'group_by':'order_release_date:week'}"/>
|
||||||
<filter string="Date to Procure (By Month)"
|
<filter name="group_release_date_month"
|
||||||
|
string="Date to Procure (By Month)"
|
||||||
context="{'group_by':'order_release_date:month'}"/>
|
context="{'group_by':'order_release_date:month'}"/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
<field name="mrp_exclude"/>
|
<field name="mrp_exclude"/>
|
||||||
<field name="mrp_verified"/>
|
<field name="mrp_verified"/>
|
||||||
<field name="mrp_nbr_days"/>
|
<field name="mrp_nbr_days"/>
|
||||||
<field name="group_estimate_days"/>
|
|
||||||
<!--hide delays for now-->
|
<!--hide delays for now-->
|
||||||
<field name="mrp_transit_delay" invisible="1"/>
|
<field name="mrp_transit_delay" invisible="1"/>
|
||||||
<field name="mrp_inspection_delay" invisible="1"/>
|
<field name="mrp_inspection_delay" invisible="1"/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# (http://www.eficent.com)
|
# (http://www.eficent.com)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, fields, models, _
|
from odoo import api, fields, models, _
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
@@ -95,6 +95,7 @@ class MrpInventoryProcure(models.TransientModel):
|
|||||||
|
|
||||||
class MrpInventoryProcureItem(models.TransientModel):
|
class MrpInventoryProcureItem(models.TransientModel):
|
||||||
_name = 'mrp.inventory.procure.item'
|
_name = 'mrp.inventory.procure.item'
|
||||||
|
_description = "MRP Inventory procure item"
|
||||||
|
|
||||||
wiz_id = fields.Many2one(
|
wiz_id = fields.Many2one(
|
||||||
comodel_name='mrp.inventory.procure', string='Wizard',
|
comodel_name='mrp.inventory.procure', string='Wizard',
|
||||||
@@ -103,7 +104,7 @@ class MrpInventoryProcureItem(models.TransientModel):
|
|||||||
qty = fields.Float(string='Quantity')
|
qty = fields.Float(string='Quantity')
|
||||||
uom_id = fields.Many2one(
|
uom_id = fields.Many2one(
|
||||||
string='Unit of Measure',
|
string='Unit of Measure',
|
||||||
comodel_name='product.uom',
|
comodel_name='uom.uom',
|
||||||
)
|
)
|
||||||
date_planned = fields.Date(string='Planned Date', required=False)
|
date_planned = fields.Date(string='Planned Date', required=False)
|
||||||
mrp_inventory_id = fields.Many2one(
|
mrp_inventory_id = fields.Many2one(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<field name="location_id" groups="stock.group_stock_multi_locations" readonly="1"/>
|
<field name="location_id" groups="stock.group_stock_multi_locations" readonly="1"/>
|
||||||
<field name="product_id" readonly="1"/>
|
<field name="product_id" readonly="1"/>
|
||||||
<field name="qty"/>
|
<field name="qty"/>
|
||||||
<field name="uom_id" groups="product.group_uom"/>
|
<field name="uom_id" groups="uom.group_uom"/>
|
||||||
<field name="date_planned"/>
|
<field name="date_planned"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -2,18 +2,17 @@
|
|||||||
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||||
# - Lois Rilo <lois.rilo@eficent.com>
|
# - Lois Rilo <lois.rilo@eficent.com>
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, fields, models, exceptions, _
|
from odoo import api, fields, models, exceptions, _
|
||||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
from datetime import date, timedelta
|
||||||
from datetime import date, datetime, timedelta
|
|
||||||
import logging
|
import logging
|
||||||
from odoo.tools.float_utils import float_round
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MultiLevelMrp(models.TransientModel):
|
class MultiLevelMrp(models.TransientModel):
|
||||||
_name = 'mrp.multi.level'
|
_name = 'mrp.multi.level'
|
||||||
|
_description = "Multi Level MRP"
|
||||||
|
|
||||||
mrp_area_ids = fields.Many2many(
|
mrp_area_ids = fields.Many2many(
|
||||||
comodel_name="mrp.area",
|
comodel_name="mrp.area",
|
||||||
@@ -27,7 +26,6 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
def _prepare_product_mrp_area_data(self, product_mrp_area):
|
def _prepare_product_mrp_area_data(self, product_mrp_area):
|
||||||
qty_available = 0.0
|
qty_available = 0.0
|
||||||
product_obj = self.env['product.product']
|
product_obj = self.env['product.product']
|
||||||
# TODO: move mrp_qty_available computation, maybe unreserved??
|
|
||||||
location_ids = product_mrp_area.mrp_area_id._get_locations()
|
location_ids = product_mrp_area.mrp_area_id._get_locations()
|
||||||
for location in location_ids:
|
for location in location_ids:
|
||||||
product_l = product_obj.with_context(
|
product_l = product_obj.with_context(
|
||||||
@@ -41,35 +39,6 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
'mrp_llc': product_mrp_area.product_id.llc,
|
'mrp_llc': product_mrp_area.product_id.llc,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _prepare_mrp_move_data_from_forecast(
|
|
||||||
self, estimate, product_mrp_area, date):
|
|
||||||
mrp_type = 'd'
|
|
||||||
origin = 'fc'
|
|
||||||
daily_qty = float_round(
|
|
||||||
estimate.daily_qty,
|
|
||||||
precision_rounding=product_mrp_area.product_id.uom_id.rounding,
|
|
||||||
rounding_method='HALF-UP')
|
|
||||||
return {
|
|
||||||
'mrp_area_id': product_mrp_area.mrp_area_id.id,
|
|
||||||
'product_id': product_mrp_area.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': -daily_qty * product_mrp_area.group_estimate_days,
|
|
||||||
'current_qty': -daily_qty,
|
|
||||||
'mrp_date': date,
|
|
||||||
'current_date': date,
|
|
||||||
'mrp_type': mrp_type,
|
|
||||||
'mrp_origin': origin,
|
|
||||||
'mrp_order_number': None,
|
|
||||||
'parent_product_id': None,
|
|
||||||
'name': 'Forecast',
|
|
||||||
'state': 'confirmed',
|
|
||||||
}
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _prepare_mrp_move_data_from_stock_move(
|
def _prepare_mrp_move_data_from_stock_move(
|
||||||
self, product_mrp_area, move, direction='in'):
|
self, product_mrp_area, move, direction='in'):
|
||||||
@@ -91,7 +60,6 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
origin = 'mo'
|
origin = 'mo'
|
||||||
mo = move.production_id.id
|
mo = move.production_id.id
|
||||||
else:
|
else:
|
||||||
# TODO: move.move_dest_id -> move.move_dest_ids. DONE, review
|
|
||||||
if move.move_dest_ids:
|
if move.move_dest_ids:
|
||||||
# move_dest_id = move.move_dest_ids[:1]
|
# move_dest_id = move.move_dest_ids[:1]
|
||||||
for move_dest_id in move.move_dest_ids:
|
for move_dest_id in move.move_dest_ids:
|
||||||
@@ -107,11 +75,8 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
if order_number is None:
|
if order_number is None:
|
||||||
order_number = move.name
|
order_number = move.name
|
||||||
mrp_date = date.today()
|
mrp_date = date.today()
|
||||||
if datetime.date(datetime.strptime(
|
if move.date_expected.date() > date.today():
|
||||||
move.date_expected,
|
mrp_date = move.date_expected.date()
|
||||||
DEFAULT_SERVER_DATETIME_FORMAT)) > date.today():
|
|
||||||
mrp_date = datetime.date(datetime.strptime(
|
|
||||||
move.date_expected, DEFAULT_SERVER_DATETIME_FORMAT))
|
|
||||||
return {
|
return {
|
||||||
'product_id': move.product_id.id,
|
'product_id': move.product_id.id,
|
||||||
'product_mrp_area_id': product_mrp_area.id,
|
'product_mrp_area_id': product_mrp_area.id,
|
||||||
@@ -192,8 +157,9 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
if calendar and product_mrp_area.mrp_lead_time:
|
if calendar and product_mrp_area.mrp_lead_time:
|
||||||
date_str = fields.Date.to_string(mrp_date)
|
date_str = fields.Date.to_string(mrp_date)
|
||||||
dt = fields.Datetime.from_string(date_str)
|
dt = fields.Datetime.from_string(date_str)
|
||||||
|
# dt is at the beginning of the day (00:00)
|
||||||
res = calendar.plan_days(
|
res = calendar.plan_days(
|
||||||
-1 * product_mrp_area.mrp_lead_time - 1, dt)
|
-1 * product_mrp_area.mrp_lead_time, dt)
|
||||||
mrp_action_date = res.date()
|
mrp_action_date = res.date()
|
||||||
else:
|
else:
|
||||||
mrp_action_date = mrp_date - timedelta(
|
mrp_action_date = mrp_date - timedelta(
|
||||||
@@ -359,35 +325,9 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
logger.info(log_msg)
|
logger.info(log_msg)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _estimates_domain(self, product_mrp_area):
|
|
||||||
locations = product_mrp_area.mrp_area_id._get_locations()
|
|
||||||
return [
|
|
||||||
('product_id', '=', product_mrp_area.product_id.id),
|
|
||||||
('location_id', 'in', locations.ids),
|
|
||||||
('date_range_id.date_end', '>=', fields.Date.today()),
|
|
||||||
]
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _init_mrp_move_from_forecast(self, product_mrp_area):
|
def _init_mrp_move_from_forecast(self, product_mrp_area):
|
||||||
if not product_mrp_area.group_estimate_days:
|
"""This method is meant to be inherited to add a forecast mechanism."""
|
||||||
return False
|
|
||||||
today = fields.Date.today()
|
|
||||||
domain = self._estimates_domain(product_mrp_area)
|
|
||||||
estimates = self.env['stock.demand.estimate'].search(domain)
|
|
||||||
for rec in estimates:
|
|
||||||
start = rec.date_range_id.date_start
|
|
||||||
if start < today:
|
|
||||||
start = today
|
|
||||||
mrp_date = fields.Date.from_string(start)
|
|
||||||
date_end = fields.Date.from_string(rec.date_range_id.date_end)
|
|
||||||
delta = timedelta(days=product_mrp_area.group_estimate_days)
|
|
||||||
while mrp_date <= date_end:
|
|
||||||
mrp_move_data = \
|
|
||||||
self._prepare_mrp_move_data_from_forecast(
|
|
||||||
rec, product_mrp_area, mrp_date)
|
|
||||||
self.env['mrp.move'].create(mrp_move_data)
|
|
||||||
mrp_date += delta
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# TODO: move this methods to product_mrp_area?? to be able to
|
# TODO: move this methods to product_mrp_area?? to be able to
|
||||||
@@ -416,7 +356,6 @@ class MultiLevelMrp(models.TransientModel):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _init_mrp_move_from_stock_move(self, product_mrp_area):
|
def _init_mrp_move_from_stock_move(self, product_mrp_area):
|
||||||
# TODO: Should we exclude the quantity done from the moves?
|
|
||||||
move_obj = self.env['stock.move']
|
move_obj = self.env['stock.move']
|
||||||
mrp_move_obj = self.env['mrp.move']
|
mrp_move_obj = self.env['mrp.move']
|
||||||
in_domain = self._in_stock_moves_domain(product_mrp_area)
|
in_domain = self._in_stock_moves_domain(product_mrp_area)
|
||||||
|
|||||||
Reference in New Issue
Block a user