Merge pull request #34922 from ruthra-kumar/refactor_payment_entry_ref_details

refactor: refactor set_missing_values and set_missing_ref_details in Payment Entry
diff --git a/CODEOWNERS b/CODEOWNERS
index 7f8c4d1..540680c 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -22,4 +22,4 @@
 erpnext/patches/                @deepeshgarg007 
 
 .github/                        @deepeshgarg007
-pyproject.toml                  @ankush
+pyproject.toml                  @phot0n
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 5cecddd..a354d7a 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -19,6 +19,8 @@
   "column_break_17",
   "enable_common_party_accounting",
   "allow_multi_currency_invoices_against_single_party_account",
+  "journals_section",
+  "merge_similar_account_heads",
   "report_setting_section",
   "use_custom_cash_flow",
   "deferred_accounting_settings_section",
@@ -369,6 +371,18 @@
    "fieldname": "book_tax_discount_loss",
    "fieldtype": "Check",
    "label": "Book Tax Loss on Early Payment Discount"
+  },
+  {
+   "fieldname": "journals_section",
+   "fieldtype": "Section Break",
+   "label": "Journals"
+  },
+  {
+   "default": "0",
+   "description": "Rows with Same Account heads will be merged on Ledger",
+   "fieldname": "merge_similar_account_heads",
+   "fieldtype": "Check",
+   "label": "Merge Similar Account Heads"
   }
  ],
  "icon": "icon-cog",
@@ -376,7 +390,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-04-14 17:22:03.680886",
+ "modified": "2023-04-17 11:45:42.049247",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 68364be..0f8ae4f 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -885,6 +885,8 @@
 	def make_gl_entries(self, cancel=0, adv_adj=0):
 		from erpnext.accounts.general_ledger import make_gl_entries
 
+		merge_entries = frappe.db.get_single_value("Accounts Settings", "merge_similar_account_heads")
+
 		gl_map = self.build_gl_map()
 		if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
 			update_outstanding = "No"
@@ -892,7 +894,13 @@
 			update_outstanding = "Yes"
 
 		if gl_map:
-			make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj, update_outstanding=update_outstanding)
+			make_gl_entries(
+				gl_map,
+				cancel=cancel,
+				adv_adj=adv_adj,
+				merge_entries=merge_entries,
+				update_outstanding=update_outstanding,
+			)
 
 	@frappe.whitelist()
 	def get_balance(self, difference_account=None):
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 29afc84..ff08ddd 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -495,6 +495,7 @@
    "allow_bulk_edit": 1,
    "fieldname": "items",
    "fieldtype": "Table",
+   "label": "Items",
    "oldfieldname": "po_details",
    "oldfieldtype": "Table",
    "options": "Purchase Order Item",
@@ -1100,8 +1101,7 @@
   {
    "fieldname": "before_items_section",
    "fieldtype": "Section Break",
-   "hide_border": 1,
-   "label": "Items"
+   "hide_border": 1
   },
   {
    "fieldname": "items_col_break",
@@ -1271,7 +1271,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-01-28 18:59:16.322824",
+ "modified": "2023-04-14 16:42:29.448464",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index c5b369b..11ff91a 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -310,7 +310,6 @@
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "hide_border": 1,
-   "label": "Items",
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
   },
@@ -318,6 +317,7 @@
    "allow_bulk_edit": 1,
    "fieldname": "items",
    "fieldtype": "Table",
+   "label": "Items",
    "oldfieldname": "po_details",
    "oldfieldtype": "Table",
    "options": "Supplier Quotation Item",
@@ -844,7 +844,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-12-12 18:35:39.740974",
+ "modified": "2023-04-14 16:43:41.714832",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier Quotation",
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 1e4fabe..479fef7 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -859,6 +859,8 @@
 
 def future_sle_exists(args, sl_entries=None):
 	key = (args.voucher_type, args.voucher_no)
+	if not hasattr(frappe.local, "future_sle"):
+		frappe.local.future_sle = {}
 
 	if validate_future_sle_not_exists(args, key, sl_entries):
 		return False
@@ -892,6 +894,9 @@
 	)
 
 	for d in data:
+		if key not in frappe.local.future_sle:
+			frappe.local.future_sle[key] = frappe._dict({})
+
 		frappe.local.future_sle[key][(d.item_code, d.warehouse)] = d.total_row
 
 	return len(data)
@@ -903,6 +908,9 @@
 		item_key = (args.get("item_code"), args.get("warehouse"))
 
 	if not sl_entries and hasattr(frappe.local, "future_sle"):
+		if key not in frappe.local.future_sle:
+			return False
+
 		if not frappe.local.future_sle.get(key) or (
 			item_key and item_key not in frappe.local.future_sle.get(key)
 		):
@@ -910,11 +918,8 @@
 
 
 def get_cached_data(args, key):
-	if not hasattr(frappe.local, "future_sle"):
-		frappe.local.future_sle = {}
-
 	if key not in frappe.local.future_sle:
-		frappe.local.future_sle[key] = frappe._dict({})
+		return False
 
 	if args.get("item_code"):
 		item_key = (args.get("item_code"), args.get("warehouse"))
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py
index 3e5d5f7..81b8eca 100644
--- a/erpnext/e_commerce/doctype/website_item/website_item.py
+++ b/erpnext/e_commerce/doctype/website_item/website_item.py
@@ -315,6 +315,7 @@
 			self.item_code, skip_quotation_creation=True
 		)
 
+	@frappe.whitelist()
 	def copy_specification_from_item_group(self):
 		self.set("website_specifications", [])
 		if self.item_group:
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 3357b06..74c8af1 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -327,6 +327,7 @@
 erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
 erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
 erpnext.patches.v14_0.update_closing_balances
+execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
 # below migration patches should always run last
 erpnext.patches.v14_0.migrate_gl_to_payment_ledger
 execute:frappe.delete_doc_if_exists("Report", "Tax Detail")
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index eb2c0a4..2ffa6a5 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -416,7 +416,6 @@
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "hide_border": 1,
-   "label": "Items",
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
   },
@@ -424,6 +423,7 @@
    "allow_bulk_edit": 1,
    "fieldname": "items",
    "fieldtype": "Table",
+   "label": "Items",
    "oldfieldname": "quotation_details",
    "oldfieldtype": "Table",
    "options": "Quotation Item",
@@ -1072,7 +1072,7 @@
  "idx": 82,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-12-12 18:32:28.671332",
+ "modified": "2023-04-14 16:50:44.550098",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation",
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 46320e5..016ebf0 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -559,8 +559,10 @@
 
 				item_row = this.frm.add_child('items', new_item);
 
-				if (field === 'qty' && value !== 0 && !this.allow_negative_stock)
-					await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse);
+				if (field === 'qty' && value !== 0 && !this.allow_negative_stock) {
+					const qty_needed = value * item_row.conversion_factor;
+					await this.check_stock_availability(item_row, qty_needed, this.frm.doc.set_warehouse);
+				}
 
 				await this.trigger_new_item_events(item_row);
 
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 088958d..3e1e394 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -161,7 +161,7 @@
 		{
 			"item_label": "User Forum",
 			"item_type": "Route",
-			"route": "https://discuss.erpnext.com",
+			"route": "https://discuss.frappe.io",
 			"is_standard": 1,
 		},
 		{
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index 3b9fe7b..1843c6e 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -6,7 +6,7 @@
 from frappe import _
 from frappe.model.document import Document
 from frappe.model.naming import make_autoname, revert_series_if_last
-from frappe.query_builder.functions import CurDate, Sum, Timestamp
+from frappe.query_builder.functions import CombineDatetime, CurDate, Sum
 from frappe.utils import cint, flt, get_link_to_form, nowtime
 from frappe.utils.data import add_days
 from frappe.utils.jinja import render_template
@@ -192,7 +192,8 @@
 				posting_time = nowtime()
 
 			query = query.where(
-				Timestamp(sle.posting_date, sle.posting_time) <= Timestamp(posting_date, posting_time)
+				CombineDatetime(sle.posting_date, sle.posting_time)
+				<= CombineDatetime(posting_date, posting_time)
 			)
 
 		out = query.run(as_list=True)[0][0] or 0
@@ -376,7 +377,7 @@
 
 	p = frappe.qb.DocType("POS Invoice").as_("p")
 	item = frappe.qb.DocType("POS Invoice Item").as_("item")
-	sum_qty = frappe.query_builder.functions.Sum(item.qty).as_("qty")
+	sum_qty = frappe.query_builder.functions.Sum(item.stock_qty).as_("qty")
 
 	reserved_batch_qty = (
 		frappe.qb.from_(p)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index e304bd1..3fd4cec 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -571,24 +571,33 @@
 			self._cancel()
 
 	def recalculate_current_qty(self, item_code, batch_no):
+		from erpnext.stock.stock_ledger import get_valuation_rate
+
+		sl_entries = []
 		for row in self.items:
 			if not (row.item_code == item_code and row.batch_no == batch_no):
 				continue
 
-			row.current_qty = get_batch_qty_for_stock_reco(
+			current_qty = get_batch_qty_for_stock_reco(
 				item_code, row.warehouse, batch_no, self.posting_date, self.posting_time, self.name
 			)
 
-			qty, val_rate = get_stock_balance(
-				item_code,
-				row.warehouse,
-				self.posting_date,
-				self.posting_time,
-				with_valuation_rate=True,
+			precesion = row.precision("current_qty")
+			if flt(current_qty, precesion) == flt(row.current_qty, precesion):
+				continue
+
+			val_rate = get_valuation_rate(
+				item_code, row.warehouse, self.doctype, self.name, company=self.company, batch_no=batch_no
 			)
 
 			row.current_valuation_rate = val_rate
+			if not row.current_qty and current_qty:
+				sle = self.get_sle_for_items(row)
+				sle.actual_qty = current_qty * -1
+				sle.valuation_rate = val_rate
+				sl_entries.append(sle)
 
+			row.current_qty = current_qty
 			row.db_set(
 				{
 					"current_qty": row.current_qty,
@@ -597,6 +606,9 @@
 				}
 			)
 
+		if sl_entries:
+			self.make_sl_entries(sl_entries)
+
 
 def get_batch_qty_for_stock_reco(
 	item_code, warehouse, batch_no, posting_date, posting_time, voucher_no
diff --git a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
index df01b14..e9c9608 100644
--- a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
+++ b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py
@@ -5,7 +5,7 @@
 import frappe
 from frappe import _
 from frappe.query_builder import Field
-from frappe.query_builder.functions import Min, Timestamp
+from frappe.query_builder.functions import CombineDatetime, Min
 from frappe.utils import add_days, getdate, today
 
 import erpnext
@@ -75,7 +75,7 @@
 			& (sle.company == report_filters.company)
 			& (sle.is_cancelled == 0)
 		)
-		.orderby(Timestamp(sle.posting_date, sle.posting_time), sle.creation)
+		.orderby(CombineDatetime(sle.posting_date, sle.posting_time), sle.creation)
 	).run(as_dict=True)
 
 	for d in data:
diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
index 106e877..5fb4565 100644
--- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
+++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py
@@ -41,7 +41,7 @@
 		key = (d.voucher_type, d.voucher_no)
 		gl_data = voucher_wise_gl_data.get(key) or {}
 		d.account_value = gl_data.get("account_value", 0)
-		d.difference_value = d.stock_value - d.account_value
+		d.difference_value = abs(d.stock_value) - abs(d.account_value)
 		if abs(d.difference_value) > 0.1:
 			data.append(d)
 
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
index 58a043e..752e464 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
@@ -11,6 +11,13 @@
 			"options": "Company",
 			"reqd": 1,
 			"default": frappe.defaults.get_user_default("Company")
+		},
+		{
+			"fieldname":"show_disabled_warehouses",
+			"label": __("Show Disabled Warehouses"),
+			"fieldtype": "Check",
+			"default": 0
+
 		}
 	],
 	"initial_depth": 3,
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
index d364b57..a0e9944 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
@@ -11,6 +11,7 @@
 class StockBalanceFilter(TypedDict):
 	company: Optional[str]
 	warehouse: Optional[str]
+	show_disabled_warehouses: Optional[int]
 
 
 SLEntry = Dict[str, Any]
@@ -18,7 +19,7 @@
 
 def execute(filters=None):
 	columns, data = [], []
-	columns = get_columns()
+	columns = get_columns(filters)
 	data = get_data(filters)
 
 	return columns, data
@@ -42,10 +43,14 @@
 
 
 def get_warehouses(report_filters: StockBalanceFilter):
+	filters = {"company": report_filters.company, "disabled": 0}
+	if report_filters.get("show_disabled_warehouses"):
+		filters["disabled"] = ("in", [0, report_filters.show_disabled_warehouses])
+
 	return frappe.get_all(
 		"Warehouse",
-		fields=["name", "parent_warehouse", "is_group"],
-		filters={"company": report_filters.company},
+		fields=["name", "parent_warehouse", "is_group", "disabled"],
+		filters=filters,
 		order_by="lft",
 	)
 
@@ -90,8 +95,8 @@
 		update_balance(warehouse, warehouse.stock_balance)
 
 
-def get_columns():
-	return [
+def get_columns(filters: StockBalanceFilter) -> List[Dict]:
+	columns = [
 		{
 			"label": _("Warehouse"),
 			"fieldname": "name",
@@ -101,3 +106,15 @@
 		},
 		{"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150},
 	]
+
+	if filters.get("show_disabled_warehouses"):
+		columns.append(
+			{
+				"label": _("Warehouse Disabled?"),
+				"fieldname": "disabled",
+				"fieldtype": "Check",
+				"width": 200,
+			}
+		)
+
+	return columns
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index b0a093d..c197769 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -545,6 +545,14 @@
 			self.get_dynamic_incoming_outgoing_rate(sle)
 
 		if (
+			sle.voucher_type == "Stock Reconciliation"
+			and sle.batch_no
+			and sle.voucher_detail_no
+			and sle.actual_qty < 0
+		):
+			self.reset_actual_qty_for_stock_reco(sle)
+
+		if (
 			sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
 			and sle.voucher_detail_no
 			and sle.actual_qty < 0
@@ -605,6 +613,16 @@
 		if not self.args.get("sle_id"):
 			self.update_outgoing_rate_on_transaction(sle)
 
+	def reset_actual_qty_for_stock_reco(self, sle):
+		current_qty = frappe.get_cached_value(
+			"Stock Reconciliation Item", sle.voucher_detail_no, "current_qty"
+		)
+
+		if current_qty:
+			sle.actual_qty = current_qty * -1
+		elif current_qty == 0:
+			sle.is_cancelled = 1
+
 	def validate_negative_stock(self, sle):
 		"""
 		validate negative stock for entries current datetime onwards
@@ -1369,12 +1387,7 @@
 
 def regenerate_sle_for_batch_stock_reco(detail):
 	doc = frappe.get_cached_doc("Stock Reconciliation", detail.voucher_no)
-	doc.docstatus = 2
-	doc.update_stock_ledger()
-
 	doc.recalculate_current_qty(detail.item_code, detail.batch_no)
-	doc.docstatus = 1
-	doc.update_stock_ledger()
 	doc.repost_future_sle_and_gle()
 
 
@@ -1401,34 +1414,53 @@
 	return stock_reco_qty_shift
 
 
-def get_next_stock_reco(args):
+def get_next_stock_reco(kwargs):
 	"""Returns next nearest stock reconciliaton's details."""
 
-	return frappe.db.sql(
-		"""
-		select
-			name, posting_date, posting_time, creation, voucher_no, item_code, batch_no, actual_qty
-		from
-			`tabStock Ledger Entry`
-		where
-			item_code = %(item_code)s
-			and warehouse = %(warehouse)s
-			and voucher_type = 'Stock Reconciliation'
-			and voucher_no != %(voucher_no)s
-			and is_cancelled = 0
-			and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
-				or (
-					timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
-					and creation > %(creation)s
+	sle = frappe.qb.DocType("Stock Ledger Entry")
+
+	query = (
+		frappe.qb.from_(sle)
+		.select(
+			sle.name,
+			sle.posting_date,
+			sle.posting_time,
+			sle.creation,
+			sle.voucher_no,
+			sle.item_code,
+			sle.batch_no,
+			sle.actual_qty,
+		)
+		.where(
+			(sle.item_code == kwargs.get("item_code"))
+			& (sle.warehouse == kwargs.get("warehouse"))
+			& (sle.voucher_type == "Stock Reconciliation")
+			& (sle.voucher_no != kwargs.get("voucher_no"))
+			& (sle.is_cancelled == 0)
+			& (
+				(
+					CombineDatetime(sle.posting_date, sle.posting_time)
+					> CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
+					| (
+						(
+							CombineDatetime(sle.posting_date, sle.posting_time)
+							== CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
+						)
+						& (sle.creation > kwargs.get("creation"))
+					)
 				)
 			)
-		order by timestamp(posting_date, posting_time) asc, creation asc
-		limit 1
-	""",
-		args,
-		as_dict=1,
+		)
+		.orderby(CombineDatetime(sle.posting_date, sle.posting_time))
+		.orderby(sle.creation)
+		.limit(1)
 	)
 
+	if kwargs.get("batch_no"):
+		query.where(sle.batch_no == kwargs.get("batch_no"))
+
+	return query.run(as_dict=True)
+
 
 def get_datetime_limit_condition(detail):
 	return f"""
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
index 3a2c53f..45289b1 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js
@@ -67,6 +67,15 @@
 			}
 		});
 
+		frm.set_query('batch_no', 'supplied_items', function(doc, cdt, cdn) {
+			var row = locals[cdt][cdn];
+			return {
+				filters: {
+					item: row.rm_item_code
+				}
+			}
+		});
+
 		let batch_no_field = frm.get_docfield("items", "batch_no");
 		if (batch_no_field) {
 			batch_no_field.get_route_options_for_new_doc = function(row) {
diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html
index 8000a24..1381dfe 100644
--- a/erpnext/templates/generators/item/item_add_to_cart.html
+++ b/erpnext/templates/generators/item/item_add_to_cart.html
@@ -11,7 +11,10 @@
 
 			<div class="product-price">
 				<!-- Final Price -->
-				{{ price_info.formatted_price_sales_uom }}
+				<span itemprop="offers" itemscope itemtype="https://schema.org/Offer">
+					<span itemprop="price" content="{{ price_info.price_list_rate }}">{{ price_info.formatted_price_sales_uom }}</span>
+					<span style="display:none;" itemprop="priceCurrency" content="{{ price_info.currency }}">{{ price_info.currency }}</span>
+				</span>
 
 				<!-- Striked Price and Discount  -->
 				{% if price_info.formatted_mrp %}