Merge pull request #31160 from ruchamahabal/fix-gratuity-status-update

diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
index 572410f..98f3420 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
@@ -102,7 +102,9 @@
 		});
 	},
 
-	before_save: function(frm) {
+	before_save: async function(frm) {
+		frappe.dom.freeze(__('Processing Sales! Please Wait...'));
+
 		frm.set_value("grand_total", 0);
 		frm.set_value("net_total", 0);
 		frm.set_value("total_quantity", 0);
@@ -112,17 +114,23 @@
 			row.expected_amount = row.opening_amount;
 		}
 
-		for (let row of frm.doc.pos_transactions) {
-			frappe.db.get_doc("POS Invoice", row.pos_invoice).then(doc => {
-				frm.doc.grand_total += flt(doc.grand_total);
-				frm.doc.net_total += flt(doc.net_total);
-				frm.doc.total_quantity += flt(doc.total_qty);
-				refresh_payments(doc, frm);
-				refresh_taxes(doc, frm);
-				refresh_fields(frm);
-				set_html_data(frm);
-			});
+		const pos_inv_promises = frm.doc.pos_transactions.map(
+			row => frappe.db.get_doc("POS Invoice", row.pos_invoice)
+		);
+
+		const pos_invoices = await Promise.all(pos_inv_promises);
+
+		for (let doc of pos_invoices) {
+			frm.doc.grand_total += flt(doc.grand_total);
+			frm.doc.net_total += flt(doc.net_total);
+			frm.doc.total_quantity += flt(doc.total_qty);
+			refresh_payments(doc, frm);
+			refresh_taxes(doc, frm);
+			refresh_fields(frm);
+			set_html_data(frm);
 		}
+
+		frappe.dom.unfreeze();
 	}
 });
 
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 05a401b..d11205a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -944,7 +944,11 @@
 		} else {
 			// company currency and doc currency is same
 			// this will prevent unnecessary conversion rate triggers
-			this.frm.set_value("conversion_rate", 1.0);
+			if(this.frm.doc.currency === this.get_company_currency()) {
+				this.frm.set_value("conversion_rate", 1.0);
+			} else {
+				this.conversion_rate();
+			}
 		}
 	}
 
diff --git a/erpnext/regional/india/e_invoice/einvoice.js b/erpnext/regional/india/e_invoice/einvoice.js
index 4748b26..ef24ce7 100644
--- a/erpnext/regional/india/e_invoice/einvoice.js
+++ b/erpnext/regional/india/e_invoice/einvoice.js
@@ -11,7 +11,7 @@
 
 			if (!invoice_eligible) return;
 
-			const { doctype, irn, irn_cancelled, ewaybill, eway_bill_cancelled, name, __unsaved } = frm.doc;
+			const { doctype, irn, irn_cancelled, ewaybill, eway_bill_cancelled, name, qrcode_image, __unsaved } = frm.doc;
 
 			const add_custom_button = (label, action) => {
 				if (!frm.custom_buttons[label]) {
@@ -175,27 +175,44 @@
 			}
 
 			if (irn && !irn_cancelled) {
-				const action = () => {
-					const dialog = frappe.msgprint({
-						title: __("Generate QRCode"),
-						message: __("Generate and attach QR Code using IRN?"),
-						primary_action: {
-							action: function() {
-								frappe.call({
-									method: 'erpnext.regional.india.e_invoice.utils.generate_qrcode',
-									args: { doctype, docname: name },
-									freeze: true,
-									callback: () => frm.reload_doc() || dialog.hide(),
-									error: () => dialog.hide()
-								});
+				let is_qrcode_attached = false;
+				if (qrcode_image && frm.attachments) {
+					let attachments = frm.attachments.get_attachments();
+					if (attachments.length != 0) {
+						for (let i = 0; i < attachments.length; i++) {
+							if (attachments[i].file_url == qrcode_image) {
+								is_qrcode_attached = true;
+								break;
 							}
-						},
+						}
+					}
+				}
+				if (!is_qrcode_attached) {
+					const action = () => {
+						if (frm.doc.__unsaved) {
+							frappe.throw(__('Please save the document to generate QRCode.'));
+						}
+						const dialog = frappe.msgprint({
+							title: __("Generate QRCode"),
+							message: __("Generate and attach QR Code using IRN?"),
+							primary_action: {
+								action: function() {
+									frappe.call({
+										method: 'erpnext.regional.india.e_invoice.utils.generate_qrcode',
+										args: { doctype, docname: name },
+										freeze: true,
+										callback: () => frm.reload_doc() || dialog.hide(),
+										error: () => dialog.hide()
+									});
+								}
+							},
 						primary_action_label: __('Yes')
 					});
 					dialog.show();
 				};
 				add_custom_button(__("Generate QRCode"), action);
 			}
+			}
 		}
 	});
 };
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index bcb3e4f..e5a1a59 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -1010,13 +1010,32 @@
 		return failed
 
 	def fetch_and_attach_qrcode_from_irn(self):
-		qrcode = self.get_qrcode_from_irn(self.invoice.irn)
-		if qrcode:
-			qrcode_file = self.create_qr_code_file(qrcode)
-			frappe.db.set_value("Sales Invoice", self.invoice.name, "qrcode_image", qrcode_file.file_url)
-			frappe.msgprint(_("QR Code attached to the invoice"), alert=True)
+		is_qrcode_file_attached = self.invoice.qrcode_image and frappe.db.exists(
+			"File",
+			{
+				"attached_to_doctype": "Sales Invoice",
+				"attached_to_name": self.invoice.name,
+				"file_url": self.invoice.qrcode_image,
+				"attached_to_field": "qrcode_image",
+			},
+		)
+		if not is_qrcode_file_attached:
+			if self.invoice.signed_qr_code:
+				self.attach_qrcode_image()
+				frappe.db.set_value(
+					"Sales Invoice", self.invoice.name, "qrcode_image", self.invoice.qrcode_image
+				)
+				frappe.msgprint(_("QR Code attached to the invoice."), alert=True)
+			else:
+				qrcode = self.get_qrcode_from_irn(self.invoice.irn)
+				if qrcode:
+					qrcode_file = self.create_qr_code_file(qrcode)
+					frappe.db.set_value("Sales Invoice", self.invoice.name, "qrcode_image", qrcode_file.file_url)
+					frappe.msgprint(_("QR Code attached to the invoice."), alert=True)
+				else:
+					frappe.msgprint(_("QR Code not found for the IRN"), alert=True)
 		else:
-			frappe.msgprint(_("QR Code not found for the IRN"), alert=True)
+			frappe.msgprint(_("QR Code is already Attached"), indicator="green", alert=True)
 
 	def get_qrcode_from_irn(self, irn):
 		import requests
@@ -1281,7 +1300,6 @@
 
 	def attach_qrcode_image(self):
 		qrcode = self.invoice.signed_qr_code
-
 		qr_image = io.BytesIO()
 		url = qrcreate(qrcode, error="L")
 		url.png(qr_image, scale=2, quiet_zone=1)