fix: allow to fix negative stock for batch using stock reco

(cherry picked from commit 2e8cde3378)
This commit is contained in:
Rohit Waghchaure
2025-01-24 22:42:04 +05:30
committed by Mergify
parent f9d96726f0
commit 69c5695f6e
5 changed files with 97 additions and 5 deletions

View File

@@ -54,7 +54,12 @@ frappe.ui.form.on("Batch", {
frappe.call({ frappe.call({
method: "erpnext.stock.doctype.batch.batch.get_batch_qty", method: "erpnext.stock.doctype.batch.batch.get_batch_qty",
args: { batch_no: frm.doc.name, item_code: frm.doc.item, for_stock_levels: for_stock_levels }, args: {
batch_no: frm.doc.name,
item_code: frm.doc.item,
for_stock_levels: for_stock_levels,
consider_negative_batches: 1,
},
callback: (r) => { callback: (r) => {
if (!r.message) { if (!r.message) {
return; return;
@@ -71,7 +76,7 @@ frappe.ui.form.on("Batch", {
// show // show
(r.message || []).forEach(function (d) { (r.message || []).forEach(function (d) {
if (d.qty > 0) { if (d.qty != 0) {
$(`<div class='row' style='margin-bottom: 10px;'> $(`<div class='row' style='margin-bottom: 10px;'>
<div class='col-sm-3 small' style='padding-top: 3px;'>${d.warehouse}</div> <div class='col-sm-3 small' style='padding-top: 3px;'>${d.warehouse}</div>
<div class='col-sm-3 small text-right' style='padding-top: 3px;'>${d.qty}</div> <div class='col-sm-3 small text-right' style='padding-top: 3px;'>${d.qty}</div>

View File

@@ -218,6 +218,7 @@ def get_batch_qty(
posting_time=None, posting_time=None,
ignore_voucher_nos=None, ignore_voucher_nos=None,
for_stock_levels=False, for_stock_levels=False,
consider_negative_batches=False,
): ):
"""Returns batch actual qty if warehouse is passed, """Returns batch actual qty if warehouse is passed,
or returns dict of qty by warehouse if warehouse is None or returns dict of qty by warehouse if warehouse is None
@@ -243,6 +244,7 @@ def get_batch_qty(
"batch_no": batch_no, "batch_no": batch_no,
"ignore_voucher_nos": ignore_voucher_nos, "ignore_voucher_nos": ignore_voucher_nos,
"for_stock_levels": for_stock_levels, "for_stock_levels": for_stock_levels,
"consider_negative_batches": consider_negative_batches,
} }
) )

View File

@@ -139,8 +139,8 @@ class StockReconciliation(StockController):
"voucher_type": self.doctype, "voucher_type": self.doctype,
"voucher_no": self.name, "voucher_no": self.name,
"voucher_detail_no": row.name, "voucher_detail_no": row.name,
"qty": row.current_qty, "qty": row.current_qty * -1,
"type_of_transaction": "Outward", "type_of_transaction": "Outward" if row.current_qty > 0 else "Inward",
"company": self.company, "company": self.company,
"is_rejected": 0, "is_rejected": 0,
"serial_nos": get_serial_nos(row.current_serial_no) "serial_nos": get_serial_nos(row.current_serial_no)
@@ -1367,6 +1367,7 @@ def get_stock_balance_for(
posting_date=posting_date, posting_date=posting_date,
posting_time=posting_time, posting_time=posting_time,
for_stock_levels=True, for_stock_levels=True,
consider_negative_batches=True,
) )
or 0 or 0
) )

View File

@@ -1330,6 +1330,84 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
self.assertEqual(stock_value_difference, 1500.00 * -1) self.assertEqual(stock_value_difference, 1500.00 * -1)
def test_stock_reco_for_negative_batch(self):
from erpnext.stock.doctype.batch.batch import get_batch_qty
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
item_code = self.make_item(
"Test Item For Negative Batch",
{
"is_stock_item": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "TEST-BATCH-NB-.###",
},
).name
warehouse = "_Test Warehouse - _TC"
se = make_stock_entry(
posting_date="2024-11-01",
posting_time="11:00",
item_code=item_code,
target=warehouse,
qty=10,
basic_rate=100,
)
batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
se = make_stock_entry(
posting_date="2024-11-01",
posting_time="11:00",
item_code=item_code,
source=warehouse,
qty=10,
basic_rate=100,
use_serial_batch_fields=1,
batch_no=batch_no,
)
sles = frappe.get_all(
"Stock Ledger Entry",
filters={"voucher_no": se.name, "is_cancelled": 0},
)
# intentionally setting negative qty
doc = frappe.get_doc("Stock Ledger Entry", sles[0].name)
doc.db_set(
{
"actual_qty": -20,
"qty_after_transaction": -10,
}
)
sabb_doc = frappe.get_doc("Serial and Batch Bundle", doc.serial_and_batch_bundle)
for row in sabb_doc.entries:
row.db_set("qty", -20)
batch_qty = get_batch_qty(batch_no, warehouse, item_code, consider_negative_batches=True)
self.assertEqual(batch_qty, -10)
sr = create_stock_reconciliation(
posting_date="2024-11-02",
posting_time="11:00",
item_code=item_code,
warehouse=warehouse,
use_serial_batch_fields=1,
batch_no=batch_no,
qty=0,
rate=100,
do_not_submit=True,
)
self.assertEqual(sr.items[0].current_qty, -10)
sr.submit()
sr.reload()
self.assertTrue(sr.items[0].current_serial_and_batch_bundle)
self.assertFalse(sr.items[0].serial_and_batch_bundle)
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)

View File

@@ -418,7 +418,13 @@ class SerialBatchBundle:
batches = frappe._dict({self.sle.batch_no: self.sle.actual_qty}) batches = frappe._dict({self.sle.batch_no: self.sle.actual_qty})
batches_qty = get_available_batches( batches_qty = get_available_batches(
frappe._dict({"item_code": self.item_code, "batch_no": list(batches.keys())}) frappe._dict(
{
"item_code": self.item_code,
"batch_no": list(batches.keys()),
"consider_negative_batches": 1,
}
)
) )
for batch_no in batches: for batch_no in batches: