Skip to content

Commit

Permalink
[IMP] stock_inventory: be able to do adjustments in same location but…
Browse files Browse the repository at this point in the history
… for different products
  • Loading branch information
JoanSForgeFlow authored and SIP committed Jun 28, 2024
1 parent 975cc9e commit 597af74
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 38 deletions.
96 changes: 59 additions & 37 deletions stock_inventory/models/stock_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,23 +253,37 @@ def refresh_stock_quant_ids(self):
for rec in self:
rec.stock_quant_ids = rec._get_quants(rec.location_ids)

def _get_quant_joined_names(self, quants, field):
return ", ".join(quants.mapped(f"{field}.display_name"))

def action_state_to_in_progress(self):
self.ensure_one()
active_rec = self.env["stock.inventory"].search(
[
("state", "=", "in_progress"),
("location_ids", "child_of", self.location_ids.ids),
],
limit=1,
)
if active_rec:
raise UserError(
_(
"There's already an Adjustment in Process using one "
"requested Location: %s"
)
% active_rec.name
search_filter = [
(
"location_id",
"child_of" if not self.exclude_sublocation else "in",
self.location_ids.ids,
),
("to_do", "=", True),
]

if self.product_ids:
search_filter.append(("product_id", "in", self.product_ids.ids))
error_field = "product_id"
error_message = _(
"There are active adjustments for the requested products: %s"
)
else:
error_field = "location_id"
error_message = _(
"There's already an Adjustment in Process using one requested Location: %s"
)

quants = self.env["stock.quant"].search(search_filter)
if quants:
names = self._get_quant_joined_names(quants, error_field)
raise ValidationError(error_message % names)

quants = self._get_quants(self.location_ids)
self.write(
{
Expand All @@ -291,7 +305,7 @@ def action_state_to_done(self):
self.state = "done"
self.stock_quant_ids.update(
{
"to_do": True,
"to_do": False,
"user_id": False,
"inventory_date": False,
}
Expand All @@ -309,7 +323,7 @@ def action_state_to_draft(self):
self.state = "draft"
self.stock_quant_ids.update(
{
"to_do": True,
"to_do": False,
"user_id": False,
"inventory_date": False,
}
Expand Down Expand Up @@ -365,30 +379,38 @@ def action_view_stock_moves(self):
result["context"] = {}
return result

@api.constrains("state", "location_ids")
def _check_inventory_in_progress_not_override(self):
inventories = self.search([("state", "=", "in_progress")])
for rec in inventories:
inventory = inventories.filtered(
lambda x, rec=rec: x.id != rec.id
and (
any(i in x.location_ids for i in rec.location_ids)
or (
any(
i in x.location_ids.child_internal_location_ids
for i in rec.location_ids
)
and not x.exclude_sublocation
for rec in self:
if rec.state == "in_progress":
location_condition = [
(
"location_ids",
"child_of" if not rec.exclude_sublocation else "in",
rec.location_ids.ids,
)
)
)
if len(inventory) > 0:
raise ValidationError(
_(
"Cannot be more than one in progress inventory adjustment "
"affecting the same location at the same time."
]
if rec.product_ids:
product_condition = [
("state", "=", "in_progress"),
("id", "!=", rec.id),
("product_ids", "in", rec.product_ids.ids),
] + location_condition
inventories = self.search(product_condition)
else:
inventories = self.search(
[("state", "=", "in_progress"), ("id", "!=", rec.id)]
+ location_condition
)
)
for inventory in inventories:
if any(
i in inventory.location_ids.ids for i in rec.location_ids.ids
):
raise ValidationError(
_(
"Cannot have more than one in-progress inventory adjustment "
"affecting the same location or product at the same time."
)
)

@api.constrains("product_selection", "product_ids")
def _check_one_product_in_product_selection(self):
Expand Down
2 changes: 1 addition & 1 deletion stock_inventory/models/stock_quant.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class StockQuant(models.Model):
_inherit = "stock.quant"

to_do = fields.Boolean(default=True)
to_do = fields.Boolean(default=False)

def _apply_inventory(self):
res = super()._apply_inventory()
Expand Down
113 changes: 113 additions & 0 deletions stock_inventory/tests/test_stock_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,116 @@ def test_07_stock_inventory_auto_complete(self):
self.assertEqual(inventory1.count_stock_moves, 2)
self.assertEqual(inventory1.count_stock_quants, 2)
self.assertEqual(inventory1.state, "done")

def test_08_multiple_inventories_same_location(self):
quant1 = self.quant_model.search(
[
("product_id", "=", self.product.id),
("location_id", "=", self.location1.id),
]
)
self.assertTrue(quant1)
self.quant_model.sudo().create(
{
"product_id": self.product2.id,
"quantity": 100.0,
"location_id": self.location1.id,
}
)
quant2 = self.quant_model.search(
[
("product_id", "=", self.product2.id),
("location_id", "=", self.location1.id),
]
)
self.assertTrue(quant2)
inventory1 = self.inventory_model.create(
{
"name": "Inventory_Test_8_1",
"product_selection": "manual",
"location_ids": [self.location1.id],
"product_ids": [self.product.id],
}
)
inventory1.action_state_to_in_progress()
self.assertEqual(inventory1.state, "in_progress")
inventory2 = self.inventory_model.create(
{
"name": "Inventory_Test_8_2",
"product_selection": "manual",
"location_ids": [self.location1.id],
"product_ids": [self.product2.id],
}
)
inventory2.action_state_to_in_progress()
self.assertEqual(inventory2.state, "in_progress")
self.assertEqual(inventory1.state, "in_progress")

def test_09_product_inventory_global_and_sublocations_review(self):
self.location4 = self.location_model.create(
{
"name": "Location 4",
"usage": "internal",
"location_id": self.location1.id,
}
)
location_global = self.location_model.create(
{
"name": "Global Location",
"usage": "internal",
}
)
self.location1.location_id = location_global.id
self.location2.location_id = location_global.id
self.location3.location_id = location_global.id
self.location4.location_id = location_global.id
inventory_global = self.inventory_model.create(
{
"name": "Inventory_Global",
"product_selection": "manual",
"location_ids": [location_global.id],
"product_ids": [self.product.id],
}
)
inventory_global.action_state_to_in_progress()
self.assertEqual(inventory_global.state, "in_progress")
inventory_sub_no_product = self.inventory_model.create(
{
"name": "Inventory_Sub_No_Product",
"product_selection": "manual",
"location_ids": [self.location4.id],
}
)
inventory_sub_no_product.action_state_to_in_progress()
self.assertEqual(inventory_sub_no_product.state, "in_progress")
with self.assertRaises(ValidationError), self.cr.savepoint():
inventory_sub_with_product = self.inventory_model.create(
{
"name": "Inventory_Sub_With_Product",
"product_selection": "manual",
"location_ids": [self.location1.id],
}
)
inventory_sub_with_product.action_state_to_in_progress()

def test_10_inventory_quant_to_do_states(self):
inventory = self.inventory_model.create(
{
"name": "Inventory_Test_10",
"product_selection": "manual",
"location_ids": [self.location1.id],
"product_ids": [self.product.id],
}
)
inventory.action_state_to_in_progress()
quants = inventory.stock_quant_ids
self.assertTrue(all(quant.to_do for quant in quants))
inventory.action_state_to_draft()
self.assertFalse(inventory.stock_quant_ids)
self.assertTrue(all(not quant.to_do for quant in quants))
inventory.action_state_to_in_progress()
quants = inventory.stock_quant_ids
self.assertTrue(all(quant.to_do for quant in quants))
self.assertTrue(inventory.stock_quant_ids)
inventory.action_state_to_done()
self.assertTrue(all(not quant.to_do for quant in quants))

0 comments on commit 597af74

Please sign in to comment.