fix: allow negative stock condition for batch item (#36586)

* fix: allow negative stock condition for batch item

* fix: test case
This commit is contained in:
rohitwaghchaure
2023-08-11 13:57:27 +05:30
committed by GitHub
parent 5488785fd8
commit ee04c6d5c5
3 changed files with 65 additions and 18 deletions

View File

@@ -282,11 +282,7 @@ class StockReconciliation(StockController):
if has_serial_no:
sl_entries = self.merge_similar_item_serial_nos(sl_entries)
allow_negative_stock = False
if has_batch_no:
allow_negative_stock = True
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
self.make_sl_entries(sl_entries, allow_negative_stock=self.has_negative_stock_allowed())
if has_serial_no and sl_entries:
self.update_valuation_rate_for_serial_no()
@@ -457,10 +453,7 @@ class StockReconciliation(StockController):
sl_entries = self.merge_similar_item_serial_nos(sl_entries)
sl_entries.reverse()
allow_negative_stock = cint(
frappe.db.get_single_value("Stock Settings", "allow_negative_stock")
)
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
self.make_sl_entries(sl_entries, allow_negative_stock=self.has_negative_stock_allowed())
def merge_similar_item_serial_nos(self, sl_entries):
# If user has put the same item in multiple row with different serial no
@@ -574,6 +567,7 @@ class StockReconciliation(StockController):
from erpnext.stock.stock_ledger import get_valuation_rate
sl_entries = []
for row in self.items:
if voucher_detail_no != row.name:
continue
@@ -619,10 +613,18 @@ class StockReconciliation(StockController):
sl_entries.append(new_sle)
if sl_entries:
self.make_sl_entries(sl_entries, allow_negative_stock=True)
if frappe.db.exists("Repost Item Valuation", {"voucher_no": self.name, "status": "Queued"}):
self.make_sl_entries(sl_entries, allow_negative_stock=self.has_negative_stock_allowed())
if not frappe.db.exists("Repost Item Valuation", {"voucher_no": self.name, "status": "Queued"}):
self.repost_future_sle_and_gle(force=True)
def has_negative_stock_allowed(self):
allow_negative_stock = cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock"))
if all(d.batch_no and flt(d.qty) == flt(d.current_qty) for d in self.items):
allow_negative_stock = True
return allow_negative_stock
def get_batch_qty_for_stock_reco(
item_code, warehouse, batch_no, posting_date, posting_time, voucher_no

View File

@@ -769,8 +769,6 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
self.assertEqual(flt(sle[0].qty_after_transaction), flt(50.0))
def test_backdated_stock_reco_entry_with_batch(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
item_code = self.make_item(
"Test New Batch Item ABCVSD",
{
@@ -868,6 +866,56 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
sr1.load_from_db()
self.assertEqual(sr1.difference_amount, 10000)
@change_settings("Stock Settings", {"allow_negative_stock": 0})
def test_negative_stock_reco_for_batch(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
item_code = self.make_item(
"Test New Batch Item ABCVSD",
{
"is_stock_item": 1,
"has_batch_no": 1,
"batch_number_series": "BNS9.####",
"create_new_batch": 1,
},
).name
warehouse = "_Test Warehouse - _TC"
# Added 100 Qty, Balace Qty 100
se = make_stock_entry(
item_code=item_code,
target=warehouse,
qty=100,
basic_rate=100,
posting_date=add_days(nowdate(), -2),
)
# Removed 100 Qty, Balace Qty 0
make_stock_entry(
item_code=item_code,
source=warehouse,
qty=100,
batch_no=se.items[0].batch_no,
basic_rate=100,
posting_date=nowdate(),
)
# Remove 100 qty, Balace Qty -100
sr = create_stock_reconciliation(
item_code=item_code,
warehouse=warehouse,
qty=0,
rate=0,
batch_no=se.items[0].batch_no,
posting_date=add_days(nowdate(), -1),
posting_time="11:00:00",
do_not_submit=True,
)
# Check if Negative Stock is blocked
self.assertRaises(frappe.ValidationError, sr.submit)
def create_batch_item_with_batch(item_name, batch_id):
batch_item_doc = create_item(item_name, is_stock_item=1)
@@ -891,7 +939,7 @@ def insert_existing_sle(warehouse, item_code="_Test Item"):
posting_time="02:00",
item_code=item_code,
target=warehouse,
qty=10,
qty=15,
basic_rate=700,
)

View File

@@ -635,7 +635,7 @@ class update_entries_after(object):
def reset_actual_qty_for_stock_reco(self, sle):
doc = frappe.get_cached_doc("Stock Reconciliation", sle.voucher_no)
doc.recalculate_current_qty(sle.voucher_detail_no, sle.creation, sle.actual_qty > 0)
doc.recalculate_current_qty(sle.voucher_detail_no, sle.creation, sle.actual_qty >= 0)
if sle.actual_qty < 0:
sle.actual_qty = (
@@ -643,9 +643,6 @@ class update_entries_after(object):
* -1
)
if abs(sle.actual_qty) == 0.0:
sle.is_cancelled = 1
def validate_negative_stock(self, sle):
"""
validate negative stock for entries current datetime onwards