fix: consider existing pick list
This commit is contained in:
parent
9ae3a54ce9
commit
b642718f08
@ -181,7 +181,11 @@ class PickList(Document):
|
||||
self.item_location_map.setdefault(
|
||||
item_code,
|
||||
get_available_item_locations(
|
||||
item_code, from_warehouses, self.item_count_map.get(item_code), self.company
|
||||
item_code,
|
||||
from_warehouses,
|
||||
self.item_count_map.get(item_code),
|
||||
self.company,
|
||||
picked_item_details=picked_items_details.get(item_code),
|
||||
),
|
||||
)
|
||||
|
||||
@ -473,31 +477,38 @@ def get_items_with_location_and_quantity(item_doc, item_location_map, docstatus)
|
||||
|
||||
|
||||
def get_available_item_locations(
|
||||
item_code, from_warehouses, required_qty, company, ignore_validation=False
|
||||
item_code,
|
||||
from_warehouses,
|
||||
required_qty,
|
||||
company,
|
||||
ignore_validation=False,
|
||||
picked_item_details=None,
|
||||
):
|
||||
locations = []
|
||||
total_picked_qty = (
|
||||
sum([v.get("picked_qty") for k, v in picked_item_details.items()]) if picked_item_details else 0
|
||||
)
|
||||
has_serial_no = frappe.get_cached_value("Item", item_code, "has_serial_no")
|
||||
has_batch_no = frappe.get_cached_value("Item", item_code, "has_batch_no")
|
||||
|
||||
if has_batch_no and has_serial_no:
|
||||
locations = get_available_item_locations_for_serial_and_batched_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty
|
||||
)
|
||||
elif has_serial_no:
|
||||
locations = get_available_item_locations_for_serialized_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty
|
||||
)
|
||||
elif has_batch_no:
|
||||
locations = get_available_item_locations_for_batched_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty
|
||||
)
|
||||
else:
|
||||
locations = get_available_item_locations_for_other_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty
|
||||
)
|
||||
|
||||
total_qty_available = sum(location.get("qty") for location in locations)
|
||||
|
||||
remaining_qty = required_qty - total_qty_available
|
||||
|
||||
if remaining_qty > 0 and not ignore_validation:
|
||||
@ -508,11 +519,44 @@ def get_available_item_locations(
|
||||
title=_("Insufficient Stock"),
|
||||
)
|
||||
|
||||
if picked_item_details:
|
||||
for location in list(locations):
|
||||
key = (
|
||||
(location["warehouse"], location["batch_no"])
|
||||
if location.get("batch_no")
|
||||
else location["warehouse"]
|
||||
)
|
||||
|
||||
if key in picked_item_details:
|
||||
picked_detail = picked_item_details[key]
|
||||
|
||||
if picked_detail.get("serial_no") and location.get("serial_no"):
|
||||
location["serial_no"] = list(
|
||||
set(location["serial_no"]).difference(set(picked_detail["serial_no"]))
|
||||
)
|
||||
location["qty"] = len(location["serial_no"])
|
||||
else:
|
||||
location["qty"] -= picked_detail.get("picked_qty")
|
||||
|
||||
if location["qty"] < 1:
|
||||
locations.remove(location)
|
||||
|
||||
total_qty_available = sum(location.get("qty") for location in locations)
|
||||
remaining_qty = required_qty - total_qty_available
|
||||
|
||||
if remaining_qty > 0 and not ignore_validation:
|
||||
frappe.msgprint(
|
||||
_("{0} units of Item {1} is picked in another Pick List.").format(
|
||||
remaining_qty, frappe.get_desk_link("Item", item_code)
|
||||
),
|
||||
title=_("Already Picked"),
|
||||
)
|
||||
|
||||
return locations
|
||||
|
||||
|
||||
def get_available_item_locations_for_serialized_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty=0
|
||||
):
|
||||
sn = frappe.qb.DocType("Serial No")
|
||||
query = (
|
||||
@ -520,7 +564,7 @@ def get_available_item_locations_for_serialized_item(
|
||||
.select(sn.name, sn.warehouse)
|
||||
.where((sn.item_code == item_code) & (sn.company == company))
|
||||
.orderby(sn.purchase_date)
|
||||
.limit(cint(required_qty))
|
||||
.limit(cint(required_qty + total_picked_qty))
|
||||
)
|
||||
|
||||
if from_warehouses:
|
||||
@ -542,7 +586,7 @@ def get_available_item_locations_for_serialized_item(
|
||||
|
||||
|
||||
def get_available_item_locations_for_batched_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty=0
|
||||
):
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
batch = frappe.qb.DocType("Batch")
|
||||
@ -562,6 +606,7 @@ def get_available_item_locations_for_batched_item(
|
||||
.groupby(sle.warehouse, sle.batch_no, sle.item_code)
|
||||
.having(Sum(sle.actual_qty) > 0)
|
||||
.orderby(IfNull(batch.expiry_date, "2200-01-01"), batch.creation, sle.batch_no, sle.warehouse)
|
||||
.limit(cint(required_qty + total_picked_qty))
|
||||
)
|
||||
|
||||
if from_warehouses:
|
||||
@ -571,7 +616,7 @@ def get_available_item_locations_for_batched_item(
|
||||
|
||||
|
||||
def get_available_item_locations_for_serial_and_batched_item(
|
||||
item_code, from_warehouses, required_qty, company
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty=0
|
||||
):
|
||||
# Get batch nos by FIFO
|
||||
locations = get_available_item_locations_for_batched_item(
|
||||
@ -594,23 +639,26 @@ def get_available_item_locations_for_serial_and_batched_item(
|
||||
(conditions) & (sn.batch_no == location.batch_no) & (sn.warehouse == location.warehouse)
|
||||
)
|
||||
.orderby(sn.purchase_date)
|
||||
.limit(cint(location.qty))
|
||||
.limit(cint(location.qty + total_picked_qty))
|
||||
).run(as_dict=True)
|
||||
|
||||
serial_nos = [sn.name for sn in serial_nos]
|
||||
location.serial_no = serial_nos
|
||||
location.qty = len(serial_nos)
|
||||
|
||||
return locations
|
||||
|
||||
|
||||
def get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company):
|
||||
def get_available_item_locations_for_other_item(
|
||||
item_code, from_warehouses, required_qty, company, total_picked_qty=0
|
||||
):
|
||||
bin = frappe.qb.DocType("Bin")
|
||||
query = (
|
||||
frappe.qb.from_(bin)
|
||||
.select(bin.warehouse, bin.actual_qty.as_("qty"))
|
||||
.where((bin.item_code == item_code) & (bin.actual_qty > 0))
|
||||
.orderby(bin.creation)
|
||||
.limit(cint(required_qty))
|
||||
.limit(cint(required_qty + total_picked_qty))
|
||||
)
|
||||
|
||||
if from_warehouses:
|
||||
|
Loading…
x
Reference in New Issue
Block a user