mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[FIX] fix orderpoint compute with purchase multiple
This commit is contained in:
committed by
Thomas Binsfeld
parent
5d2c71c85f
commit
98e451917b
@@ -2,6 +2,7 @@
|
||||
# Copyright 2015-2017 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import float_compare
|
||||
|
||||
|
||||
class ProcurementOrder(models.Model):
|
||||
@@ -28,3 +29,38 @@ class ProcurementOrder(models.Model):
|
||||
self.product_qty, new_uom_id)
|
||||
res['product_qty'] = max(qty, seller.min_qty)
|
||||
return res
|
||||
|
||||
|
||||
class Orderpoint(models.Model):
|
||||
_inherit = 'stock.warehouse.orderpoint'
|
||||
|
||||
@api.multi
|
||||
def subtract_procurements_from_orderpoints(self):
|
||||
# In this method we need to access the purchase order line quantity
|
||||
# to correctly evaluate the forecast.
|
||||
# Imagine a product with a minimum rule of 4 units and a purchase
|
||||
# multiple of 12. The first run will generate a procurement for 4 Pc
|
||||
# but a purchase for 12 units.
|
||||
# Let's change the minimum rule to 5 units.
|
||||
# The standard subtract_procurements_from_orderpoints will return 4
|
||||
# and Odoo will create a procurement for 1 unit which will trigger a
|
||||
# purchase of 12 due to the multiple. So the original purchase will
|
||||
# be increased to 24 units which is wrong.
|
||||
# This override will return 12 and no additionnal procurement will be
|
||||
# created
|
||||
res = super(Orderpoint, self).subtract_procurements_from_orderpoints()
|
||||
for orderpoint in self:
|
||||
procs = self.env['procurement.order'].search(
|
||||
[('orderpoint_id', '=', orderpoint.id),
|
||||
('state', 'not in', ['cancel', 'done'])])
|
||||
if procs:
|
||||
po_lines = procs.mapped('purchase_line_id').filtered(
|
||||
lambda x: x.state == 'draft')
|
||||
if po_lines:
|
||||
qty = sum([line.product_qty for line in po_lines])
|
||||
precision = orderpoint.product_uom.rounding
|
||||
if float_compare(
|
||||
qty, res[orderpoint.id],
|
||||
precision_rounding=precision) >= 0:
|
||||
res[orderpoint.id] = qty
|
||||
return res
|
||||
|
||||
@@ -259,3 +259,117 @@ class TestProcurementOrder(common.TransactionCase):
|
||||
proc1.purchase_line_id.product_uom)
|
||||
self.assertEqual(36, proc1.purchase_line_id.price_unit)
|
||||
proc1.purchase_id.button_confirm()
|
||||
|
||||
def test_procurement_from_orderpoint_draft_po(self):
|
||||
# Define a multiple of 12 on supplier info
|
||||
# Trigger a stock minimum rule of 10 PC
|
||||
# A purchase line with 12 PC should be generated
|
||||
# Change the stock minimum to 11 PC
|
||||
# The purchase quantity should remains 12
|
||||
# Change the stock minimum to 13 PC
|
||||
# The purchase quantity should increase up to 24
|
||||
warehouse = self.env.ref('stock.warehouse0')
|
||||
product = self.env.ref('product.product_product_3')
|
||||
product.route_ids = [(
|
||||
4, self.env.ref("purchase.route_warehouse0_buy").id)]
|
||||
self.env.ref('product.product_uom_dozen').rounding = 1
|
||||
procurement_obj = self.env['procurement.order']
|
||||
|
||||
self.sp_30.min_qty = 1
|
||||
self.sp_30.min_qty_uom_id = self.env.ref('product.product_uom_dozen')
|
||||
|
||||
orderpoint = self.env['stock.warehouse.orderpoint'].create({
|
||||
'warehouse_id': warehouse.id,
|
||||
'location_id': warehouse.lot_stock_id.id,
|
||||
'product_id': product.id,
|
||||
'product_min_qty': 10,
|
||||
'product_max_qty': 10,
|
||||
})
|
||||
procurement_obj.run_scheduler()
|
||||
proc = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
self.assertEqual(len(proc), 1)
|
||||
self.assertTrue(proc.purchase_line_id)
|
||||
self.assertEqual(proc.purchase_line_id.product_qty, 12)
|
||||
|
||||
# change order_point level and rerun
|
||||
orderpoint.product_min_qty = 11
|
||||
orderpoint.product_max_qty = 11
|
||||
|
||||
procurement_obj.run_scheduler()
|
||||
procs = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
|
||||
self.assertTrue(procs)
|
||||
self.assertEqual(len(procs), 1)
|
||||
|
||||
# change order_point level and rerun
|
||||
orderpoint.product_min_qty = 13
|
||||
orderpoint.product_max_qty = 13
|
||||
|
||||
procurement_obj.run_scheduler()
|
||||
procs = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
|
||||
self.assertTrue(procs)
|
||||
self.assertEqual(len(procs), 2)
|
||||
|
||||
for proc in procs:
|
||||
self.assertTrue(proc.purchase_line_id)
|
||||
self.assertEqual(proc.purchase_line_id.product_qty, 24)
|
||||
|
||||
def test_procurement_from_orderpoint_confirmed_po(self):
|
||||
# Define a multiple of 12 on supplier info
|
||||
# Trigger a stock minimum rule of 10 PC
|
||||
# A purchase line with 12 PC should be generated
|
||||
# Confirm the purchase order
|
||||
# Change the stock minimum to 11 PC
|
||||
# No new purchase should be generated
|
||||
# Change the stock minimum to 13 PC
|
||||
# A new purchase should be generated
|
||||
warehouse = self.env.ref('stock.warehouse0')
|
||||
product = self.env.ref('product.product_product_3')
|
||||
product.route_ids = [(
|
||||
4, self.env.ref("purchase.route_warehouse0_buy").id)]
|
||||
self.env.ref('product.product_uom_dozen').rounding = 1
|
||||
procurement_obj = self.env['procurement.order']
|
||||
|
||||
self.sp_30.min_qty = 1
|
||||
self.sp_30.min_qty_uom_id = self.env.ref('product.product_uom_dozen')
|
||||
|
||||
orderpoint = self.env['stock.warehouse.orderpoint'].create({
|
||||
'warehouse_id': warehouse.id,
|
||||
'location_id': warehouse.lot_stock_id.id,
|
||||
'product_id': product.id,
|
||||
'product_min_qty': 10,
|
||||
'product_max_qty': 10,
|
||||
})
|
||||
procurement_obj.run_scheduler()
|
||||
proc = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
self.assertEqual(len(proc), 1)
|
||||
self.assertTrue(proc.purchase_line_id)
|
||||
self.assertEqual(proc.purchase_line_id.product_qty, 12)
|
||||
|
||||
proc.purchase_line_id.order_id.button_confirm()
|
||||
|
||||
# change order_point level and rerun
|
||||
orderpoint.product_min_qty = 11
|
||||
orderpoint.product_max_qty = 11
|
||||
|
||||
procurement_obj.run_scheduler()
|
||||
proc = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
|
||||
self.assertTrue(proc)
|
||||
self.assertEqual(len(proc), 1)
|
||||
self.assertEqual(proc.purchase_line_id.product_qty, 12)
|
||||
|
||||
# change order_point level and rerun
|
||||
orderpoint.product_min_qty = 13
|
||||
orderpoint.product_max_qty = 13
|
||||
|
||||
procurement_obj.run_scheduler()
|
||||
procs = procurement_obj.search([('orderpoint_id', '=', orderpoint.id)])
|
||||
|
||||
self.assertTrue(procs)
|
||||
self.assertEqual(len(procs), 2)
|
||||
|
||||
for proc in procs:
|
||||
self.assertTrue(proc.purchase_line_id)
|
||||
self.assertEqual(proc.purchase_line_id.product_qty, 12)
|
||||
|
||||
Reference in New Issue
Block a user