fix: serial no valuation rate (#40221)
This commit is contained in:
parent
863abc3ee5
commit
a5232d9c10
@ -8,9 +8,12 @@ from pypika import Order
|
||||
class DeprecatedSerialNoValuation:
|
||||
@deprecated
|
||||
def calculate_stock_value_from_deprecarated_ledgers(self):
|
||||
serial_nos = list(
|
||||
filter(lambda x: x not in self.serial_no_incoming_rate and x, self.get_serial_nos())
|
||||
)
|
||||
if not frappe.db.get_value(
|
||||
"Stock Ledger Entry", {"serial_no": ("is", "set"), "is_cancelled": 0}, "name"
|
||||
):
|
||||
return
|
||||
|
||||
serial_nos = self.get_serial_nos()
|
||||
|
||||
actual_qty = flt(self.sle.actual_qty)
|
||||
|
||||
@ -25,23 +28,12 @@ class DeprecatedSerialNoValuation:
|
||||
@deprecated
|
||||
def get_incoming_value_for_serial_nos(self, serial_nos):
|
||||
# get rate from serial nos within same company
|
||||
all_serial_nos = frappe.get_all(
|
||||
"Serial No", fields=["purchase_rate", "name", "company"], filters={"name": ("in", serial_nos)}
|
||||
)
|
||||
|
||||
incoming_values = 0.0
|
||||
for d in all_serial_nos:
|
||||
if d.company == self.sle.company:
|
||||
self.serial_no_incoming_rate[d.name] += flt(d.purchase_rate)
|
||||
incoming_values += flt(d.purchase_rate)
|
||||
|
||||
# Get rate for serial nos which has been transferred to other company
|
||||
invalid_serial_nos = [d.name for d in all_serial_nos if d.company != self.sle.company]
|
||||
for serial_no in invalid_serial_nos:
|
||||
for serial_no in serial_nos:
|
||||
table = frappe.qb.DocType("Stock Ledger Entry")
|
||||
incoming_rate = (
|
||||
stock_ledgers = (
|
||||
frappe.qb.from_(table)
|
||||
.select(table.incoming_rate)
|
||||
.select(table.incoming_rate, table.actual_qty, table.stock_value_difference)
|
||||
.where(
|
||||
(
|
||||
(table.serial_no == serial_no)
|
||||
@ -51,15 +43,18 @@ class DeprecatedSerialNoValuation:
|
||||
)
|
||||
& (table.company == self.sle.company)
|
||||
& (table.serial_and_batch_bundle.isnull())
|
||||
& (table.actual_qty > 0)
|
||||
& (table.is_cancelled == 0)
|
||||
)
|
||||
.orderby(table.posting_date, order=Order.desc)
|
||||
.limit(1)
|
||||
).run()
|
||||
.orderby(table.posting_datetime, order=Order.desc)
|
||||
).run(as_dict=1)
|
||||
|
||||
self.serial_no_incoming_rate[serial_no] += flt(incoming_rate[0][0]) if incoming_rate else 0
|
||||
incoming_values += self.serial_no_incoming_rate[serial_no]
|
||||
for sle in stock_ledgers:
|
||||
self.serial_no_incoming_rate[serial_no] += (
|
||||
flt(sle.incoming_rate)
|
||||
if sle.actual_qty > 0
|
||||
else (sle.stock_value_difference / sle.actual_qty) * -1
|
||||
)
|
||||
incoming_values += self.serial_no_incoming_rate[serial_no]
|
||||
|
||||
return incoming_values
|
||||
|
||||
|
@ -2118,7 +2118,7 @@ def is_serial_batch_no_exists(item_code, type_of_transaction, serial_no=None, ba
|
||||
|
||||
make_serial_no(serial_no, item_code)
|
||||
|
||||
if batch_no and frappe.db.exists("Batch", batch_no):
|
||||
if batch_no and not frappe.db.exists("Batch", batch_no):
|
||||
if type_of_transaction != "Inward":
|
||||
frappe.throw(_("Batch No {0} does not exists").format(batch_no))
|
||||
|
||||
|
@ -540,6 +540,110 @@ class TestSerialandBatchBundle(FrappeTestCase):
|
||||
|
||||
self.assertRaises(frappe.exceptions.ValidationError, pr2.save)
|
||||
|
||||
def test_serial_no_valuation_for_legacy_ledgers(self):
|
||||
sn_item = make_item(
|
||||
"Test Serial No Valuation for Legacy Ledgers",
|
||||
properties={"has_serial_no": 1, "serial_no_series": "SNN-TSNVL.-#####"},
|
||||
).name
|
||||
|
||||
serial_nos = []
|
||||
for serial_no in [f"{sn_item}-0001", f"{sn_item}-0002"]:
|
||||
if not frappe.db.exists("Serial No", serial_no):
|
||||
sn_doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Serial No",
|
||||
"serial_no": serial_no,
|
||||
"item_code": sn_item,
|
||||
}
|
||||
).insert(ignore_permissions=True)
|
||||
serial_nos.append(serial_no)
|
||||
|
||||
frappe.flags.ignore_serial_batch_bundle_validation = True
|
||||
|
||||
qty_after_transaction = 0.0
|
||||
stock_value = 0.0
|
||||
for row in [{"qty": 2, "rate": 100}, {"qty": -2, "rate": 100}, {"qty": 2, "rate": 200}]:
|
||||
row = frappe._dict(row)
|
||||
qty_after_transaction += row.qty
|
||||
stock_value += row.rate * row.qty
|
||||
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Stock Ledger Entry",
|
||||
"posting_date": today(),
|
||||
"posting_time": nowtime(),
|
||||
"incoming_rate": row.rate if row.qty > 0 else 0,
|
||||
"qty_after_transaction": qty_after_transaction,
|
||||
"stock_value_difference": row.rate * row.qty,
|
||||
"stock_value": stock_value,
|
||||
"valuation_rate": row.rate,
|
||||
"actual_qty": row.qty,
|
||||
"item_code": sn_item,
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"serial_no": "\n".join(serial_nos),
|
||||
"company": "_Test Company",
|
||||
}
|
||||
)
|
||||
doc.flags.ignore_permissions = True
|
||||
doc.flags.ignore_mandatory = True
|
||||
doc.flags.ignore_links = True
|
||||
doc.flags.ignore_validate = True
|
||||
doc.submit()
|
||||
|
||||
for sn in serial_nos:
|
||||
sn_doc = frappe.get_doc("Serial No", sn)
|
||||
if row.qty > 0:
|
||||
sn_doc.db_set("warehouse", "_Test Warehouse - _TC")
|
||||
else:
|
||||
sn_doc.db_set("warehouse", "")
|
||||
|
||||
frappe.flags.ignore_serial_batch_bundle_validation = False
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=sn_item,
|
||||
qty=2,
|
||||
source="_Test Warehouse - _TC",
|
||||
serial_no="\n".join(serial_nos),
|
||||
use_serial_batch_fields=True,
|
||||
do_not_submit=True,
|
||||
)
|
||||
|
||||
se.save()
|
||||
se.submit()
|
||||
|
||||
stock_value_difference = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": se.name, "is_cancelled": 0, "voucher_type": "Stock Entry"},
|
||||
"stock_value_difference",
|
||||
)
|
||||
|
||||
self.assertEqual(flt(stock_value_difference, 2), 400.0 * -1)
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=sn_item,
|
||||
qty=1,
|
||||
rate=353,
|
||||
target="_Test Warehouse - _TC",
|
||||
)
|
||||
|
||||
serial_no = get_serial_nos_from_bundle(se.items[0].serial_and_batch_bundle)[0]
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=sn_item,
|
||||
qty=1,
|
||||
source="_Test Warehouse - _TC",
|
||||
serial_no=serial_no,
|
||||
use_serial_batch_fields=True,
|
||||
)
|
||||
|
||||
stock_value_difference = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": se.name, "is_cancelled": 0, "voucher_type": "Stock Entry"},
|
||||
"stock_value_difference",
|
||||
)
|
||||
|
||||
self.assertEqual(flt(stock_value_difference, 2), 353.0 * -1)
|
||||
|
||||
|
||||
def get_batch_from_bundle(bundle):
|
||||
from erpnext.stock.serial_batch_bundle import get_batch_nos
|
||||
|
Loading…
x
Reference in New Issue
Block a user