Merge pull request #32667 from rohitwaghchaure/fixed-bom-cost-update-message

fix: BOM cost update message
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7f245fd..9487489 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -995,7 +995,9 @@
 		if self.payment_type in ("Receive", "Pay") and self.party:
 			for d in self.get("references"):
 				if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
-					frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
+					frappe.get_doc(
+						d.reference_doctype, d.reference_name, for_update=True
+					).set_total_advance_paid()
 
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		self.reference_no = reference_doc.name
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index afd5a59..0c03c55 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2017,6 +2017,9 @@
 			update_address(
 				target_doc, "shipping_address", "shipping_address_display", source_doc.customer_address
 			)
+			update_address(
+				target_doc, "billing_address", "billing_address_display", source_doc.customer_address
+			)
 
 			if currency:
 				target_doc.currency = currency
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index ed45106..fb94e8a 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -133,7 +133,7 @@
 				(%(from_time)s <= jctl.from_time and %(to_time)s >= jctl.to_time) {0}
 			)
 			and jctl.name != %(name)s and jc.name != %(parent)s and jc.docstatus < 2 {1}
-			order by jctl.to_time desc limit 1""".format(
+			order by jctl.to_time desc""".format(
 				extra_cond, validate_overlap_for
 			),
 			{
diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py
index ac71141..4d2dab7 100644
--- a/erpnext/manufacturing/doctype/job_card/test_job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py
@@ -136,6 +136,45 @@
 		)
 		self.assertRaises(OverlapError, jc2.save)
 
+	def test_job_card_overlap_with_capacity(self):
+		wo2 = make_wo_order_test_record(item="_Test FG Item 2", qty=2)
+
+		workstation = make_workstation(workstation_name=random_string(5)).name
+		frappe.db.set_value("Workstation", workstation, "production_capacity", 1)
+
+		jc1 = frappe.get_last_doc("Job Card", {"work_order": self.work_order.name})
+		jc2 = frappe.get_last_doc("Job Card", {"work_order": wo2.name})
+
+		jc1.workstation = workstation
+		jc1.append(
+			"time_logs",
+			{"from_time": "2021-01-01 00:00:00", "to_time": "2021-01-01 08:00:00", "completed_qty": 1},
+		)
+		jc1.save()
+
+		jc2.workstation = workstation
+
+		# add a new entry in same time slice
+		jc2.append(
+			"time_logs",
+			{"from_time": "2021-01-01 00:01:00", "to_time": "2021-01-01 06:00:00", "completed_qty": 1},
+		)
+		self.assertRaises(OverlapError, jc2.save)
+
+		frappe.db.set_value("Workstation", workstation, "production_capacity", 2)
+		jc2.load_from_db()
+
+		jc2.workstation = workstation
+
+		# add a new entry in same time slice
+		jc2.append(
+			"time_logs",
+			{"from_time": "2021-01-01 00:01:00", "to_time": "2021-01-01 06:00:00", "completed_qty": 1},
+		)
+
+		jc2.save()
+		self.assertTrue(jc2.name)
+
 	def test_job_card_multiple_materials_transfer(self):
 		"Test transferring RMs separately against Job Card with multiple RMs."
 		self.transfer_material_against = "Job Card"
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 4bb4dcc..000ee07 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -27,6 +27,7 @@
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
 from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.stock.get_item_details import get_conversion_factor
 from erpnext.utilities.transaction_base import validate_uom_is_integer
 
 
@@ -648,13 +649,23 @@
 			else:
 				material_request = material_request_map[key]
 
+			conversion_factor = 1.0
+			if (
+				material_request_type == "Purchase"
+				and item_doc.purchase_uom
+				and item_doc.purchase_uom != item_doc.stock_uom
+			):
+				conversion_factor = (
+					get_conversion_factor(item_doc.name, item_doc.purchase_uom).get("conversion_factor") or 1.0
+				)
+
 			# add item
 			material_request.append(
 				"items",
 				{
 					"item_code": item.item_code,
 					"from_warehouse": item.from_warehouse,
-					"qty": item.quantity,
+					"qty": item.quantity / conversion_factor,
 					"schedule_date": schedule_date,
 					"warehouse": item.warehouse,
 					"sales_order": item.sales_order,
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 60e6398..c4ab0f8 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -806,6 +806,35 @@
 		self.assertEqual(pln.status, "Completed")
 		self.assertEqual(pln.po_items[0].produced_qty, 5)
 
+	def test_material_request_item_for_purchase_uom(self):
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		fg_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name
+		bom_item = make_item(
+			properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1", "purchase_uom": "Nos"}
+		).name
+
+		if not frappe.db.exists("UOM Conversion Detail", {"parent": bom_item, "uom": "Nos"}):
+			doc = frappe.get_doc("Item", bom_item)
+			doc.append("uoms", {"uom": "Nos", "conversion_factor": 10})
+			doc.save()
+
+		make_bom(item=fg_item, raw_materials=[bom_item], source_warehouse="_Test Warehouse - _TC")
+
+		pln = create_production_plan(
+			item_code=fg_item, planned_qty=10, ignore_existing_ordered_qty=1, stock_uom="_Test UOM 1"
+		)
+
+		pln.make_material_request()
+		for row in frappe.get_all(
+			"Material Request Item",
+			filters={"production_plan": pln.name},
+			fields=["item_code", "uom", "qty"],
+		):
+			self.assertEqual(row.item_code, bom_item)
+			self.assertEqual(row.uom, "Nos")
+			self.assertEqual(row.qty, 1)
+
 
 def create_production_plan(**args):
 	"""
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 1a309ba..b0082bd 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -28,7 +28,7 @@
 	},
 	"open_general_ledger": function(data) {
 		if (!data.account) return;
-		var project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; })
+		let project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; });
 
 		frappe.route_options = {
 			"account": data.account,
@@ -37,7 +37,16 @@
 			"to_date": data.to_date || data.year_end_date,
 			"project": (project && project.length > 0) ? project[0].$input.val() : ""
 		};
-		frappe.set_route("query-report", "General Ledger");
+
+		let report = "General Ledger";
+
+		if (["Payable", "Receivable"].includes(data.account_type)) {
+			report = data.account_type == "Payable" ? "Accounts Payable" : "Accounts Receivable";
+			frappe.route_options["party_account"] = data.account;
+			frappe.route_options["report_date"] = data.year_end_date;
+		}
+
+		frappe.set_route("query-report", report);
 	},
 	"tree": true,
 	"name_field": "account",
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 70ae085..6b42e4d 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -84,11 +84,12 @@
 			}
 		}
 
-		if(doc.docstatus == 1 && !(['Lost', 'Ordered']).includes(doc.status)) {
-			if(!doc.valid_till || frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) >= 0) {
-				cur_frm.add_custom_button(__('Sales Order'),
-					cur_frm.cscript['Make Sales Order'], __('Create'));
-			}
+		if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) {
+			this.frm.add_custom_button(
+				__("Sales Order"),
+				this.frm.cscript["Make Sales Order"],
+				__("Create")
+			);
 
 			if(doc.status!=="Ordered") {
 				this.frm.add_custom_button(__('Set as Lost'), () => {
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 36d5a6c..9dd28dc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -842,6 +842,9 @@
 			update_address(
 				target_doc, "shipping_address", "shipping_address_display", source_doc.customer_address
 			)
+			update_address(
+				target_doc, "billing_address", "billing_address_display", source_doc.customer_address
+			)
 
 			update_taxes(
 				target_doc,