diff --git a/mrp_mto_with_stock/__manifest__.py b/mrp_mto_with_stock/__manifest__.py
index fb12f2dff..23cb051fc 100644
--- a/mrp_mto_with_stock/__manifest__.py
+++ b/mrp_mto_with_stock/__manifest__.py
@@ -9,11 +9,15 @@
"author": "John Walsh, Eficent, Odoo Community Association (OCA)",
"website": "https://odoo-community.org/",
"category": "Manufacturing",
- "version": "11.0.1.0.0",
+ "version": "11.0.2.0.0",
"license": "AGPL-3",
"application": False,
"installable": True,
- "depends": ["stock", "sale", "purchase", "mrp"],
+ "depends": [
+ "stock",
+ "mrp",
+ "stock_available_unreserved",
+ ],
"data": [
'views/product_template_view.xml',
'views/stock_warehouse.xml',
diff --git a/mrp_mto_with_stock/models/mrp_production.py b/mrp_mto_with_stock/models/mrp_production.py
index 118f3ca2a..73ad9012b 100644
--- a/mrp_mto_with_stock/models/mrp_production.py
+++ b/mrp_mto_with_stock/models/mrp_production.py
@@ -1,20 +1,19 @@
-# Copyright 2017 Eficent Business and IT Consulting Services S.L.
+# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
# Copyright 2015 John Walsh
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
from odoo.exceptions import UserError
import copy
-import logging
-_logger = logging.getLogger(__name__)
class MrpProduction(models.Model):
_inherit = 'mrp.production'
- def _get_procurement_group_data(self, move):
- return {'partner_id': move.partner_id.id,
- 'name': '{0}:{1}'.format(self.name, move.product_id.name)}
+ def _mto_with_stock_condition(self, move):
+ """Extensibility-enhancer method for modifying the scenarios when
+ MTO/MTS method should apply."""
+ return move.location_id in move.product_id.mrp_mts_mto_location_ids
@api.multi
def action_assign(self):
@@ -34,28 +33,9 @@ class MrpProduction(models.Model):
new_move = False
qty_to_procure = 0.0
if move.state in ('partially_available', 'confirmed') \
- and move.location_id in \
- move.product_id.mrp_mts_mto_location_ids \
- and not mto_with_no_move_dest_id:
- # We have to split the move because we can't have
- # a part of the move that have ancestors and not the
- # other else it won't ever be reserved.
- qty_to_procure = (
- move.product_uom_qty - move.reserved_availability)
- if qty_to_procure < move.product_uom_qty:
- move._do_unreserve()
- new_move_id = move._split(
- qty_to_procure,
- restrict_partner_id=move.restrict_partner_id)
- new_move = move_obj.browse(new_move_id)
- move._action_assign()
- else:
- new_move = move
- elif move.state in ('partially_available', 'confirmed') \
and move.procure_method == 'make_to_stock' \
and mto_with_no_move_dest_id and \
- move.location_id in \
- move.product_id.mrp_mts_mto_location_ids:
+ self._mto_with_stock_condition(move):
qty_to_procure = production.get_mto_qty_to_procure(move)
if qty_to_procure > 0.0:
new_move = move
@@ -66,6 +46,55 @@ class MrpProduction(models.Model):
mto_with_no_move_dest_id)
return res
+ @api.multi
+ def _adjust_procure_method(self):
+ """When configured as MTO/MTS manufacturing location, if there is
+ stock available unreserved, use it and procure the remaining."""
+ res = super()._adjust_procure_method()
+ warehouse = self.location_src_id.get_warehouse()
+ mto_with_no_move_dest_id = warehouse.mrp_mto_mts_forecast_qty
+ for move in self.move_raw_ids:
+ if not self._mto_with_stock_condition(move):
+ continue
+ new_move = False
+ qty_to_procure = 0.0
+ if not mto_with_no_move_dest_id:
+ # We have to split the move because we can't have
+ # a part of the move that have ancestors and not the
+ # other else it won't ever be reserved.
+ qty_to_procure = min(
+ move.product_uom_qty -
+ move.product_id.qty_available_not_res,
+ move.product_uom_qty)
+ if 0.0 < qty_to_procure < move.product_uom_qty:
+ # we need to adjust the unit_factor of the stock moves
+ # to split correctly the load of each one.
+ ratio = qty_to_procure / move.product_uom_qty
+ new_move = move.copy({
+ 'product_uom_qty': qty_to_procure,
+ 'procure_method': 'make_to_order',
+ 'unit_factor': move.unit_factor * ratio,
+ })
+ move.write({
+ 'product_uom_qty':
+ move.product_uom_qty - qty_to_procure,
+ 'unit_factor': move.unit_factor * (1 - ratio),
+ })
+ move._action_confirm()
+ move._action_assign()
+ elif qty_to_procure > 0.0:
+ new_move = move
+ else:
+ # If we don't need to procure, we reserve the qty
+ # for this move so it won't be available for others,
+ # which would generate planning issues.
+ move._action_confirm()
+ move._action_assign()
+ if new_move:
+ self.run_procurement(
+ new_move, qty_to_procure, mto_with_no_move_dest_id)
+ return res
+
@api.multi
def run_procurement(self, move, qty, mto_with_no_move_dest_id):
self.ensure_one()
@@ -75,8 +104,7 @@ class MrpProduction(models.Model):
# And the previous move generated now.
if mto_with_no_move_dest_id:
values.pop('move_dest_ids', None)
- origin = '{0}:{1}'.format(self.name, move.product_id.name) + \
- ':MTO -> Production'
+ origin = self.origin or move.origin
values['route_ids'] = move.product_id.route_ids
try:
self.env['procurement.group'].run(
diff --git a/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py b/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py
index 24e3db02b..7a5b3187d 100644
--- a/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py
+++ b/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py
@@ -106,16 +106,14 @@ class TestMrpMtoWithStock(TransactionCase):
2)
self._update_product_qty(self.subproduct2, self.stock_location_stock,
4)
-
- self.production = self.production_model.create(
- self._get_production_vals())
-
self._update_product_qty(self.subproduct_1_1,
self.stock_location_stock, 50)
+ self.production = self.production_model.create(
+ self._get_production_vals())
+ self.assertEqual(len(self.production.move_raw_ids), 3)
+
# Create MO and check it create sub assemblie MO.
- self.production.action_assign()
- self.assertEqual(self.production.state, 'confirmed')
mo = self.production_model.search(
[('origin', 'ilike', self.production.name)])
self.assertEqual(mo.product_qty, 3)
@@ -147,6 +145,15 @@ class TestMrpMtoWithStock(TransactionCase):
wizard = wizard_obj.create(wizard_vals)
wizard.do_produce()
+ # Check that not extra moves were generated and qty's are ok:
+ self.assertEqual(len(self.production.move_raw_ids), 3)
+ for move in self.production.move_raw_ids:
+ if move.product_id == self.subproduct1 and \
+ move.procure_method == 'make_to_order':
+ qty = 3.0
+ else:
+ qty = 2.0
+ self.assertEqual(move.quantity_done, qty)
self.assertTrue(self.production.check_to_done)
self.production.button_mark_done()
diff --git a/mrp_mto_with_stock/views/product_template_view.xml b/mrp_mto_with_stock/views/product_template_view.xml
index 5eff34d89..99d027ae0 100644
--- a/mrp_mto_with_stock/views/product_template_view.xml
+++ b/mrp_mto_with_stock/views/product_template_view.xml
@@ -10,10 +10,10 @@
product.template
-
+
-
+
diff --git a/oca_dependencies.txt b/oca_dependencies.txt
index 16abec0ad..ab4a3dafd 100644
--- a/oca_dependencies.txt
+++ b/oca_dependencies.txt
@@ -2,3 +2,4 @@
# Add a repository url and branch if you need a forked version
product-attribute
purchase-workflow
+stock-logistics-warehouse