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..337c93e 100644
--- a/erpnext/accounts/doctype/bank/bank.js
+++ b/erpnext/accounts/doctype/bank/bank.js
@@ -25,6 +25,10 @@
 			frm.add_custom_button(__('Refresh Plaid Link'), () => {
 				new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
 			});
+
+			frm.add_custom_button(__('Reset Plaid Link'), () => {
+				new erpnext.integrations.plaidLink(frm);
+			});
 		}
 	}
 });
@@ -121,3 +125,101 @@
 		frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
 	}
 };
+
+erpnext.integrations.plaidLink = class plaidLink {
+	constructor(parent) {
+		this.frm = parent;
+		this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
+		this.init_config();
+	}
+
+	async init_config() {
+		this.product = ["auth", "transactions"];
+		this.plaid_env = this.frm.doc.plaid_env;
+		this.client_name = frappe.boot.sitename;
+		this.token = await this.get_link_token();
+		this.init_plaid();
+	}
+
+	async get_link_token() {
+		const token = await this.frm.call("get_link_token").then(resp => resp.message);
+		if (!token) {
+			frappe.throw(__('Cannot retrieve link token. Check Error Log for more information'));
+		}
+		return token;
+	}
+
+	init_plaid() {
+		const me = this;
+		me.loadScript(me.plaidUrl)
+			.then(() => {
+				me.onScriptLoaded(me);
+			})
+			.then(() => {
+				if (me.linkHandler) {
+					me.linkHandler.open();
+				}
+			})
+			.catch((error) => {
+				me.onScriptError(error);
+			});
+	}
+
+	loadScript(src) {
+		return new Promise(function (resolve, reject) {
+			if (document.querySelector('script[src="' + src + '"]')) {
+				resolve();
+				return;
+			}
+			const el = document.createElement('script');
+			el.type = 'text/javascript';
+			el.async = true;
+			el.src = src;
+			el.addEventListener('load', resolve);
+			el.addEventListener('error', reject);
+			el.addEventListener('abort', reject);
+			document.head.appendChild(el);
+		});
+	}
+
+	onScriptLoaded(me) {
+		me.linkHandler = Plaid.create({
+			clientName: me.client_name,
+			product: me.product,
+			env: me.plaid_env,
+			token: me.token,
+			onSuccess: me.plaid_success
+		});
+	}
+
+	onScriptError(error) {
+		frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
+		console.log(error);
+	}
+
+	plaid_success(token, response) {
+		const me = this;
+
+		frappe.prompt({
+			fieldtype: "Link",
+			options: "Company",
+			label: __("Company"),
+			fieldname: "company",
+			reqd: 1
+		}, (data) => {
+			me.company = data.company;
+			frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_institution', {
+				token: token,
+				response: response
+			}).then((result) => {
+				frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_bank_accounts', {
+					response: response,
+					bank: result,
+					company: me.company
+				});
+			}).then(() => {
+				frappe.show_alert({ message: __("Bank accounts added"), indicator: 'green' });
+			});
+		}, __("Select a company"), __("Continue"));
+	}
+};
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.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):