[11.0][FIX] Consider *Qty Multiple* on product to propose the quantity to procure.

This commit is contained in:
Lois Rilo
2018-08-30 11:28:09 +02:00
committed by Lois Rilo
parent 585e5b5c7c
commit ca6d93ecd6
6 changed files with 124 additions and 11 deletions

View File

@@ -3,7 +3,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'MRP Multi Level',
'version': '11.0.1.0.1',
'version': '11.0.1.1.0',
'development_status': 'Beta',
'license': 'AGPL-3',
'author': 'Ucamco, '

View File

@@ -2,6 +2,8 @@
# © 2016-18 Eficent Business and IT Consulting Services S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from math import ceil
from odoo import api, fields, models
@@ -118,15 +120,16 @@ class MrpProduct(models.Model):
@api.multi
def _adjust_qty_to_order(self, qty_to_order):
# TODO: consider mrp_qty_multiple?
self.ensure_one()
if not self.mrp_maximum_order_qty and not self.mrp_minimum_order_qty:
if (not self.mrp_maximum_order_qty and not
self.mrp_minimum_order_qty and self.mrp_qty_multiple == 1.0):
return qty_to_order
if qty_to_order < self.mrp_minimum_order_qty:
return self.mrp_minimum_order_qty
if self.mrp_qty_multiple:
multiplier = ceil(qty_to_order / self.mrp_qty_multiple)
qty_to_order = multiplier * self.mrp_qty_multiple
if self.mrp_maximum_order_qty and qty_to_order > \
self.mrp_maximum_order_qty:
qty = self.mrp_maximum_order_qty
else:
qty = qty_to_order
return qty
return self.mrp_maximum_order_qty
return qty_to_order

View File

@@ -1,3 +1,9 @@
11.0.1.1.0 (2018-08-30)
~~~~~~~~~~~~~~~~~~~~~~~
* [FIX] Consider *Qty Multiple* on product to propose the quantity to procure.
(`#297 <https://github.com/OCA/manufacture/pull/297>`_)
11.0.1.0.1 (2018-08-03)
~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -0,0 +1,2 @@
* The functionality related to field *Nbr. Days* in products is not
functional for the time being. Please, stay tuned to future updates.

View File

@@ -54,8 +54,38 @@ class TestMrpMultiLevel(SavepointCase):
'route_ids': [(6, 0, [route_buy])],
'seller_ids': [(0, 0, {'name': vendor1.id, 'price': 20.0})],
})
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})],
'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})],
'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})],
'mrp_minimum_order_qty': 50.0,
'mrp_maximum_order_qty': 500.0,
'mrp_qty_multiple': 25.0,
})
# Create test picking:
# 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({
@@ -86,6 +116,45 @@ class TestMrpMultiLevel(SavepointCase):
})
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({
@@ -372,5 +441,28 @@ class TestMrpMultiLevel(SavepointCase):
mo_date_start = mos.date_planned_start.split(' ')[0]
self.assertEqual(mo_date_start, self.date_5)
def test_08_adjust_qty_to_order(self):
"""Test the adjustments made to the qty to procure when minimum,
maximum order quantities and quantity multiple are set."""
# minimum order quantity:
mrp_inv_min = self.mrp_inventory_obj.search([
('mrp_product_id.product_id', '=', self.prod_min.id)])
self.assertEqual(mrp_inv_min.to_procure, 50.0)
# maximum order quantity:
mrp_inv_max = self.mrp_inventory_obj.search([
('mrp_product_id.product_id', '=', self.prod_max.id)])
self.assertEqual(mrp_inv_max.to_procure, 150)
moves = self.mrp_move_obj.search([
('product_id', '=', self.prod_max.id),
('mrp_action', '!=', 'none'),
])
self.assertEqual(len(moves), 2)
self.assertIn(100.0, moves.mapped('mrp_qty'))
self.assertIn(50.0, moves.mapped('mrp_qty'))
# quantity multiple:
mrp_inv_multiple = self.mrp_inventory_obj.search([
('mrp_product_id.product_id', '=', self.prod_multiple.id)])
self.assertEqual(mrp_inv_multiple.to_procure, 125)
# TODO: test procure wizard: pos, multiple...
# TODO: test multiple destination IDS:...

View File

@@ -17,9 +17,9 @@ class MrpInventoryProcure(models.TransientModel):
)
@api.model
def _prepare_item(self, mrp_inventory):
def _prepare_item(self, mrp_inventory, qty_override=0.0):
return {
'qty': mrp_inventory.to_procure,
'qty': qty_override if qty_override else mrp_inventory.to_procure,
'uom_id': mrp_inventory.uom_id.id,
'date_planned': mrp_inventory.date,
'mrp_inventory_id': mrp_inventory.id,
@@ -57,7 +57,17 @@ class MrpInventoryProcure(models.TransientModel):
items = item_obj = self.env['mrp.inventory.procure.item']
for line in mrp_inventory_obj.browse(mrp_inventory_ids):
items += item_obj.create(self._prepare_item(line))
max_order = line.mrp_product_id.mrp_maximum_order_qty
qty_to_order = line.to_procure
if max_order and max_order < qty_to_order:
# split the procurement in batches:
while qty_to_order > 0.0:
qty = line.mrp_product_id._adjust_qty_to_order(
qty_to_order)
items += item_obj.create(self._prepare_item(line, qty))
qty_to_order -= qty
else:
items += item_obj.create(self._prepare_item(line))
res['item_ids'] = [(6, 0, items.ids)]
return res