mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[FIX] stock_reserve_rule: allow removal strategy based on lots and/or owner
The lot is ignored in _apply_strategy which makes it not possible to create removal rules based on it. A practical example is to create a rule with a quant_domain on lot_id.use_date (Best Before Date). Even though the quants will be filtered, the lots wont be taken into consideration in _apply_strategy and so random lots will be reserved. With tis the signature for the _apply_strategy_%s methods is changed to require returning the lot also or set it to None if it is not used. The same rationale applies for the owner of the quant.
This commit is contained in:
committed by
Alessandro Uffreduzzi
parent
f313930916
commit
f53db888b3
@@ -85,16 +85,22 @@ class StockMove(models.Model):
|
||||
next_quant = strategy.send(still_need)
|
||||
if not next_quant:
|
||||
continue
|
||||
location, location_quantity, to_take = next_quant
|
||||
(
|
||||
location,
|
||||
location_quantity,
|
||||
to_take,
|
||||
strat_lot_id,
|
||||
strat_owner_id,
|
||||
) = next_quant
|
||||
taken_in_loc = super()._update_reserved_quantity(
|
||||
# in this strategy, we take as much as we can
|
||||
# from this bin
|
||||
to_take,
|
||||
location_quantity,
|
||||
location_id=location,
|
||||
lot_id=lot_id,
|
||||
lot_id=strat_lot_id,
|
||||
package_id=package_id,
|
||||
owner_id=owner_id,
|
||||
owner_id=strat_owner_id,
|
||||
strict=strict,
|
||||
)
|
||||
still_need -= taken_in_loc
|
||||
|
||||
@@ -195,7 +195,7 @@ class StockReserveRuleRemoval(models.Model):
|
||||
each time the strategy decides to take quantities in a location,
|
||||
it has to yield and retrieve the remaining needed using:
|
||||
|
||||
need = yield location, location_quantity, quantity_to_take
|
||||
need = yield location, location_quantity, quantity_to_take, lot, owner
|
||||
|
||||
See '_apply_strategy_default' for a short example.
|
||||
|
||||
@@ -212,6 +212,8 @@ class StockReserveRuleRemoval(models.Model):
|
||||
quant.location_id,
|
||||
quant.quantity - quant.reserved_quantity,
|
||||
need,
|
||||
quant.lot_id,
|
||||
quant.owner_id,
|
||||
)
|
||||
|
||||
def _apply_strategy_empty_bin(self, quants):
|
||||
@@ -247,7 +249,7 @@ class StockReserveRuleRemoval(models.Model):
|
||||
continue
|
||||
|
||||
if float_compare(need, location_quantity, rounding) != -1:
|
||||
need = yield location, location_quantity, need
|
||||
need = yield location, location_quantity, need, None, None
|
||||
|
||||
def _apply_strategy_packaging(self, quants):
|
||||
need = yield
|
||||
@@ -293,4 +295,4 @@ class StockReserveRuleRemoval(models.Model):
|
||||
if enough_for_packaging and asked_at_least_packaging_qty:
|
||||
# compute how much packaging we can get
|
||||
take = (need // pack_quantity) * pack_quantity
|
||||
need = yield location, location_quantity, take
|
||||
need = yield location, location_quantity, take, None, None
|
||||
|
||||
@@ -105,9 +105,16 @@ class TestReserveRule(common.SavepointCase):
|
||||
)
|
||||
return picking
|
||||
|
||||
def _update_qty_in_location(self, location, product, quantity, in_date=None):
|
||||
def _update_qty_in_location(
|
||||
self, location, product, quantity, in_date=None, lot_id=None, owner_id=None
|
||||
):
|
||||
self.env["stock.quant"]._update_available_quantity(
|
||||
product, location, quantity, in_date=in_date
|
||||
product,
|
||||
location,
|
||||
quantity,
|
||||
in_date=in_date,
|
||||
lot_id=lot_id,
|
||||
owner_id=owner_id,
|
||||
)
|
||||
|
||||
def _create_rule(self, rule_values, removal_values):
|
||||
@@ -371,6 +378,63 @@ class TestReserveRule(common.SavepointCase):
|
||||
)
|
||||
self.assertEqual(move.state, "assigned")
|
||||
|
||||
def test_quant_domain_lot_and_owner(self):
|
||||
lot = self.env["stock.production.lot"].create(
|
||||
{
|
||||
"name": "P0001",
|
||||
"product_id": self.product1.id,
|
||||
"company_id": self.env.user.company_id.id,
|
||||
}
|
||||
)
|
||||
owner = self.env["res.partner"].create({"name": "Owner", "ref": "C0001"})
|
||||
self._update_qty_in_location(self.loc_zone1_bin1, self.product1, 100)
|
||||
self._update_qty_in_location(
|
||||
self.loc_zone1_bin1, self.product1, 100, lot_id=lot
|
||||
)
|
||||
self._update_qty_in_location(self.loc_zone2_bin1, self.product1, 100)
|
||||
self._update_qty_in_location(
|
||||
self.loc_zone2_bin1, self.product1, 100, owner_id=owner
|
||||
)
|
||||
picking = self._create_picking(self.wh, [(self.product1, 200)])
|
||||
picking.owner_id = owner
|
||||
|
||||
self._create_rule(
|
||||
{},
|
||||
[
|
||||
{
|
||||
"location_id": self.loc_zone1.id,
|
||||
"sequence": 1,
|
||||
"quant_domain": [("lot_id.name", "ilike", "P%")],
|
||||
},
|
||||
{
|
||||
"location_id": self.loc_zone2.id,
|
||||
"sequence": 2,
|
||||
"quant_domain": [("owner_id.ref", "ilike", "C%")],
|
||||
},
|
||||
],
|
||||
)
|
||||
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,
|
||||
"lot_id": lot.id,
|
||||
"owner_id": False,
|
||||
},
|
||||
{
|
||||
"location_id": self.loc_zone2_bin1.id,
|
||||
"product_qty": 100,
|
||||
"lot_id": False,
|
||||
"owner_id": owner.id,
|
||||
},
|
||||
],
|
||||
)
|
||||
self.assertEqual(move.state, "assigned")
|
||||
|
||||
def test_rule_empty_bin(self):
|
||||
self._update_qty_in_location(self.loc_zone1_bin1, self.product1, 300)
|
||||
self._update_qty_in_location(self.loc_zone1_bin2, self.product1, 150)
|
||||
|
||||
Reference in New Issue
Block a user