Merge branch 'develop' into FIX-ISS-23-24-00368
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 0575429..c3fa894 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -741,7 +741,7 @@
 					sco_doc = frappe.get_doc("Subcontracting Order", sco)
 					sco_doc.update_status()
 
-	def set_missing_values_in_additional_costs(self):
+	def calculate_additional_costs(self):
 		self.total_additional_costs = sum(flt(item.amount) for item in self.get("additional_costs"))
 
 		if self.total_additional_costs:
diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py
index 0e6fe95..4ea4fd1 100644
--- a/erpnext/controllers/tests/test_subcontracting_controller.py
+++ b/erpnext/controllers/tests/test_subcontracting_controller.py
@@ -36,7 +36,7 @@
 		sco.remove_empty_rows()
 		self.assertEqual((len_before - 1), len(sco.service_items))
 
-	def test_set_missing_values_in_additional_costs(self):
+	def test_calculate_additional_costs(self):
 		sco = get_subcontracting_order(do_not_submit=1)
 
 		rate_without_additional_cost = sco.items[0].rate
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 103ed4a..6106809 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -781,13 +781,21 @@
 				d.db_update()
 
 	def update_rate_on_subcontracting_receipt(self, sle, outgoing_rate):
-		if frappe.db.exists(sle.voucher_type + " Item", sle.voucher_detail_no):
-			frappe.db.set_value(sle.voucher_type + " Item", sle.voucher_detail_no, "rate", outgoing_rate)
+		if frappe.db.exists("Subcontracting Receipt Item", sle.voucher_detail_no):
+			frappe.db.set_value("Subcontracting Receipt Item", sle.voucher_detail_no, "rate", outgoing_rate)
 		else:
 			frappe.db.set_value(
-				"Subcontracting Receipt Supplied Item", sle.voucher_detail_no, "rate", outgoing_rate
+				"Subcontracting Receipt Supplied Item",
+				sle.voucher_detail_no,
+				{"rate": outgoing_rate, "amount": abs(sle.actual_qty) * outgoing_rate},
 			)
 
+		scr = frappe.get_doc("Subcontracting Receipt", sle.voucher_no, for_update=True)
+		scr.calculate_items_qty_and_amount()
+		scr.db_update()
+		for d in scr.items:
+			d.db_update()
+
 	def get_serialized_values(self, sle):
 		incoming_rate = flt(sle.incoming_rate)
 		actual_qty = flt(sle.actual_qty)
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py
index e6de72d..3919733 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py
+++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py
@@ -77,22 +77,22 @@
 					frappe.throw(_(msg))
 
 	def set_missing_values(self):
-		self.set_missing_values_in_additional_costs()
-		self.set_missing_values_in_service_items()
-		self.set_missing_values_in_supplied_items()
-		self.set_missing_values_in_items()
+		self.calculate_additional_costs()
+		self.calculate_service_costs()
+		self.calculate_supplied_items_qty_and_amount()
+		self.calculate_items_qty_and_amount()
 
-	def set_missing_values_in_service_items(self):
+	def calculate_service_costs(self):
 		for idx, item in enumerate(self.get("service_items")):
 			self.items[idx].service_cost_per_qty = item.amount / self.items[idx].qty
 
-	def set_missing_values_in_supplied_items(self):
+	def calculate_supplied_items_qty_and_amount(self):
 		for item in self.get("items"):
 			bom = frappe.get_doc("BOM", item.bom)
 			rm_cost = sum(flt(rm_item.amount) for rm_item in bom.items)
 			item.rm_cost_per_qty = rm_cost / flt(bom.quantity)
 
-	def set_missing_values_in_items(self):
+	def calculate_items_qty_and_amount(self):
 		total_qty = total = 0
 		for item in self.items:
 			item.rate = item.rm_cost_per_qty + item.service_cost_per_qty + flt(item.additional_cost_per_qty)
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
index 4f8e045..2c84262 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
@@ -113,9 +113,9 @@
 
 	@frappe.whitelist()
 	def set_missing_values(self):
-		self.set_missing_values_in_additional_costs()
-		self.set_missing_values_in_supplied_items()
-		self.set_missing_values_in_items()
+		self.calculate_additional_costs()
+		self.calculate_supplied_items_qty_and_amount()
+		self.calculate_items_qty_and_amount()
 
 	def set_available_qty_for_consumption(self):
 		supplied_items_details = {}
@@ -147,13 +147,13 @@
 					item.rm_item_code, 0
 				)
 
-	def set_missing_values_in_supplied_items(self):
+	def calculate_supplied_items_qty_and_amount(self):
 		for item in self.get("supplied_items") or []:
 			item.amount = item.rate * item.consumed_qty
 
 		self.set_available_qty_for_consumption()
 
-	def set_missing_values_in_items(self):
+	def calculate_items_qty_and_amount(self):
 		rm_supp_cost = {}
 		for item in self.get("supplied_items") or []:
 			if item.reference_name in rm_supp_cost:
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
index 72ed4d4..dfb72c3 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
@@ -6,7 +6,7 @@
 
 import frappe
 from frappe.tests.utils import FrappeTestCase
-from frappe.utils import cint, flt
+from frappe.utils import add_days, cint, cstr, flt, today
 
 import erpnext
 from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -26,6 +26,9 @@
 from erpnext.stock.doctype.item.test_item import make_item
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
+	create_stock_reconciliation,
+)
 from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
 	make_subcontracting_receipt,
 )
@@ -528,6 +531,69 @@
 		# consumed_qty should be (accepted_qty * qty_consumed_per_unit) = (6 * 1) = 6
 		self.assertEqual(scr.supplied_items[0].consumed_qty, 6)
 
+	def test_supplied_items_cost_after_reposting(self):
+		# Set Backflush Based On as "BOM"
+		set_backflush_based_on("BOM")
+
+		# Create Material Receipt for RM's
+		make_stock_entry(
+			item_code="_Test Item",
+			qty=100,
+			target="_Test Warehouse 1 - _TC",
+			basic_rate=100,
+			posting_date=add_days(today(), -2),
+		)
+		make_stock_entry(
+			item_code="_Test Item Home Desktop 100",
+			qty=100,
+			target="_Test Warehouse 1 - _TC",
+			basic_rate=100,
+		)
+
+		service_items = [
+			{
+				"warehouse": "_Test Warehouse - _TC",
+				"item_code": "Subcontracted Service Item 1",
+				"qty": 10,
+				"rate": 100,
+				"fg_item": "_Test FG Item",
+				"fg_item_qty": 10,
+			},
+		]
+
+		# Create Subcontracting Order
+		sco = get_subcontracting_order(service_items=service_items)
+
+		# Transfer RM's
+		rm_items = get_rm_items(sco.supplied_items)
+
+		itemwise_details = make_stock_in_entry(rm_items=rm_items)
+		make_stock_transfer_entry(
+			sco_no=sco.name,
+			rm_items=rm_items,
+			itemwise_details=copy.deepcopy(itemwise_details),
+		)
+
+		# Create Subcontracting Receipt
+		scr = make_subcontracting_receipt(sco.name)
+		scr.save()
+		scr.submit()
+
+		# Create Backdated Stock Reconciliation
+		sr = create_stock_reconciliation(
+			item_code=rm_items[0].get("item_code"),
+			warehouse="_Test Warehouse 1 - _TC",
+			qty=100,
+			rate=50,
+			posting_date=add_days(today(), -1),
+		)
+
+		# Cost should be updated in Subcontracting Receipt after reposting
+		prev_cost = scr.supplied_items[0].rate
+		scr.load_from_db()
+		self.assertNotEqual(scr.supplied_items[0].rate, prev_cost)
+		self.assertEqual(scr.supplied_items[0].rate, sr.items[0].valuation_rate)
+
 
 def make_return_subcontracting_receipt(**args):
 	args = frappe._dict(args)