Skip to content

Commit

Permalink
fix: incorrect current qty for the batch in stock reco (backport #42434
Browse files Browse the repository at this point in the history
…) (backport #42459) (#42463)

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 9cd3374)

Co-authored-by: rohitwaghchaure <[email protected]>
(cherry picked from commit 298a569)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mergify[bot] authored Jul 24, 2024
1 parent e28c1e9 commit 4bae419
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand All @@ -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":
Expand Down
25 changes: 16 additions & 9 deletions erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
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):
Expand Down Expand Up @@ -952,14 +952,21 @@ def recalculate_current_qty(self, voucher_detail_no):
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1182,6 +1183,98 @@ def test_not_reconcile_all_serial_nos(self):
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)
Expand Down

0 comments on commit 4bae419

Please sign in to comment.