mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[FIX] stock_reserve_rule: rule matching
A move from "Stock/Zone1/A" must match removal rules defined for "Stock/Zone1"
This commit is contained in:
@@ -161,6 +161,7 @@ Contributors
|
|||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||||
|
* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
||||||
|
|
||||||
Maintainers
|
Maintainers
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Copyright 2019 Camptocamp SA
|
# Copyright 2019 Camptocamp SA
|
||||||
|
# Copyright 2019-2021 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
from odoo import models
|
from odoo import models
|
||||||
from odoo.tools.float_utils import float_compare
|
from odoo.tools.float_utils import float_compare
|
||||||
@@ -50,7 +51,12 @@ class StockMove(models.Model):
|
|||||||
# it can use both rules.
|
# it can use both rules.
|
||||||
# If we have a stock.move with "Stock/Zone2" as source location,
|
# If we have a stock.move with "Stock/Zone2" as source location,
|
||||||
# it should never use "Stock/Zone1"
|
# it should never use "Stock/Zone1"
|
||||||
if not removal_rule.location_id.is_sublocation_of(location_id):
|
# If we have a stock.move with "Stock/Zone1/A" as source location,
|
||||||
|
# it should use "Stock/Zone1" rule
|
||||||
|
if not (
|
||||||
|
removal_rule.location_id.is_sublocation_of(location_id)
|
||||||
|
or location_id.is_sublocation_of(removal_rule.location_id)
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
quants = self.env["stock.quant"]._gather(
|
quants = self.env["stock.quant"]._gather(
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||||
|
* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Copyright 2019 Camptocamp (https://www.camptocamp.com)
|
# Copyright 2019 Camptocamp (https://www.camptocamp.com)
|
||||||
|
# Copyright 2019-2021 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
|
||||||
|
|
||||||
from odoo import exceptions, fields
|
from odoo import exceptions, fields
|
||||||
from odoo.tests import common
|
from odoo.tests import common
|
||||||
@@ -71,7 +72,7 @@ class TestReserveRule(common.SavepointCase):
|
|||||||
{"name": "Pallet", "code": "PALLET", "sequence": 5}
|
{"name": "Pallet", "code": "PALLET", "sequence": 5}
|
||||||
)
|
)
|
||||||
|
|
||||||
def _create_picking(self, wh, products=None):
|
def _create_picking(self, wh, products=None, location_src_id=None):
|
||||||
"""Create picking
|
"""Create picking
|
||||||
|
|
||||||
Products must be a list of tuples (product, quantity).
|
Products must be a list of tuples (product, quantity).
|
||||||
@@ -82,7 +83,7 @@ class TestReserveRule(common.SavepointCase):
|
|||||||
|
|
||||||
picking = self.env["stock.picking"].create(
|
picking = self.env["stock.picking"].create(
|
||||||
{
|
{
|
||||||
"location_id": wh.lot_stock_id.id,
|
"location_id": location_src_id or wh.lot_stock_id.id,
|
||||||
"location_dest_id": wh.wh_output_stock_loc_id.id,
|
"location_dest_id": wh.wh_output_stock_loc_id.id,
|
||||||
"partner_id": self.partner_delta.id,
|
"partner_id": self.partner_delta.id,
|
||||||
"picking_type_id": wh.pick_type_id.id,
|
"picking_type_id": wh.pick_type_id.id,
|
||||||
@@ -97,7 +98,7 @@ class TestReserveRule(common.SavepointCase):
|
|||||||
"product_uom_qty": qty,
|
"product_uom_qty": qty,
|
||||||
"product_uom": product.uom_id.id,
|
"product_uom": product.uom_id.id,
|
||||||
"picking_id": picking.id,
|
"picking_id": picking.id,
|
||||||
"location_id": wh.lot_stock_id.id,
|
"location_id": location_src_id or wh.lot_stock_id.id,
|
||||||
"location_dest_id": wh.wh_output_stock_loc_id.id,
|
"location_dest_id": wh.wh_output_stock_loc_id.id,
|
||||||
"state": "confirmed",
|
"state": "confirmed",
|
||||||
}
|
}
|
||||||
@@ -180,6 +181,43 @@ class TestReserveRule(common.SavepointCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(move.state, "assigned")
|
self.assertEqual(move.state, "assigned")
|
||||||
|
|
||||||
|
def test_rule_match_parent(self):
|
||||||
|
all_locs = (
|
||||||
|
self.loc_zone1_bin1,
|
||||||
|
self.loc_zone1_bin2,
|
||||||
|
self.loc_zone2_bin1,
|
||||||
|
self.loc_zone2_bin2,
|
||||||
|
self.loc_zone3_bin1,
|
||||||
|
self.loc_zone3_bin2,
|
||||||
|
)
|
||||||
|
for loc in all_locs:
|
||||||
|
self._update_qty_in_location(loc, self.product1, 100)
|
||||||
|
|
||||||
|
picking = self._create_picking(
|
||||||
|
self.wh, [(self.product1, 200)], self.loc_zone1.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self._create_rule(
|
||||||
|
{},
|
||||||
|
[
|
||||||
|
{"location_id": self.loc_zone1.id, "sequence": 2},
|
||||||
|
{"location_id": self.loc_zone2.id, "sequence": 1},
|
||||||
|
{"location_id": self.loc_zone3.id, "sequence": 3},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
picking.action_assign()
|
||||||
|
move = picking.move_lines
|
||||||
|
ml = move.move_line_ids
|
||||||
|
self.assertRecordValues(
|
||||||
|
ml,
|
||||||
|
[
|
||||||
|
{"location_id": self.loc_zone1_bin1.id, "product_qty": 100},
|
||||||
|
{"location_id": self.loc_zone1_bin2.id, "product_qty": 100},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(move.state, "assigned")
|
||||||
|
|
||||||
def test_rule_take_all_in_2_and_3(self):
|
def test_rule_take_all_in_2_and_3(self):
|
||||||
self._update_qty_in_location(self.loc_zone1_bin1, self.product1, 100)
|
self._update_qty_in_location(self.loc_zone1_bin1, self.product1, 100)
|
||||||
self._update_qty_in_location(self.loc_zone2_bin1, self.product1, 100)
|
self._update_qty_in_location(self.loc_zone2_bin1, self.product1, 100)
|
||||||
|
|||||||
Reference in New Issue
Block a user