Skip to content
Permalink
Browse files

[FIX] stock: multiple orderpoint

- the oderpoint_id field on the purchase order line wasn't used to not
  merge the po lines
- if the orderpoint_id field is set, use the orderpoint location to
  create the move
- if multiple stock moves with different source locations go through
  `_merge_moves`, they should obviously NOT be merged
- `virtual_available` computed field was not being invalidated when the
  context keys "warehouse" and "location" changed

task-2001462
  • Loading branch information
sle-odoo committed Nov 19, 2019
1 parent 0a46e08 commit f0864338268eced7be621db0cdbf44bd0315c779
@@ -360,7 +360,7 @@ def _prepare_stock_moves(self, picking):
'date': self.order_id.date_order,
'date_expected': self.date_planned,
'location_id': self.order_id.partner_id.property_stock_supplier.id,
'location_dest_id': self.order_id._get_destination_location(),
'location_dest_id': self.orderpoint_id and self.orderpoint_id.location_id.id or self.order_id._get_destination_location(),
'picking_id': picking.id,
'partner_id': self.order_id.dest_address_id.id,
'move_dest_ids': [(4, x) for x in self.move_dest_ids.ids],
@@ -400,5 +400,5 @@ def _find_candidate(self, product_id, product_qty, product_uom, location_id, nam
args can be merged. If it returns an empty record then a new line will
be created.
"""
lines = self.filtered(lambda l: l.propagate_date == values['propagate_date'] and l.propagate_date_minimum_delta == values['propagate_date_minimum_delta'] and l.propagate_cancel == values['propagate_cancel'])
lines = self.filtered(lambda l: l.propagate_date == values['propagate_date'] and l.propagate_date_minimum_delta == values['propagate_date_minimum_delta'] and l.propagate_cancel == values['propagate_cancel'] and l.orderpoint_id == values['orderpoint_id'])
return lines and lines[0] or self.env['purchase.order.line']
@@ -1,49 +1,51 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.tests.common import TransactionCase
from odoo.tests.common import SavepointCase
from odoo.tests import Form

class TestReorderingRule(TransactionCase):
class TestReorderingRule(SavepointCase):

def test_reordering_rule(self):
"""
- Receive products in 2 steps
- The product has a reordering rule
- On the po generated, the source document should be the name of the reordering rule
"""
warehouse_1 = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.id)], limit=1)
warehouse_1.write({'reception_steps': 'two_steps'})

# Create a supplier
partner = self.env['res.partner'].create({
@classmethod
def setUpClass(cls):
super(TestReorderingRule, cls).setUpClass()
cls.partner = cls.env['res.partner'].create({
'name': 'Smith'
})

# create product and set the vendor
product_form = Form(self.env['product.product'])
product_form = Form(cls.env['product.product'])
product_form.name = 'Product A'
product_form.type = 'product'
with product_form.seller_ids.new() as seller:
seller.name = partner
product_form.route_ids.add(self.env.ref('purchase_stock.route_warehouse0_buy'))
product_01 = product_form.save()
seller.name = cls.partner
product_form.route_ids.add(cls.env.ref('purchase_stock.route_warehouse0_buy'))
cls.product_01 = product_form.save()

def test_reordering_rule_1(self):
"""
- Receive products in 2 steps
- The product has a reordering rule
- On the po generated, the source document should be the name of the reordering rule
"""
warehouse_1 = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.id)], limit=1)
warehouse_1.write({'reception_steps': 'two_steps'})

# create reordering rule
orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
orderpoint_form.warehouse_id = warehouse_1
orderpoint_form.location_id = warehouse_1.lot_stock_id
orderpoint_form.product_id = product_01
orderpoint_form.product_id = self.product_01
orderpoint_form.product_min_qty = 0.000
orderpoint_form.product_max_qty = 0.000
order_point = orderpoint_form.save()

# Create Delivery Order of 10 product
picking_form = Form(self.env['stock.picking'])
picking_form.partner_id = partner
picking_form.partner_id = self.partner
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
with picking_form.move_ids_without_package.new() as move:
move.product_id = product_01
move.product_id = self.product_01
move.product_uom_qty = 10.0
customer_picking = picking_form.save()

@@ -54,8 +56,68 @@ def test_reordering_rule(self):
self.env['procurement.group'].run_scheduler()

# Check purchase order created or not
purchase_order = self.env['purchase.order'].search([('partner_id', '=', partner.id)])
purchase_order = self.env['purchase.order'].search([('partner_id', '=', self.partner.id)])
self.assertTrue(purchase_order, 'No purchase order created.')

# On the po generated, the source document should be the name of the reordering rule
self.assertEqual(order_point.name, purchase_order.origin, 'Source document on purchase order should be the name of the reordering rule.')

def test_reordering_rule_2(self):
"""
- Receive products in 1 steps
- The product has two reordering rules, each one applying in a sublocation
- Processing the purchase order should fulfill the two sublocations
"""
warehouse_1 = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.id)], limit=1)
subloc_1 = self.env['stock.location'].create({'name': 'subloc_1', 'location_id': warehouse_1.lot_stock_id.id})
subloc_2 = self.env['stock.location'].create({'name': 'subloc_2', 'location_id': warehouse_1.lot_stock_id.id})

# create reordering rules
orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
orderpoint_form.warehouse_id = warehouse_1
orderpoint_form.location_id = subloc_1
orderpoint_form.product_id = self.product_01
orderpoint_form.product_min_qty = 0.000
orderpoint_form.product_max_qty = 0.000
order_point_1 = orderpoint_form.save()
orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
orderpoint_form.warehouse_id = warehouse_1
orderpoint_form.location_id = subloc_2
orderpoint_form.product_id = self.product_01
orderpoint_form.product_min_qty = 0.000
orderpoint_form.product_max_qty = 0.000
order_point_2 = orderpoint_form.save()

# Create Delivery Order of 10 product
picking_form = Form(self.env['stock.picking'])
picking_form.partner_id = self.partner
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product_01
move.product_uom_qty = 10.0
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product_01
move.product_uom_qty = 10.0
customer_picking = picking_form.save()
customer_picking.move_lines[0].location_id = subloc_1.id
customer_picking.move_lines[1].location_id = subloc_2.id

# picking confirm
customer_picking.action_confirm()
self.assertEqual(self.product_01.with_context(location=subloc_1.id).virtual_available, -10)
self.assertEqual(self.product_01.with_context(location=subloc_2.id).virtual_available, -10)

# Run scheduler
self.env['procurement.group'].run_scheduler()

# Check purchase order created or not
purchase_order = self.env['purchase.order'].search([('partner_id', '=', self.partner.id)])
self.assertTrue(purchase_order, 'No purchase order created.')
self.assertEqual(len(purchase_order.order_line), 2, 'Not enough purchase order lines created.')

purchase_order.button_confirm()
res = purchase_order.picking_ids.button_validate()
Form(self.env[res['res_model']].with_context(res['context'])).save().process()
self.assertEqual(self.product_01.with_context(location=subloc_1.id).virtual_available, 0)
self.assertEqual(self.product_01.with_context(location=subloc_2.id).virtual_available, 0)

@@ -94,7 +94,7 @@ class Product(models.Model):
@api.depends('stock_move_ids.product_qty', 'stock_move_ids.state')
@api.depends_context(
'lot_id', 'owner_id', 'package_id', 'from_date', 'to_date',
'company_owned',
'company_owned', 'location', 'warehouse',
)
def _compute_quantities(self):
products = self.filtered(lambda p: p.type != 'service')
@@ -692,7 +692,7 @@ def _merge_moves_fields(self):
@api.model
def _prepare_merge_moves_distinct_fields(self):
return [
'product_id', 'price_unit', 'procure_method',
'product_id', 'price_unit', 'procure_method', 'location_id', 'location_dest_id',
'product_uom', 'restrict_partner_id', 'scrapped', 'origin_returned_move_id',
'package_level_id', 'propagate_cancel', 'propagate_date', 'propagate_date_minimum_delta',
'delay_alert',
@@ -702,7 +702,7 @@ def _prepare_merge_moves_distinct_fields(self):
def _prepare_merge_move_sort_method(self, move):
move.ensure_one()
return [
move.product_id.id, move.price_unit, move.procure_method,
move.product_id.id, move.price_unit, move.procure_method, move.location_id, move.location_dest_id,
move.product_uom.id, move.restrict_partner_id.id, move.scrapped, move.origin_returned_move_id.id,
move.package_level_id.id, move.propagate_cancel, move.propagate_date, move.propagate_date_minimum_delta,
move.delay_alert,

0 comments on commit f086433

Please sign in to comment.
You can’t perform that action at this time.