mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-21 16:02:15 +00:00
fix: stock reco negative qty validation
(cherry picked from commit 289495c308)
# Conflicts:
# erpnext/stock/stock_ledger.py
This commit is contained in:
committed by
Mergify
parent
62702b8bd6
commit
aee03fe2ef
@@ -986,6 +986,108 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
|
|||||||
active_serial_no = frappe.get_all("Serial No", filters={"status": "Active", "item_code": item_code})
|
active_serial_no = frappe.get_all("Serial No", filters={"status": "Active", "item_code": item_code})
|
||||||
self.assertEqual(len(active_serial_no), 5)
|
self.assertEqual(len(active_serial_no), 5)
|
||||||
|
|
||||||
|
def test_balance_qty_for_batch_with_backdated_stock_reco_and_future_entries(self):
|
||||||
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
|
|
||||||
|
item = self.make_item(
|
||||||
|
"Test Batch Item Original Test",
|
||||||
|
{
|
||||||
|
"is_stock_item": 1,
|
||||||
|
"has_batch_no": 1,
|
||||||
|
"create_new_batch": 1,
|
||||||
|
"batch_number_series": "TEST-BATCH-SRWFEE-.###",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
warehouse = "_Test Warehouse - _TC"
|
||||||
|
se1 = make_stock_entry(
|
||||||
|
item_code=item.name,
|
||||||
|
target=warehouse,
|
||||||
|
qty=50,
|
||||||
|
basic_rate=100,
|
||||||
|
posting_date=add_days(nowdate(), -2),
|
||||||
|
)
|
||||||
|
batch1 = get_batch_from_bundle(se1.items[0].serial_and_batch_bundle)
|
||||||
|
|
||||||
|
se2 = make_stock_entry(
|
||||||
|
item_code=item.name,
|
||||||
|
target=warehouse,
|
||||||
|
qty=50,
|
||||||
|
basic_rate=100,
|
||||||
|
posting_date=add_days(nowdate(), -2),
|
||||||
|
)
|
||||||
|
batch2 = get_batch_from_bundle(se2.items[0].serial_and_batch_bundle)
|
||||||
|
|
||||||
|
se3 = make_stock_entry(
|
||||||
|
item_code=item.name,
|
||||||
|
target=warehouse,
|
||||||
|
qty=100,
|
||||||
|
basic_rate=100,
|
||||||
|
posting_date=add_days(nowdate(), -2),
|
||||||
|
)
|
||||||
|
batch3 = get_batch_from_bundle(se3.items[0].serial_and_batch_bundle)
|
||||||
|
|
||||||
|
se3 = make_stock_entry(
|
||||||
|
item_code=item.name,
|
||||||
|
target=warehouse,
|
||||||
|
qty=100,
|
||||||
|
basic_rate=100,
|
||||||
|
posting_date=nowdate(),
|
||||||
|
)
|
||||||
|
|
||||||
|
sle = frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
filters={
|
||||||
|
"item_code": item.name,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"is_cancelled": 0,
|
||||||
|
"voucher_no": se3.name,
|
||||||
|
},
|
||||||
|
fields=["qty_after_transaction"],
|
||||||
|
order_by="posting_time desc, creation desc",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(flt(sle[0].qty_after_transaction), flt(300.0))
|
||||||
|
|
||||||
|
sr = create_stock_reconciliation(
|
||||||
|
item_code=item.name,
|
||||||
|
warehouse=warehouse,
|
||||||
|
qty=0,
|
||||||
|
batch_no=batch1,
|
||||||
|
posting_date=add_days(nowdate(), -1),
|
||||||
|
use_serial_batch_fields=1,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
for batch in [batch2, batch3]:
|
||||||
|
sr.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": item.name,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"qty": 0,
|
||||||
|
"batch_no": batch,
|
||||||
|
"use_serial_batch_fields": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
sr.save()
|
||||||
|
sr.submit()
|
||||||
|
|
||||||
|
sle = frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
filters={
|
||||||
|
"item_code": item.name,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"is_cancelled": 0,
|
||||||
|
"voucher_no": se3.name,
|
||||||
|
},
|
||||||
|
fields=["qty_after_transaction"],
|
||||||
|
order_by="posting_time desc, creation desc",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(flt(sle[0].qty_after_transaction), flt(100.0))
|
||||||
|
|
||||||
|
|
||||||
def create_batch_item_with_batch(item_name, batch_id):
|
def create_batch_item_with_batch(item_name, batch_id):
|
||||||
batch_item_doc = create_item(item_name, is_stock_item=1)
|
batch_item_doc = create_item(item_name, is_stock_item=1)
|
||||||
|
|||||||
@@ -1728,6 +1728,10 @@ def get_stock_reco_qty_shift(args):
|
|||||||
stock_reco_qty_shift = flt(args.qty_after_transaction) - flt(last_balance)
|
stock_reco_qty_shift = flt(args.qty_after_transaction) - flt(last_balance)
|
||||||
else:
|
else:
|
||||||
stock_reco_qty_shift = flt(args.actual_qty)
|
stock_reco_qty_shift = flt(args.actual_qty)
|
||||||
|
|
||||||
|
elif args.get("serial_and_batch_bundle"):
|
||||||
|
stock_reco_qty_shift = flt(args.actual_qty)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# reco is being submitted
|
# reco is being submitted
|
||||||
last_balance = get_previous_sle_of_current_voucher(args, "<=", exclude_current_voucher=True).get(
|
last_balance = get_previous_sle_of_current_voucher(args, "<=", exclude_current_voucher=True).get(
|
||||||
@@ -1799,7 +1803,20 @@ def get_datetime_limit_condition(detail):
|
|||||||
def validate_negative_qty_in_future_sle(args, allow_negative_stock=False):
|
def validate_negative_qty_in_future_sle(args, allow_negative_stock=False):
|
||||||
if allow_negative_stock or is_negative_stock_allowed(item_code=args.item_code):
|
if allow_negative_stock or is_negative_stock_allowed(item_code=args.item_code):
|
||||||
return
|
return
|
||||||
|
<<<<<<< HEAD
|
||||||
if not (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation"):
|
if not (args.actual_qty < 0 or args.voucher_type == "Stock Reconciliation"):
|
||||||
|
=======
|
||||||
|
|
||||||
|
if (
|
||||||
|
args.voucher_type == "Stock Reconciliation"
|
||||||
|
and args.actual_qty < 0
|
||||||
|
and args.get("serial_and_batch_bundle")
|
||||||
|
and frappe.db.get_value("Stock Reconciliation Item", args.voucher_detail_no, "qty") > 0
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
if args.actual_qty >= 0 and args.voucher_type != "Stock Reconciliation":
|
||||||
|
>>>>>>> 289495c308 (fix: stock reco negative qty validation)
|
||||||
return
|
return
|
||||||
|
|
||||||
neg_sle = get_future_sle_with_negative_qty(args)
|
neg_sle = get_future_sle_with_negative_qty(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user