From 244b638fe319bdd156c0e0dbf7887c058b418a33 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Wed, 20 Jun 2018 17:51:52 +0000 Subject: [PATCH] Dev cleanup --- .../doctype/subscription/subscription.py | 12 ++- .../templates/pages/integrations/__init__.py | 0 .../integrations/gocardless_checkout.html | 16 ++++ .../pages/integrations/gocardless_checkout.py | 76 +++++++++++++++++ .../integrations/gocardless_confirmation.html | 16 ++++ .../integrations/gocardless_confirmation.py | 85 +++++++++++++++++++ 6 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 erpnext/templates/pages/integrations/__init__.py create mode 100644 erpnext/templates/pages/integrations/gocardless_checkout.html create mode 100644 erpnext/templates/pages/integrations/gocardless_checkout.py create mode 100644 erpnext/templates/pages/integrations/gocardless_confirmation.html create mode 100644 erpnext/templates/pages/integrations/gocardless_confirmation.py diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 00dc61876dd..2b18a62e1b5 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -13,9 +13,9 @@ from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_l class Subscription(Document): def before_insert(self): # update start just before the subscription doc is created - self.update_subscription_period(self.start, init=True) + self.update_subscription_period(self.start) - def update_subscription_period(self, date=None, init=False): + def update_subscription_period(self, date=None): """ Subscription period is the period to be billed. This method updates the beginning of the billing period and end of the billing period. @@ -25,7 +25,7 @@ class Subscription(Document): as `current_invoice_end`. """ self.set_current_invoice_start(date) - self.set_current_invoice_end(init=False) + self.set_current_invoice_end() def set_current_invoice_start(self, date=None): """ @@ -40,7 +40,7 @@ class Subscription(Document): else: self.current_invoice_start = nowdate() - def set_current_invoice_end(self, init=False): + def set_current_invoice_end(self): """ This sets the date of the end of the current billing period. @@ -51,9 +51,7 @@ class Subscription(Document): current billing period where `x` is the billing interval from the `Subscription Plan` in the `Subscription`. """ - if init==True: - return - elif self.is_trialling(): + if self.is_trialling(): self.current_invoice_end = self.trial_period_end else: billing_cycle_info = self.get_billing_cycle_data() diff --git a/erpnext/templates/pages/integrations/__init__.py b/erpnext/templates/pages/integrations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.html b/erpnext/templates/pages/integrations/gocardless_checkout.html new file mode 100644 index 00000000000..bbe5640d5e4 --- /dev/null +++ b/erpnext/templates/pages/integrations/gocardless_checkout.html @@ -0,0 +1,16 @@ +{% extends "templates/web.html" %} + +{% block title %} Payment {% endblock %} + +{%- block header -%}{% endblock %} + +{% block script %} + +{% endblock %} + +{%- block page_content -%} +

+ {{ _("Loading Payment System") }} +

+ +{% endblock %} \ No newline at end of file diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.py b/erpnext/templates/pages/integrations/gocardless_checkout.py new file mode 100644 index 00000000000..2ba7001a615 --- /dev/null +++ b/erpnext/templates/pages/integrations/gocardless_checkout.py @@ -0,0 +1,76 @@ +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import flt +import json +from erpnext.erpnext_integrations.doctype.gocardless_settings.gocardless_settings import gocardless_initialization, get_gateway_controller +from frappe.utils import get_url + +no_cache = 1 +no_sitemap = 1 + +expected_keys = ('amount', 'title', 'description', 'reference_doctype', 'reference_docname', + 'payer_name', 'payer_email', 'order_id', 'currency') + +def get_context(context): + context.no_cache = 1 + + # all these keys exist in form_dict + if not (set(expected_keys) - set(frappe.form_dict.keys())): + for key in expected_keys: + context[key] = frappe.form_dict[key] + + context['amount'] = flt(context['amount']) + + gateway_controller = get_gateway_controller(context.reference_docname) + context['header_img'] = frappe.db.get_value("GoCardless Settings", gateway_controller, "header_img") + + else: + frappe.redirect_to_message(_('Some information is missing'), + _('Looks like someone sent you to an incomplete URL. Please ask them to look into it.')) + frappe.local.flags.redirect_location = frappe.local.response.location + raise frappe.Redirect + +@frappe.whitelist(allow_guest=True) +def check_mandate(data, reference_doctype, reference_docname): + data = json.loads(data) + + client = gocardless_initialization(reference_docname) + + payer = frappe.get_doc("Customer", data["payer_name"]) + + if payer.customer_type == "Individual" and payer.customer_primary_contact is not None: + primary_contact = frappe.get_doc("Contact", payer.customer_primary_contact) + prefilled_customer = { + "company_name": payer.name, + "given_name": primary_contact.first_name, + "family_name": primary_contact.last_name, + } + if primary_contact.email_id is not None: + prefilled_customer.update({"email": primary_contact.email_id}) + else: + prefilled_customer.update({"email": frappe.session.user}) + + else: + prefilled_customer = { + "company_name": payer.name, + "email": frappe.session.user + } + + success_url = get_url("./integrations/gocardless_confirmation?reference_doctype=" + reference_doctype + "&reference_docname=" + reference_docname) + + try: + redirect_flow = client.redirect_flows.create(params={ + "description": _("Pay {0} {1}".format(data['amount'], data['currency'])), + "session_token": frappe.session.user, + "success_redirect_url": success_url, + "prefilled_customer": prefilled_customer + }) + + return {"redirect_to": redirect_flow.redirect_url} + + except Exception as e: + frappe.log_error(e, "GoCardless Payment Error") + return {"redirect_to": '/integrations/payment-failed'} \ No newline at end of file diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.html b/erpnext/templates/pages/integrations/gocardless_confirmation.html new file mode 100644 index 00000000000..15674876573 --- /dev/null +++ b/erpnext/templates/pages/integrations/gocardless_confirmation.html @@ -0,0 +1,16 @@ +{% extends "templates/web.html" %} + +{% block title %} Payment {% endblock %} + +{%- block header -%}{% endblock %} + +{% block script %} + +{% endblock %} + +{%- block page_content -%} +

+ {{ _("Payment Confirmation") }} +

+ +{% endblock %} \ No newline at end of file diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.py b/erpnext/templates/pages/integrations/gocardless_confirmation.py new file mode 100644 index 00000000000..069d90050e2 --- /dev/null +++ b/erpnext/templates/pages/integrations/gocardless_confirmation.py @@ -0,0 +1,85 @@ +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt +from __future__ import unicode_literals +import frappe +from frappe import _ +from erpnext.erpnext_integrations.doctype.gocardless_settings.gocardless_settings import gocardless_initialization, get_gateway_controller + +no_cache = 1 +no_sitemap = 1 + +expected_keys = ('redirect_flow_id', 'reference_doctype', 'reference_docname') + +def get_context(context): + context.no_cache = 1 + + # all these keys exist in form_dict + if not (set(expected_keys) - set(frappe.form_dict.keys())): + for key in expected_keys: + context[key] = frappe.form_dict[key] + + else: + frappe.redirect_to_message(_('Some information is missing'), + _('Looks like someone sent you to an incomplete URL. Please ask them to look into it.')) + frappe.local.flags.redirect_location = frappe.local.response.location + raise frappe.Redirect + +@frappe.whitelist(allow_guest=True) +def confirm_payment(redirect_flow_id, reference_doctype, reference_docname): + + client = gocardless_initialization(reference_docname) + + try: + redirect_flow = client.redirect_flows.complete( + redirect_flow_id, + params={ + "session_token": frappe.session.user + }) + + data = { + "mandate": redirect_flow.links.mandate, + "customer": redirect_flow.links.customer, + "redirect_to": redirect_flow.confirmation_url, + "redirect_message": "Mandate successfully created", + "reference_doctype": reference_doctype, + "reference_docname": reference_docname + } + + try: + create_mandate(data) + except Exception as e: + frappe.log_error(e, "GoCardless Mandate Registration Error") + + gateway_controller = get_gateway_controller(reference_docname) + frappe.get_doc("GoCardless Settings", gateway_controller).create_payment_request(data) + + return {"redirect_to": redirect_flow.confirmation_url} + + except Exception as e: + frappe.log_error(e, "GoCardless Payment Error") + return {"redirect_to": '/integrations/payment-failed'} + + +def create_mandate(data): + data = frappe._dict(data) + frappe.logger().debug(data) + + mandate = data.get('mandate') + + if frappe.db.exists("GoCardless Mandate", mandate): + return + + else: + reference_doc = frappe.db.get_value(data.get('reference_doctype'), data.get('reference_docname'), ["reference_doctype", "reference_name"], as_dict=1) + erpnext_customer = frappe.db.get_value(reference_doc.reference_doctype, reference_doc.reference_name, ["customer_name"], as_dict=1) + + try: + frappe.get_doc({ + "doctype": "GoCardless Mandate", + "mandate": mandate, + "customer": erpnext_customer.customer_name, + "gocardless_customer": data.get('customer') + }).insert(ignore_permissions=True) + + except Exception: + frappe.log_error(frappe.get_traceback()) \ No newline at end of file