From 0134e13631342a7dc7aaa1bdd50ad2316e8a9985 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Wed, 20 Jun 2018 17:38:13 +0000 Subject: [PATCH] Subscription integration --- .../payment_request/payment_request.js | 15 +- .../payment_request/payment_request.json | 51 ++- .../payment_request/payment_request.py | 35 +- .../doctype/subscription/subscription.py | 19 +- .../subscription_plan/subscription_plan.json | 130 +++++++- .../subscription_plan/subscription_plan.py | 13 + .../doctype/payment_plan/__init__.py | 0 .../doctype/payment_plan/payment_plan.js | 6 - .../doctype/payment_plan/payment_plan.json | 195 ----------- .../doctype/payment_plan/test_payment_plan.js | 23 -- .../doctype/payment_plan/test_payment_plan.py | 9 - .../doctype/stripe_settings/__init__.py | 0 .../stripe_settings/stripe_settings.js | 6 - .../stripe_settings/stripe_settings.json | 315 ------------------ .../stripe_settings/stripe_settings.py | 159 --------- .../stripe_settings/test_stripe_settings.js | 23 -- .../stripe_settings/test_stripe_settings.py | 9 - .../payment_plan.py => stripe_integration.py} | 20 +- .../includes/integrations/stripe_checkout.js | 85 ----- .../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 ----- .../pages/integrations/stripe_checkout.css | 113 ------- .../pages/integrations/stripe_checkout.html | 56 ---- .../pages/integrations/stripe_checkout.py | 70 ---- requirements.txt | 1 - 28 files changed, 246 insertions(+), 1300 deletions(-) delete mode 100644 erpnext/erpnext_integrations/doctype/payment_plan/__init__.py delete mode 100644 erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.js delete mode 100644 erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.json delete mode 100644 erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.js delete mode 100644 erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.py delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/__init__.py delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.js delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.json delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.py delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.js delete mode 100644 erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.py rename erpnext/erpnext_integrations/{doctype/payment_plan/payment_plan.py => stripe_integration.py} (82%) delete mode 100644 erpnext/templates/includes/integrations/stripe_checkout.js delete mode 100644 erpnext/templates/pages/integrations/__init__.py delete mode 100644 erpnext/templates/pages/integrations/gocardless_checkout.html delete mode 100644 erpnext/templates/pages/integrations/gocardless_checkout.py delete mode 100644 erpnext/templates/pages/integrations/gocardless_confirmation.html delete mode 100644 erpnext/templates/pages/integrations/gocardless_confirmation.py delete mode 100644 erpnext/templates/pages/integrations/stripe_checkout.css delete mode 100644 erpnext/templates/pages/integrations/stripe_checkout.html delete mode 100644 erpnext/templates/pages/integrations/stripe_checkout.py diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js index 379dc86123..a80042937b 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.js +++ b/erpnext/accounts/doctype/payment_request/payment_request.js @@ -59,5 +59,18 @@ frappe.ui.form.on("Payment Request", "refresh", function(frm) { frappe.ui.form.on("Payment Request", "is_a_subscription", function(frm) { frm.toggle_reqd("payment_gateway_account", frm.doc.is_a_subscription); - frm.toggle_reqd("payment_plan", frm.doc.is_a_subscription); + frm.toggle_reqd("subscription_plans", frm.doc.is_a_subscription); + + if (frm.doc.is_a_subscription) { + frappe.call({ + method: "get_subscription_details", + doc: frm.doc, + freeze: true, + callback: function(r){ + if(!r.exc) { + frm.refresh_field("subscription_plans"); + } + } + }); + } }); diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 13a18f125c..4148dce3b4 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -307,6 +307,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_a_subscription", + "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": "Is a Subscription", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -380,9 +412,11 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "collapsible_depends_on": "", "columns": 0, - "fieldname": "is_a_subscription", - "fieldtype": "Check", + "depends_on": "eval:doc.is_a_subscription", + "fieldname": "subscription_section", + "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -390,7 +424,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Is a subscription", + "label": "Subscription Section", "length": 0, "no_copy": 0, "permlevel": 0, @@ -413,9 +447,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.is_a_subscription", - "fieldname": "payment_plan", - "fieldtype": "Link", + "fieldname": "subscription_plans", + "fieldtype": "Table", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -423,10 +456,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Payment Plan", + "label": "Subscription Plans", "length": 0, "no_copy": 0, - "options": "Payment Plan", + "options": "Subscription Plan Detail", "permlevel": 0, "precision": "", "print_hide": 0, @@ -842,7 +875,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-23 11:36:49.975929", + "modified": "2018-06-20 17:06:43.850174", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index a633cc31a6..8af0bcc728 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -12,8 +12,9 @@ from erpnext.accounts.utils import get_account_currency from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, get_company_defaults from frappe.integrations.utils import get_payment_gateway_controller from frappe.utils.background_jobs import enqueue +from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription -class PaymentRequest(Document): +class PaymentRequest(Document): def validate(self): self.validate_reference_document() self.validate_payment_request() @@ -33,6 +34,25 @@ class PaymentRequest(Document): if self.payment_account and ref_doc.currency != frappe.db.get_value("Account", self.payment_account, "account_currency"): frappe.throw(_("Transaction currency must be same as Payment Gateway currency")) + def on_update(self): + self.validate_subscription_details() + + def validate_subscription_details(self): + if self.is_a_subscription: + amount = 0 + for subscription_plan in self.subscription_plans: + plan = frappe.get_doc("Subscription Plan", subscription_plan.plan) + if plan.payment_gateway != self.payment_gateway_account: + frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request'.format(plan.name))) + + rate = plan.get_plan_rate() + frappe.log_error(rate) + + amount += rate + + if amount != self.grand_total: + frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.".format(self.grand_total, amount))) + def on_submit(self): send_mail = self.payment_gateway_validation() ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) @@ -235,6 +255,19 @@ class PaymentRequest(Document): return redirect_to + def create_subscription(self, payment_provider, gateway_controller, data): + if payment_provider == "stripe": + return create_stripe_subscription(gateway_controller, data) + + def get_subscription_details(self): + if self.reference_doctype == "Sales Invoice": + subscriptions = frappe.db.sql("""SELECT parent as sub_name FROM `tabSubscription Invoice` WHERE invoice='{0}'""".format(self.reference_name), as_dict=1) + self.subscription_plans = [] + for subscription in subscriptions: + plans = frappe.get_doc("Subscription", subscription.sub_name).plans + for plan in plans: + self.append('subscription_plans', plan) + @frappe.whitelist(allow_guest=True) def make_payment_request(**args): """Make payment request""" diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 6b3c7d2c8e..00dc61876d 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -8,7 +8,6 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt -from erpnext.utilities.product import get_price class Subscription(Document): @@ -300,21 +299,13 @@ class Subscription(Document): prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start) items = [] + customer = self.get_customer(self.subscriber) for plan in plans: subscription_plan = frappe.get_doc("Subscription Plan", plan.plan) - if subscription_plan.price_determination == "Fixed rate": - if not prorate: - items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': subscription_plan.cost}) - else: - items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': (subscription_plan.cost * prorate_factor)}) - elif subscription_plan.price_determination == "Based on price list": - customer = self.get_customer(self.subscriber) - customer_group = frappe.db.get_value("Customer", customer, "customer_group") - rate = get_price(item_code=subscription_plan.item, price_list=subscription_plan.price_list, customer_group=customer_group, company=None, qty=plan.qty) - if not prorate: - items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': rate}) - else: - items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': (rate * prorate_factor)}) + if not prorate: + items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': subscription_plan.get_plan_rate(customer)}) + else: + items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': (subscription_plan.get_plan_rate(customer) * prorate_factor)}) return items diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 0865998cba..453521d04d 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -434,6 +434,134 @@ "set_only_once": 0, "translatable": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "payment_plan_section", + "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, + "label": "Payment Plan", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "payment_plan_id", + "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": "Payment Plan", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_16", + "fieldtype": "Column 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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "payment_gateway", + "fieldtype": "Link", + "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": "Payment Gateway", + "length": 0, + "no_copy": 0, + "options": "Payment Gateway Account", + "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, + "translatable": 0, + "unique": 0 } ], "has_web_view": 0, @@ -446,7 +574,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-06-20 15:43:10.152762", + "modified": "2018-06-20 16:59:54.082358", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription Plan", diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index 4b8c8fcedd..da16ee0e8a 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from erpnext.utilities.product import get_price class SubscriptionPlan(Document): def validate(self): @@ -13,3 +14,15 @@ class SubscriptionPlan(Document): def validate_interval_count(self): if self.billing_interval_count < 1: frappe.throw('Billing Interval Count cannot be less than 1') + + def get_plan_rate(self, quantity=1, customer=None): + if self.price_determination == "Fixed rate": + return self.cost + + elif self.price_determination == "Based on price list": + if customer: + customer_group = frappe.db.get_value("Customer", customer, "customer_group") + else: + customer_group = None + + return get_price(item_code=self.item, price_list=self.price_list, customer_group=customer_group, company=None, qty=quantity).price_list_rate diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/__init__.py b/erpnext/erpnext_integrations/doctype/payment_plan/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.js b/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.js deleted file mode 100644 index d37bed9283..0000000000 --- a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.js +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Payment Plan', { - -}); diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.json b/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.json deleted file mode 100644 index 7550cb4135..0000000000 --- a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.json +++ /dev/null @@ -1,195 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:payment_plan_id", - "beta": 0, - "creation": "2018-05-23 10:17:31.108746", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan", - "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": "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_plan_id", - "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": "ID", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_gateway", - "fieldtype": "Link", - "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", - "length": 0, - "no_copy": 0, - "options": "Payment Gateway Account", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Monthly", - "description": "", - "fieldname": "recurrence", - "fieldtype": "Select", - "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": "Recurrence", - "length": 0, - "no_copy": 0, - "options": "Daily\nWeekly\nMonthly\nEvery 3 Months\nEvery 6 Months\nYearly", - "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, - "translatable": 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": "2018-05-23 18:25:48.200621", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "Payment Plan", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 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 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "payment_plan", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.js b/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.js deleted file mode 100644 index 330e71c2ab..0000000000 --- a/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Payment Plan", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Payment Plan - () => frappe.tests.make('Payment Plan', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.py b/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.py deleted file mode 100644 index b5935e4b5c..0000000000 --- a/erpnext/erpnext_integrations/doctype/payment_plan/test_payment_plan.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import unittest - -class TestPaymentPlan(unittest.TestCase): - pass diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/__init__.py b/erpnext/erpnext_integrations/doctype/stripe_settings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.js b/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.js deleted file mode 100644 index fbc8e7fbfb..0000000000 --- a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.js +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Stripe Settings', { - -}); diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.json b/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.json deleted file mode 100644 index 4129e74d74..0000000000 --- a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.json +++ /dev/null @@ -1,315 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:gateway_name", - "beta": 0, - "creation": "2017-03-09 17:18:29.458397", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "publishable_key", - "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": "Publishable Key", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column 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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "secret_key", - "fieldtype": "Password", - "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": "Secret Key", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "header_img", - "fieldtype": "Attach Image", - "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": "Header Image", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_7", - "fieldtype": "Column 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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "redirect_url", - "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": "Redirect URL", - "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, - "translatable": 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": "2018-05-23 18:15:55.584782", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "Stripe Settings", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.py b/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.py deleted file mode 100644 index cc71a58dd8..0000000000 --- a/erpnext/erpnext_integrations/doctype/stripe_settings/stripe_settings.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.document import Document -from frappe import _ -from six.moves.urllib.parse import urlencode -from frappe.utils import get_url, call_hook_method, cint, flt -from frappe.integrations.utils import make_get_request, create_request_log, create_payment_gateway -import stripe - -class StripeSettings(Document): - supported_currencies = [ - "AED", "ALL", "ANG", "ARS", "AUD", "AWG", "BBD", "BDT", "BIF", "BMD", "BND", - "BOB", "BRL", "BSD", "BWP", "BZD", "CAD", "CHF", "CLP", "CNY", "COP", "CRC", "CVE", "CZK", "DJF", - "DKK", "DOP", "DZD", "EGP", "ETB", "EUR", "FJD", "FKP", "GBP", "GIP", "GMD", "GNF", "GTQ", "GYD", - "HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "INR", "ISK", "JMD", "JPY", "KES", "KHR", "KMF", - "KRW", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "MAD", "MDL", "MNT", "MOP", "MRO", "MUR", "MVR", - "MWK", "MXN", "MYR", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "PAB", "PEN", "PGK", "PHP", "PKR", - "PLN", "PYG", "QAR", "RUB", "SAR", "SBD", "SCR", "SEK", "SGD", "SHP", "SLL", "SOS", "STD", "SVC", - "SZL", "THB", "TOP", "TTD", "TWD", "TZS", "UAH", "UGX", "USD", "UYU", "UZS", "VND", "VUV", "WST", - "XAF", "XOF", "XPF", "YER", "ZAR" - ] - - currency_wise_minimum_charge_amount = { - 'JPY': 50, 'MXN': 10, 'DKK': 2.50, 'HKD': 4.00, 'NOK': 3.00, 'SEK': 3.00, - 'USD': 0.50, 'AUD': 0.50, 'BRL': 0.50, 'CAD': 0.50, 'CHF': 0.50, 'EUR': 0.50, - 'GBP': 0.30, 'NZD': 0.50, 'SGD': 0.50 - } - - def on_update(self): - create_payment_gateway('Stripe-' + self.gateway_name, settings='Stripe Settings', controller=self.gateway_name) - call_hook_method('payment_gateway_enabled', gateway='Stripe-' + self.gateway_name) - if not self.flags.ignore_mandatory: - self.validate_stripe_credentails() - - def validate_stripe_credentails(self): - if self.publishable_key and self.secret_key: - header = {"Authorization": "Bearer {0}".format(self.get_password(fieldname="secret_key", raise_exception=False))} - try: - make_get_request(url="https://api.stripe.com/v1/charges", headers=header) - except Exception: - frappe.throw(_("Seems Publishable Key or Secret Key is wrong !!!")) - - def validate_transaction_currency(self, currency): - if currency not in self.supported_currencies: - frappe.throw(_("Please select another payment method. Stripe does not support transactions in currency '{0}'").format(currency)) - - def validate_minimum_transaction_amount(self, currency, amount): - if currency in self.currency_wise_minimum_charge_amount: - if flt(amount) < self.currency_wise_minimum_charge_amount.get(currency, 0.0): - frappe.throw(_("For currency {0}, the minimum transaction amount should be {1}").format(currency, - self.currency_wise_minimum_charge_amount.get(currency, 0.0))) - - def get_payment_url(self, **kwargs): - return get_url("./integrations/stripe_checkout?{0}".format(urlencode(kwargs))) - - def create_request(self, data): - self.data = frappe._dict(data) - stripe.api_key = self.get_password(fieldname="secret_key", raise_exception=False) - stripe.default_http_client = stripe.http_client.RequestsClient() - - try: - self.integration_request = create_request_log(self.data, "Host", "Stripe") - if frappe.db.get_value("Payment Request", self.data.reference_docname, 'is_a_subscription'): - self.payment_plan = frappe.db.get_value("Payment Request", self.data.reference_docname, 'payment_plan') - return self.create_subscription_on_stripe() - else: - return self.create_charge_on_stripe() - - except Exception: - frappe.log_error(frappe.get_traceback()) - return{ - "redirect_to": frappe.redirect_to_message(_('Server Error'), _("It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.")), - "status": 401 - } - - def create_charge_on_stripe(self): - try: - charge = stripe.Charge.create(amount=cint(flt(self.data.amount)*100), currency=self.data.currency, source=self.data.stripe_token_id, description=self.data.description) - - if charge.captured == True: - self.integration_request.db_set('status', 'Completed', update_modified=False) - self.flags.status_changed_to = "Completed" - - else: - frappe.log_error(charge.failure_message, 'Stripe Payment not completed') - - except Exception: - frappe.log_error(frappe.get_traceback()) - - return self.finalize_request() - - def create_subscription_on_stripe(self): - items = [ - { - "plan": self.payment_plan - } - ] - - try: - customer = stripe.Customer.create(description=self.data.payer_name, email=self.data.payer_email, source=self.data.stripe_token_id) - subscription = stripe.Subscription.create(customer=customer, items=items) - - if subscription.status == "active": - self.integration_request.db_set('status', 'Completed', update_modified=False) - self.flags.status_changed_to = "Completed" - - else: - self.integration_request.db_set('status', 'Failed', update_modified=False) - frappe.log_error('Subscription N°: ' + subscription.id, 'Stripe Payment not completed') - - except Exception: - self.integration_request.db_set('status', 'Failed', update_modified=False) - frappe.log_error(frappe.get_traceback()) - - return self.finalize_request() - - def finalize_request(self): - redirect_to = self.data.get('redirect_to') or None - redirect_message = self.data.get('redirect_message') or None - status = self.integration_request.status - - if self.flags.status_changed_to == "Completed": - if self.data.reference_doctype and self.data.reference_docname: - custom_redirect_to = None - try: - custom_redirect_to = frappe.get_doc(self.data.reference_doctype, - self.data.reference_docname).run_method("on_payment_authorized", self.flags.status_changed_to) - except Exception: - frappe.log_error(frappe.get_traceback()) - - if custom_redirect_to: - redirect_to = custom_redirect_to - - redirect_url = 'payment-success' - - if self.redirect_url: - redirect_url = self.redirect_url - redirect_to = None - else: - redirect_url = 'payment-failed' - - if redirect_to: - redirect_url += '?' + urlencode({'redirect_to': redirect_to}) - if redirect_message: - redirect_url += '&' + urlencode({'redirect_message': redirect_message}) - - 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 diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.js b/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.js deleted file mode 100644 index b491ba5737..0000000000 --- a/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: Stripe Settings", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially([ - // insert a new Stripe Settings - () => frappe.tests.make('Stripe Settings', [ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.py b/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.py deleted file mode 100644 index 0c5aa83c65..0000000000 --- a/erpnext/erpnext_integrations/doctype/stripe_settings/test_stripe_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import unittest - -class TestStripeSettings(unittest.TestCase): - pass diff --git a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.py b/erpnext/erpnext_integrations/stripe_integration.py similarity index 82% rename from erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.py rename to erpnext/erpnext_integrations/stripe_integration.py index 0e71fbca5f..c33adf90d8 100644 --- a/erpnext/erpnext_integrations/doctype/payment_plan/payment_plan.py +++ b/erpnext/erpnext_integrations/stripe_integration.py @@ -9,10 +9,6 @@ from frappe import _ from frappe.integrations.utils import create_request_log import stripe -class PaymentPlan(Document): - pass - - def create_stripe_subscription(gateway_controller, data): stripe_settings = frappe.get_doc("Stripe Settings", gateway_controller) stripe_settings.data = frappe._dict(data) @@ -22,7 +18,7 @@ def create_stripe_subscription(gateway_controller, data): try: stripe_settings.integration_request = create_request_log(stripe_settings.data, "Host", "Stripe") - stripe_settings.payment_plan = frappe.db.get_value("Payment Request", stripe_settings.data.reference_docname, 'payment_plan') + stripe_settings.payment_plans = frappe.get_doc("Payment Request", stripe_settings.data.reference_docname).subscription_plans return create_subscription_on_stripe(stripe_settings) except Exception: @@ -34,11 +30,13 @@ def create_stripe_subscription(gateway_controller, data): def create_subscription_on_stripe(stripe_settings): - items = [ - { - "plan": stripe_settings.payment_plan - } - ] + items = [] + for payment_plan in stripe_settings.payment_plans: + plan = frappe.db.get_value("Subscription Plan", payment_plan.plan, "payment_plan_id") + items.append({"plan": plan, "quantity": payment_plan.qty}) + + frappe.log_error(items, 'Items') + try: customer = stripe.Customer.create(description=stripe_settings.data.payer_name, email=stripe_settings.data.payer_email, source=stripe_settings.data.stripe_token_id) @@ -56,4 +54,4 @@ def create_subscription_on_stripe(stripe_settings): stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False) frappe.log_error(frappe.get_traceback()) - return stripe_settings.finalize_request() + return stripe_settings.finalize_request() \ No newline at end of file diff --git a/erpnext/templates/includes/integrations/stripe_checkout.js b/erpnext/templates/includes/integrations/stripe_checkout.js deleted file mode 100644 index 1ce3b12b7a..0000000000 --- a/erpnext/templates/includes/integrations/stripe_checkout.js +++ /dev/null @@ -1,85 +0,0 @@ -var stripe = Stripe("{{ publishable_key }}"); - -var elements = stripe.elements(); - -var style = { - base: { - color: '#32325d', - lineHeight: '18px', - fontFamily: '"Helvetica Neue", Helvetica, sans-serif', - fontSmoothing: 'antialiased', - fontSize: '16px', - '::placeholder': { - color: '#aab7c4' - } - }, - invalid: { - color: '#fa755a', - iconColor: '#fa755a' - } -}; - -var card = elements.create('card', { - hidePostalCode: true, - style: style -}); - -card.mount('#card-element'); - -function setOutcome(result) { - - if (result.token) { - $('#submit').prop('disabled', true) - $('#submit').html(__('Processing...')) - frappe.call({ - method:"erpnext.templates.pages.integrations.stripe_checkout.make_payment", - freeze:true, - headers: {"X-Requested-With": "XMLHttpRequest"}, - args: { - "stripe_token_id": result.token.id, - "data": JSON.stringify({{ frappe.form_dict|json }}), - "reference_doctype": "{{ reference_doctype }}", - "reference_docname": "{{ reference_docname }}" - }, - callback: function(r) { - if (r.message.status == "Completed") { - $('#submit').hide() - $('.success').show() - setTimeout(function() { - window.location.href = r.message.redirect_to - }, 2000); - } else { - $('#submit').hide() - $('.error').show() - setTimeout(function() { - window.location.href = r.message.redirect_to - }, 2000); - } - } - }); - - } else if (result.error) { - $('.error').html() = result.error.message; - $('.error').show() - } -} - -card.on('change', function(event) { - var displayError = document.getElementById('card-errors'); - if (event.error) { - displayError.textContent = event.error.message; - } else { - displayError.textContent = ''; - } -}); - -frappe.ready(function() { - $('#submit').off("click").on("click", function(e) { - e.preventDefault(); - var extraDetails = { - name: $('input[name=cardholder-name]').val(), - email: $('input[name=cardholder-email]').val() - } - stripe.createToken(card, extraDetails).then(setOutcome); - }) -}); diff --git a/erpnext/templates/pages/integrations/__init__.py b/erpnext/templates/pages/integrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.html b/erpnext/templates/pages/integrations/gocardless_checkout.html deleted file mode 100644 index eb124cafb6..0000000000 --- a/erpnext/templates/pages/integrations/gocardless_checkout.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "templates/web.html" %} - -{% block title %} Payment {% endblock %} - -{%- block header -%}{% endblock %} - -{% block script %} - -{% endblock %} - -{%- block page_content -%} -

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

- -{% endblock %} diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.py b/erpnext/templates/pages/integrations/gocardless_checkout.py deleted file mode 100644 index 3c2466ea2f..0000000000 --- a/erpnext/templates/pages/integrations/gocardless_checkout.py +++ /dev/null @@ -1,76 +0,0 @@ -# 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'} diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.html b/erpnext/templates/pages/integrations/gocardless_confirmation.html deleted file mode 100644 index 1baf23be26..0000000000 --- a/erpnext/templates/pages/integrations/gocardless_confirmation.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "templates/web.html" %} - -{% block title %} Payment {% endblock %} - -{%- block header -%}{% endblock %} - -{% block script %} - -{% endblock %} - -{%- block page_content -%} -

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

- -{% endblock %} diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.py b/erpnext/templates/pages/integrations/gocardless_confirmation.py deleted file mode 100644 index fc564c3df9..0000000000 --- a/erpnext/templates/pages/integrations/gocardless_confirmation.py +++ /dev/null @@ -1,85 +0,0 @@ -# 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()) diff --git a/erpnext/templates/pages/integrations/stripe_checkout.css b/erpnext/templates/pages/integrations/stripe_checkout.css deleted file mode 100644 index a42808aa7f..0000000000 --- a/erpnext/templates/pages/integrations/stripe_checkout.css +++ /dev/null @@ -1,113 +0,0 @@ -.StripeElement { - background-color: white; - height: 40px; - padding: 10px 12px; - border-radius: 4px; - border: 1px solid transparent; - box-shadow: 0 1px 3px 0 #e6ebf1; - -webkit-transition: box-shadow 150ms ease; - transition: box-shadow 150ms ease; -} - -.StripeElement--focus { - box-shadow: 0 1px 3px 0 #cfd7df; -} - -.StripeElement--invalid { - border-color: #fa755a; -} - -.StripeElement--webkit-autofill { - background-color: #fefde5; -} - -.stripe #payment-form { - margin-top: 80px; -} - -.stripe button { - float: right; - display: block; - background: #5e64ff; - color: white; - box-shadow: 0 7px 14px 0 rgba(49, 49, 93, 0.10), 0 3px 6px 0 rgba(0, 0, 0, 0.08); - border-radius: 4px; - border: 0; - margin-top: 20px; - font-size: 15px; - font-weight: 400; - max-width: 40%; - height: 40px; - line-height: 38px; - outline: none; -} - -.stripe button:hover, .stripe button:focus { - background: #2b33ff; - border-color: #0711ff; -} - -.stripe button:active { - background: #5e64ff; -} - -.stripe button:disabled { - background: #515e80; -} - -.stripe .group { - background: white; - box-shadow: 2px 7px 14px 2px rgba(49, 49, 93, 0.10), 0 3px 6px 0 rgba(0, 0, 0, 0.08); - border-radius: 4px; - margin-bottom: 20px; -} - -.stripe label { - position: relative; - color: #8898AA; - font-weight: 300; - height: 40px; - line-height: 40px; - margin-left: 20px; - display: block; -} - -.stripe .group label:not(:last-child) { - border-bottom: 1px solid #F0F5FA; -} - -.stripe label>span { - width: 20%; - text-align: right; - float: left; -} - -.current-card { - margin-left: 20px; -} - -.field { - background: transparent; - font-weight: 300; - border: 0; - color: #31325F; - outline: none; - padding-right: 10px; - padding-left: 10px; - cursor: text; - width: 70%; - height: 40px; - float: right; -} - -.field::-webkit-input-placeholder { - color: #CFD7E0; -} - -.field::-moz-placeholder { - color: #CFD7E0; -} - -.field:-ms-input-placeholder { - color: #CFD7E0; -} diff --git a/erpnext/templates/pages/integrations/stripe_checkout.html b/erpnext/templates/pages/integrations/stripe_checkout.html deleted file mode 100644 index b52428667b..0000000000 --- a/erpnext/templates/pages/integrations/stripe_checkout.html +++ /dev/null @@ -1,56 +0,0 @@ -{% extends "templates/web.html" %} - -{% block title %} Payment {% endblock %} - -{%- block header -%} -{% endblock %} - -{% block script %} - - -{% endblock %} - -{%- block page_content -%} - -
-
- -

{{description}}

-
-
-
-
- -
-
-
-
- -
-
-
- -
- -
- -
- - -
-
-
-
- - -{% endblock %} diff --git a/erpnext/templates/pages/integrations/stripe_checkout.py b/erpnext/templates/pages/integrations/stripe_checkout.py deleted file mode 100644 index 6faf8f1cc9..0000000000 --- a/erpnext/templates/pages/integrations/stripe_checkout.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2015, 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 cint, fmt_money -import json -from erpnext.erpnext_integrations.doctype.stripe_settings.stripe_settings import get_gateway_controller -from erpnext.erpnext_integrations.doctype.payment_plan.payment_plan import create_stripe_subscription - -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(list(frappe.form_dict))): - for key in expected_keys: - context[key] = frappe.form_dict[key] - - gateway_controller = get_gateway_controller(context.reference_docname) - context.publishable_key = get_api_key(context.reference_docname, gateway_controller) - context.image = get_header_image(context.reference_docname, gateway_controller) - - context['amount'] = fmt_money(amount=context['amount'], currency=context['currency']) - - if frappe.db.get_value(context.reference_doctype, context.reference_docname, "is_a_subscription"): - payment_plan = frappe.db.get_value(context.reference_doctype, context.reference_docname, "payment_plan") - recurrence = frappe.db.get_value("Payment Plan", payment_plan, "recurrence") - - context['amount'] = context['amount'] + " " + _(recurrence) - - 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 - -def get_api_key(doc, gateway_controller): - publishable_key = frappe.db.get_value("Stripe Settings", gateway_controller, "publishable_key") - if cint(frappe.form_dict.get("use_sandbox")): - publishable_key = frappe.conf.sandbox_publishable_key - - return publishable_key - -def get_header_image(doc, gateway_controller): - header_image = frappe.db.get_value("Stripe Settings", gateway_controller, "header_img") - return header_image - -@frappe.whitelist(allow_guest=True) -def make_payment(stripe_token_id, data, reference_doctype=None, reference_docname=None): - data = json.loads(data) - - data.update({ - "stripe_token_id": stripe_token_id - }) - - gateway_controller = get_gateway_controller(reference_docname) - - if frappe.db.get_value("Payment Request", reference_docname, 'is_a_subscription'): - data = create_stripe_subscription(gateway_controller, data) - else: - data = frappe.get_doc("Stripe Settings", gateway_controller).create_request(data) - - frappe.db.commit() - return data diff --git a/requirements.txt b/requirements.txt index 2da865c277..13055ac2ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,3 @@ python-stdnum braintree gocardless_pro woocommerce -stripe