fix: valuation rate for the subcontracting receipt supplied items with Serial and Batch Bundle (#38094)
fix: valuation rate for the subcontracting receipt supplied items with batch
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 5fa66b1..3d55a08 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -626,6 +626,18 @@
(row.item_code, row.get(self.subcontract_data.order_field))
] -= row.qty
+ def __set_rate_for_serial_and_batch_bundle(self):
+ if self.doctype != "Subcontracting Receipt":
+ return
+
+ for row in self.get(self.raw_material_table):
+ if not row.get("serial_and_batch_bundle"):
+ continue
+
+ row.rate = frappe.get_cached_value(
+ "Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"
+ )
+
def __modify_serial_and_batch_bundle(self):
if self.is_new():
return
@@ -681,6 +693,7 @@
self.__remove_changed_rows()
self.__set_supplied_items()
self.__modify_serial_and_batch_bundle()
+ self.__set_rate_for_serial_and_batch_bundle()
def __validate_batch_no(self, row, key):
if row.get("batch_no") and row.get("batch_no") not in self.__transferred_items.get(key).get(
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
index dcbd9b2..be37994 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
@@ -12,6 +12,7 @@
"posting_date",
"posting_time",
"is_adjustment_entry",
+ "auto_created_serial_and_batch_bundle",
"column_break_6",
"voucher_type",
"voucher_no",
@@ -340,6 +341,13 @@
"fieldname": "is_adjustment_entry",
"fieldtype": "Check",
"label": "Is Adjustment Entry"
+ },
+ {
+ "default": "0",
+ "depends_on": "serial_and_batch_bundle",
+ "fieldname": "auto_created_serial_and_batch_bundle",
+ "fieldtype": "Check",
+ "label": "Auto Created Serial and Batch Bundle"
}
],
"hide_toolbar": 1,
@@ -348,7 +356,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2023-10-23 18:07:42.063615",
+ "modified": "2023-11-14 16:47:39.791967",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Ledger Entry",
diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py
index 5998274..da98455 100644
--- a/erpnext/stock/serial_batch_bundle.py
+++ b/erpnext/stock/serial_batch_bundle.py
@@ -129,7 +129,9 @@
frappe.throw(_(error_msg))
def set_serial_and_batch_bundle(self, sn_doc):
- self.sle.db_set("serial_and_batch_bundle", sn_doc.name)
+ self.sle.db_set(
+ {"serial_and_batch_bundle": sn_doc.name, "auto_created_serial_and_batch_bundle": 1}
+ )
if sn_doc.is_rejected:
frappe.db.set_value(
@@ -143,6 +145,12 @@
@property
def child_doctype(self):
child_doctype = self.sle.voucher_type + " Item"
+
+ if (
+ self.sle.voucher_type == "Subcontracting Receipt" and self.sle.dependant_sle_voucher_detail_no
+ ):
+ child_doctype = "Subcontracting Receipt Supplied Item"
+
if self.sle.voucher_type == "Stock Entry":
child_doctype = "Stock Entry Detail"
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 6390894..9142a27 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -766,7 +766,9 @@
sle.doctype = "Stock Ledger Entry"
frappe.get_doc(sle).db_update()
- if not self.args.get("sle_id"):
+ if not self.args.get("sle_id") or (
+ sle.serial_and_batch_bundle and sle.auto_created_serial_and_batch_bundle
+ ):
self.update_outgoing_rate_on_transaction(sle)
def reset_actual_qty_for_stock_reco(self, sle):
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
index 19a1c93..36001eb 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
@@ -13,6 +13,16 @@
frm.trigger('set_queries');
},
+ on_submit(frm) {
+ frm.events.refresh_serial_batch_bundle_field(frm);
+ },
+
+ refresh_serial_batch_bundle_field(frm) {
+ frappe.route_hooks.after_submit = (frm_obj) => {
+ frm_obj.reload_doc();
+ }
+ },
+
refresh: (frm) => {
if (frm.doc.docstatus > 0) {
frm.add_custom_button(__('Stock Ledger'), () => {
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
index 96babf2..6191a8c 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
@@ -576,6 +576,97 @@
self.assertEqual(scr.items[0].rm_cost_per_qty, 300)
self.assertEqual(scr.items[0].service_cost_per_qty, 100)
+ def test_subcontracting_receipt_valuation_with_auto_created_serial_batch_bundle(self):
+ set_backflush_based_on("BOM")
+
+ fg_item = make_item(properties={"is_stock_item": 1, "is_sub_contracted_item": 1}).name
+ rm_item1 = make_item(
+ properties={
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "BNGS-.####",
+ }
+ ).name
+
+ rm_item2 = make_item(
+ properties={
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "has_serial_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "BNGS-.####",
+ "serial_no_series": "BNSS-.####",
+ }
+ ).name
+
+ rm_item3 = make_item(
+ properties={
+ "is_stock_item": 1,
+ "has_serial_no": 1,
+ "serial_no_series": "BSSSS-.####",
+ }
+ ).name
+
+ bom = make_bom(item=fg_item, raw_materials=[rm_item1, rm_item2, rm_item3])
+
+ rm_batch_no = None
+ for row in bom.items:
+ make_stock_entry(
+ item_code=row.item_code,
+ qty=1,
+ target="_Test Warehouse 1 - _TC",
+ rate=300,
+ )
+
+ make_stock_entry(
+ item_code=row.item_code,
+ qty=1,
+ target="_Test Warehouse 1 - _TC",
+ rate=400,
+ )
+
+ service_items = [
+ {
+ "warehouse": "_Test Warehouse - _TC",
+ "item_code": "Subcontracted Service Item 1",
+ "qty": 1,
+ "rate": 100,
+ "fg_item": fg_item,
+ "fg_item_qty": 1,
+ },
+ ]
+ sco = get_subcontracting_order(service_items=service_items)
+
+ frappe.db.set_single_value(
+ "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1
+ )
+ scr = make_subcontracting_receipt(sco.name)
+ scr.save()
+ for row in scr.supplied_items:
+ self.assertNotEqual(row.rate, 300.00)
+ self.assertFalse(row.serial_and_batch_bundle)
+
+ scr.submit()
+ scr.reload()
+
+ for row in scr.supplied_items:
+ self.assertEqual(row.rate, 300.00)
+ self.assertTrue(row.serial_and_batch_bundle)
+ auto_created_serial_batch = frappe.db.get_value(
+ "Stock Ledger Entry",
+ {"voucher_no": scr.name, "voucher_detail_no": row.name},
+ "auto_created_serial_and_batch_bundle",
+ )
+
+ self.assertTrue(auto_created_serial_batch)
+
+ self.assertEqual(scr.items[0].rm_cost_per_qty, 900)
+ self.assertEqual(scr.items[0].service_cost_per_qty, 100)
+ frappe.db.set_single_value(
+ "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0
+ )
+
def test_subcontracting_receipt_raw_material_rate(self):
# Step - 1: Set Backflush Based On as "BOM"
set_backflush_based_on("BOM")