fix: incorrect current qty for the batch in stock reco (backport #42434) (#42459)

fix: incorrect current qty for the batch in stock reco (#42434)

(cherry picked from commit 9cd3374101)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
This commit is contained in:
mergify[bot]
2024-07-24 18:37:13 +05:30
committed by GitHub
parent bf34c94483
commit 298a5699f1
3 changed files with 124 additions and 9 deletions

View File

@@ -2188,6 +2188,8 @@ def get_stock_ledgers_for_serial_nos(kwargs):
def get_stock_ledgers_batches(kwargs):
from erpnext.stock.utils import get_combine_datetime
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
batch_table = frappe.qb.DocType("Batch")
@@ -2214,6 +2216,19 @@ def get_stock_ledgers_batches(kwargs):
else:
query = query.where(stock_ledger_entry[field] == kwargs.get(field))
if kwargs.get("posting_date"):
if kwargs.get("posting_time") is None:
kwargs.posting_time = nowtime()
timestamp_condition = stock_ledger_entry.posting_datetime <= get_combine_datetime(
kwargs.posting_date, kwargs.posting_time
)
query = query.where(timestamp_condition)
if kwargs.get("ignore_voucher_nos"):
query = query.where(stock_ledger_entry.voucher_no.notin(kwargs.get("ignore_voucher_nos")))
if kwargs.based_on == "LIFO":
query = query.orderby(batch_table.creation, order=frappe.qb.desc)
elif kwargs.based_on == "Expiry":

View File

@@ -16,7 +16,7 @@ from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle impor
get_available_serial_nos,
)
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.utils import get_stock_balance
from erpnext.stock.utils import get_incoming_rate, get_stock_balance
class OpeningEntryAccountError(frappe.ValidationError):
@@ -952,14 +952,21 @@ class StockReconciliation(StockController):
precesion = row.precision("current_qty")
if flt(current_qty, precesion) != flt(row.current_qty, precesion):
if not row.serial_no:
val_rate = get_valuation_rate(
row.item_code,
row.warehouse,
self.doctype,
self.name,
company=self.company,
batch_no=row.batch_no,
serial_and_batch_bundle=row.current_serial_and_batch_bundle,
val_rate = get_incoming_rate(
frappe._dict(
{
"item_code": row.item_code,
"warehouse": row.warehouse,
"qty": current_qty * -1,
"serial_and_batch_bundle": row.current_serial_and_batch_bundle,
"batch_no": row.batch_no,
"voucher_type": self.doctype,
"voucher_no": self.name,
"company": self.company,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
}
)
)
row.current_valuation_rate = val_rate

View File

@@ -4,6 +4,7 @@
# ERPNext - web based ERP (http://erpnext.com)
# For license information, please see license.txt
import json
import frappe
from frappe.tests.utils import FrappeTestCase, change_settings
@@ -1182,6 +1183,98 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
self.assertAlmostEqual(row.incoming_rate, 1000.00)
self.assertEqual(row.serial_no, serial_nos[row.idx - 1])
def test_stock_reco_with_legacy_batch(self):
from erpnext.stock.doctype.batch.batch import get_batch_qty
batch_item_code = self.make_item(
"Test Batch Item Legacy Batch 1",
{
"is_stock_item": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "BH1-NRALL-S-.###",
},
).name
warehouse = "_Test Warehouse - _TC"
frappe.flags.ignore_serial_batch_bundle_validation = True
frappe.flags.use_serial_and_batch_fields = True
batch_id = "BH1-NRALL-S-0001"
if not frappe.db.exists("Batch", batch_id):
batch_doc = frappe.get_doc(
{
"doctype": "Batch",
"batch_id": batch_id,
"item": batch_item_code,
"use_batchwise_valuation": 0,
}
).insert(ignore_permissions=True)
self.assertTrue(batch_doc.use_batchwise_valuation)
stock_queue = []
qty_after_transaction = 0
balance_value = 0
i = 0
for qty, valuation in {10: 100, 20: 200}.items():
i += 1
stock_queue.append([qty, valuation])
qty_after_transaction += qty
balance_value += qty_after_transaction * valuation
doc = frappe.get_doc(
{
"doctype": "Stock Ledger Entry",
"posting_date": add_days(nowdate(), -2 * i),
"posting_time": nowtime(),
"batch_no": batch_id,
"incoming_rate": valuation,
"qty_after_transaction": qty_after_transaction,
"stock_value_difference": valuation * qty,
"balance_value": balance_value,
"valuation_rate": balance_value / qty_after_transaction,
"actual_qty": qty,
"item_code": batch_item_code,
"warehouse": "_Test Warehouse - _TC",
"stock_queue": json.dumps(stock_queue),
}
)
doc.flags.ignore_permissions = True
doc.flags.ignore_mandatory = True
doc.flags.ignore_links = True
doc.flags.ignore_validate = True
doc.submit()
doc.reload()
frappe.flags.ignore_serial_batch_bundle_validation = False
frappe.flags.use_serial_and_batch_fields = False
batch_doc = frappe.get_doc("Batch", batch_id)
qty = get_batch_qty(batch_id, warehouse, batch_item_code)
self.assertEqual(qty, 30)
sr = create_stock_reconciliation(
item_code=batch_item_code,
posting_date=add_days(nowdate(), -3),
posting_time=nowtime(),
warehouse=warehouse,
qty=100,
rate=1000,
reconcile_all_serial_batch=0,
batch_no=batch_id,
use_serial_batch_fields=1,
)
self.assertEqual(sr.items[0].current_qty, 20)
self.assertEqual(sr.items[0].qty, 100)
qty = get_batch_qty(batch_id, warehouse, batch_item_code)
self.assertEqual(qty, 110)
def create_batch_item_with_batch(item_name, batch_id):
batch_item_doc = create_item(item_name, is_stock_item=1)