mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-02 06:29:54 +00:00
Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com> fix(stock): add warehouse filter to pick work order raw materials (#53748)
This commit is contained in:
@@ -523,8 +523,26 @@ class PickList(TransactionBase):
|
||||
self.item_location_map = frappe._dict()
|
||||
|
||||
from_warehouses = [self.parent_warehouse] if self.parent_warehouse else []
|
||||
if self.parent_warehouse:
|
||||
from_warehouses.extend(get_descendants_of("Warehouse", self.parent_warehouse))
|
||||
|
||||
if self.work_order:
|
||||
root_warehouse = frappe.db.get_value(
|
||||
"Warehouse", {"company": self.company, "parent_warehouse": ["IS", "NOT SET"], "is_group": 1}
|
||||
)
|
||||
|
||||
from_warehouses = [root_warehouse]
|
||||
|
||||
if from_warehouses:
|
||||
from_warehouses.extend(get_descendants_of("Warehouse", from_warehouses[0]))
|
||||
|
||||
item_warehouse_dict = frappe._dict()
|
||||
if self.work_order:
|
||||
item_warehouse_list = frappe.get_all(
|
||||
"Work Order Item",
|
||||
filters={"parent": self.work_order},
|
||||
fields=["item_code", "source_warehouse"],
|
||||
)
|
||||
if item_warehouse_list:
|
||||
item_warehouse_dict = {item.item_code: item.source_warehouse for item in item_warehouse_list}
|
||||
|
||||
# Create replica before resetting, to handle empty table on update after submit.
|
||||
locations_replica = self.get("locations")
|
||||
@@ -542,6 +560,13 @@ class PickList(TransactionBase):
|
||||
len_idx = len(self.get("locations")) or 0
|
||||
for item_doc in items:
|
||||
item_code = item_doc.item_code
|
||||
priority_warehouses = []
|
||||
|
||||
if self.work_order and item_warehouse_dict.get(item_code):
|
||||
source_warehouse = item_warehouse_dict.get(item_code)
|
||||
priority_warehouses = [source_warehouse]
|
||||
priority_warehouses.extend(get_descendants_of("Warehouse", source_warehouse))
|
||||
from_warehouses = list(dict.fromkeys(priority_warehouses + from_warehouses))
|
||||
|
||||
self.item_location_map.setdefault(
|
||||
item_code,
|
||||
@@ -552,6 +577,7 @@ class PickList(TransactionBase):
|
||||
self.company,
|
||||
picked_item_details=picked_items_details.get(item_code),
|
||||
consider_rejected_warehouses=self.consider_rejected_warehouses,
|
||||
priority_warehouses=priority_warehouses,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -969,6 +995,7 @@ def get_available_item_locations(
|
||||
ignore_validation=False,
|
||||
picked_item_details=None,
|
||||
consider_rejected_warehouses=False,
|
||||
priority_warehouses=None,
|
||||
):
|
||||
locations = []
|
||||
|
||||
@@ -1009,7 +1036,7 @@ def get_available_item_locations(
|
||||
locations = filter_locations_by_picked_materials(locations, picked_item_details)
|
||||
|
||||
if locations:
|
||||
locations = get_locations_based_on_required_qty(locations, required_qty)
|
||||
locations = get_locations_based_on_required_qty(locations, required_qty, priority_warehouses)
|
||||
|
||||
if not ignore_validation:
|
||||
validate_picked_materials(item_code, required_qty, locations, picked_item_details)
|
||||
@@ -1017,9 +1044,14 @@ def get_available_item_locations(
|
||||
return locations
|
||||
|
||||
|
||||
def get_locations_based_on_required_qty(locations, required_qty):
|
||||
def get_locations_based_on_required_qty(locations, required_qty, priority_warehouses):
|
||||
filtered_locations = []
|
||||
|
||||
if priority_warehouses:
|
||||
priority_locations = [loc for loc in locations if loc.warehouse in priority_warehouses]
|
||||
fallback_locations = [loc for loc in locations if loc.warehouse not in priority_warehouses]
|
||||
locations = priority_locations + fallback_locations
|
||||
|
||||
for location in locations:
|
||||
if location.qty >= required_qty:
|
||||
location.qty = required_qty
|
||||
|
||||
@@ -1050,6 +1050,53 @@ class TestPickList(ERPNextTestSuite):
|
||||
pl = create_pick_list(so.name)
|
||||
self.assertFalse(pl.locations)
|
||||
|
||||
def test_pick_list_warehouse_for_work_order(self):
|
||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import create_pick_list, make_work_order
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
# Create Warehouses for Work Order
|
||||
source_warehouse = create_warehouse("_Test WO Warehouse")
|
||||
wip_warehouse = create_warehouse("_Test WIP Warehouse", company="_Test Company")
|
||||
fg_warehouse = create_warehouse("_Test Finished Goods Warehouse", company="_Test Company")
|
||||
|
||||
# Create Finished Good Item
|
||||
fg_item = make_item("Test Work Order Finished Good Item", properties={"is_stock_item": 1}).name
|
||||
|
||||
# Create Raw Material Item
|
||||
rm_item = make_item("Test Work Order Raw Material Item", properties={"is_stock_item": 1}).name
|
||||
|
||||
# Create BOM
|
||||
bom = make_bom(item=fg_item, rate=100, raw_materials=[rm_item])
|
||||
|
||||
# Create Inward entry for Raw Material
|
||||
make_stock_entry(item=rm_item, to_warehouse=wip_warehouse, qty=10)
|
||||
make_stock_entry(item=rm_item, to_warehouse=source_warehouse, qty=10)
|
||||
|
||||
# Create Work Order
|
||||
wo = make_work_order(item=fg_item, qty=5, bom_no=bom.name, company="_Test Company")
|
||||
wo.required_items[0].source_warehouse = source_warehouse
|
||||
wo.fg_warehouse = fg_warehouse
|
||||
wo.skip_transfer = True
|
||||
wo.submit()
|
||||
|
||||
# Create Pick List
|
||||
pl = create_pick_list(wo.name, for_qty=wo.qty)
|
||||
|
||||
# System prioritises the Source Warehouse
|
||||
self.assertEqual(pl.locations[0].warehouse, source_warehouse)
|
||||
self.assertEqual(pl.locations[0].item_code, rm_item)
|
||||
self.assertEqual(pl.locations[0].qty, 5)
|
||||
|
||||
# Create Outward Entry from Source Warehouse
|
||||
make_stock_entry(item=rm_item, from_warehouse=source_warehouse, qty=10)
|
||||
pl.set_item_locations()
|
||||
|
||||
# System should pick other available warehouses
|
||||
self.assertEqual(pl.locations[0].warehouse, wip_warehouse)
|
||||
self.assertEqual(pl.locations[0].item_code, rm_item)
|
||||
self.assertEqual(pl.locations[0].qty, 5)
|
||||
|
||||
def test_pick_list_validation_for_serial_no(self):
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
item = make_item(
|
||||
|
||||
Reference in New Issue
Block a user