refactor!: remove `GoCardless Settings`
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py
deleted file mode 100644
index 65be599..0000000
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-
-import hashlib
-import hmac
-import json
-
-import frappe
-
-
-@frappe.whitelist(allow_guest=True)
-def webhooks():
- r = frappe.request
- if not r:
- return
-
- if not authenticate_signature(r):
- raise frappe.AuthenticationError
-
- gocardless_events = json.loads(r.get_data()) or []
- for event in gocardless_events["events"]:
- set_status(event)
-
- return 200
-
-
-def set_status(event):
- resource_type = event.get("resource_type", {})
-
- if resource_type == "mandates":
- set_mandate_status(event)
-
-
-def set_mandate_status(event):
- mandates = []
- if isinstance(event["links"], (list,)):
- for link in event["links"]:
- mandates.append(link["mandate"])
- else:
- mandates.append(event["links"]["mandate"])
-
- if (
- event["action"] == "pending_customer_approval"
- or event["action"] == "pending_submission"
- or event["action"] == "submitted"
- or event["action"] == "active"
- ):
- disabled = 0
- else:
- disabled = 1
-
- for mandate in mandates:
- frappe.db.set_value("GoCardless Mandate", mandate, "disabled", disabled)
-
-
-def authenticate_signature(r):
- """Returns True if the received signature matches the generated signature"""
- received_signature = frappe.get_request_header("Webhook-Signature")
-
- if not received_signature:
- return False
-
- for key in get_webhook_keys():
- computed_signature = hmac.new(key.encode("utf-8"), r.get_data(), hashlib.sha256).hexdigest()
- if hmac.compare_digest(str(received_signature), computed_signature):
- return True
-
- return False
-
-
-def get_webhook_keys():
- def _get_webhook_keys():
- webhook_keys = [
- d.webhooks_secret
- for d in frappe.get_all(
- "GoCardless Settings",
- fields=["webhooks_secret"],
- )
- if d.webhooks_secret
- ]
-
- return webhook_keys
-
- return frappe.cache().get_value("gocardless_webhooks_secret", _get_webhook_keys)
-
-
-def clear_cache():
- frappe.cache().delete_value("gocardless_webhooks_secret")
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js
deleted file mode 100644
index 2411297..0000000
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies and contributors
-// 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
deleted file mode 100644
index cca3653..0000000
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.json
+++ /dev/null
@@ -1,211 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "field:gateway_name",
- "beta": 0,
- "creation": "2018-02-06 16:11:10.028249",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "gateway_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Payment Gateway Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_2",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "access_token",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Access Token",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "webhooks_secret",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Webhooks Secret",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "use_sandbox",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Use Sandbox",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2022-02-12 14:18:47.209114",
- "modified_by": "Administrator",
- "module": "ERPNext Integrations",
- "name": "GoCardless Settings",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py
deleted file mode 100644
index 4a29a6a..0000000
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-
-from urllib.parse import urlencode
-
-import frappe
-import gocardless_pro
-from frappe import _
-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 erpnext.utilities import payment_app_import_guard
-
-
-class GoCardlessSettings(Document):
- supported_currencies = ["EUR", "DKK", "GBP", "SEK", "AUD", "NZD", "CAD", "USD"]
-
- def validate(self):
- self.initialize_client()
-
- def initialize_client(self):
- self.environment = self.get_environment()
- try:
- self.client = gocardless_pro.Client(
- access_token=self.access_token, environment=self.environment
- )
- return self.client
- except Exception as e:
- 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
- )
- call_hook_method("payment_gateway_enabled", gateway="GoCardless-" + self.gateway_name)
-
- def on_payment_request_submission(self, data):
- if data.reference_doctype != "Fees":
- customer_data = frappe.db.get_value(
- data.reference_doctype, data.reference_name, ["company", "customer_name"], as_dict=1
- )
-
- data = {
- "amount": flt(data.grand_total, data.precision("grand_total")),
- "title": customer_data.company.encode("utf-8"),
- "description": data.subject.encode("utf-8"),
- "reference_doctype": data.doctype,
- "reference_docname": data.name,
- "payer_email": data.email_to or frappe.session.user,
- "payer_name": customer_data.customer_name,
- "order_id": data.name,
- "currency": data.currency,
- }
-
- valid_mandate = self.check_mandate_validity(data)
- if valid_mandate is not None:
- data.update(valid_mandate)
-
- self.create_payment_request(data)
- return False
- else:
- return True
-
- def check_mandate_validity(self, data):
-
- if frappe.db.exists("GoCardless Mandate", dict(customer=data.get("payer_name"), disabled=0)):
- registered_mandate = frappe.db.get_value(
- "GoCardless Mandate", dict(customer=data.get("payer_name"), disabled=0), "mandate"
- )
- self.initialize_client()
- mandate = self.client.mandates.get(registered_mandate)
-
- if (
- mandate.status == "pending_customer_approval"
- or mandate.status == "pending_submission"
- or mandate.status == "submitted"
- or mandate.status == "active"
- ):
- return {"mandate": registered_mandate}
- else:
- return None
- else:
- return None
-
- def get_environment(self):
- if self.use_sandbox:
- return "sandbox"
- else:
- return "live"
-
- def validate_transaction_currency(self, currency):
- if currency not in self.supported_currencies:
- frappe.throw(
- _(
- "Please select another payment method. Go Cardless does not support transactions in currency '{0}'"
- ).format(currency)
- )
-
- def get_payment_url(self, **kwargs):
- return get_url("./integrations/gocardless_checkout?{0}".format(urlencode(kwargs)))
-
- def create_payment_request(self, data):
- self.data = frappe._dict(data)
-
- try:
- self.integration_request = create_request_log(self.data, "Host", "GoCardless")
- return self.create_charge_on_gocardless()
-
- except Exception:
- frappe.log_error("Gocardless payment reqeust failed")
- return {
- "redirect_to": frappe.redirect_to_message(
- _("Server Error"),
- _(
- "There seems to be an issue with the server's GoCardless configuration. Don't worry, in case of failure, the amount will get refunded to your account."
- ),
- ),
- "status": 401,
- }
-
- def create_charge_on_gocardless(self):
- redirect_to = self.data.get("redirect_to") or None
- redirect_message = self.data.get("redirect_message") or None
-
- reference_doc = frappe.get_doc(
- self.data.get("reference_doctype"), self.data.get("reference_docname")
- )
- self.initialize_client()
-
- try:
- payment = self.client.payments.create(
- params={
- "amount": cint(reference_doc.grand_total * 100),
- "currency": reference_doc.currency,
- "links": {"mandate": self.data.get("mandate")},
- "metadata": {
- "reference_doctype": reference_doc.doctype,
- "reference_document": reference_doc.name,
- },
- },
- headers={
- "Idempotency-Key": self.data.get("reference_docname"),
- },
- )
-
- if (
- payment.status == "pending_submission"
- or payment.status == "pending_customer_approval"
- or payment.status == "submitted"
- ):
- self.integration_request.db_set("status", "Authorized", update_modified=False)
- self.flags.status_changed_to = "Completed"
- self.integration_request.db_set("output", payment.status, update_modified=False)
-
- elif payment.status == "confirmed" or payment.status == "paid_out":
- self.integration_request.db_set("status", "Completed", update_modified=False)
- self.flags.status_changed_to = "Completed"
- self.integration_request.db_set("output", payment.status, update_modified=False)
-
- elif (
- payment.status == "cancelled"
- or payment.status == "customer_approval_denied"
- or payment.status == "charged_back"
- ):
- self.integration_request.db_set("status", "Cancelled", update_modified=False)
- frappe.log_error("Gocardless payment cancelled")
- self.integration_request.db_set("error", payment.status, update_modified=False)
- else:
- self.integration_request.db_set("status", "Failed", update_modified=False)
- frappe.log_error("Gocardless payment failed")
- self.integration_request.db_set("error", payment.status, update_modified=False)
-
- except Exception as e:
- frappe.log_error("GoCardless Payment Error")
-
- if self.flags.status_changed_to == "Completed":
- status = "Completed"
- if "reference_doctype" in self.data and "reference_docname" in self.data:
- custom_redirect_to = None
- try:
- custom_redirect_to = frappe.get_doc(
- self.data.get("reference_doctype"), self.data.get("reference_docname")
- ).run_method("on_payment_authorized", self.flags.status_changed_to)
- except Exception:
- frappe.log_error("Gocardless redirect failed")
-
- if custom_redirect_to:
- redirect_to = custom_redirect_to
-
- redirect_url = redirect_to
- else:
- status = "Error"
- redirect_url = "payment-failed"
-
- if redirect_message:
- redirect_url += "&" + urlencode({"redirect_message": redirect_message})
-
- redirect_url = get_url(redirect_url)
-
- return {"redirect_to": redirect_url, "status": status}
-
-
-def get_gateway_controller(doc):
- payment_request = frappe.get_doc("Payment Request", doc)
- gateway_controller = frappe.db.get_value(
- "Payment Gateway", payment_request.payment_gateway, "gateway_controller"
- )
- return gateway_controller
-
-
-def gocardless_initialization(doc):
- gateway_controller = get_gateway_controller(doc)
- settings = frappe.get_doc("GoCardless Settings", gateway_controller)
- client = settings.initialize_client()
- return client
diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py
deleted file mode 100644
index 379afe5..0000000
--- a/erpnext/erpnext_integrations/doctype/gocardless_settings/test_gocardless_settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2018, Frappe Technologies and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestGoCardlessSettings(unittest.TestCase):
- pass
diff --git a/pyproject.toml b/pyproject.toml
index 7841c92..604aa44 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,11 +16,9 @@
"holidays~=0.28",
# integration dependencies
- "gocardless-pro~=1.22.0",
"googlemaps",
"plaid-python~=7.2.1",
"python-youtube~=0.8.0",
- "tweepy~=4.14.0",
# Not used directly - required by PyQRCode for PNG generation
"pypng~=0.20220715.0",