Merge pull request #25869 from nextchamp-saqib/plaid-link-reset

fix(plaid): cannot reset plaid link for a bank account
diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js
index 059e1d3..19041a3 100644
--- a/erpnext/accounts/doctype/bank/bank.js
+++ b/erpnext/accounts/doctype/bank/bank.js
@@ -120,4 +120,4 @@
 	plaid_success(token, response) {
 		frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
 	}
-};
+};
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
index 5f990cd..42d4b9b 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
@@ -99,5 +99,7 @@
 				response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions))
 				transactions.extend(response["transactions"])
 			return transactions
+		except ItemError as e:
+			raise e
 		except Exception:
 			frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
index bbc2ca8..37bf282 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
@@ -16,6 +16,10 @@
 				new erpnext.integrations.plaidLink(frm);
 			});
 
+			frm.add_custom_button(__('Reset Plaid Link'), () => {
+				new erpnext.integrations.plaidLink(frm);
+			});
+
 			frm.add_custom_button(__("Sync Now"), () => {
 				frappe.call({
 					method: "erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.enqueue_synchronization",
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index ce15e47..3ef069b 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -12,6 +12,7 @@
 from frappe.model.document import Document
 from frappe.utils import add_months, formatdate, getdate, today
 
+from plaid.errors import ItemError
 
 class PlaidSettings(Document):
 	@staticmethod
@@ -51,7 +52,7 @@
 			})
 			bank.insert()
 		except Exception:
-			frappe.throw(frappe.get_traceback())
+			frappe.log_error(frappe.get_traceback(), title=_('Plaid Link Error'))
 	else:
 		bank = frappe.get_doc("Bank", response["institution"]["name"])
 		bank.plaid_access_token = access_token
@@ -83,7 +84,12 @@
 		if not acc_subtype:
 			add_account_subtype(account["subtype"])
 
-		if not frappe.db.exists("Bank Account", dict(integration_id=account["id"])):
+		existing_bank_account = frappe.db.exists("Bank Account", {
+			'account_name': account["name"],
+			'bank': bank["bank_name"]
+		})
+
+		if not existing_bank_account:
 			try:
 				new_account = frappe.get_doc({
 					"doctype": "Bank Account",
@@ -103,10 +109,27 @@
 			except frappe.UniqueValidationError:
 				frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(account["name"]))
 			except Exception:
-				frappe.throw(frappe.get_traceback())
+				frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
+				frappe.throw(_("There was an error creating Bank Account while linking with Plaid."), 
+					title=_("Plaid Link Failed"))
 
 		else:
-			result.append(frappe.db.get_value("Bank Account", dict(integration_id=account["id"]), "name"))
+			try:
+				existing_account = frappe.get_doc('Bank Account', existing_bank_account)
+				existing_account.update({
+					"bank": bank["bank_name"],
+					"account_name": account["name"],
+					"account_type": account.get("type", ""),
+					"account_subtype": account.get("subtype", ""),
+					"mask": account.get("mask", ""),
+					"integration_id": account["id"]
+				})
+				existing_account.save()
+				result.append(existing_bank_account)
+			except Exception:
+				frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
+				frappe.throw(_("There was an error updating Bank Account {} while linking with Plaid.").format(
+					existing_bank_account), title=_("Plaid Link Failed"))
 
 	return result
 
@@ -172,9 +195,16 @@
 		account_id = None
 
 	plaid = PlaidConnector(access_token)
-	transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
 
-	return transactions
+	try:
+		transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
+	except ItemError as e:
+		if e.code == "ITEM_LOGIN_REQUIRED":
+			msg = _("There was an error syncing transactions.") + " "
+			msg += _("Please refresh or reset the Plaid linking of the Bank {}.").format(bank) + " "
+			frappe.log_error(msg, title=_("Plaid Link Refresh Required"))
+
+	return transactions or []
 
 
 def new_bank_transaction(transaction):