Merge pull request #32156 from ruthra-kumar/bug_multiple_call_to_ple_creation

fix: remove duplicate call to ple creation
diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml
new file mode 100644
index 0000000..ef38974
--- /dev/null
+++ b/.github/workflows/initiate_release.yml
@@ -0,0 +1,32 @@
+# This workflow is agnostic to branches. Only maintain on develop branch.
+# To add/remove versions just modify the matrix.
+
+name: Create weekly release pull requests
+on:
+  schedule:
+    # 9:30 UTC => 3 PM IST Tuesday
+    - cron: "30 9 * * 2"
+  workflow_dispatch:
+
+jobs:
+  release:
+    name: Release
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        version: ["13", "14"]
+
+    steps:
+      - uses: octokit/request-action@v2.x
+        with:
+          route: POST /repos/{owner}/{repo}/pulls
+          owner: frappe
+          repo: erpnext
+          title: |-
+            "chore: release v${{ matrix.version }}"
+          body: "Automated weekly release."
+          base: version-${{ matrix.version }}
+          head: version-${{ matrix.version }}-hotfix
+        env:
+          GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
index a964965..f745620 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
@@ -141,7 +141,7 @@
 	},
 
 	show_import_status(frm) {
-		let import_log = JSON.parse(frm.doc.import_log || "[]");
+		let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
 		let successful_records = import_log.filter((log) => log.success);
 		let failed_records = import_log.filter((log) => !log.success);
 		if (successful_records.length === 0) return;
@@ -309,7 +309,7 @@
 	// method: 'frappe.core.doctype.data_import.data_import.get_preview_from_template',
 
 	show_import_preview(frm, preview_data) {
-		let import_log = JSON.parse(frm.doc.import_log || "[]");
+		let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
 
 		if (
 			frm.import_preview &&
@@ -439,7 +439,7 @@
 	},
 
 	show_import_log(frm) {
-		let import_log = JSON.parse(frm.doc.import_log || "[]");
+		let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
 		let logs = import_log;
 		frm.toggle_display("import_log", false);
 		frm.toggle_display("import_log_section", logs.length > 0);
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
index 7ffff02..eede3bd 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
@@ -24,7 +24,7 @@
   "section_import_preview",
   "import_preview",
   "import_log_section",
-  "import_log",
+  "statement_import_log",
   "show_failed_logs",
   "import_log_preview",
   "reference_doctype",
@@ -91,12 +91,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "import_log",
-   "fieldtype": "Code",
-   "label": "Import Log",
-   "options": "JSON"
-  },
-  {
    "fieldname": "import_log_section",
    "fieldtype": "Section Break",
    "label": "Import Log"
@@ -198,11 +192,17 @@
   {
    "fieldname": "column_break_4",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "statement_import_log",
+   "fieldtype": "Code",
+   "label": "Statement Import Log",
+   "options": "JSON"
   }
  ],
  "hide_toolbar": 1,
  "links": [],
- "modified": "2021-05-12 14:17:37.777246",
+ "modified": "2022-09-07 11:11:40.293317",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Bank Statement Import",
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
index 82705a9..0da44a4 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
@@ -25,7 +25,7 @@
 	</div>
 	<br>
 
-	<table class="table table-bordered">
+	<table class="table table-bordered" style="font-size: 10px">
 		<thead>
 			<tr>
 				<th style="width: 12%">{{ _("Date") }}</th>
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 4008863..1f5879d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -710,6 +710,7 @@
 		if (
 			cint(frappe.db.get_single_value("Selling Settings", "maintain_same_sales_rate"))
 			and not self.is_return
+			and not self.is_internal_customer
 		):
 			self.validate_rate_with_reference_doc(
 				[["Sales Order", "sales_order", "so_detail"], ["Delivery Note", "delivery_note", "dn_detail"]]
@@ -2161,6 +2162,17 @@
 
 	def update_item(source, target, source_parent):
 		target.qty = flt(source.qty) - received_items.get(source.name, 0.0)
+		if source.doctype == "Purchase Order Item" and target.doctype == "Sales Order Item":
+			target.purchase_order = source.parent
+			target.purchase_order_item = source.name
+
+		if (
+			source.get("purchase_order")
+			and source.get("purchase_order_item")
+			and target.doctype == "Purchase Invoice Item"
+		):
+			target.purchase_order = source.purchase_order
+			target.po_detail = source.purchase_order_item
 
 	item_field_map = {
 		"doctype": target_doctype + " Item",
@@ -2187,6 +2199,12 @@
 				"serial_no": "serial_no",
 			}
 		)
+	elif target_doctype == "Sales Order":
+		item_field_map["field_map"].update(
+			{
+				source_document_warehouse_field: "warehouse",
+			}
+		)
 
 	doclist = get_mapped_doc(
 		doctype,
@@ -2231,6 +2249,7 @@
 
 def set_purchase_references(doc):
 	# add internal PO or PR links if any
+
 	if doc.is_internal_transfer():
 		if doc.doctype == "Purchase Receipt":
 			so_item_map = get_delivery_note_details(doc.inter_company_invoice_reference)
@@ -2260,15 +2279,6 @@
 					warehouse_map,
 				)
 
-			if list(so_item_map.values()):
-				pd_item_map, parent_child_map, warehouse_map = get_pd_details(
-					"Purchase Order Item", so_item_map, "sales_order_item"
-				)
-
-				update_pi_items(
-					doc, "po_detail", "purchase_order", so_item_map, pd_item_map, parent_child_map, warehouse_map
-				)
-
 
 def update_pi_items(
 	doc,
@@ -2284,13 +2294,19 @@
 		item.set(parent_field, parent_child_map.get(sales_item_map.get(item.sales_invoice_item)))
 		if doc.update_stock:
 			item.warehouse = warehouse_map.get(sales_item_map.get(item.sales_invoice_item))
+			if not item.warehouse and item.get("purchase_order") and item.get("purchase_order_item"):
+				item.warehouse = frappe.db.get_value(
+					"Purchase Order Item", item.purchase_order_item, "warehouse"
+				)
 
 
 def update_pr_items(doc, sales_item_map, purchase_item_map, parent_child_map, warehouse_map):
 	for item in doc.get("items"):
-		item.purchase_order_item = purchase_item_map.get(sales_item_map.get(item.delivery_note_item))
 		item.warehouse = warehouse_map.get(sales_item_map.get(item.delivery_note_item))
-		item.purchase_order = parent_child_map.get(sales_item_map.get(item.delivery_note_item))
+		if not item.warehouse and item.get("purchase_order") and item.get("purchase_order_item"):
+			item.warehouse = frappe.db.get_value(
+				"Purchase Order Item", item.purchase_order_item, "warehouse"
+			)
 
 
 def get_delivery_note_details(internal_reference):
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 7cddf12..4f97b63 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -96,6 +96,10 @@
   "delivery_note",
   "dn_detail",
   "delivered_qty",
+  "internal_transfer_section",
+  "purchase_order",
+  "column_break_92",
+  "purchase_order_item",
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
@@ -840,12 +844,38 @@
    "fieldtype": "Check",
    "label": "Grant Commission",
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "eval:parent.is_internal_customer == 1",
+   "fieldname": "internal_transfer_section",
+   "fieldtype": "Section Break",
+   "label": "Internal Transfer"
+  },
+  {
+   "fieldname": "purchase_order",
+   "fieldtype": "Link",
+   "label": "Purchase Order",
+   "options": "Purchase Order",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_92",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "purchase_order_item",
+   "fieldtype": "Data",
+   "label": "Purchase Order Item",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-08-26 12:06:31.205417",
+ "modified": "2022-09-06 14:17:43.394309",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index aa50487..acca380 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -60,6 +60,7 @@
   "section_break_45",
   "before_items_section",
   "scan_barcode",
+  "set_from_warehouse",
   "items_col_break",
   "set_warehouse",
   "items_section",
@@ -1166,13 +1167,20 @@
    "hidden": 1,
    "label": "Is Old Subcontracting Flow",
    "read_only": 1
+  },
+  {
+   "depends_on": "is_internal_supplier",
+   "fieldname": "set_from_warehouse",
+   "fieldtype": "Link",
+   "label": "Set From Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-06-15 15:40:58.527065",
+ "modified": "2022-09-07 11:06:46.035093",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
index 01b55c0..05b5a8e 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py
@@ -23,5 +23,6 @@
 				"items": ["Material Request", "Supplier Quotation", "Project", "Auto Repeat"],
 			},
 			{"label": _("Sub-contracting"), "items": ["Subcontracting Order", "Stock Entry"]},
+			{"label": _("Internal"), "items": ["Sales Order"]},
 		],
 	}
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index bd7e4e8..6c1bcc7 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -7,8 +7,10 @@
 import frappe
 from frappe.tests.utils import FrappeTestCase
 from frappe.utils import add_days, flt, getdate, nowdate
+from frappe.utils.data import today
 
 from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+from erpnext.buying.doctype.purchase_order.purchase_order import make_inter_company_sales_order
 from erpnext.buying.doctype.purchase_order.purchase_order import (
 	make_purchase_invoice as make_pi_from_po,
 )
@@ -796,6 +798,111 @@
 
 		automatically_fetch_payment_terms(enable=0)
 
+	def test_internal_transfer_flow(self):
+		from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
+			make_inter_company_purchase_invoice,
+		)
+		from erpnext.selling.doctype.sales_order.sales_order import (
+			make_delivery_note,
+			make_sales_invoice,
+		)
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+
+		frappe.db.set_value("Selling Settings", None, "maintain_same_sales_rate", 1)
+		frappe.db.set_value("Buying Settings", None, "maintain_same_rate", 1)
+
+		prepare_data_for_internal_transfer()
+		supplier = "_Test Internal Supplier 2"
+
+		po = create_purchase_order(
+			company="_Test Company with perpetual inventory",
+			supplier=supplier,
+			warehouse="Stores - TCP1",
+			from_warehouse="_Test Internal Warehouse New 1 - TCP1",
+			qty=2,
+			rate=1,
+		)
+
+		so = make_inter_company_sales_order(po.name)
+		so.items[0].delivery_date = today()
+		self.assertEqual(so.items[0].warehouse, "_Test Internal Warehouse New 1 - TCP1")
+		self.assertTrue(so.items[0].purchase_order)
+		self.assertTrue(so.items[0].purchase_order_item)
+		so.submit()
+
+		dn = make_delivery_note(so.name)
+		dn.items[0].target_warehouse = "_Test Internal Warehouse GIT - TCP1"
+		self.assertEqual(dn.items[0].warehouse, "_Test Internal Warehouse New 1 - TCP1")
+		self.assertTrue(dn.items[0].purchase_order)
+		self.assertTrue(dn.items[0].purchase_order_item)
+
+		self.assertEqual(po.items[0].name, dn.items[0].purchase_order_item)
+		dn.submit()
+
+		pr = make_inter_company_purchase_receipt(dn.name)
+		self.assertEqual(pr.items[0].warehouse, "Stores - TCP1")
+		self.assertTrue(pr.items[0].purchase_order)
+		self.assertTrue(pr.items[0].purchase_order_item)
+		self.assertEqual(po.items[0].name, pr.items[0].purchase_order_item)
+		pr.submit()
+
+		si = make_sales_invoice(so.name)
+		self.assertEqual(si.items[0].warehouse, "_Test Internal Warehouse New 1 - TCP1")
+		self.assertTrue(si.items[0].purchase_order)
+		self.assertTrue(si.items[0].purchase_order_item)
+		si.submit()
+
+		pi = make_inter_company_purchase_invoice(si.name)
+		self.assertTrue(pi.items[0].purchase_order)
+		self.assertTrue(pi.items[0].po_detail)
+		pi.submit()
+
+		po.load_from_db()
+		self.assertEqual(po.status, "Completed")
+
+
+def prepare_data_for_internal_transfer():
+	from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
+	from erpnext.selling.doctype.customer.test_customer import create_internal_customer
+	from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+	from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
+
+	company = "_Test Company with perpetual inventory"
+
+	create_internal_customer(
+		"_Test Internal Customer 2",
+		company,
+		company,
+	)
+
+	create_internal_supplier(
+		"_Test Internal Supplier 2",
+		company,
+		company,
+	)
+
+	warehouse = create_warehouse("_Test Internal Warehouse New 1", company=company)
+
+	create_warehouse("_Test Internal Warehouse GIT", company=company)
+
+	make_purchase_receipt(company=company, warehouse=warehouse, qty=2, rate=100)
+
+	if not frappe.db.get_value("Company", company, "unrealized_profit_loss_account"):
+		account = "Unrealized Profit and Loss - TCP1"
+		if not frappe.db.exists("Account", account):
+			frappe.get_doc(
+				{
+					"doctype": "Account",
+					"account_name": "Unrealized Profit and Loss",
+					"parent_account": "Direct Income - TCP1",
+					"company": company,
+					"is_group": 0,
+					"account_type": "Income Account",
+				}
+			).insert()
+
+		frappe.db.set_value("Company", company, "unrealized_profit_loss_account", account)
+
 
 def make_pr_against_po(po, received_qty=0):
 	pr = make_purchase_receipt(po)
@@ -847,6 +954,7 @@
 			{
 				"item_code": args.item or args.item_code or "_Test Item",
 				"warehouse": args.warehouse or "_Test Warehouse - _TC",
+				"from_warehouse": args.from_warehouse,
 				"qty": args.qty or 10,
 				"rate": args.rate or 500,
 				"schedule_date": add_days(nowdate(), 1),
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 1a98453..82e92e8 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -10,12 +10,14 @@
   "item_code",
   "supplier_part_no",
   "item_name",
+  "brand",
   "product_bundle",
   "fg_item",
   "fg_item_qty",
   "column_break_4",
   "schedule_date",
   "expected_delivery_date",
+  "item_group",
   "section_break_5",
   "description",
   "col_break1",
@@ -58,9 +60,12 @@
   "base_net_rate",
   "base_net_amount",
   "warehouse_and_reference",
+  "from_warehouse",
   "warehouse",
+  "column_break_54",
   "actual_qty",
   "company_total_stock",
+  "references_section",
   "material_request",
   "material_request_item",
   "sales_order",
@@ -73,8 +78,6 @@
   "against_blanket_order",
   "blanket_order",
   "blanket_order_rate",
-  "item_group",
-  "brand",
   "section_break_56",
   "received_qty",
   "returned_qty",
@@ -442,13 +445,13 @@
   {
    "fieldname": "warehouse_and_reference",
    "fieldtype": "Section Break",
-   "label": "Warehouse and Reference"
+   "label": "Warehouse Settings"
   },
   {
    "fieldname": "warehouse",
    "fieldtype": "Link",
    "in_list_view": 1,
-   "label": "Warehouse",
+   "label": "Target Warehouse",
    "oldfieldname": "warehouse",
    "oldfieldtype": "Link",
    "options": "Warehouse",
@@ -760,7 +763,7 @@
    "allow_on_submit": 1,
    "fieldname": "actual_qty",
    "fieldtype": "Float",
-   "label": "Available Qty at Warehouse",
+   "label": "Available Qty at Target Warehouse",
    "print_hide": 1,
    "read_only": 1
   },
@@ -868,13 +871,30 @@
    "fieldtype": "Float",
    "label": "Finished Good Item Qty",
    "mandatory_depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow"
+  },
+  {
+   "depends_on": "eval:parent.is_internal_supplier",
+   "fieldname": "from_warehouse",
+   "fieldtype": "Link",
+   "label": "From Warehouse",
+   "options": "Warehouse"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "references_section",
+   "fieldtype": "Section Break",
+   "label": "References"
+  },
+  {
+   "fieldname": "column_break_54",
+   "fieldtype": "Column Break"
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-06-17 05:29:40.602349",
+ "modified": "2022-09-07 11:12:38.634976",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index e689d56..9244844 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -205,6 +205,10 @@
 	def on_trash(self):
 		# delete sl and gl entries on deletion of transaction
 		if frappe.db.get_single_value("Accounts Settings", "delete_linked_ledger_entries"):
+			ple = frappe.qb.DocType("Payment Ledger Entry")
+			frappe.qb.from_(ple).delete().where(
+				(ple.voucher_type == self.doctype) & (ple.voucher_no == self.name)
+			).run()
 			frappe.db.sql(
 				"delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s", (self.doctype, self.name)
 			)
@@ -373,7 +377,7 @@
 				)
 
 	def validate_inter_company_reference(self):
-		if self.doctype not in ("Purchase Invoice", "Purchase Receipt", "Purchase Order"):
+		if self.doctype not in ("Purchase Invoice", "Purchase Receipt"):
 			return
 
 		if self.is_internal_transfer():
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/status_updater.py b/erpnext/controllers/status_updater.py
index 197d2ba..6e7d2b3 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -307,6 +307,20 @@
 
 	def limits_crossed_error(self, args, item, qty_or_amount):
 		"""Raise exception for limits crossed"""
+		if (
+			self.doctype in ["Sales Invoice", "Delivery Note"]
+			and qty_or_amount == "amount"
+			and self.is_internal_customer
+		):
+			return
+
+		elif (
+			self.doctype in ["Purchase Invoice", "Purchase Receipt"]
+			and qty_or_amount == "amount"
+			and self.is_internal_supplier
+		):
+			return
+
 		if qty_or_amount == "qty":
 			action_msg = _(
 				'To allow over receipt / delivery, update "Over Receipt/Delivery Allowance" in Stock Settings or the Item.'
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 36bed36..9149b4d 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
 
@@ -688,6 +700,47 @@
 			else:
 				create_repost_item_valuation_entry(args)
 
+	def add_gl_entry(
+		self,
+		gl_entries,
+		account,
+		cost_center,
+		debit,
+		credit,
+		remarks,
+		against_account,
+		debit_in_account_currency=None,
+		credit_in_account_currency=None,
+		account_currency=None,
+		project=None,
+		voucher_detail_no=None,
+		item=None,
+		posting_date=None,
+	):
+
+		gl_entry = {
+			"account": account,
+			"cost_center": cost_center,
+			"debit": debit,
+			"credit": credit,
+			"against": against_account,
+			"remarks": remarks,
+		}
+
+		if voucher_detail_no:
+			gl_entry.update({"voucher_detail_no": voucher_detail_no})
+
+		if debit_in_account_currency:
+			gl_entry.update({"debit_in_account_currency": debit_in_account_currency})
+
+		if credit_in_account_currency:
+			gl_entry.update({"credit_in_account_currency": credit_in_account_currency})
+
+		if posting_date:
+			gl_entry.update({"posting_date": posting_date})
+
+		gl_entries.append(self.get_gl_dict(gl_entry, item=item))
+
 
 def repost_required_for_queue(doc: StockController) -> bool:
 	"""check if stock document contains repeated item-warehouse with queue based valuation.
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 1372c89..bbd950e 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -7,6 +7,7 @@
 
 import frappe
 from frappe import _
+from frappe.model.mapper import get_mapped_doc
 from frappe.utils import cint, cstr, flt, get_link_to_form
 
 from erpnext.controllers.stock_controller import StockController
@@ -870,7 +871,18 @@
 def make_return_stock_entry_for_subcontract(
 	available_materials, order_doc, rm_details, order_doctype="Subcontracting Order"
 ):
-	ste_doc = frappe.new_doc("Stock Entry")
+	ste_doc = get_mapped_doc(
+		order_doctype,
+		order_doc.name,
+		{
+			order_doctype: {
+				"doctype": "Stock Entry",
+				"field_no_map": ["purchase_order", "subcontracting_order"],
+			},
+		},
+		ignore_child_tables=True,
+	)
+
 	ste_doc.purpose = "Material Transfer"
 
 	if order_doctype == "Purchase Order":
diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py
index bc503f5..8490d14 100644
--- a/erpnext/controllers/tests/test_subcontracting_controller.py
+++ b/erpnext/controllers/tests/test_subcontracting_controller.py
@@ -897,7 +897,7 @@
 			"item_name": row.item_code,
 			"rate": row.rate or 100,
 			"stock_uom": row.stock_uom or "Nos",
-			"warehouse": row.warehuose or "_Test Warehouse - _TC",
+			"warehouse": row.warehouse or "_Test Warehouse - _TC",
 		}
 
 		item_details = args.itemwise_details.get(row.item_code)
@@ -1031,9 +1031,9 @@
 	if not args.service_items:
 		service_items = [
 			{
-				"warehouse": "_Test Warehouse - _TC",
+				"warehouse": args.warehouse or "_Test Warehouse - _TC",
 				"item_code": "Subcontracted Service Item 7",
-				"qty": 5,
+				"qty": 10,
 				"rate": 100,
 				"fg_item": "Subcontracted Item SA7",
 				"fg_item_qty": 10,
@@ -1046,6 +1046,7 @@
 		rm_items=service_items,
 		is_subcontracted=1,
 		supplier_warehouse=args.supplier_warehouse or "_Test Warehouse 1 - _TC",
+		company=args.company,
 	)
 
 	return create_subcontracting_order(po_name=po.name, **args)
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index 5f5923d..6e7ba1f 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -7,7 +7,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import get_url, getdate
+from frappe.utils import get_url, getdate, now
 from frappe.utils.verified_command import get_signed_params
 
 
@@ -104,16 +104,28 @@
 		# Return if already linked
 		if self.party:
 			return
+
 		lead = frappe.get_doc(
 			{
 				"doctype": "Lead",
 				"lead_name": self.customer_name,
 				"email_id": self.customer_email,
-				"notes": self.customer_details,
 				"phone": self.customer_phone_number,
 			}
 		)
+
+		if self.customer_details:
+			lead.append(
+				"notes",
+				{
+					"note": self.customer_details,
+					"added_by": frappe.session.user,
+					"added_on": now(),
+				},
+			)
+
 		lead.insert(ignore_permissions=True)
+
 		# Link lead
 		self.party = lead.name
 
diff --git a/erpnext/crm/doctype/appointment/test_appointment.py b/erpnext/crm/doctype/appointment/test_appointment.py
index 776e604..178b9d2 100644
--- a/erpnext/crm/doctype/appointment/test_appointment.py
+++ b/erpnext/crm/doctype/appointment/test_appointment.py
@@ -6,29 +6,20 @@
 
 import frappe
 
-
-def create_test_lead():
-	test_lead = frappe.db.get_value("Lead", {"email_id": "test@example.com"})
-	if test_lead:
-		return frappe.get_doc("Lead", test_lead)
-	test_lead = frappe.get_doc(
-		{"doctype": "Lead", "lead_name": "Test Lead", "email_id": "test@example.com"}
-	)
-	test_lead.insert(ignore_permissions=True)
-	return test_lead
+LEAD_EMAIL = "test_appointment_lead@example.com"
 
 
-def create_test_appointments():
+def create_test_appointment():
 	test_appointment = frappe.get_doc(
 		{
 			"doctype": "Appointment",
-			"email": "test@example.com",
 			"status": "Open",
 			"customer_name": "Test Lead",
 			"customer_phone_number": "666",
 			"customer_skype": "test",
-			"customer_email": "test@example.com",
+			"customer_email": LEAD_EMAIL,
 			"scheduled_time": datetime.datetime.now(),
+			"customer_details": "Hello, Friend!",
 		}
 	)
 	test_appointment.insert()
@@ -36,16 +27,16 @@
 
 
 class TestAppointment(unittest.TestCase):
-	test_appointment = test_lead = None
+	def setUpClass():
+		frappe.db.delete("Lead", {"email_id": LEAD_EMAIL})
 
 	def setUp(self):
-		self.test_lead = create_test_lead()
-		self.test_appointment = create_test_appointments()
+		self.test_appointment = create_test_appointment()
+		self.test_appointment.set_verified(self.test_appointment.customer_email)
 
 	def test_calendar_event_created(self):
 		cal_event = frappe.get_doc("Event", self.test_appointment.calendar_event)
 		self.assertEqual(cal_event.starts_on, self.test_appointment.scheduled_time)
 
 	def test_lead_linked(self):
-		lead = frappe.get_doc("Lead", self.test_lead.name)
-		self.assertIsNotNone(lead)
+		self.assertTrue(self.test_appointment.party)
diff --git a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
index 063ebba..998b0e4 100644
--- a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
+++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.py
@@ -4,6 +4,7 @@
 
 import frappe
 from frappe import _
+from frappe.query_builder.functions import IfNull
 from frappe.utils import cint
 
 
@@ -17,70 +18,70 @@
 def get_item_list(wo_list, filters):
 	out = []
 
-	# Add a row for each item/qty
-	for wo_details in wo_list:
-		desc = frappe.db.get_value("BOM", wo_details.bom_no, "description")
+	if wo_list:
+		bin = frappe.qb.DocType("Bin")
+		bom = frappe.qb.DocType("BOM")
+		bom_item = frappe.qb.DocType("BOM Item")
 
-		for wo_item_details in frappe.db.get_values(
-			"Work Order Item", {"parent": wo_details.name}, ["item_code", "source_warehouse"], as_dict=1
-		):
+		# Add a row for each item/qty
+		for wo_details in wo_list:
+			desc = frappe.db.get_value("BOM", wo_details.bom_no, "description")
 
-			item_list = frappe.db.sql(
-				"""SELECT
-					bom_item.item_code as item_code,
-					ifnull(ledger.actual_qty*bom.quantity/bom_item.stock_qty,0) as build_qty
-				FROM
-					`tabBOM` as bom, `tabBOM Item` AS bom_item
-					LEFT JOIN `tabBin` AS ledger
-						ON bom_item.item_code = ledger.item_code
-						AND ledger.warehouse = ifnull(%(warehouse)s,%(filterhouse)s)
-				WHERE
-					bom.name = bom_item.parent
-					and bom_item.item_code = %(item_code)s
-					and bom.name = %(bom)s
-				GROUP BY
-					bom_item.item_code""",
-				{
-					"bom": wo_details.bom_no,
-					"warehouse": wo_item_details.source_warehouse,
-					"filterhouse": filters.warehouse,
-					"item_code": wo_item_details.item_code,
-				},
-				as_dict=1,
-			)
+			for wo_item_details in frappe.db.get_values(
+				"Work Order Item", {"parent": wo_details.name}, ["item_code", "source_warehouse"], as_dict=1
+			):
+				item_list = (
+					frappe.qb.from_(bom)
+					.from_(bom_item)
+					.left_join(bin)
+					.on(
+						(bom_item.item_code == bin.item_code)
+						& (bin.warehouse == IfNull(wo_item_details.source_warehouse, filters.warehouse))
+					)
+					.select(
+						bom_item.item_code.as_("item_code"),
+						IfNull(bin.actual_qty * bom.quantity / bom_item.stock_qty, 0).as_("build_qty"),
+					)
+					.where(
+						(bom.name == bom_item.parent)
+						& (bom_item.item_code == wo_item_details.item_code)
+						& (bom.name == wo_details.bom_no)
+					)
+					.groupby(bom_item.item_code)
+				).run(as_dict=1)
 
-			stock_qty = 0
-			count = 0
-			buildable_qty = wo_details.qty
-			for item in item_list:
-				count = count + 1
-				if item.build_qty >= (wo_details.qty - wo_details.produced_qty):
-					stock_qty = stock_qty + 1
-				elif buildable_qty >= item.build_qty:
-					buildable_qty = item.build_qty
+				stock_qty = 0
+				count = 0
+				buildable_qty = wo_details.qty
+				for item in item_list:
+					count = count + 1
+					if item.build_qty >= (wo_details.qty - wo_details.produced_qty):
+						stock_qty = stock_qty + 1
+					elif buildable_qty >= item.build_qty:
+						buildable_qty = item.build_qty
 
-			if count == stock_qty:
-				build = "Y"
-			else:
-				build = "N"
+				if count == stock_qty:
+					build = "Y"
+				else:
+					build = "N"
 
-			row = frappe._dict(
-				{
-					"work_order": wo_details.name,
-					"status": wo_details.status,
-					"req_items": cint(count),
-					"instock": stock_qty,
-					"description": desc,
-					"source_warehouse": wo_item_details.source_warehouse,
-					"item_code": wo_item_details.item_code,
-					"bom_no": wo_details.bom_no,
-					"qty": wo_details.qty,
-					"buildable_qty": buildable_qty,
-					"ready_to_build": build,
-				}
-			)
+				row = frappe._dict(
+					{
+						"work_order": wo_details.name,
+						"status": wo_details.status,
+						"req_items": cint(count),
+						"instock": stock_qty,
+						"description": desc,
+						"source_warehouse": wo_item_details.source_warehouse,
+						"item_code": wo_item_details.item_code,
+						"bom_no": wo_details.bom_no,
+						"qty": wo_details.qty,
+						"buildable_qty": buildable_qty,
+						"ready_to_build": build,
+					}
+				)
 
-			out.append(row)
+				out.append(row)
 
 	return out
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 4729add..d780213 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -312,4 +312,5 @@
 erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022
 erpnext.patches.v14_0.fix_crm_no_of_employees
 erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes
+erpnext.patches.v14_0.fix_subcontracting_receipt_gl_entries
 erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger
diff --git a/erpnext/patches/v14_0/fix_subcontracting_receipt_gl_entries.py b/erpnext/patches/v14_0/fix_subcontracting_receipt_gl_entries.py
new file mode 100644
index 0000000..159c6dc
--- /dev/null
+++ b/erpnext/patches/v14_0/fix_subcontracting_receipt_gl_entries.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+
+from erpnext.stock.report.stock_and_account_value_comparison.stock_and_account_value_comparison import (
+	get_data,
+)
+
+
+def execute():
+	data = []
+
+	for company in frappe.db.get_list("Company", pluck="name"):
+		data += get_data(
+			frappe._dict(
+				{
+					"company": company,
+				}
+			)
+		)
+
+	if data:
+		for d in data:
+			if d and d.get("voucher_type") == "Subcontracting Receipt":
+				doc = frappe.new_doc("Repost Item Valuation")
+				doc.voucher_type = d.get("voucher_type")
+				doc.voucher_no = d.get("voucher_no")
+				doc.save()
+				doc.submit()
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index f2bea58..6d64625 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -226,7 +226,7 @@
 						if (!found) {
 							filters.splice(index, 0, {
 								"fieldname": dimension["fieldname"],
-								"label": __(dimension["label"]),
+								"label": __(dimension["doctype"]),
 								"fieldtype": "MultiSelectList",
 								get_data: function(txt) {
 									return frappe.db.get_link_options(dimension["doctype"], txt);
diff --git a/erpnext/regional/saudi_arabia/utils.py b/erpnext/regional/saudi_arabia/utils.py
index b47adc9..cac5ec1 100644
--- a/erpnext/regional/saudi_arabia/utils.py
+++ b/erpnext/regional/saudi_arabia/utils.py
@@ -84,7 +84,7 @@
 		tlv_array.append("".join([tag, length, value]))
 
 		# Invoice Amount
-		invoice_amount = str(doc.grand_total)
+		invoice_amount = str(doc.base_grand_total)
 		tag = bytes([4]).hex()
 		length = bytes([len(invoice_amount)]).hex()
 		value = invoice_amount.encode("utf-8").hex()
@@ -144,7 +144,7 @@
 
 	for tax in doc.get("taxes"):
 		if tax.account_head in vat_accounts:
-			vat_amount += tax.tax_amount
+			vat_amount += tax.base_tax_amount
 
 	return vat_amount
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 6b6ea89..386c12b 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -59,7 +59,36 @@
 				})
 			});
 		}
+
+		if (frm.doc.docstatus === 0 && frm.doc.is_internal_customer) {
+			frm.events.get_items_from_internal_purchase_order(frm);
+		}
 	},
+
+	get_items_from_internal_purchase_order(frm) {
+		frm.add_custom_button(__('Purchase Order'), () => {
+			erpnext.utils.map_current_doc({
+				method: 'erpnext.buying.doctype.purchase_order.purchase_order.make_inter_company_sales_order',
+				source_doctype: 'Purchase Order',
+				target: frm,
+				setters: [
+					{
+						label: 'Supplier',
+						fieldname: 'supplier',
+						fieldtype: 'Link',
+						options: 'Supplier'
+					}
+				],
+				get_query_filters: {
+					company: frm.doc.company,
+					is_internal_supplier: 1,
+					docstatus: 1,
+					status: ['!=', 'Completed']
+				}
+			});
+		}, __('Get Items From'));
+	},
+
 	onload: function(frm) {
 		if (!frm.doc.transaction_date){
 			frm.set_value('transaction_date', frappe.datetime.get_today())
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index 3187999..2cf836f 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -92,7 +92,11 @@
   "section_break_63",
   "page_break",
   "item_tax_rate",
-  "transaction_date"
+  "transaction_date",
+  "inter_transfer_reference_section",
+  "purchase_order",
+  "column_break_89",
+  "purchase_order_item"
  ],
  "fields": [
   {
@@ -809,12 +813,36 @@
    "label": "Picked Qty (in Stock UOM)",
    "no_copy": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "inter_transfer_reference_section",
+   "fieldtype": "Section Break",
+   "label": "Inter Transfer Reference"
+  },
+  {
+   "fieldname": "purchase_order",
+   "fieldtype": "Link",
+   "label": "Purchase Order",
+   "options": "Purchase Order",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_89",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "purchase_order_item",
+   "fieldtype": "Data",
+   "label": "Purchase Order Item",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-06-17 05:27:41.603006",
+ "modified": "2022-09-06 13:24:18.065312",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order Item",
diff --git a/erpnext/setup/doctype/employee/employee.json b/erpnext/setup/doctype/employee/employee.json
index 7a806d5..39e0acd 100644
--- a/erpnext/setup/doctype/employee/employee.json
+++ b/erpnext/setup/doctype/employee/employee.json
@@ -10,79 +10,89 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
+  "basic_details_tab",
   "basic_information",
   "employee",
   "naming_series",
   "first_name",
   "middle_name",
   "last_name",
-  "salutation",
   "employee_name",
-  "image",
-  "column_break1",
-  "company",
-  "status",
+  "column_break_9",
   "gender",
   "date_of_birth",
+  "salutation",
+  "column_break1",
   "date_of_joining",
-  "employee_number",
-  "emergency_contact_details",
-  "person_to_be_contacted",
-  "relation",
-  "column_break_19",
-  "emergency_phone_number",
+  "image",
+  "status",
   "erpnext_user",
   "user_id",
   "create_user",
   "create_user_permission",
-  "employment_details",
-  "scheduled_confirmation_date",
-  "final_confirmation_date",
-  "col_break_22",
-  "contract_end_date",
-  "notice_number_of_days",
-  "date_of_retirement",
-  "job_profile",
+  "company_details_section",
+  "company",
   "department",
+  "employee_number",
+  "column_break_25",
   "designation",
   "reports_to",
-  "column_break_31",
+  "column_break_18",
   "branch",
+  "employment_details",
+  "scheduled_confirmation_date",
+  "column_break_32",
+  "final_confirmation_date",
+  "contract_end_date",
+  "col_break_22",
+  "notice_number_of_days",
+  "date_of_retirement",
+  "contact_details",
+  "cell_number",
+  "column_break_40",
+  "personal_email",
+  "company_email",
+  "column_break4",
+  "prefered_contact_email",
+  "prefered_email",
+  "unsubscribed",
+  "address_section",
+  "current_address",
+  "current_accommodation_type",
+  "column_break_46",
+  "permanent_address",
+  "permanent_accommodation_type",
+  "emergency_contact_details",
+  "person_to_be_contacted",
+  "column_break_55",
+  "emergency_phone_number",
+  "column_break_19",
+  "relation",
   "attendance_and_leave_details",
   "attendance_device_id",
   "column_break_44",
   "holiday_list",
   "salary_information",
-  "salary_currency",
   "ctc",
-  "payroll_cost_center",
-  "column_break_52",
+  "salary_currency",
+  "salary_mode",
+  "bank_details_section",
   "bank_name",
   "bank_ac_no",
-  "contact_details",
-  "cell_number",
-  "prefered_email",
-  "personal_email",
-  "unsubscribed",
-  "permanent_accommodation_type",
-  "permanent_address",
-  "column_break4",
-  "prefered_contact_email",
-  "company_email",
-  "current_accommodation_type",
-  "current_address",
-  "sb53",
-  "bio",
   "personal_details",
-  "passport_number",
-  "date_of_issue",
-  "valid_upto",
-  "place_of_issue",
   "marital_status",
-  "blood_group",
-  "column_break6",
   "family_background",
+  "column_break6",
+  "blood_group",
   "health_details",
+  "passport_details_section",
+  "passport_number",
+  "valid_upto",
+  "column_break_73",
+  "date_of_issue",
+  "place_of_issue",
+  "profile_tab",
+  "bio",
   "educational_qualification",
   "education",
   "previous_work_experience",
@@ -92,16 +102,20 @@
   "exit",
   "resignation_letter_date",
   "relieving_date",
-  "reason_for_leaving",
-  "leave_encashed",
-  "encashment_date",
   "exit_interview_details",
   "held_on",
   "new_workplace",
+  "column_break_99",
+  "leave_encashed",
+  "encashment_date",
+  "feedback_section",
+  "reason_for_leaving",
+  "column_break_104",
   "feedback",
   "lft",
   "rgt",
-  "old_parent"
+  "old_parent",
+  "connections_tab"
  ],
  "fields": [
   {
@@ -261,7 +275,7 @@
    "collapsible": 1,
    "fieldname": "erpnext_user",
    "fieldtype": "Section Break",
-   "label": "ERPNext User"
+   "label": "User Details"
   },
   {
    "description": "System User (login) ID. If set, it will become default for all HR forms.",
@@ -289,8 +303,8 @@
    "allow_in_quick_entry": 1,
    "collapsible": 1,
    "fieldname": "employment_details",
-   "fieldtype": "Section Break",
-   "label": "Joining Details"
+   "fieldtype": "Tab Break",
+   "label": "Joining"
   },
   {
    "fieldname": "scheduled_confirmation_date",
@@ -332,12 +346,6 @@
    "oldfieldtype": "Date"
   },
   {
-   "collapsible": 1,
-   "fieldname": "job_profile",
-   "fieldtype": "Section Break",
-   "label": "Department"
-  },
-  {
    "fieldname": "department",
    "fieldtype": "Link",
    "in_standard_filter": 1,
@@ -367,10 +375,6 @@
    "options": "Employee"
   },
   {
-   "fieldname": "column_break_31",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "branch",
    "fieldtype": "Link",
    "label": "Branch",
@@ -391,7 +395,7 @@
   {
    "collapsible": 1,
    "fieldname": "salary_information",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Salary Details",
    "oldfieldtype": "Section Break",
    "width": "50%"
@@ -423,8 +427,8 @@
   {
    "collapsible": 1,
    "fieldname": "contact_details",
-   "fieldtype": "Section Break",
-   "label": "Contact Details"
+   "fieldtype": "Tab Break",
+   "label": "Contact"
   },
   {
    "fieldname": "cell_number",
@@ -494,12 +498,6 @@
    "label": "Current Address"
   },
   {
-   "collapsible": 1,
-   "fieldname": "sb53",
-   "fieldtype": "Section Break",
-   "label": "Personal Bio"
-  },
-  {
    "description": "Short biography for website and other publications.",
    "fieldname": "bio",
    "fieldtype": "Text Editor",
@@ -508,7 +506,7 @@
   {
    "collapsible": 1,
    "fieldname": "personal_details",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Personal Details"
   },
   {
@@ -601,7 +599,7 @@
   {
    "collapsible": 1,
    "fieldname": "exit",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Exit",
    "oldfieldtype": "Section Break"
   },
@@ -702,7 +700,7 @@
   {
    "collapsible": 1,
    "fieldname": "attendance_and_leave_details",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Attendance and Leave Details"
   },
   {
@@ -714,10 +712,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "fieldname": "column_break_52",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "salary_currency",
    "fieldtype": "Link",
    "label": "Salary Currency",
@@ -728,13 +722,95 @@
    "fieldtype": "Currency",
    "label": "Cost to Company (CTC)",
    "options": "salary_currency"
+  },
+  {
+   "fieldname": "basic_details_tab",
+   "fieldtype": "Tab Break",
+   "label": "Basic Details"
+  },
+  {
+   "fieldname": "company_details_section",
+   "fieldtype": "Section Break",
+   "label": "Company Details"
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "address_section",
+   "fieldtype": "Section Break",
+   "label": "Address"
+  },
+  {
+   "fieldname": "column_break_46",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "profile_tab",
+   "fieldtype": "Tab Break",
+   "label": "Profile"
+  },
+  {
+   "fieldname": "passport_details_section",
+   "fieldtype": "Section Break",
+   "label": "Passport Details"
+  },
+  {
+   "fieldname": "column_break_73",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "bank_details_section",
+   "fieldtype": "Section Break",
+   "label": "Bank Details"
+  },
+  {
+   "fieldname": "column_break_9",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_25",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "connections_tab",
+   "fieldtype": "Tab Break",
+   "label": "Connections",
+   "show_dashboard": 1
+  },
+  {
+   "fieldname": "column_break_32",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_40",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_55",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_99",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "feedback_section",
+   "fieldtype": "Section Break",
+   "label": "Feedback"
+  },
+  {
+   "fieldname": "column_break_104",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-user",
  "idx": 24,
  "image_field": "image",
  "links": [],
- "modified": "2022-06-27 01:29:32.952091",
+ "modified": "2022-08-23 13:47:46.944993",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Employee",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 0e68e85..36d5a6c 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -178,6 +178,7 @@
 		if (
 			cint(frappe.db.get_single_value("Selling Settings", "maintain_same_sales_rate"))
 			and not self.is_return
+			and not self.is_internal_customer
 		):
 			self.validate_rate_with_reference_doc(
 				[
@@ -896,6 +897,8 @@
 					"name": "delivery_note_item",
 					"batch_no": "batch_no",
 					"serial_no": "serial_no",
+					"purchase_order": "purchase_order",
+					"purchase_order_item": "purchase_order_item",
 				},
 				"field_no_map": ["warehouse"],
 			},
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 2de4842..0911cdb 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -86,6 +86,10 @@
   "expense_account",
   "allow_zero_valuation_rate",
   "column_break_71",
+  "internal_transfer_section",
+  "purchase_order",
+  "column_break_82",
+  "purchase_order_item",
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
@@ -777,13 +781,39 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "eval:parent.is_internal_customer == 1",
+   "fieldname": "internal_transfer_section",
+   "fieldtype": "Section Break",
+   "label": "Internal Transfer"
+  },
+  {
+   "fieldname": "purchase_order",
+   "fieldtype": "Link",
+   "label": "Purchase Order",
+   "options": "Purchase Order",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_82",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "purchase_order_item",
+   "fieldtype": "Data",
+   "label": "Purchase Order Item",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2022-06-17 05:25:47.711177",
+ "modified": "2022-09-06 14:19:42.876357",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note Item",
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)
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json
index 56832f3..bda1218 100644
--- a/erpnext/stock/doctype/item_barcode/item_barcode.json
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.json
@@ -17,6 +17,7 @@
    "in_list_view": 1,
    "label": "Barcode",
    "no_copy": 1,
+   "reqd": 1,
    "unique": 1
   },
   {
@@ -36,7 +37,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2022-06-01 06:24:33.969534",
+ "modified": "2022-08-24 19:59:47.871677",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item Barcode",
diff --git a/erpnext/stock/doctype/item_supplier/item_supplier.json b/erpnext/stock/doctype/item_supplier/item_supplier.json
index 6cff8e0..84649a6 100644
--- a/erpnext/stock/doctype/item_supplier/item_supplier.json
+++ b/erpnext/stock/doctype/item_supplier/item_supplier.json
@@ -1,95 +1,43 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2013-02-22 01:28:01", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2013-02-22 01:28:01",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "supplier",
+  "supplier_part_no"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "supplier", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Supplier", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Supplier", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "supplier",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Supplier",
+   "options": "Supplier",
+   "reqd": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "supplier_part_no", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Supplier Part Number", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "200px", 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "fieldname": "supplier_part_no",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "in_list_view": 1,
+   "label": "Supplier Part Number",
+   "print_width": "200px",
    "width": "200px"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2017-02-20 13:29:32.569715", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Item Supplier", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "idx": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2022-09-07 12:33:55.780062",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Item Supplier",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 84da3cc..f85c478 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -362,6 +362,12 @@
 						if credit_currency == self.company_currency
 						else flt(d.net_amount, d.precision("net_amount"))
 					)
+
+					outgoing_amount = d.base_net_amount
+					if self.is_internal_supplier and d.valuation_rate:
+						outgoing_amount = d.valuation_rate * d.stock_qty
+						credit_amount = outgoing_amount
+
 					if credit_amount:
 						account = warehouse_account[d.from_warehouse]["account"] if d.from_warehouse else stock_rbnb
 
@@ -369,7 +375,7 @@
 							gl_entries=gl_entries,
 							account=account,
 							cost_center=d.cost_center,
-							debit=-1 * flt(d.base_net_amount, d.precision("base_net_amount")),
+							debit=-1 * flt(outgoing_amount, d.precision("base_net_amount")),
 							credit=0.0,
 							remarks=remarks,
 							against_account=warehouse_account_name,
@@ -456,7 +462,7 @@
 
 					# divisional loss adjustment
 					valuation_amount_as_per_doc = (
-						flt(d.base_net_amount, d.precision("base_net_amount"))
+						flt(outgoing_amount, d.precision("base_net_amount"))
 						+ flt(d.landed_cost_voucher_amount)
 						+ flt(d.rm_supp_cost)
 						+ flt(d.item_tax_amount)
@@ -631,47 +637,6 @@
 
 					i += 1
 
-	def add_gl_entry(
-		self,
-		gl_entries,
-		account,
-		cost_center,
-		debit,
-		credit,
-		remarks,
-		against_account,
-		debit_in_account_currency=None,
-		credit_in_account_currency=None,
-		account_currency=None,
-		project=None,
-		voucher_detail_no=None,
-		item=None,
-		posting_date=None,
-	):
-
-		gl_entry = {
-			"account": account,
-			"cost_center": cost_center,
-			"debit": debit,
-			"credit": credit,
-			"against": against_account,
-			"remarks": remarks,
-		}
-
-		if voucher_detail_no:
-			gl_entry.update({"voucher_detail_no": voucher_detail_no})
-
-		if debit_in_account_currency:
-			gl_entry.update({"debit_in_account_currency": debit_in_account_currency})
-
-		if credit_in_account_currency:
-			gl_entry.update({"credit_in_account_currency": credit_in_account_currency})
-
-		if posting_date:
-			gl_entry.update({"posting_date": posting_date})
-
-		gl_entries.append(self.get_gl_dict(gl_entry, item=item))
-
 	def get_asset_gl_entry(self, gl_entries):
 		for item in self.get("items"):
 			if item.is_fixed_asset:
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d0d115d..b77c3a5 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -5,6 +5,7 @@
 import frappe
 from frappe.tests.utils import FrappeTestCase, change_settings
 from frappe.utils import add_days, cint, cstr, flt, today
+from pypika import functions as fn
 
 import erpnext
 from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -1156,6 +1157,125 @@
 			if gle.account == account:
 				self.assertEqual(gle.credit, 50)
 
+	def test_backdated_transaction_for_internal_transfer(self):
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+		prepare_data_for_internal_transfer()
+		customer = "_Test Internal Customer 2"
+		company = "_Test Company with perpetual inventory"
+
+		from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company)
+		to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company)
+		item_doc = create_item("Test Internal Transfer Item")
+
+		target_warehouse = create_warehouse("_Test Internal GIT Warehouse New", company=company)
+
+		make_purchase_receipt(
+			item_code=item_doc.name,
+			company=company,
+			posting_date=add_days(today(), -1),
+			warehouse=from_warehouse,
+			qty=1,
+			rate=100,
+		)
+
+		dn1 = create_delivery_note(
+			item_code=item_doc.name,
+			company=company,
+			customer=customer,
+			cost_center="Main - TCP1",
+			expense_account="Cost of Goods Sold - TCP1",
+			qty=1,
+			rate=500,
+			warehouse=from_warehouse,
+			target_warehouse=target_warehouse,
+		)
+
+		self.assertEqual(dn1.items[0].rate, 100)
+
+		pr1 = make_inter_company_purchase_receipt(dn1.name)
+		pr1.items[0].warehouse = to_warehouse
+		self.assertEqual(pr1.items[0].rate, 100)
+		pr1.submit()
+
+		# Backdated purchase receipt entry, the valuation rate should be updated for DN1 and PR1
+		make_purchase_receipt(
+			item_code=item_doc.name,
+			company=company,
+			posting_date=add_days(today(), -2),
+			warehouse=from_warehouse,
+			qty=1,
+			rate=200,
+		)
+
+		dn_value = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{"voucher_type": "Delivery Note", "voucher_no": dn1.name, "warehouse": target_warehouse},
+			"stock_value_difference",
+		)
+
+		self.assertEqual(abs(dn_value), 200.00)
+
+		pr_value = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{"voucher_type": "Purchase Receipt", "voucher_no": pr1.name, "warehouse": to_warehouse},
+			"stock_value_difference",
+		)
+
+		self.assertEqual(abs(pr_value), 200.00)
+		pr1.load_from_db()
+
+		self.assertEqual(pr1.items[0].valuation_rate, 200)
+		self.assertEqual(pr1.items[0].rate, 100)
+
+		Gl = frappe.qb.DocType("GL Entry")
+
+		query = (
+			frappe.qb.from_(Gl)
+			.select(
+				(fn.Sum(Gl.debit) - fn.Sum(Gl.credit)).as_("value"),
+			)
+			.where((Gl.voucher_type == pr1.doctype) & (Gl.voucher_no == pr1.name))
+		).run(as_dict=True)
+
+		self.assertEqual(query[0].value, 0)
+
+
+def prepare_data_for_internal_transfer():
+	from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
+	from erpnext.selling.doctype.customer.test_customer import create_internal_customer
+
+	company = "_Test Company with perpetual inventory"
+
+	create_internal_customer(
+		"_Test Internal Customer 2",
+		company,
+		company,
+	)
+
+	create_internal_supplier(
+		"_Test Internal Supplier 2",
+		company,
+		company,
+	)
+
+	if not frappe.db.get_value("Company", company, "unrealized_profit_loss_account"):
+		account = "Unrealized Profit and Loss - TCP1"
+		if not frappe.db.exists("Account", account):
+			frappe.get_doc(
+				{
+					"doctype": "Account",
+					"account_name": "Unrealized Profit and Loss",
+					"parent_account": "Direct Income - TCP1",
+					"company": company,
+					"is_group": 0,
+					"account_type": "Income Account",
+				}
+			).insert()
+
+		frappe.db.set_value("Company", company, "unrealized_profit_loss_account", account)
+
 
 def get_sl_entries(voucher_type, voucher_no):
 	return frappe.db.sql(
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.js b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.js
index eae7305..d595a80 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.js
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.js
@@ -58,6 +58,21 @@
 		}
 
 		frm.trigger('show_reposting_progress');
+
+		if (frm.doc.status === 'Queued' && frm.doc.docstatus === 1) {
+			frm.trigger('execute_reposting');
+		}
+	},
+
+	execute_reposting(frm) {
+		frm.add_custom_button(__("Start Reposting"), () => {
+			frappe.call({
+				method: 'erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.execute_repost_item_valuation',
+				callback: function() {
+					frappe.msgprint(__('Reposting has been started in the background.'));
+				}
+			});
+		});
 	},
 
 	show_reposting_progress: function(frm) {
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 7c57ecd..c470524 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -307,3 +307,9 @@
 		return end_time >= now_time >= start_time
 	else:
 		return now_time >= start_time or now_time <= end_time
+
+
+@frappe.whitelist()
+def execute_repost_item_valuation():
+	"""Execute repost item valuation via scheduler."""
+	frappe.get_doc("Scheduled Job Type", "repost_item_valuation.repost_entries").enqueue(force=True)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 1bbe570..a952a93 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -815,7 +815,8 @@
 			return {
 				"filters": {
 					"docstatus": 1,
-					"company": me.frm.doc.company
+					"company": me.frm.doc.company,
+					"status": ["not in", ["Completed", "Closed"]]
 				}
 			};
 		});
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index d709522..76bba8a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -117,6 +117,7 @@
 		self.validate_work_order()
 		self.validate_bom()
 		self.validate_purchase_order()
+		self.validate_subcontracting_order()
 
 		if self.purpose in ("Manufacture", "Repack"):
 			self.mark_finished_and_scrap_items()
@@ -875,25 +876,24 @@
 						)
 					)
 
-				parent = frappe.qb.DocType("Stock Entry")
-				child = frappe.qb.DocType("Stock Entry Detail")
-
-				conditions = (
-					(parent.docstatus == 1)
-					& (child.item_code == se_item.item_code)
-					& (
-						(parent.purchase_order == self.purchase_order)
-						if self.subcontract_data.order_doctype == "Purchase Order"
-						else (parent.subcontracting_order == self.subcontracting_order)
-					)
-				)
+				se = frappe.qb.DocType("Stock Entry")
+				se_detail = frappe.qb.DocType("Stock Entry Detail")
 
 				total_supplied = (
-					frappe.qb.from_(parent)
-					.inner_join(child)
-					.on(parent.name == child.parent)
-					.select(Sum(child.transfer_qty))
-					.where(conditions)
+					frappe.qb.from_(se)
+					.inner_join(se_detail)
+					.on(se.name == se_detail.parent)
+					.select(Sum(se_detail.transfer_qty))
+					.where(
+						(se.purpose == "Send to Subcontractor")
+						& (se.docstatus == 1)
+						& (se_detail.item_code == se_item.item_code)
+						& (
+							(se.purchase_order == self.purchase_order)
+							if self.subcontract_data.order_doctype == "Purchase Order"
+							else (se.subcontracting_order == self.subcontracting_order)
+						)
+					)
 				).run()[0][0]
 
 				if flt(total_supplied, precision) > flt(total_allowed, precision):
@@ -960,6 +960,20 @@
 					)
 				)
 
+	def validate_subcontracting_order(self):
+		if self.get("subcontracting_order") and self.purpose in [
+			"Send to Subcontractor",
+			"Material Transfer",
+		]:
+			sco_status = frappe.db.get_value("Subcontracting Order", self.subcontracting_order, "status")
+
+			if sco_status == "Closed":
+				frappe.throw(
+					_("Cannot create Stock Entry against a closed Subcontracting Order {0}.").format(
+						self.subcontracting_order
+					)
+				)
+
 	def mark_finished_and_scrap_items(self):
 		if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
 			return
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 3524a47..5030964 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -649,21 +649,25 @@
 
 			elif (
 				sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
-				and sle.actual_qty > 0
+				and sle.voucher_detail_no
 				and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
 			):
-				sle_details = frappe.db.get_value(
-					"Stock Ledger Entry",
-					{
-						"voucher_type": sle.voucher_type,
-						"voucher_no": sle.voucher_no,
-						"dependant_sle_voucher_detail_no": sle.voucher_detail_no,
-					},
-					["stock_value_difference", "actual_qty"],
-					as_dict=1,
+				field = (
+					"delivery_note_item" if sle.voucher_type == "Purchase Receipt" else "sales_invoice_item"
+				)
+				doctype = (
+					"Delivery Note Item" if sle.voucher_type == "Purchase Receipt" else "Sales Invoice Item"
+				)
+				refernce_name = frappe.get_cached_value(
+					sle.voucher_type + " Item", sle.voucher_detail_no, field
 				)
 
-				rate = abs(sle_details.stock_value_difference / sle.actual_qty)
+				if refernce_name:
+					rate = frappe.get_cached_value(
+						doctype,
+						refernce_name,
+						"incoming_rate",
+					)
 			else:
 				if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
 					rate_field = "valuation_rate"
@@ -745,7 +749,12 @@
 	def update_rate_on_purchase_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, "base_net_rate", outgoing_rate
+				sle.voucher_type + " Item",
+				sle.voucher_detail_no,
+				{
+					"base_net_rate": outgoing_rate,
+					"valuation_rate": outgoing_rate,
+				},
 			)
 		else:
 			frappe.db.set_value(
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
index 065ef39..40963f8 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
+++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
@@ -107,7 +107,7 @@
 	get_materials_from_supplier: function (frm) {
 		let sco_rm_details = [];
 
-		if (frm.doc.supplied_items && frm.doc.per_received > 0) {
+		if (frm.doc.status != "Closed" && frm.doc.supplied_items && frm.doc.per_received > 0) {
 			frm.doc.supplied_items.forEach(d => {
 				if (d.total_supplied_qty > 0 && d.total_supplied_qty != d.consumed_qty) {
 					sco_rm_details.push(d.name);
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py
index 098242a..d054ce0 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py
+++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py
@@ -187,22 +187,13 @@
 		self.assertEqual(len(ste.items), len(rm_items))
 
 	def test_update_reserved_qty_for_subcontracting(self):
-		# Make stock available for raw materials
-		make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
+		# Create RM Material Receipt
+		make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item", qty=10, basic_rate=100)
 		make_stock_entry(
 			target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100", qty=20, basic_rate=100
 		)
-		make_stock_entry(
-			target="_Test Warehouse 1 - _TC", item_code="_Test Item", qty=30, basic_rate=100
-		)
-		make_stock_entry(
-			target="_Test Warehouse 1 - _TC",
-			item_code="_Test Item Home Desktop 100",
-			qty=30,
-			basic_rate=100,
-		)
 
-		bin1 = frappe.db.get_value(
+		bin_before_sco = frappe.db.get_value(
 			"Bin",
 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
 			fieldname=["reserved_qty_for_sub_contract", "projected_qty", "modified"],
@@ -222,102 +213,97 @@
 		]
 		sco = get_subcontracting_order(service_items=service_items)
 
-		bin2 = frappe.db.get_value(
+		bin_after_sco = frappe.db.get_value(
 			"Bin",
 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
 			fieldname=["reserved_qty_for_sub_contract", "projected_qty", "modified"],
 			as_dict=1,
 		)
 
-		self.assertEqual(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
-		self.assertEqual(bin2.projected_qty, bin1.projected_qty - 10)
-		self.assertNotEqual(bin1.modified, bin2.modified)
+		# reserved_qty_for_sub_contract should be increased by 10
+		self.assertEqual(
+			bin_after_sco.reserved_qty_for_sub_contract, bin_before_sco.reserved_qty_for_sub_contract + 10
+		)
 
-		# Create stock transfer
+		# projected_qty should be decreased by 10
+		self.assertEqual(bin_after_sco.projected_qty, bin_before_sco.projected_qty - 10)
+
+		self.assertNotEqual(bin_before_sco.modified, bin_after_sco.modified)
+
+		# Create Stock Entry(Send to Subcontractor)
 		rm_items = [
 			{
 				"item_code": "_Test FG Item",
 				"rm_item_code": "_Test Item",
 				"item_name": "_Test Item",
-				"qty": 6,
+				"qty": 10,
 				"warehouse": "_Test Warehouse - _TC",
 				"rate": 100,
-				"amount": 600,
+				"amount": 1000,
 				"stock_uom": "Nos",
-			}
+			},
+			{
+				"item_code": "_Test FG Item",
+				"rm_item_code": "_Test Item Home Desktop 100",
+				"item_name": "_Test Item Home Desktop 100",
+				"qty": 20,
+				"warehouse": "_Test Warehouse - _TC",
+				"rate": 100,
+				"amount": 2000,
+				"stock_uom": "Nos",
+			},
 		]
 		ste = frappe.get_doc(make_rm_stock_entry(sco.name, rm_items))
 		ste.to_warehouse = "_Test Warehouse 1 - _TC"
 		ste.save()
 		ste.submit()
 
-		bin3 = frappe.db.get_value(
+		bin_after_rm_transfer = frappe.db.get_value(
 			"Bin",
 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
 			fieldname="reserved_qty_for_sub_contract",
 			as_dict=1,
 		)
 
-		self.assertEqual(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
-
-		make_stock_entry(
-			target="_Test Warehouse 1 - _TC", item_code="_Test Item", qty=40, basic_rate=100
-		)
-		make_stock_entry(
-			target="_Test Warehouse 1 - _TC",
-			item_code="_Test Item Home Desktop 100",
-			qty=40,
-			basic_rate=100,
+		# reserved_qty_for_sub_contract should be decreased by 10
+		self.assertEqual(
+			bin_after_rm_transfer.reserved_qty_for_sub_contract,
+			bin_after_sco.reserved_qty_for_sub_contract - 10,
 		)
 
-		# Make SCR against the SCO
-		scr = make_subcontracting_receipt(sco.name)
-		scr.save()
-		scr.submit()
-
-		bin4 = frappe.db.get_value(
-			"Bin",
-			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
-			fieldname="reserved_qty_for_sub_contract",
-			as_dict=1,
-		)
-
-		self.assertEqual(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
-
-		# Cancel SCR
-		scr.reload()
-		scr.cancel()
-		bin5 = frappe.db.get_value(
-			"Bin",
-			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
-			fieldname="reserved_qty_for_sub_contract",
-			as_dict=1,
-		)
-
-		self.assertEqual(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
-
-		# Cancel Stock Entry
+		# Cancel Stock Entry(Send to Subcontractor)
 		ste.cancel()
-		bin6 = frappe.db.get_value(
+		bin_after_cancel_ste = frappe.db.get_value(
 			"Bin",
 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
 			fieldname="reserved_qty_for_sub_contract",
 			as_dict=1,
 		)
 
-		self.assertEqual(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
+		# reserved_qty_for_sub_contract should be increased by 10
+		self.assertEqual(
+			bin_after_cancel_ste.reserved_qty_for_sub_contract,
+			bin_after_rm_transfer.reserved_qty_for_sub_contract + 10,
+		)
 
-		# Cancel PO
+		# Cancel SCO
 		sco.reload()
 		sco.cancel()
-		bin7 = frappe.db.get_value(
+		bin_after_cancel_sco = frappe.db.get_value(
 			"Bin",
 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
 			fieldname="reserved_qty_for_sub_contract",
 			as_dict=1,
 		)
 
-		self.assertEqual(bin7.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
+		# reserved_qty_for_sub_contract should be decreased by 10
+		self.assertEqual(
+			bin_after_cancel_sco.reserved_qty_for_sub_contract,
+			bin_after_cancel_ste.reserved_qty_for_sub_contract - 10,
+		)
+		self.assertEqual(
+			bin_after_cancel_sco.reserved_qty_for_sub_contract, bin_before_sco.reserved_qty_for_sub_contract
+		)
 
 	def test_exploded_items(self):
 		item_code = "_Test Subcontracted FG Item 11"
@@ -516,6 +502,35 @@
 
 		set_backflush_based_on("BOM")
 
+	def test_get_materials_from_supplier(self):
+		# Create SCO
+		sco = get_subcontracting_order()
+
+		# Transfer RM
+		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 SCR (Partial)
+		scr = make_subcontracting_receipt(sco.name)
+		scr.items[0].qty -= 5
+		scr.save()
+		scr.submit()
+
+		# Get RM from Supplier
+		ste = get_materials_from_supplier(sco.name, [d.name for d in sco.supplied_items])
+		ste.save()
+		ste.submit()
+
+		sco.load_from_db()
+
+		self.assertEqual(sco.status, "Closed")
+		self.assertEqual(sco.supplied_items[0].returned_qty, 5)
+
 
 def create_subcontracting_order(**args):
 	args = frappe._dict(args)
@@ -524,7 +539,7 @@
 	for item in sco.items:
 		item.include_exploded_items = args.get("include_exploded_items", 1)
 
-	if args.get("warehouse"):
+	if args.warehouse:
 		for item in sco.items:
 			item.warehouse = args.warehouse
 	else:
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
index 021d9aa..cd05b74 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
@@ -5,6 +5,8 @@
 from frappe import _
 from frappe.utils import cint, flt, getdate, nowdate
 
+import erpnext
+from erpnext.accounts.utils import get_account_currency
 from erpnext.controllers.subcontracting_controller import SubcontractingController
 
 
@@ -75,6 +77,7 @@
 		self.get_current_stock()
 
 	def on_submit(self):
+		self.validate_available_qty_for_consumption()
 		self.update_status_updater_args()
 		self.update_prevdoc_status()
 		self.set_subcontracting_order_status()
@@ -107,10 +110,42 @@
 		self.set_missing_values_in_supplied_items()
 		self.set_missing_values_in_items()
 
+	def set_available_qty_for_consumption(self):
+		supplied_items_details = {}
+
+		sco_supplied_item = frappe.qb.DocType("Subcontracting Order Supplied Item")
+		for item in self.get("items"):
+			supplied_items = (
+				frappe.qb.from_(sco_supplied_item)
+				.select(
+					sco_supplied_item.rm_item_code,
+					sco_supplied_item.reference_name,
+					(sco_supplied_item.total_supplied_qty - sco_supplied_item.consumed_qty).as_("available_qty"),
+				)
+				.where(
+					(sco_supplied_item.parent == item.subcontracting_order)
+					& (sco_supplied_item.main_item_code == item.item_code)
+					& (sco_supplied_item.reference_name == item.subcontracting_order_item)
+				)
+			).run(as_dict=True)
+
+			if supplied_items:
+				supplied_items_details[item.name] = {}
+
+				for supplied_item in supplied_items:
+					supplied_items_details[item.name][supplied_item.rm_item_code] = supplied_item.available_qty
+		else:
+			for item in self.get("supplied_items"):
+				item.available_qty_for_consumption = supplied_items_details.get(item.reference_name, {}).get(
+					item.rm_item_code, 0
+				)
+
 	def set_missing_values_in_supplied_items(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):
 		rm_supp_cost = {}
 		for item in self.get("supplied_items") or []:
@@ -147,6 +182,17 @@
 						_("Rejected Warehouse is mandatory against rejected Item {0}").format(item.item_code)
 					)
 
+	def validate_available_qty_for_consumption(self):
+		for item in self.get("supplied_items"):
+			if (
+				item.available_qty_for_consumption and item.available_qty_for_consumption < item.consumed_qty
+			):
+				frappe.throw(
+					_(
+						"Row {0}: Consumed Qty must be less than or equal to Available Qty For Consumption in Consumed Items Table."
+					).format(item.idx)
+				)
+
 	def set_items_cost_center(self):
 		if self.company:
 			cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
@@ -181,6 +227,137 @@
 		if status:
 			frappe.db.set_value("Subcontracting Receipt", self.name, "status", status, update_modified)
 
+	def get_gl_entries(self, warehouse_account=None):
+		from erpnext.accounts.general_ledger import process_gl_map
+
+		gl_entries = []
+		self.make_item_gl_entries(gl_entries, warehouse_account)
+
+		return process_gl_map(gl_entries)
+
+	def make_item_gl_entries(self, gl_entries, warehouse_account=None):
+		if erpnext.is_perpetual_inventory_enabled(self.company):
+			stock_rbnb = self.get_company_default("stock_received_but_not_billed")
+			expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
+
+		warehouse_with_no_account = []
+
+		for item in self.items:
+			if flt(item.rate) and flt(item.qty):
+				if warehouse_account.get(item.warehouse):
+					stock_value_diff = frappe.db.get_value(
+						"Stock Ledger Entry",
+						{
+							"voucher_type": "Subcontracting Receipt",
+							"voucher_no": self.name,
+							"voucher_detail_no": item.name,
+							"warehouse": item.warehouse,
+							"is_cancelled": 0,
+						},
+						"stock_value_difference",
+					)
+
+					warehouse_account_name = warehouse_account[item.warehouse]["account"]
+					warehouse_account_currency = warehouse_account[item.warehouse]["account_currency"]
+					supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account")
+					supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get(
+						"account_currency"
+					)
+					remarks = self.get("remarks") or _("Accounting Entry for Stock")
+
+					# FG Warehouse Account (Debit)
+					self.add_gl_entry(
+						gl_entries=gl_entries,
+						account=warehouse_account_name,
+						cost_center=item.cost_center,
+						debit=stock_value_diff,
+						credit=0.0,
+						remarks=remarks,
+						against_account=stock_rbnb,
+						account_currency=warehouse_account_currency,
+						item=item,
+					)
+
+					# Supplier Warehouse Account (Credit)
+					if flt(item.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse):
+						self.add_gl_entry(
+							gl_entries=gl_entries,
+							account=supplier_warehouse_account,
+							cost_center=item.cost_center,
+							debit=0.0,
+							credit=flt(item.rm_supp_cost),
+							remarks=remarks,
+							against_account=warehouse_account_name,
+							account_currency=supplier_warehouse_account_currency,
+							item=item,
+						)
+
+					# Expense Account (Credit)
+					if flt(item.service_cost_per_qty):
+						self.add_gl_entry(
+							gl_entries=gl_entries,
+							account=item.expense_account,
+							cost_center=item.cost_center,
+							debit=0.0,
+							credit=flt(item.service_cost_per_qty) * flt(item.qty),
+							remarks=remarks,
+							against_account=warehouse_account_name,
+							account_currency=get_account_currency(item.expense_account),
+							item=item,
+						)
+
+					# Loss Account (Credit)
+					divisional_loss = flt(item.amount - stock_value_diff, item.precision("amount"))
+
+					if divisional_loss:
+						if self.is_return:
+							loss_account = expenses_included_in_valuation
+						else:
+							loss_account = item.expense_account
+
+						self.add_gl_entry(
+							gl_entries=gl_entries,
+							account=loss_account,
+							cost_center=item.cost_center,
+							debit=divisional_loss,
+							credit=0.0,
+							remarks=remarks,
+							against_account=warehouse_account_name,
+							account_currency=get_account_currency(loss_account),
+							project=item.project,
+							item=item,
+						)
+				elif (
+					item.warehouse not in warehouse_with_no_account
+					or item.rejected_warehouse not in warehouse_with_no_account
+				):
+					warehouse_with_no_account.append(item.warehouse)
+
+		# Additional Costs Expense Accounts (Credit)
+		for row in self.additional_costs:
+			credit_amount = (
+				flt(row.base_amount)
+				if (row.base_amount or row.account_currency != self.company_currency)
+				else flt(row.amount)
+			)
+
+			self.add_gl_entry(
+				gl_entries=gl_entries,
+				account=row.expense_account,
+				cost_center=self.cost_center or self.get_company_default("cost_center"),
+				debit=0.0,
+				credit=credit_amount,
+				remarks=remarks,
+				against_account=None,
+			)
+
+		if warehouse_with_no_account:
+			frappe.msgprint(
+				_("No accounting entries for the following warehouses")
+				+ ": \n"
+				+ "\n".join(warehouse_with_no_account)
+			)
+
 
 @frappe.whitelist()
 def make_subcontract_return(source_name, target_doc=None):
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
index 763e768..090f145 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
@@ -6,8 +6,10 @@
 
 import frappe
 from frappe.tests.utils import FrappeTestCase
-from frappe.utils import flt
+from frappe.utils import cint, flt
 
+import erpnext
+from erpnext.accounts.doctype.account.test_account import get_inventory_account
 from erpnext.controllers.sales_and_purchase_return import make_return_doc
 from erpnext.controllers.tests.test_subcontracting_controller import (
 	get_rm_items,
@@ -22,6 +24,7 @@
 	set_backflush_based_on,
 )
 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.subcontracting.doctype.subcontracting_order.subcontracting_order import (
 	make_subcontracting_receipt,
@@ -70,6 +73,55 @@
 		rm_supp_cost = sum(item.amount for item in scr.get("supplied_items"))
 		self.assertEqual(scr.get("items")[0].rm_supp_cost, flt(rm_supp_cost))
 
+	def test_available_qty_for_consumption(self):
+		make_stock_entry(
+			item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100
+		)
+		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,
+			},
+		]
+		sco = get_subcontracting_order(service_items=service_items)
+		rm_items = [
+			{
+				"main_item_code": "_Test FG Item",
+				"item_code": "_Test Item",
+				"qty": 5.0,
+				"rate": 100.0,
+				"stock_uom": "_Test UOM",
+				"warehouse": "_Test Warehouse - _TC",
+			},
+			{
+				"main_item_code": "_Test FG Item",
+				"item_code": "_Test Item Home Desktop 100",
+				"qty": 10.0,
+				"rate": 100.0,
+				"stock_uom": "_Test UOM",
+				"warehouse": "_Test Warehouse - _TC",
+			},
+		]
+		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),
+		)
+		scr = make_subcontracting_receipt(sco.name)
+		scr.save()
+		self.assertRaises(frappe.ValidationError, scr.submit)
+
 	def test_subcontracting_gle_fg_item_rate_zero(self):
 		from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
 
@@ -317,6 +369,103 @@
 		args = frappe._dict(scr_name=scr1.name, qty=-15)
 		self.assertRaises(OverAllowanceError, make_return_subcontracting_receipt, **args)
 
+	def test_subcontracting_receipt_no_gl_entry(self):
+		sco = get_subcontracting_order()
+		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),
+		)
+
+		scr = make_subcontracting_receipt(sco.name)
+		scr.append(
+			"additional_costs",
+			{
+				"expense_account": "Expenses Included In Valuation - _TC",
+				"description": "Test Additional Costs",
+				"amount": 100,
+			},
+		)
+		scr.save()
+		scr.submit()
+
+		stock_value_difference = frappe.db.get_value(
+			"Stock Ledger Entry",
+			{
+				"voucher_type": "Subcontracting Receipt",
+				"voucher_no": scr.name,
+				"item_code": "Subcontracted Item SA7",
+				"warehouse": "_Test Warehouse - _TC",
+			},
+			"stock_value_difference",
+		)
+
+		# Service Cost(100 * 10) + Raw Materials Cost(50 * 10) + Additional Costs(100) = 1600
+		self.assertEqual(stock_value_difference, 1600)
+		self.assertFalse(get_gl_entries("Subcontracting Receipt", scr.name))
+
+	def test_subcontracting_receipt_gl_entry(self):
+		sco = get_subcontracting_order(
+			company="_Test Company with perpetual inventory",
+			warehouse="Stores - TCP1",
+			supplier_warehouse="Work In Progress - TCP1",
+		)
+		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),
+		)
+
+		scr = make_subcontracting_receipt(sco.name)
+		additional_costs_expense_account = "Expenses Included In Valuation - TCP1"
+		scr.append(
+			"additional_costs",
+			{
+				"expense_account": additional_costs_expense_account,
+				"description": "Test Additional Costs",
+				"amount": 100,
+				"base_amount": 100,
+			},
+		)
+		scr.save()
+		scr.submit()
+
+		self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(scr.company)), 1)
+
+		gl_entries = get_gl_entries("Subcontracting Receipt", scr.name)
+
+		self.assertTrue(gl_entries)
+
+		fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse)
+		supplier_warehouse_ac = get_inventory_account(scr.company, scr.supplier_warehouse)
+		expense_account = scr.items[0].expense_account
+
+		if fg_warehouse_ac == supplier_warehouse_ac:
+			expected_values = {
+				fg_warehouse_ac: [2100.0, 1000.0],  # FG Amount (D), RM Cost (C)
+				expense_account: [0.0, 1000.0],  # Service Cost (C)
+				additional_costs_expense_account: [0.0, 100.0],  # Additional Cost (C)
+			}
+		else:
+			expected_values = {
+				fg_warehouse_ac: [2100.0, 0.0],  # FG Amount (D)
+				supplier_warehouse_ac: [0.0, 1000.0],  # RM Cost (C)
+				expense_account: [0.0, 1000.0],  # Service Cost (C)
+				additional_costs_expense_account: [0.0, 100.0],  # Additional Cost (C)
+			}
+
+		for gle in gl_entries:
+			self.assertEqual(expected_values[gle.account][0], gle.debit)
+			self.assertEqual(expected_values[gle.account][1], gle.credit)
+
+		scr.reload()
+		scr.cancel()
+		self.assertTrue(get_gl_entries("Subcontracting Receipt", scr.name))
+
 
 def make_return_subcontracting_receipt(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.json b/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.json
index 100a806..ddbb806 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.json
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.json
@@ -19,6 +19,7 @@
         "col_break2",
         "amount",
         "secbreak_2",
+        "available_qty_for_consumption",
         "required_qty",
         "col_break3",
         "consumed_qty",
@@ -75,8 +76,7 @@
         {
             "fieldname": "required_qty",
             "fieldtype": "Float",
-            "in_list_view": 1,
-            "label": "Available Qty For Consumption",
+            "label": "Required Qty",
             "print_hide": 1,
             "read_only": 1
         },
@@ -85,7 +85,7 @@
             "fieldname": "consumed_qty",
             "fieldtype": "Float",
             "in_list_view": 1,
-            "label": "Qty to be Consumed",
+            "label": "Consumed Qty",
             "reqd": 1
         },
         {
@@ -179,12 +179,21 @@
             "options": "Subcontracting Order",
             "print_hide": 1,
             "read_only": 1
+        },
+        {
+            "default": "0",
+            "fieldname": "available_qty_for_consumption",
+            "fieldtype": "Float",
+            "in_list_view": 1,
+            "label": "Available Qty For Consumption",
+            "print_hide": 1,
+            "read_only": 1
         }
     ],
     "idx": 1,
     "istable": 1,
     "links": [],
-    "modified": "2022-04-18 10:45:16.538479",
+    "modified": "2022-09-02 22:28:53.392381",
     "modified_by": "Administrator",
     "module": "Subcontracting",
     "name": "Subcontracting Receipt Supplied Item",
@@ -193,6 +202,6 @@
     "permissions": [],
     "sort_field": "modified",
     "sort_order": "DESC",
-    "track_changes": 1,
-    "states": []
+    "states": [],
+    "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index cd1bf9f..21a0a55 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -71,6 +71,9 @@
 						self.validate_value(field, condition, prevdoc_values[field], doc)
 
 	def validate_rate_with_reference_doc(self, ref_details):
+		if self.get("is_internal_supplier"):
+			return
+
 		buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]
 
 		if self.doctype in buying_doctypes: