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:
@@ -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":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user