Merge branch 'develop' into lcv-future-stock-update
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 1ba8011..979b5c4 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -4,7 +4,7 @@
 
 import frappe
 from frappe.tests.utils import FrappeTestCase
-from frappe.utils import add_to_date, flt, now
+from frappe.utils import add_days, add_to_date, flt, now
 
 from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
@@ -120,6 +120,61 @@
 					expected_values[gle.account][1], gle.credit, msg=f"incorrect credit for {gle.account}"
 				)
 
+	def test_landed_cost_voucher_stock_impact(self):
+		"Test impact of LCV on future stock balances."
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		item = make_item("LCV Stock Item", {"is_stock_item": 1})
+		warehouse = "Stores - _TC"
+
+		pr1 = make_purchase_receipt(
+			item_code=item.name,
+			warehouse=warehouse,
+			qty=500,
+			rate=80,
+			posting_date=add_days(frappe.utils.nowdate(), -2),
+		)
+		pr2 = make_purchase_receipt(
+			item_code=item.name,
+			warehouse=warehouse,
+			qty=100,
+			rate=80,
+			posting_date=frappe.utils.nowdate(),
+		)
+
+		last_sle = frappe.db.get_value(  # SLE of second PR
+			"Stock Ledger Entry",
+			{
+				"voucher_type": pr2.doctype,
+				"voucher_no": pr2.name,
+				"item_code": item.name,
+				"warehouse": warehouse,
+				"is_cancelled": 0,
+			},
+			fieldname=["qty_after_transaction", "stock_value"],
+			as_dict=1,
+		)
+
+		create_landed_cost_voucher("Purchase Receipt", pr1.name, pr1.company)
+
+		last_sle_after_landed_cost = frappe.db.get_value(  # SLE of second PR after LCV's effect
+			"Stock Ledger Entry",
+			{
+				"voucher_type": pr2.doctype,
+				"voucher_no": pr2.name,
+				"item_code": item.name,
+				"warehouse": warehouse,
+				"is_cancelled": 0,
+			},
+			fieldname=["qty_after_transaction", "stock_value"],
+			as_dict=1,
+		)
+
+		self.assertEqual(
+			last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction
+		)
+		self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 50.0)
+
 	def test_landed_cost_voucher_against_purchase_invoice(self):
 
 		pi = make_purchase_invoice(
@@ -219,11 +274,11 @@
 		landed costs, this should be allowed for serial nos too.
 
 		Case:
-		        - receipt a serial no @ X rate
-		        - delivery the serial no @ X rate
-		        - add LCV to receipt X + Y
-		        - LCV should be successful
-		        - delivery should reflect X+Y valuation.
+		                - receipt a serial no @ X rate
+		                - delivery the serial no @ X rate
+		                - add LCV to receipt X + Y
+		                - LCV should be successful
+		                - delivery should reflect X+Y valuation.
 		"""
 		serial_no = "LCV_TEST_SR_NO"
 		item_code = "_Test Serialized Item"
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index b1842e7..c146e42 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -95,27 +95,26 @@
 		if not args.get("posting_date"):
 			args["posting_date"] = nowdate()
 
-		if args.get("is_cancelled") and via_landed_cost_voucher:
-			return
-
-		# Reposts only current voucher SL Entries
-		# Updates valuation rate, stock value, stock queue for current transaction
-		update_entries_after(
-			{
-				"item_code": args.get("item_code"),
-				"warehouse": args.get("warehouse"),
-				"posting_date": args.get("posting_date"),
-				"posting_time": args.get("posting_time"),
-				"voucher_type": args.get("voucher_type"),
-				"voucher_no": args.get("voucher_no"),
-				"sle_id": args.get("name"),
-				"creation": args.get("creation"),
-			},
-			allow_negative_stock=allow_negative_stock,
-			via_landed_cost_voucher=via_landed_cost_voucher,
-		)
+		if not (args.get("is_cancelled") and via_landed_cost_voucher):
+			# Reposts only current voucher SL Entries
+			# Updates valuation rate, stock value, stock queue for current transaction
+			update_entries_after(
+				{
+					"item_code": args.get("item_code"),
+					"warehouse": args.get("warehouse"),
+					"posting_date": args.get("posting_date"),
+					"posting_time": args.get("posting_time"),
+					"voucher_type": args.get("voucher_type"),
+					"voucher_no": args.get("voucher_no"),
+					"sle_id": args.get("name"),
+					"creation": args.get("creation"),
+				},
+				allow_negative_stock=allow_negative_stock,
+				via_landed_cost_voucher=via_landed_cost_voucher,
+			)
 
 		# update qty in future sle and Validate negative qty
+		# For LCV: update future balances with -ve LCV SLE, which will be balanced by +ve LCV SLE
 		update_qty_in_future_sle(args, allow_negative_stock)