Merge pull request #32063 from rohitwaghchaure/fixed-fetch-from-parent

fix: inventory dimension issues
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index a3d41ab..5e9c069 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -311,6 +311,7 @@
 									"sales_invoice_item": d.get("sales_invoice_item"),
 									"dn_detail": d.get("dn_detail"),
 									"incoming_rate": p.get("incoming_rate"),
+									"item_row": p,
 								}
 							)
 						)
@@ -334,6 +335,7 @@
 							"sales_invoice_item": d.get("sales_invoice_item"),
 							"dn_detail": d.get("dn_detail"),
 							"incoming_rate": d.get("incoming_rate"),
+							"item_row": d,
 						}
 					)
 				)
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 36bed36..d4f9aba 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -390,6 +390,10 @@
 		return sl_dict
 
 	def update_inventory_dimensions(self, row, sl_dict) -> None:
+		# To handle delivery note and sales invoice
+		if row.get("item_row"):
+			row = row.get("item_row")
+
 		dimensions = get_evaluated_inventory_dimension(row, sl_dict, parent_doc=self)
 		for dimension in dimensions:
 			if not dimension:
@@ -407,9 +411,17 @@
 						"DocField", {"parent": self.doctype, "options": dimension.fetch_from_parent}, "fieldname"
 					)
 
+					if not fieldname:
+						fieldname = frappe.get_cached_value(
+							"Custom Field", {"dt": self.doctype, "options": dimension.fetch_from_parent}, "fieldname"
+						)
+
 					if fieldname and self.get(fieldname):
 						sl_dict[dimension.target_fieldname] = self.get(fieldname)
 
+				if sl_dict[dimension.target_fieldname] and self.docstatus == 1:
+					row.db_set(dimension.source_fieldname, sl_dict[dimension.target_fieldname])
+
 	def make_sl_entries(self, sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
 		from erpnext.stock.stock_ledger import make_sl_entries
 
diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.js b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.js
index 07cb73b..79e7895 100644
--- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.js
+++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.js
@@ -30,6 +30,7 @@
 
 	onload(frm) {
 		frm.trigger('render_traget_field');
+		frm.trigger("set_parent_fields");
 	},
 
 	refresh(frm) {
@@ -52,6 +53,30 @@
 		}
 	},
 
+	document_type(frm) {
+		frm.trigger("set_parent_fields");
+	},
+
+	set_parent_fields(frm) {
+		if (frm.doc.apply_to_all_doctypes) {
+			frm.set_df_property("fetch_from_parent", "options", frm.doc.reference_document);
+		} else if (frm.doc.document_type && frm.doc.istable) {
+			frappe.call({
+				method: 'erpnext.stock.doctype.inventory_dimension.inventory_dimension.get_parent_fields',
+				args: {
+					child_doctype: frm.doc.document_type,
+					dimension_name: frm.doc.reference_document
+				},
+				callback: (r) => {
+					if (r.message && r.message.length) {
+						frm.set_df_property("fetch_from_parent", "options",
+							[""].concat(r.message));
+					}
+				}
+			});
+		}
+	},
+
 	delete_dimension(frm) {
 		let msg = (`
 			Custom fields related to this dimension will be deleted on deletion of dimension.
diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.json b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.json
index 03e7fda..09f4f63 100644
--- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.json
+++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.json
@@ -144,16 +144,15 @@
    "fieldtype": "Column Break"
   },
   {
-   "depends_on": "istable",
    "description": "Set fieldname or DocType name like Supplier, Customer etc.",
    "fieldname": "fetch_from_parent",
-   "fieldtype": "Data",
+   "fieldtype": "Select",
    "label": "Fetch Value From Parent Form"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2022-08-17 11:43:24.722441",
+ "modified": "2022-09-02 13:29:04.098469",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Inventory Dimension",
diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py
index 4ff8f33..9e8c10b 100644
--- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py
+++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py
@@ -236,3 +236,30 @@
 def delete_dimension(dimension):
 	doc = frappe.get_doc("Inventory Dimension", dimension)
 	doc.delete()
+
+
+@frappe.whitelist()
+def get_parent_fields(child_doctype, dimension_name):
+	parent_doctypes = frappe.get_all(
+		"DocField", fields=["parent"], filters={"options": child_doctype}
+	)
+
+	fields = []
+
+	fields.extend(
+		frappe.get_all(
+			"DocField",
+			fields=["fieldname as value", "label"],
+			filters={"options": dimension_name, "parent": ("in", [d.parent for d in parent_doctypes])},
+		)
+	)
+
+	fields.extend(
+		frappe.get_all(
+			"Custom Field",
+			fields=["fieldname as value", "label"],
+			filters={"options": dimension_name, "dt": ("in", [d.parent for d in parent_doctypes])},
+		)
+	)
+
+	return fields
diff --git a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py
index cc90b74..19ddc44 100644
--- a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py
+++ b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py
@@ -2,14 +2,17 @@
 # See license.txt
 
 import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
 from frappe.tests.utils import FrappeTestCase
 
+from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
 from erpnext.stock.doctype.inventory_dimension.inventory_dimension import (
 	CanNotBeChildDoc,
 	CanNotBeDefaultDimension,
 	DoNotChangeError,
 	delete_dimension,
 )
+from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
 
@@ -136,6 +139,58 @@
 		self.assertTrue(inv_dim1.has_stock_ledger())
 		self.assertRaises(DoNotChangeError, inv_dim1.save)
 
+	def test_inventory_dimension_for_purchase_receipt_and_delivery_note(self):
+		create_inventory_dimension(
+			reference_document="Rack",
+			type_of_transaction="Both",
+			dimension_name="Rack",
+			apply_to_all_doctypes=1,
+			fetch_from_parent="Rack",
+		)
+
+		create_custom_field(
+			"Purchase Receipt", dict(fieldname="rack", label="Rack", fieldtype="Link", options="Rack")
+		)
+
+		create_custom_field(
+			"Delivery Note", dict(fieldname="rack", label="Rack", fieldtype="Link", options="Rack")
+		)
+
+		frappe.reload_doc("stock", "doctype", "purchase_receipt_item")
+		frappe.reload_doc("stock", "doctype", "delivery_note_item")
+
+		pr_doc = make_purchase_receipt(qty=2, do_not_submit=True)
+		pr_doc.rack = "Rack 1"
+		pr_doc.save()
+		pr_doc.submit()
+
+		pr_doc.load_from_db()
+
+		self.assertEqual(pr_doc.items[0].rack, "Rack 1")
+		sle_rack = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{"voucher_detail_no": pr_doc.items[0].name, "voucher_type": pr_doc.doctype},
+			"rack",
+		)
+
+		self.assertEqual(sle_rack, "Rack 1")
+
+		dn_doc = create_delivery_note(qty=2, do_not_submit=True)
+		dn_doc.rack = "Rack 1"
+		dn_doc.save()
+		dn_doc.submit()
+
+		dn_doc.load_from_db()
+
+		self.assertEqual(dn_doc.items[0].rack, "Rack 1")
+		sle_rack = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{"voucher_detail_no": dn_doc.items[0].name, "voucher_type": dn_doc.doctype},
+			"rack",
+		)
+
+		self.assertEqual(sle_rack, "Rack 1")
+
 
 def prepare_test_data():
 	if not frappe.db.exists("DocType", "Shelf"):
@@ -160,6 +215,28 @@
 
 	create_warehouse("Shelf Warehouse")
 
+	if not frappe.db.exists("DocType", "Rack"):
+		frappe.get_doc(
+			{
+				"doctype": "DocType",
+				"name": "Rack",
+				"module": "Stock",
+				"custom": 1,
+				"naming_rule": "By fieldname",
+				"autoname": "field:rack_name",
+				"fields": [{"label": "Rack Name", "fieldname": "rack_name", "fieldtype": "Data"}],
+				"permissions": [
+					{"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1}
+				],
+			}
+		).insert(ignore_permissions=True)
+
+	for rack in ["Rack 1"]:
+		if not frappe.db.exists("Rack", rack):
+			frappe.get_doc({"doctype": "Rack", "rack_name": rack}).insert(ignore_permissions=True)
+
+	create_warehouse("Rack Warehouse")
+
 
 def create_inventory_dimension(**args):
 	args = frappe._dict(args)