Merge pull request #33269 from ssiyad/fix/ecommerce/breadcrumb_base

fix(ecommerce): remove query parameters from referrer
diff --git a/.github/helper/site_config_mariadb.json b/.github/helper/site_config_mariadb.json
index 49e7fcf..8c86f73 100644
--- a/.github/helper/site_config_mariadb.json
+++ b/.github/helper/site_config_mariadb.json
@@ -11,6 +11,6 @@
  "root_login": "root",
  "root_password": "root",
  "host_name": "http://test_site:8000",
- "install_apps": ["erpnext"],
+ "install_apps": ["payments", "erpnext"],
  "throttle_user_limit": 100
 }
diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js
index 8f09bc3..aff067e 100644
--- a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js
+++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js
@@ -3,6 +3,7 @@
 
 frappe.ui.form.on('Payment Gateway Account', {
 	refresh(frm) {
+		erpnext.utils.check_payments_app();
 		if(!frm.doc.__islocal) {
 			frm.set_df_property('payment_gateway', 'read_only', 1);
 		}
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 8665b70..d82083c 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -9,7 +9,6 @@
 from frappe.model.document import Document
 from frappe.utils import flt, get_url, nowdate
 from frappe.utils.background_jobs import enqueue
-from payments.utils import get_payment_gateway_controller
 
 from erpnext.accounts.doctype.payment_entry.payment_entry import (
 	get_company_defaults,
@@ -19,6 +18,14 @@
 from erpnext.accounts.party import get_party_account, get_party_bank_account
 from erpnext.accounts.utils import get_account_currency
 from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription
+from erpnext.utilities import payment_app_import_guard
+
+
+def _get_payment_gateway_controller(*args, **kwargs):
+	with payment_app_import_guard():
+		from payments.utils import get_payment_gateway_controller
+
+	return get_payment_gateway_controller(*args, **kwargs)
 
 
 class PaymentRequest(Document):
@@ -107,7 +114,7 @@
 			self.request_phone_payment()
 
 	def request_phone_payment(self):
-		controller = get_payment_gateway_controller(self.payment_gateway)
+		controller = _get_payment_gateway_controller(self.payment_gateway)
 		request_amount = self.get_request_amount()
 
 		payment_record = dict(
@@ -156,7 +163,7 @@
 
 	def payment_gateway_validation(self):
 		try:
-			controller = get_payment_gateway_controller(self.payment_gateway)
+			controller = _get_payment_gateway_controller(self.payment_gateway)
 			if hasattr(controller, "on_payment_request_submission"):
 				return controller.on_payment_request_submission(self)
 			else:
@@ -189,7 +196,7 @@
 			)
 			data.update({"company": frappe.defaults.get_defaults().company})
 
-		controller = get_payment_gateway_controller(self.payment_gateway)
+		controller = _get_payment_gateway_controller(self.payment_gateway)
 		controller.validate_transaction_currency(self.currency)
 
 		if hasattr(controller, "validate_minimum_transaction_amount"):
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.js b/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
index 7d6f2ae..00727f1 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
@@ -5,5 +5,9 @@
 	price_determination: function(frm) {
 		frm.toggle_reqd("cost", frm.doc.price_determination === 'Fixed rate');
 		frm.toggle_reqd("price_list", frm.doc.price_determination === 'Based on price list');
-	}
+	},
+
+	subscription_plan: function (frm) {
+		erpnext.utils.check_payments_app();
+	},
 });
diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js
index 69b9cfa..c37fa2f 100644
--- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js
+++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.js
@@ -48,5 +48,11 @@
 			frm.set_value('default_customer_group', '');
 			frm.set_value('quotation_series', '');
 		}
+	},
+
+	enable_checkout: function(frm) {
+		if (frm.doc.enable_checkout) {
+			erpnext.utils.check_payments_app();
+		}
 	}
 });
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js
index b649d9d..2411297 100644
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js
+++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js
@@ -2,4 +2,7 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('GoCardless Settings', {
+	refresh: function(frm) {
+		erpnext.utils.check_payments_app();
+	}
 });
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.json b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.json
index 9738106..cca3653 100644
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.json
+++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.json
@@ -173,7 +173,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 0,
- "modified": "2018-02-12 14:18:47.209114",
+ "modified": "2022-02-12 14:18:47.209114",
  "modified_by": "Administrator",
  "module": "ERPNext Integrations",
  "name": "GoCardless Settings",
@@ -201,7 +201,6 @@
    "write": 1
   }
  ],
- "quick_entry": 1,
  "read_only": 0,
  "read_only_onload": 0,
  "show_name_in_global_search": 0,
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py
index f9a293f..4a29a6a 100644
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py
+++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py
@@ -10,7 +10,8 @@
 from frappe.integrations.utils import create_request_log
 from frappe.model.document import Document
 from frappe.utils import call_hook_method, cint, flt, get_url
-from payments.utils import create_payment_gateway
+
+from erpnext.utilities import payment_app_import_guard
 
 
 class GoCardlessSettings(Document):
@@ -30,6 +31,9 @@
 			frappe.throw(e)
 
 	def on_update(self):
+		with payment_app_import_guard():
+			from payments.utils import create_payment_gateway
+
 		create_payment_gateway(
 			"GoCardless-" + self.gateway_name, settings="GoCardLess Settings", controller=self.gateway_name
 		)
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.js b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.js
index 7c8ae5c..447d720 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.js
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.js
@@ -7,6 +7,8 @@
 	},
 
 	refresh: function(frm) {
+		erpnext.utils.check_payments_app();
+
 		frappe.realtime.on("refresh_mpesa_dashboard", function(){
 			frm.reload_doc();
 			frm.events.setup_account_balance_html(frm);
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
index b534783..a298e11 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py
@@ -9,13 +9,13 @@
 from frappe.integrations.utils import create_request_log
 from frappe.model.document import Document
 from frappe.utils import call_hook_method, fmt_money, get_request_site_address
-from payments.utils import create_payment_gateway
 
 from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_connector import MpesaConnector
 from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_custom_fields import (
 	create_custom_pos_fields,
 )
 from erpnext.erpnext_integrations.utils import create_mode_of_payment
+from erpnext.utilities import payment_app_import_guard
 
 
 class MpesaSettings(Document):
@@ -30,6 +30,9 @@
 			)
 
 	def on_update(self):
+		with payment_app_import_guard():
+			from payments.utils import create_payment_gateway
+
 		create_custom_pos_fields()
 		create_payment_gateway(
 			"Mpesa-" + self.payment_gateway_name,
diff --git a/erpnext/erpnext_integrations/stripe_integration.py b/erpnext/erpnext_integrations/stripe_integration.py
index 2d7e8a5..634e5c2 100644
--- a/erpnext/erpnext_integrations/stripe_integration.py
+++ b/erpnext/erpnext_integrations/stripe_integration.py
@@ -2,12 +2,16 @@
 # For license information, please see license.txt
 
 import frappe
-import stripe
 from frappe import _
 from frappe.integrations.utils import create_request_log
 
+from erpnext.utilities import payment_app_import_guard
+
 
 def create_stripe_subscription(gateway_controller, data):
+	with payment_app_import_guard():
+		import stripe
+
 	stripe_settings = frappe.get_doc("Stripe Settings", gateway_controller)
 	stripe_settings.data = frappe._dict(data)
 
@@ -35,6 +39,9 @@
 
 
 def create_subscription_on_stripe(stripe_settings):
+	with payment_app_import_guard():
+		import stripe
+
 	items = []
 	for payment_plan in stripe_settings.payment_plans:
 		plan = frappe.db.get_value("Subscription Plan", payment_plan.plan, "product_price_id")
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 92601b3..fd19d25 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -8,7 +8,6 @@
 app_license = "GNU General Public License (v3)"
 source_link = "https://github.com/frappe/erpnext"
 app_logo_url = "/assets/erpnext/images/erpnext-logo.svg"
-required_apps = ["payments"]
 
 
 develop_version = "14.x.x-develop"
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 6d64625..d37b7bb 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -333,8 +333,18 @@
 			}
 			frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
 		});
-	}
+	},
 
+	// check if payments app is installed on site, if not warn user.
+	check_payments_app: () => {
+		if (frappe.boot.versions && !frappe.boot.versions.payments) {
+			const marketplace_link = '<a href="https://frappecloud.com/marketplace/apps/payments">Marketplace</a>'
+			const github_link = '<a href="https://github.com/frappe/payments/">GitHub</a>'
+			const msg = __("payments app is not installed. Please install it from {0} or {1}", [marketplace_link, github_link])
+			frappe.msgprint(msg);
+		}
+
+	},
 });
 
 erpnext.utils.select_alternate_items = function(opts) {
diff --git a/erpnext/utilities/__init__.py b/erpnext/utilities/__init__.py
index c2b4229..24bfdc6 100644
--- a/erpnext/utilities/__init__.py
+++ b/erpnext/utilities/__init__.py
@@ -1,6 +1,9 @@
 ## temp utility
 
+from contextlib import contextmanager
+
 import frappe
+from frappe import _
 from frappe.utils import cstr
 
 from erpnext.utilities.activation import get_level
@@ -35,3 +38,16 @@
 		domain = frappe.get_cached_value("Company", cstr(company), "domain")
 
 	return {"company": company, "domain": domain, "activation": get_level()}
+
+
+@contextmanager
+def payment_app_import_guard():
+	marketplace_link = '<a href="https://frappecloud.com/marketplace/apps/payments">Marketplace</a>'
+	github_link = '<a href="https://github.com/frappe/payments/">GitHub</a>'
+	msg = _("payments app is not installed. Please install it from {} or {}").format(
+		marketplace_link, github_link
+	)
+	try:
+		yield
+	except ImportError:
+		frappe.throw(msg, title=_("Missing Payments App"))