Skip to content

Commit

Permalink
fix: manual pick allow to pick more than available stock
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitwaghchaure committed Jul 3, 2024
1 parent cbd25ae commit 84dde1a
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
59 changes: 58 additions & 1 deletion erpnext/stock/doctype/pick_list/pick_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from itertools import groupby

import frappe
from frappe import _
from frappe import _, bold
from frappe.model.document import Document
from frappe.model.mapper import map_child_doc
from frappe.query_builder import Case
Expand Down Expand Up @@ -73,6 +73,9 @@ def onload(self) -> None:

def validate(self):
self.validate_for_qty()
if self.pick_manually and self.get("locations"):
self.validate_stock_qty()
self.check_serial_no_status()

def before_save(self):
self.update_status()
Expand All @@ -82,6 +85,60 @@ def before_save(self):
if self.get("locations"):
self.validate_sales_order_percentage()

def validate_stock_qty(self):
from erpnext.stock.doctype.batch.batch import get_batch_qty

for row in self.get("locations"):
if row.batch_no and not row.qty:
batch_qty = get_batch_qty(row.batch_no, row.warehouse, row.item_code)

if row.qty > batch_qty:
frappe.throw(
_(
"At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} for the batch {4} in the warehouse {5}."
).format(row.idx, row.item_code, batch_qty, row.batch_no, bold(row.warehouse)),
title=_("Insufficient Stock"),
)

continue

bin_qty = frappe.db.get_value(
"Bin",
{"item_code": row.item_code, "warehouse": row.warehouse},
"actual_qty",
)

if row.qty > bin_qty:
frappe.throw(
_(
"At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} in the warehouse {4}."
).format(row.idx, row.qty, bold(row.item_code), bin_qty, bold(row.warehouse)),
title=_("Insufficient Stock"),
)

def check_serial_no_status(self):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

for row in self.get("locations"):
if not row.serial_no:
continue

picked_serial_nos = get_serial_nos(row.serial_no)
validated_serial_nos = frappe.get_all(
"Serial No",
filters={"name": ("in", picked_serial_nos), "warehouse": row.warehouse},
pluck="name",
)

incorrect_serial_nos = set(picked_serial_nos) - set(validated_serial_nos)
if incorrect_serial_nos:
frappe.throw(
_("The Serial No at Row #{0}: {1} is not available in warehouse {2}.").format(
row.idx, ", ".join(incorrect_serial_nos), row.warehouse
),
title=_("Incorrect Warehouse"),
)

def validate_sales_order_percentage(self):
# set percentage picked in SO
for location in self.get("locations"):
Expand Down
42 changes: 42 additions & 0 deletions erpnext/stock/doctype/pick_list/test_pick_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -1132,3 +1132,45 @@ def test_pick_list_for_multiple_sales_orders_for_non_serialized_item(self):
pl.save()

self.assertEqual(pl.locations[0].qty, 80.0)

def test_validate_picked_qty_with_manual_option(self):
warehouse = "_Test Warehouse - _TC"
non_serialized_item = make_item(
"Test Non Serialized Pick List Item For Manual Option", properties={"is_stock_item": 1}
).name

serialized_item = make_item(
"Test Serialized Pick List Item For Manual Option",
properties={"is_stock_item": 1, "has_serial_no": 1, "serial_no_series": "SN-HSNMSPLI-.####"},
).name

batched_item = make_item(
"Test Batched Pick List Item For Manual Option",
properties={
"is_stock_item": 1,
"has_batch_no": 1,
"batch_number_series": "SN-HBNMSPLI-.####",
"create_new_batch": 1,
},
).name

make_stock_entry(item=non_serialized_item, to_warehouse=warehouse, qty=10, basic_rate=100)
make_stock_entry(item=serialized_item, to_warehouse=warehouse, qty=10, basic_rate=100)
make_stock_entry(item=batched_item, to_warehouse=warehouse, qty=10, basic_rate=100)

so = make_sales_order(
item_code=non_serialized_item, qty=10, rate=100, do_not_save=True, warehouse=warehouse
)
so.append("items", {"item_code": serialized_item, "qty": 10, "rate": 100, "warehouse": warehouse})
so.append("items", {"item_code": batched_item, "qty": 10, "rate": 100, "warehouse": warehouse})
so.set_missing_values()
so.save()
so.submit()

pl = create_pick_list(so.name)
pl.pick_manually = 1

for row in pl.locations:
row.qty = row.qty + 10

self.assertRaises(frappe.ValidationError, pl.save)

0 comments on commit 84dde1a

Please sign in to comment.