瀏覽代碼

Deprecate Integration Broker (#2831)

* [fix] remove razorpay from integration service

* [fix] clean-up js side integration service dependancies

* [fix] remove integration service, .py cleanup, move integration request to integration

* [fix] move oauth to integrations and deprecate integration broker

* [fix] mark services enabled and update integrations listing

* [fix] V7.1 and V7.2 integration service related pathch fixes and move payment gateway dotype to core module

* [fix] create payment gateway records if not exists

* [fix] module page for integrations

* [minor][fix] minor checks

* [fix] remove integration broker module only if not allocated to any doctype
version-14
Saurabh 8 年之前
committed by Rushabh Mehta
父節點
當前提交
7620bb3789
共有 60 個文件被更改,包括 507 次插入997 次删除
  1. +1
    -1
      frappe/api.py
  2. +7
    -0
      frappe/config/desktop.py
  3. +57
    -0
      frappe/config/integrations.py
  4. +12
    -33
      frappe/config/setup.py
  5. +0
    -0
      frappe/core/doctype/payment_gateway/__init__.py
  6. +8
    -0
      frappe/core/doctype/payment_gateway/payment_gateway.js
  7. +91
    -0
      frappe/core/doctype/payment_gateway/payment_gateway.json
  8. +3
    -3
      frappe/core/doctype/payment_gateway/payment_gateway.py
  9. +12
    -0
      frappe/core/doctype/payment_gateway/test_payment_gateway.py
  10. +6
    -3
      frappe/hooks.py
  11. +0
    -78
      frappe/integration_broker/doctype/integration_service/integration_service.js
  12. +0
    -230
      frappe/integration_broker/doctype/integration_service/integration_service.json
  13. +0
    -113
      frappe/integration_broker/doctype/integration_service/integration_service.py
  14. +0
    -26
      frappe/integration_broker/doctype/integration_service/test_integration_service.py
  15. +0
    -113
      frappe/integration_broker/doctype/integration_service_parameter/integration_service_parameter.json
  16. +0
    -0
      frappe/integration_broker/doctype/oauth_authorization_code/__init__.py
  17. +0
    -0
      frappe/integration_broker/doctype/oauth_bearer_token/__init__.py
  18. +0
    -0
      frappe/integration_broker/doctype/oauth_client/__init__.py
  19. +0
    -12
      frappe/integration_broker/integration_controller.py
  20. +0
    -25
      frappe/integrations/doctype/dropbox_settings/dropbox_settings.js
  21. +41
    -3
      frappe/integrations/doctype/dropbox_settings/dropbox_settings.json
  22. +3
    -60
      frappe/integrations/doctype/dropbox_settings/dropbox_settings.py
  23. +0
    -0
      frappe/integrations/doctype/integration_request/__init__.py
  24. +0
    -0
      frappe/integrations/doctype/integration_request/integration_request.js
  25. +2
    -2
      frappe/integrations/doctype/integration_request/integration_request.json
  26. +0
    -0
      frappe/integrations/doctype/integration_request/integration_request.py
  27. +0
    -0
      frappe/integrations/doctype/integration_request/test_integration_request.py
  28. +0
    -23
      frappe/integrations/doctype/ldap_settings/ldap_settings.js
  29. +51
    -2
      frappe/integrations/doctype/ldap_settings/ldap_settings.json
  30. +2
    -48
      frappe/integrations/doctype/ldap_settings/ldap_settings.py
  31. +0
    -0
      frappe/integrations/doctype/oauth_authorization_code/__init__.py
  32. +0
    -0
      frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.js
  33. +2
    -2
      frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.json
  34. +0
    -0
      frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py
  35. +0
    -0
      frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py
  36. +0
    -0
      frappe/integrations/doctype/oauth_bearer_token/__init__.py
  37. +0
    -0
      frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.js
  38. +2
    -2
      frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.json
  39. +0
    -0
      frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py
  40. +0
    -0
      frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py
  41. +0
    -0
      frappe/integrations/doctype/oauth_client/__init__.py
  42. +0
    -0
      frappe/integrations/doctype/oauth_client/oauth_client.js
  43. +2
    -2
      frappe/integrations/doctype/oauth_client/oauth_client.json
  44. +0
    -0
      frappe/integrations/doctype/oauth_client/oauth_client.py
  45. +0
    -0
      frappe/integrations/doctype/oauth_client/test_oauth_client.py
  46. +0
    -23
      frappe/integrations/doctype/paypal_settings/paypal_settings.js
  47. +15
    -66
      frappe/integrations/doctype/paypal_settings/paypal_settings.py
  48. +1
    -26
      frappe/integrations/doctype/razorpay_settings/razorpay_settings.js
  49. +15
    -75
      frappe/integrations/doctype/razorpay_settings/razorpay_settings.py
  50. +2
    -2
      frappe/integrations/oauth2.py
  51. +94
    -0
      frappe/integrations/utils.py
  52. +1
    -2
      frappe/modules.txt
  53. +1
    -0
      frappe/patches.txt
  54. +14
    -6
      frappe/patches/v7_1/setup_integration_services.py
  55. +5
    -2
      frappe/patches/v7_2/setup_ldap_config.py
  56. +50
    -0
      frappe/patches/v8_0/deprecate_integration_broker.py
  57. +3
    -3
      frappe/utils/oauth.py
  58. +0
    -7
      frappe/utils/scheduler.py
  59. +2
    -2
      frappe/website/doctype/web_form/web_form.json
  60. +2
    -2
      frappe/website/doctype/web_form/web_form.py

+ 1
- 1
frappe/api.py 查看文件

@@ -133,7 +133,7 @@ def validate_oauth():
form_dict = frappe.local.form_dict
authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
if authorization_header and authorization_header[0].lower() == "bearer":
from frappe.integration_broker.oauth2 import get_oauth_server
from frappe.integrations.oauth2 import get_oauth_server
token = authorization_header[1]
r = frappe.request
parsed_url = urlparse(r.url)


+ 7
- 0
frappe/config/desktop.py 查看文件

@@ -36,6 +36,13 @@ def get_data():
"type": "module",
"hidden": 1
},
{
"module_name": "Integrations",
"color": "#16a085",
"icon": "octicon octicon-globe",
"type": "module",
"hidden": 1
},
{
"module_name": "Setup",
"color": "#bdc3c7",


+ 57
- 0
frappe/config/integrations.py 查看文件

@@ -0,0 +1,57 @@
from __future__ import unicode_literals
from frappe import _

def get_data():
return [
{
"label": _("Payments"),
"icon": "fa fa-star",
"items": [
{
"type": "doctype",
"name": "PayPal Settings",
"description": _("PayPal payment gateway settings"),
},
{
"type": "doctype",
"name": "Razorpay Settings",
"description": _("Razorpay Payment gateway settings"),
},
]
},
{
"label": _("Backup"),
"items": [
{
"type": "doctype",
"name": "Dropbox Settings",
"description": _("Dropbox backup settings"),
},
]
},
{
"label": _("Authentication"),
"items": [
{
"type": "doctype",
"name": "Social Login Keys",
"description": _("Enter keys to enable login via Facebook, Google, GitHub."),
},
{
"type": "doctype",
"name": "LDAP Settings",
"description": _("Ldap settings"),
},
{
"type": "doctype",
"name": "OAuth Client",
"description": _("Register OAuth Client App"),
},
{
"type": "doctype",
"name": "OAuth Provider Settings",
"description": _("Settings for OAuth Provider"),
},
]
}
]

+ 12
- 33
frappe/config/setup.py 查看文件

@@ -204,39 +204,6 @@ def get_data():
},
]
},
{
"label": _("Integrations"),
"icon": "fa fa-star",
"items": [
{
"type": "page",
"name": "applications",
"label": _("Application Installer"),
"description": _("Install Applications."),
"icon": "fa fa-download"
},
{
"type": "doctype",
"name": "Social Login Keys",
"description": _("Enter keys to enable login via Facebook, Google, GitHub."),
},
{
"type": "doctype",
"name": "Integration Service",
"description": _("Centralize access to Integrations"),
},
{
"type": "doctype",
"name": "OAuth Client",
"description": _("Register OAuth Client App"),
},
{
"type": "doctype",
"name": "OAuth Provider Settings",
"description": _("Settings for OAuth Provider"),
},
]
},
{
"label": _("Customize"),
"icon": "fa fa-glass",
@@ -277,6 +244,18 @@ def get_data():

]
},
{
"label": _("Applications"),
"items":[
{
"type": "page",
"name": "applications",
"label": _("Application Installer"),
"description": _("Install Applications."),
"icon": "fa fa-download"
},
]
}
]
add_setup_section(data, "frappe", "website", _("Website"), "fa fa-globe")
return data

frappe/integration_broker/__init__.py → frappe/core/doctype/payment_gateway/__init__.py 查看文件


+ 8
- 0
frappe/core/doctype/payment_gateway/payment_gateway.js 查看文件

@@ -0,0 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

frappe.ui.form.on('Payment Gateway', {
refresh: function(frm) {

}
});

+ 91
- 0
frappe/core/doctype/payment_gateway/payment_gateway.json 查看文件

@@ -0,0 +1,91 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:gateway",
"beta": 0,
"creation": "2015-12-15 22:26:45.221162",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "gateway",
"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": "Gateway",
"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
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-03-09 12:40:56.176464",
"modified_by": "Administrator",
"module": "Core",
"name": "Payment Gateway",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"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
}

frappe/integration_broker/doctype/integration_service_parameter/integration_service_parameter.py → frappe/core/doctype/payment_gateway/payment_gateway.py 查看文件

@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies and contributors
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe.model.document import Document

class IntegrationServiceParameter(Document):
pass
class PaymentGateway(Document):
pass

+ 12
- 0
frappe/core/doctype/payment_gateway/test_payment_gateway.py 查看文件

@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals

import frappe
import unittest

# test_records = frappe.get_test_records('Payment Gateway')

class TestPaymentGateway(unittest.TestCase):
pass

+ 6
- 3
frappe/hooks.py 查看文件

@@ -125,6 +125,7 @@ scheduler_events = {
"frappe.email.doctype.email_account.email_account.pull",
"frappe.email.doctype.email_account.email_account.notify_unreplied",
"frappe.oauth.delete_oauth2_data",
"frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment"
],
"hourly": [
"frappe.model.utils.link_count.update_link_count",
@@ -145,7 +146,11 @@ scheduler_events = {
"frappe.email.doctype.auto_email_report.auto_email_report.send_daily",
"frappe.desk.page.backups.backups.delete_downloadable_backups",
"frappe.core.doctype.feedback_request.feedback_request.delete_feedback_request",
"frappe.core.doctype.authentication_log.authentication_log.clear_authentication_logs"
"frappe.core.doctype.authentication_log.authentication_log.clear_authentication_logs",
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily"
],
"weekly": [
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_weekly"
],
"monthly": [
"frappe.email.doctype.auto_email_report.auto_email_report.send_monthly"
@@ -179,5 +184,3 @@ bot_parsers = [

setup_wizard_exception = "frappe.desk.page.setup_wizard.setup_wizard.email_setup_wizard_exception"
before_write_file = "frappe.limits.validate_space_limit"

integration_services = ["PayPal", "Razorpay", "Dropbox", "LDAP"]

+ 0
- 78
frappe/integration_broker/doctype/integration_service/integration_service.js 查看文件

@@ -1,78 +0,0 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.provide("frappe.integration_service");

{% include 'frappe/integrations/doctype/razorpay_settings/razorpay_settings.js' %}
{% include 'frappe/integrations/doctype/paypal_settings/paypal_settings.js' %}
{% include 'frappe/integrations/doctype/dropbox_settings/dropbox_settings.js' %}
{% include 'frappe/integrations/doctype/ldap_settings/ldap_settings.js' %}

frappe.ui.form.on('Integration Service', {
onload: function(frm) {
frappe.call({
method: "frappe.integration_broker.doctype.integration_service.integration_service.get_integration_services",
callback: function(r){
set_field_options("service", r.message)
}
})
},

refresh: function(frm){
if (frm.doc.service){
frm.events.setup_custom_buttons(frm);
frm.events.setup_service_details(frm);
}
},
service: function(frm){
frm.events.setup_custom_buttons(frm);
frm.events.setup_service_details(frm);
},
setup_custom_buttons: function(frm) {
frm.clear_custom_buttons();

frm.add_custom_button(__("{0} Settings", [frm.doc.service]), function(){
frappe.set_route("List", frm.doc.service + " Settings");
});

frm.add_custom_button(__("Show Log"), function(){
frappe.route_options = {"integration_request_service": frm.doc.service};
frappe.set_route("List", "Integration Request");
});
},
setup_service_details: function(frm) {
var service_name = frm.doc.service.toLowerCase().replace(/ /g, "_");
var service_handelr = service_name + "_settings";
service_handelr = new frappe.integration_service[service_handelr]();
service_handelr.get_service_info(frm);
var scheduler_job_info = service_handelr.get_scheduler_job_info();
frm.events.render_scheduler_jobs(frm, scheduler_job_info);
},
render_scheduler_jobs: function(frm, scheduler_job_info) {
var schduler_job_view = frm.fields_dict.scheduler_events_html.wrapper;

$(schduler_job_view).empty();
$(schduler_job_view).append('\
<table class="table table-bordered">\
<thead>\
<tr>\
<th class="text-muted"> Event </th>\
<th class="text-muted"> Action </th>\
</tr>\
</thead> \
<tbody></tbody> \
</table>')

$.each(scheduler_job_info, function(evnt, help){
$row = $("<tr>").appendTo($(schduler_job_view).find("tbody"));
$("<td>").appendTo($row).html(evnt).css("font-size", "12px");
$("<td>").appendTo($row).html(help).css("font-size", "12px");
})
}
});

+ 0
- 230
frappe/integration_broker/doctype/integration_service/integration_service.json 查看文件

@@ -1,230 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:service",
"beta": 0,
"creation": "2016-08-01 12:59:46.408707",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "System",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "service",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Service",
"length": 0,
"no_copy": 0,
"options": "",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "enabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Enabled",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_3",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "integration_service_help",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"options": "",
"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_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fieldname": "background_events",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Background Events",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "scheduler_events_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 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
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:30.774208",
"modified_by": "Administrator",
"module": "Integration Broker",
"name": "Integration Service",
"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,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

+ 0
- 113
frappe/integration_broker/doctype/integration_service/integration_service.py 查看文件

@@ -1,113 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
import json, urlparse
from frappe.utils import get_request_session

class IntegrationService(Document):
def on_update(self):
if self.enabled:
if not self.flags.ignore_mandatory:
self.enable_service()
self.install_fixtures()

frappe.cache().delete_value('scheduler_events')

def install_fixtures(self):
pass

def enable_service(self):
service_doc = "{0} Settings".format(self.service)
frappe.get_doc(service_doc).enable()

#rest request handler
def get_request(self, url, auth=None, data=None):
if not auth:
auth = ''
if not data:
data = {}

try:
s = get_request_session()
frappe.flags.integration_request = s.get(url, data={}, auth=auth)
frappe.flags.integration_request.raise_for_status()
return frappe.flags.integration_request.json()

except Exception, exc:
frappe.log_error(frappe.get_traceback())
raise exc

def post_request(self, url, auth=None, data=None):
if not auth:
auth = ''
if not data:
data = {}
try:
s = get_request_session()
res = s.post(url, data=data, auth=auth)
res.raise_for_status()

if res.headers.get("content-type") == "text/plain; charset=utf-8":
return urlparse.parse_qs(res.text)

return res.json()
except Exception, exc:
frappe.log_error()
raise exc

def put_request(url, auth=None, data=None):
pass

def create_request(self, data, integration_type, service_name, name=None):
if isinstance(data, basestring):
data = json.loads(data)

integration_request = frappe.get_doc({
"doctype": "Integration Request",
"integration_type": integration_type,
"integration_request_service": service_name,
"reference_doctype": data.get("reference_doctype"),
"reference_docname": data.get("reference_docname"),
"data": json.dumps(data)
})

if name:
integration_request.flags._name = name

integration_request.insert(ignore_permissions=True)
frappe.db.commit()

return integration_request

def get_integration_controller(service_name):
'''Returns integration controller module from app_name.integrations.{service}'''
try:
return frappe.get_doc("{0} Settings".format(service_name))
except Exception:
frappe.throw(_("Module {service} not found".format(service=service_name)))

@frappe.whitelist()
def get_integration_services():
services = [""]
for app in frappe.get_installed_apps():
services.extend(frappe.get_hooks("integration_services", app_name = app))

return services

def get_integration_service_events():
'''Get scheduler events for enabled integrations'''
events = {}
for service in frappe.get_all("Integration Service", filters={"enabled": 1},
fields=["name"]):
controller = get_integration_controller(service.name)

if hasattr(controller, "scheduler_events"):
for key, handlers in controller.scheduler_events.items():
events.setdefault(key, []).extend(handlers)

return events

+ 0
- 26
frappe/integration_broker/doctype/integration_service/test_integration_service.py 查看文件

@@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals

import frappe
import unittest
from frappe.utils.scheduler import get_scheduler_events

# test_records = frappe.get_test_records('Integration Service')

class TestIntegrationService(unittest.TestCase):
def test_scheudler_events(self):
if not frappe.db.exists("Integration Service", "Dropbox"):
frappe.get_doc({
"doctype": "Integration Service",
"service": "Dropbox"
}).insert(ignore_permissions=True)

frappe.db.set_value("Integration Service", "Dropbox", "enabled", 1)
frappe.cache().delete_key('scheduler_events')
events = get_scheduler_events('daily_long')

self.assertTrue('frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily' in events)

frappe.db.set_value("Integration Service", "Dropbox", "enabled", 0)

+ 0
- 113
frappe/integration_broker/doctype/integration_service_parameter/integration_service_parameter.json 查看文件

@@ -1,113 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-08-01 12:51:31.838970",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "System",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "label",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Parameter",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "value",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Value",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "fieldname",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Fieldname",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-08-03 05:36:47.261367",
"modified_by": "Administrator",
"module": "Integration Broker",
"name": "Integration Service Parameter",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

+ 0
- 0
frappe/integration_broker/doctype/oauth_authorization_code/__init__.py 查看文件


+ 0
- 0
frappe/integration_broker/doctype/oauth_bearer_token/__init__.py 查看文件


+ 0
- 0
frappe/integration_broker/doctype/oauth_client/__init__.py 查看文件


+ 0
- 12
frappe/integration_broker/integration_controller.py 查看文件

@@ -1,12 +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

from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService

class IntegrationController(IntegrationService):
def __init__(self, setup=True):
'''Load the current controller data if setup is true'''
if setup:
super(IntegrationController, self).__init__('Integration Service', self.service_name)

+ 0
- 25
frappe/integrations/doctype/dropbox_settings/dropbox_settings.js 查看文件

@@ -1,8 +1,6 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.provide("frappe.integration_service")

frappe.ui.form.on('Dropbox Settings', {
refresh: function(frm) {
frm.clear_custom_buttons();
@@ -39,26 +37,3 @@ frappe.ui.form.on('Dropbox Settings', {
}
});

frappe.integration_service.dropbox_settings = Class.extend({
init: function(frm) {

},

get_scheduler_job_info: function() {
return {
"Daily": "Take backup of database and files to dropbox on daily basis",
"Weekly": "Take backup of database and files to dropbox on weekly basis"
}
},

get_service_info: function(frm) {
frappe.call({
method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.get_service_details",
callback: function(r){
var integration_service_help = frm.fields_dict.integration_service_help.wrapper;
$(integration_service_help).empty();
$(integration_service_help).append(r.message);
}
})
}
})

+ 41
- 3
frappe/integrations/doctype/dropbox_settings/dropbox_settings.json 查看文件

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -10,6 +11,35 @@
"document_type": "System",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enabled",
"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": "Enabled",
"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_on_submit": 0,
"bold": 0,
@@ -21,6 +51,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Send Notifications To",
@@ -49,6 +80,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Backup Frequency",
@@ -79,6 +111,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "App Access Key",
@@ -108,6 +141,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "App Secret Key",
@@ -136,6 +170,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Dropbox Access",
@@ -164,6 +199,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Dropbox Access Key",
@@ -192,6 +228,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Dropbox Access Secret",
@@ -220,6 +257,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Dropbox Setup via Site Config",
@@ -238,17 +276,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:39:48.832630",
"modified": "2017-03-08 17:25:45.564492",
"modified_by": "Administrator",
"module": "Integrations",
"name": "Dropbox Settings",
@@ -265,7 +303,6 @@
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -280,6 +317,7 @@
"quick_entry": 0,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,


+ 3
- 60
frappe/integrations/doctype/dropbox_settings/dropbox_settings.py 查看文件

@@ -10,20 +10,11 @@ from frappe.utils.backups import new_backup
from frappe.utils.background_jobs import enqueue
from frappe.utils import (cint, split_emails, get_request_site_address, cstr,
get_files_path, get_backups_path, encode)
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService
from frappe.model.document import Document

ignore_list = [".DS_Store"]

class DropboxSettings(IntegrationService):
scheduler_events = {
"daily_long": [
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily"
],
"weekly_long": [
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_weekly"
]
}

class DropboxSettings(Document):
def onload(self):
if not self.app_access_key and frappe.conf.dropbox_access_key:
self.dropbox_setup_via_site_config = 1
@@ -32,14 +23,6 @@ class DropboxSettings(IntegrationService):
if not self.flags.ignore_mandatory:
self.validate_dropbox_credentails()

def on_update(self):
pass

def enable(self):
""" enable service """
if not self.flags.ignore_mandatory:
self.validate_dropbox_credentails()

def validate_dropbox_credentails(self):
try:
self.get_dropbox_session()
@@ -63,46 +46,6 @@ class DropboxSettings(IntegrationService):

return sess

@frappe.whitelist()
def get_service_details():
return """
<div>
Steps to enable dropbox backup service:
<ol>
<li> Create a dropbox app then get App Key and App Secret,
<a href="https://www.dropbox.com/developers/apps" target="_blank">
https://www.dropbox.com/developers/apps
</a>
</li>
<br>
<li> Setup credentials on Dropbox Settings doctype.
Click on
<button class="btn btn-default btn-xs disabled"> Dropbox Settings </button>
top right corner
</li>
<br>
<li> After settings up App key and App Secret, generate access token
<button class="btn btn-default btn-xs disabled"> Allow Dropbox Access </button>
</li>
<br>
<li>
After saving settings,
<label>
<span class="input-area">
<input type="checkbox" class="input-with-feedback" checked disabled>
</span>
<span class="label-area small">Enable</span>
</label>
Dropbox Integration Service and Save a document.
</li>
</ol>
<p>
After enabling service, system will take backup of files and database on daily or weekly basis
as per set on Dropbox Settings page and upload it to your dropbox.
</p>
</div>
"""

#get auth token
@frappe.whitelist()
def get_dropbox_authorize_url():
@@ -179,7 +122,7 @@ def take_backups_if(freq):
def take_backup_to_dropbox():
did_not_upload, error_log = [], []
try:
if cint(frappe.db.get_value("Integration Service", "Dropbox", "enabled")):
if cint(frappe.db.get_value("Dropbox Settings", None, "enabled")):
did_not_upload, error_log = backup_to_dropbox()
if did_not_upload: raise Exception



frappe/integration_broker/doctype/__init__.py → frappe/integrations/doctype/integration_request/__init__.py 查看文件


frappe/integration_broker/doctype/integration_request/integration_request.js → frappe/integrations/doctype/integration_request/integration_request.js 查看文件


frappe/integration_broker/doctype/integration_request/integration_request.json → frappe/integrations/doctype/integration_request/integration_request.json 查看文件

@@ -252,9 +252,9 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:00.783063",
"modified": "2017-03-08 14:40:00.783063",
"modified_by": "Administrator",
"module": "Integration Broker",
"module": "Integrations",
"name": "Integration Request",
"name_case": "",
"owner": "Administrator",

frappe/integration_broker/doctype/integration_request/integration_request.py → frappe/integrations/doctype/integration_request/integration_request.py 查看文件


frappe/integration_broker/doctype/integration_request/test_integration_request.py → frappe/integrations/doctype/integration_request/test_integration_request.py 查看文件


+ 0
- 23
frappe/integrations/doctype/ldap_settings/ldap_settings.js 查看文件

@@ -1,31 +1,8 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.provide("frappe.integration_service")

frappe.ui.form.on('LDAP Settings', {
refresh: function(frm) {

}
});

frappe.integration_service.ldap_settings = Class.extend({
init: function(frm) {
},
get_scheduler_job_info: function() {
return {}
},
get_service_info: function(frm) {
frappe.call({
method: "frappe.integrations.doctype.ldap_settings.ldap_settings.get_service_details",
callback: function(r){
var integration_service_help = frm.fields_dict.integration_service_help.wrapper;
$(integration_service_help).empty();
$(integration_service_help).append(r.message);
}
})
}
})

+ 51
- 2
frappe/integrations/doctype/ldap_settings/ldap_settings.json 查看文件

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -10,6 +11,35 @@
"document_type": "System",
"editable_grid": 1,
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enabled",
"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": "Enabled",
"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_on_submit": 0,
"bold": 0,
@@ -20,6 +50,8 @@
"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": "LDAP Server Url",
@@ -47,6 +79,8 @@
"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": "Organizational Unit",
@@ -74,6 +108,8 @@
"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": "Base Distinguished Name (DN)",
@@ -101,6 +137,8 @@
"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": "Password for Base DN",
@@ -128,6 +166,8 @@
"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,
@@ -154,6 +194,8 @@
"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": "LDAP Search String",
@@ -181,6 +223,8 @@
"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": "LDAP First Name Field",
@@ -208,6 +252,8 @@
"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": "LDAP Email Field",
@@ -235,6 +281,8 @@
"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": "LDAP Username Field",
@@ -253,17 +301,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-02-06 15:37:20.481090",
"modified": "2017-03-08 17:16:01.087365",
"modified_by": "Administrator",
"module": "Integrations",
"name": "LDAP Settings",
@@ -294,6 +342,7 @@
"quick_entry": 0,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,


+ 2
- 48
frappe/integrations/doctype/ldap_settings/ldap_settings.py 查看文件

@@ -6,19 +6,12 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cstr, cint
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService
from frappe.model.document import Document

class LDAPSettings(IntegrationService):
def on_update(self):
pass
class LDAPSettings(Document):
def validate(self):
if not self.flags.ignore_mandatory:
self.validate_ldap_credentails()
def enable(self):
if not self.flags.ignore_mandatory:
self.validate_ldap_credentails()

def validate_ldap_credentails(self):
try:
@@ -40,50 +33,11 @@ class LDAPSettings(IntegrationService):
conn.unbind_s()
frappe.throw("Incorrect UserId or Password")

@frappe.whitelist()
def get_service_details():
return """
<div>
<p> Steps to configure Service
<ol>
<li> Setup credentials on LDAP settings doctype
Click on
<button class="btn btn-default btn-xs disabled"> LDAP Settings </button>
top right corner
<br>
To setup LDAP you need,
<ul>
<li> Server URL & Port : ldap://ldap.forumsys.com:389</li>
<li> Base Distinguished Name : cn=read-only-admin,dc=example,dc=com</li>
<li> Organisational Unit : ou=mathematicians,dc=example,dc=com</li>
<li> Password : Base DN password</li>
<li> LDAP Search Criteria : uid=*{0}</li>
<li> LDAP First Name Fields : cn</li>
<li> LDAP Username Field : ui</li>
<li> LDAP Email Field : mail</li>
</ul>
</li>
<br>
<li>
After saving settings,
<label>
<span class="input-area">
<input type="checkbox" class="input-with-feedback" checked disabled>
</span>
<span class="label-area small">Enable</span>
</label>
LDAP Integration Service and Save a document.
</li>
</ol>
</div>
"""

def get_ldap_settings():
try:
settings = frappe.get_doc("LDAP Settings")

settings.update({
"enabled": cint(frappe.db.get_value("Integration Service", "LDAP", "enabled")),
"method": "frappe.integrations.doctype.ldap_settings.ldap_settings.login"
})
return settings


frappe/integration_broker/doctype/integration_request/__init__.py → frappe/integrations/doctype/oauth_authorization_code/__init__.py 查看文件


frappe/integration_broker/doctype/oauth_authorization_code/oauth_authorization_code.js → frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.js 查看文件


frappe/integration_broker/doctype/oauth_authorization_code/oauth_authorization_code.json → frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.json 查看文件

@@ -217,9 +217,9 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:04.113884",
"modified": "2017-03-08 14:40:04.113884",
"modified_by": "Administrator",
"module": "Integration Broker",
"module": "Integrations",
"name": "OAuth Authorization Code",
"name_case": "",
"owner": "Administrator",

frappe/integration_broker/doctype/oauth_authorization_code/oauth_authorization_code.py → frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py 查看文件


frappe/integration_broker/doctype/oauth_authorization_code/test_oauth_authorization_code.py → frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py 查看文件


frappe/integration_broker/doctype/integration_service/__init__.py → frappe/integrations/doctype/oauth_bearer_token/__init__.py 查看文件


frappe/integration_broker/doctype/oauth_bearer_token/oauth_bearer_token.js → frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.js 查看文件


frappe/integration_broker/doctype/oauth_bearer_token/oauth_bearer_token.json → frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.json 查看文件

@@ -244,9 +244,9 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:04.209039",
"modified": "2017-03-08 14:40:04.209039",
"modified_by": "Administrator",
"module": "Integration Broker",
"module": "Integrations",
"name": "OAuth Bearer Token",
"name_case": "",
"owner": "Administrator",

frappe/integration_broker/doctype/oauth_bearer_token/oauth_bearer_token.py → frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py 查看文件


frappe/integration_broker/doctype/oauth_bearer_token/test_oauth_bearer_token.py → frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py 查看文件


frappe/integration_broker/doctype/integration_service_parameter/__init__.py → frappe/integrations/doctype/oauth_client/__init__.py 查看文件


frappe/integration_broker/doctype/oauth_client/oauth_client.js → frappe/integrations/doctype/oauth_client/oauth_client.js 查看文件


frappe/integration_broker/doctype/oauth_client/oauth_client.json → frappe/integrations/doctype/oauth_client/oauth_client.json 查看文件

@@ -446,9 +446,9 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:03.031779",
"modified": "2017-03-08 14:40:03.031779",
"modified_by": "Administrator",
"module": "Integration Broker",
"module": "Integrations",
"name": "OAuth Client",
"name_case": "",
"owner": "Administrator",

frappe/integration_broker/doctype/oauth_client/oauth_client.py → frappe/integrations/doctype/oauth_client/oauth_client.py 查看文件


frappe/integration_broker/doctype/oauth_client/test_oauth_client.py → frappe/integrations/doctype/oauth_client/test_oauth_client.py 查看文件


+ 0
- 23
frappe/integrations/doctype/paypal_settings/paypal_settings.js 查看文件

@@ -1,31 +1,8 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.provide("frappe.integration_service")

frappe.ui.form.on('PayPal Settings', {
refresh: function(frm) {

}
});

frappe.integration_service.paypal_settings = Class.extend({
init: function(frm) {
},
get_scheduler_job_info: function() {
return {}
},
get_service_info: function(frm) {
frappe.call({
method: "frappe.integrations.doctype.paypal_settings.paypal_settings.get_service_details",
callback: function(r){
var integration_service_help = frm.fields_dict.integration_service_help.wrapper;
$(integration_service_help).empty();
$(integration_service_help).append(r.message);
}
})
}
})

+ 15
- 66
frappe/integrations/doctype/paypal_settings/paypal_settings.py 查看文件

@@ -9,9 +9,9 @@

Example:

from frappe.integration_broker.doctype.integration_service.integration_service import get_integration_controller
from frappe.integrations.utils import get_payment_gateway_controller

controller = get_integration_controller("PayPal")
controller = get_payment_gateway_controller("PayPal")
controller().validate_transaction_currency(currency)

### 2. Redirect for payment
@@ -27,7 +27,8 @@ Example:
"payer_email": "NuranVerkleij@example.com",
"payer_name": "Nuran Verkleij",
"order_id": "111",
"currency": "USD"
"currency": "USD",
"payment_gateway": "Razorpay"
}

# redirect the user to this url
@@ -60,12 +61,11 @@ import json
from frappe import _
from frappe.utils import get_url, call_hook_method, cint
from urllib import urlencode
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService
from frappe.model.document import Document
import urllib
from frappe.integrations.utils import create_request_log, make_post_request, create_payment_gateway

class PayPalSettings(IntegrationService):
service_name = "PayPal"

class PayPalSettings(Document):
supported_currencies = ["AUD", "BRL", "CAD", "CZK", "DKK", "EUR", "HKD", "HUF", "ILS", "JPY", "MYR", "MXN",
"TWD", "NZD", "NOK", "PHP", "PLN", "GBP", "RUB", "SGD", "SEK", "CHF", "THB", "TRY", "USD"]

@@ -77,20 +77,17 @@ class PayPalSettings(IntegrationService):
setattr(self, "use_sandbox", cint(frappe._dict(data).use_sandbox) or 0)

def validate(self):
create_payment_gateway("PayPal")
call_hook_method('payment_gateway_enabled', gateway="PayPal")
if not self.flags.ignore_mandatory:
self.validate_paypal_credentails()

def on_update(self):
pass

def enable(self):
call_hook_method('payment_gateway_enabled', gateway=self.service_name)
if not self.flags.ignore_mandatory:
self.validate_paypal_credentails()

def validate_transaction_currency(self, currency):
if currency not in self.supported_currencies:
frappe.throw(_("Please select another payment method. {0} does not support transactions in currency '{1}'").format(self.service_name, currency))
frappe.throw(_("Please select another payment method. PayPal does not support transactions in currency '{0}'").format(currency))

def get_paypal_params_and_url(self):
params = {
@@ -117,7 +114,7 @@ class PayPalSettings(IntegrationService):
params = urlencode(params)

try:
res = self.post_request(url=url, data=params.encode("utf-8"))
res = make_post_request(url=url, data=params.encode("utf-8"))

if res["ACK"][0] == "Failure":
raise Exception
@@ -140,7 +137,7 @@ class PayPalSettings(IntegrationService):
"correlation_id": response.get("CORRELATIONID")[0]
})

self.integration_request = self.create_request(kwargs, "Remote", self.service_name, response.get("TOKEN")[0])
self.integration_request = create_request_log(kwargs, "Remote", "PayPal", response.get("TOKEN")[0])

return return_url.format(kwargs["token"])

@@ -157,49 +154,12 @@ class PayPalSettings(IntegrationService):

params = urlencode(params)

response = self.post_request(url, data=params.encode("utf-8"))
response = make_post_request(url, data=params.encode("utf-8"))
if response.get("ACK")[0] != "Success":
frappe.throw("Looks like something is wrong with this site's Paypal configuration.")

return response

@frappe.whitelist()
def get_service_details():
return """
<div>
<p> Steps to configure Service
<ol>
<li> Get PayPal api credentials from link:
<a href="https://developer.paypal.com/docs/classic/api/apiCredentials/" target="_blank">
https://developer.paypal.com/docs/classic/api/apiCredentials/
</a>
</li>
<br>
<li> Setup credentials on PayPal settings doctype.
Click on
<button class="btn btn-default btn-xs disabled"> PayPal Settings </button>
top right corner
</li>
<br>
<li>
After saving settings,
<label>
<span class="input-area">
<input type="checkbox" class="input-with-feedback" checked disabled>
</span>
<span class="label-area small">Enabled</span>
</label>
PayPal Integration Service and Save a document.
</li>
<br>
<li>
To view PayPal payment logs,
<button class="btn btn-default btn-xs disabled"> Show Log </button>
</li>
</ol>
</div>
"""

@frappe.whitelist(allow_guest=True, xss_safe=True)
def get_express_checkout_details(token):
try:
@@ -212,7 +172,7 @@ def get_express_checkout_details(token):
"TOKEN": token
})

response = doc.post_request(url, data=params)
response = make_post_request(url, data=params)

if response.get("ACK")[0] != "Success":
frappe.respond_as_web_page(_("Something went wrong"),
@@ -259,7 +219,7 @@ def confirm_payment(token):
"PAYMENTREQUEST_0_CURRENCYCODE": data.get("currency").upper()
})

response = doc.post_request(url, data=params)
response = make_post_request(url, data=params)

if response.get("ACK")[0] == "Success":
update_integration_request_status(token, {
@@ -291,14 +251,3 @@ def confirm_payment(token):

def update_integration_request_status(token, data, status, error=False):
frappe.get_doc("Integration Request", token).update_status(data, status)

@frappe.whitelist(allow_guest=True, xss_safe=True)
def get_checkout_url(**kwargs):
try:
doc = frappe.get_doc("PayPal Settings")
return doc.get_payment_url(**kwargs)
except Exception:
frappe.respond_as_web_page(_("Something went wrong"),
_("Looks like something is wrong with this site's Paypal configuration. Don't worry! No payment has been made from your Paypal account."),
indicator_color='red',
http_status_code=frappe.ValidationError.http_status_code)

+ 1
- 26
frappe/integrations/doctype/razorpay_settings/razorpay_settings.js 查看文件

@@ -1,33 +1,8 @@
// Copyright (c) 2016, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.provide("frappe.integration_service")

frappe.ui.form.on('Razorpay Settings', {
refresh: function(frm) {
}
});

frappe.integration_service.razorpay_settings = Class.extend({
init: function(frm) {
},
get_scheduler_job_info: function() {
return {
"Execute on every few minits of interval": " Captures all authorised payments"
}
},
get_service_info: function(frm) {
frappe.call({
method: "frappe.integrations.doctype.razorpay_settings.razorpay_settings.get_service_details",
callback: function(r){
var integration_service_help = frm.fields_dict.integration_service_help.wrapper;
$(integration_service_help).empty();
$(integration_service_help).append(r.message);
}
})
}
})
});

+ 15
- 75
frappe/integrations/doctype/razorpay_settings/razorpay_settings.py 查看文件

@@ -9,9 +9,9 @@

Example:

from frappe.integration_broker.doctype.integration_service.integration_service import get_integration_controller
from frappe.integrations.utils import get_payment_gateway_controller

controller = get_integration_controller("Razorpay")
controller = get_payment_gateway_controller("Razorpay")
controller().validate_transaction_currency(currency)

### 2. Redirect for payment
@@ -27,7 +27,8 @@ Example:
"payer_email": "NuranVerkleij@example.com",
"payer_name": "Nuran Verkleij",
"order_id": "111",
"currency": "INR"
"currency": "INR",
"payment_gateway": "Razorpay"
}

# Redirect the user to this url
@@ -53,45 +54,32 @@ For razorpay payment status is Authorized

from __future__ import unicode_literals
import frappe
from frappe.utils import get_url, call_hook_method, cint
from frappe import _
import urllib, json
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService
from frappe.model.document import Document
from frappe.utils import get_url, call_hook_method, cint
from frappe.integrations.utils import make_get_request, make_post_request, create_request_log, create_payment_gateway

class RazorpaySettings(IntegrationService):
service_name = "Razorpay"
class RazorpaySettings(Document):
supported_currencies = ["INR"]

scheduler_events = {
"all": [
"frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment"
]
}

def validate(self):
if not self.flags.ignore_mandatory:
self.validate_razorpay_credentails()

def on_update(self):
pass

def enable(self):
create_payment_gateway('Razorpay')
call_hook_method('payment_gateway_enabled', gateway='Razorpay')

if not self.flags.ignore_mandatory:
self.validate_razorpay_credentails()

def validate_razorpay_credentails(self):
if self.api_key and self.api_secret:
try:
self.get_request(url="https://api.razorpay.com/v1/payments",
make_get_request(url="https://api.razorpay.com/v1/payments",
auth=(self.api_key, self.get_password(fieldname="api_secret", raise_exception=False)))
except Exception:
frappe.throw(_("Seems API Key or API Secret is wrong !!!"))

def validate_transaction_currency(self, currency):
if currency not in self.supported_currencies:
frappe.throw(_("Please select another payment method. {0} does not support transactions in currency '{1}'").format(self.service_name, currency))
frappe.throw(_("Please select another payment method. Razorpay does not support transactions in currency '{0}'").format(currency))

def get_payment_url(self, **kwargs):
return get_url("./integrations/razorpay_checkout?{0}".format(urllib.urlencode(kwargs)))
@@ -100,8 +88,7 @@ class RazorpaySettings(IntegrationService):
self.data = frappe._dict(data)

try:
self.integration_request = super(RazorpaySettings, self).create_request(self.data, "Host", \
"Razorpay")
self.integration_request = create_request_log(self.data, "Host", "Razorpay")
return self.authorize_payment()

except Exception:
@@ -124,7 +111,7 @@ class RazorpaySettings(IntegrationService):
redirect_message = data.get('notes', {}).get('redirect_message') or None

try:
resp = self.get_request("https://api.razorpay.com/v1/payments/{0}"
resp = make_get_request("https://api.razorpay.com/v1/payments/{0}"
.format(self.data.razorpay_payment_id), auth=(settings.api_key,
settings.api_secret))

@@ -201,7 +188,7 @@ def capture_payment(is_sandbox=False, sanbox_response=None):
data = json.loads(doc.data)
settings = controller.get_settings(data)

resp = controller.post_request("https://api.razorpay.com/v1/payments/{0}/capture".format(data.get("razorpay_payment_id")),
resp = make_post_request("https://api.razorpay.com/v1/payments/{0}/capture".format(data.get("razorpay_payment_id")),
auth=(settings.api_key, settings.api_secret), data={"amount": data.get("amount")})

if resp.get("status") == "captured":
@@ -211,51 +198,4 @@ def capture_payment(is_sandbox=False, sanbox_response=None):
doc = frappe.get_doc("Integration Request", doc.name)
doc.status = "Failed"
doc.error = frappe.get_traceback()
frappe.log_error(doc.error, '{0} Failed'.format(doc.name))

@frappe.whitelist(allow_guest=True, xss_safe=True)
def get_checkout_url(**kwargs):
try:
return frappe.get_doc("Razorpay Settings").get_payment_url(**kwargs)
except Exception:
frappe.respond_as_web_page(_("Something went wrong"),
_("Looks like something is wrong with this site's Razorpay configuration. No payment has been made."),
indicator_color='red',
http_status_code=frappe.ValidationError.http_status_code)

@frappe.whitelist()
def get_service_details():
return """
<div>
<p> Steps to configure Service
<ol>
<li> Get Razorpay api credentials by login to:
<a href="https://razorpay.com/" target="_blank">
https://razorpay.com/
</a>
</li>
<br>
<li> Setup credentials on Razorpay Settings doctype.
Click on
<button class="btn btn-default btn-xs disabled"> Razorpay Settings </button>
top right corner
</li>
<br>
<li>
After saving settings,
<label>
<span class="input-area">
<input type="checkbox" class="input-with-feedback" checked disabled>
</span>
<span class="label-area small">Enable</span>
</label>
Razorpay Integration Service and Save a document.
</li>
<br>
<li>
To view Razorpays payment logs,
<button class="btn btn-default btn-xs disabled"> Show Log </button>
</li>
</ol>
</div>
"""
frappe.log_error(doc.error, '{0} Failed'.format(doc.name))

frappe/integration_broker/oauth2.py → frappe/integrations/oauth2.py 查看文件

@@ -53,13 +53,13 @@ def authorize(*args, **kwargs):
oauth_settings = get_oauth_settings()
params = get_urlparams_from_kwargs(kwargs)
request_url = urlparse(frappe.request.url)
success_url = request_url.scheme + "://" + request_url.netloc + "/api/method/frappe.integration_broker.oauth2.approve?" + params
success_url = request_url.scheme + "://" + request_url.netloc + "/api/method/frappe.integrations.oauth2.approve?" + params
failure_url = frappe.form_dict["redirect_uri"] + "?error=access_denied"

if frappe.session['user']=='Guest':
#Force login, redirect to preauth again.
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = "/login?redirect-to=/api/method/frappe.integration_broker.oauth2.authorize?" + quote(params.replace("+"," "))
frappe.local.response["location"] = "/login?redirect-to=/api/method/frappe.integrations.oauth2.authorize?" + quote(params.replace("+"," "))

elif frappe.session['user']!='Guest':
try:

+ 94
- 0
frappe/integrations/utils.py 查看文件

@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
import json, urlparse
from frappe.utils import get_request_session
from frappe import _

def make_get_request(url, auth=None, data=None):
if not auth:
auth = ''
if not data:
data = {}

try:
s = get_request_session()
frappe.flags.integration_request = s.get(url, data={}, auth=auth)
frappe.flags.integration_request.raise_for_status()
return frappe.flags.integration_request.json()

except Exception, exc:
frappe.log_error(frappe.get_traceback())
raise exc

def make_post_request(url, auth=None, data=None):
if not auth:
auth = ''
if not data:
data = {}
try:
s = get_request_session()
res = s.post(url, data=data, auth=auth)
res.raise_for_status()

if res.headers.get("content-type") == "text/plain; charset=utf-8":
return urlparse.parse_qs(res.text)

return res.json()
except Exception, exc:
frappe.log_error()
raise exc

def create_request_log(data, integration_type, service_name, name=None):
if isinstance(data, basestring):
data = json.loads(data)

integration_request = frappe.get_doc({
"doctype": "Integration Request",
"integration_type": integration_type,
"integration_request_service": service_name,
"reference_doctype": data.get("reference_doctype"),
"reference_docname": data.get("reference_docname"),
"data": json.dumps(data)
})

if name:
integration_request.flags._name = name

integration_request.insert(ignore_permissions=True)
frappe.db.commit()

return integration_request

def get_payment_gateway_controller(payment_gateway):
'''Return payment gateway controller'''
try:
return frappe.get_doc("{0} Settings".format(payment_gateway))
except Exception:
frappe.throw(_("{0} Settings not found".format(payment_gateway)))

@frappe.whitelist(allow_guest=True, xss_safe=True)
def get_checkout_url(**kwargs):
try:
if kwargs.get('payment_gateway'):
doc = frappe.get_doc("{0} Settings".format(kwargs.get('payment_gateway')))
return doc.get_payment_url(**kwargs)
else:
raise Exception
except Exception:
frappe.respond_as_web_page(_("Something went wrong"),
_("Looks like something is wrong with this site's payment gateway configuration. No payment has been made."),
indicator_color='red',
http_status_code=frappe.ValidationError.http_status_code)

def create_payment_gateway(gateway):
# NOTE: we don't translate Payment Gateway name because it is an internal doctype
if not frappe.db.exists("Payment Gateway", gateway):
payment_gateway = frappe.get_doc({
"doctype": "Payment Gateway",
"gateway": gateway
})
payment_gateway.insert(ignore_permissions=True)

+ 1
- 2
frappe/modules.txt 查看文件

@@ -6,5 +6,4 @@ Custom
Geo
Desk
Print
Integrations
Integration Broker
Integrations

+ 1
- 0
frappe/patches.txt 查看文件

@@ -170,3 +170,4 @@ execute:frappe.rename_doc('Country', 'Syrian Arab Republic', 'Syria', ignore_if_
frappe.patches.v8_0.rename_listsettings_to_usersettings
frappe.patches.v7_2.update_communications
frappe.patches.v8_0.update_published_in_global_search
frappe.patches.v8_0.deprecate_integration_broker

+ 14
- 6
frappe/patches/v7_1/setup_integration_services.py 查看文件

@@ -3,6 +3,7 @@ import frappe
from frappe.exceptions import DataError
from frappe.utils.password import get_decrypted_password
from frappe.utils import cstr
import os

app_list = [
{"app_name": "razorpay_integration", "service_name": "Razorpay", "doctype": "Razorpay Settings", "remove": True},
@@ -11,8 +12,6 @@ app_list = [
]

def execute():
frappe.reload_doc("integration_broker", "doctype", "integration_service")

installed_apps = frappe.get_installed_apps()

for app_details in app_list:
@@ -34,6 +33,14 @@ def setup_integration_service(app_details, settings=None):

setup_service_settings(app_details["service_name"], settings)

doc_path = frappe.get_app_path("frappe", "integration_broker", "doctype",
"integration_service", "integration_service.json")

if not os.path.exists(doc_path):
return

frappe.reload_doc("integration_broker", "doctype", "integration_service")

if frappe.db.exists("Integration Service", app_details["service_name"]):
integration_service = frappe.get_doc("Integration Service", app_details["service_name"])
else:
@@ -49,9 +56,9 @@ def get_app_settings(app_details):
doctype = docname = app_details["doctype"]

app_settings = get_parameters(app_details)
if app_settings:
if app_settings:
settings = app_settings["settings"]
frappe.reload_doc("integrations", "doctype", "{0}_settings".format(app_details["service_name"].lower()))
frappe.reload_doc("integrations", "doctype", "{0}_settings".format(app_details["service_name"].lower()))
controller = frappe.get_meta("{0} Settings".format(app_details["service_name"]))

for d in controller.fields:
@@ -86,7 +93,7 @@ def get_parameters(app_details):
elif app_details["service_name"] == "Dropbox":
doc = frappe.db.get_value(app_details["doctype"], None,
["dropbox_access_key", "dropbox_access_secret", "upload_backups_to_dropbox"], as_dict=1)
if not doc:
return

@@ -99,7 +106,8 @@ def get_parameters(app_details):
"app_secret_key": frappe.conf.dropbox_secret_key,
"dropbox_access_key": doc.dropbox_access_key,
"dropbox_access_secret": doc.dropbox_access_secret,
"backup_frequency": doc.upload_backups_to_dropbox
"backup_frequency": doc.upload_backups_to_dropbox,
"enabled": doc.send_backups_to_dropbox
}
}



+ 5
- 2
frappe/patches/v7_2/setup_ldap_config.py 查看文件

@@ -4,10 +4,13 @@ from frappe.utils import cint
def execute():
frappe.reload_doc("integrations", "doctype", "ldap_settings")

if not frappe.db.exists("Integration Server", "LDAP"):
if not frappe.db.exists("DocType", "Integration Service"):
return

if not cint(frappe.db.get_value("Integration Server", "LDAP", 'enabled')):
if not frappe.db.exists("Integration Service", "LDAP"):
return

if not cint(frappe.db.get_value("Integration Service", "LDAP", 'enabled')):
return

import ldap


+ 50
- 0
frappe/patches/v8_0/deprecate_integration_broker.py 查看文件

@@ -0,0 +1,50 @@
import frappe
from frappe.integrations.utils import create_payment_gateway

def execute():
setup_enabled_integrations()

for doctype in ["integration_request", "oauth_authorization_code", "oauth_bearer_token", "oauth_client"]:
frappe.reload_doc('integrations', 'doctype', doctype)
frappe.reload_doc("core", "doctype", "payment_gateway")
update_doctype_module()
create_payment_gateway_master_records()

for doctype in ["Integration Service", "Integration Service Parameter"]:
frappe.delete_doc("DocType", doctype)
if not frappe.db.get_value("DocType", {"module": "Integration Broker"}, "name"):
frappe.delete_doc("Module Def", "Integration Broker")

def setup_enabled_integrations():
if not frappe.db.exists("DocType", "Integration Service"):
return

for service in frappe.get_all("Integration Service",
filters={"enabled": 1, "service": ('in', ("Dropbox", "LDAP"))}, fields=["name"]):

doctype = "{0} Settings".format(service.name)
frappe.db.set_value(doctype, doctype, 'enabled', 1)

def update_doctype_module():
frappe.db.sql("""update tabDocType set module='Integrations'
where name in ('Integration Request', 'Oauth Authorization Code',
'Oauth Bearer Token', 'Oauth Client') """)

frappe.db.sql(""" update tabDocType set module='Core' where name = 'Payment Gateway'""")

def create_payment_gateway_master_records():
for payment_gateway in ["Razorpay", "PayPal"]:
doctype = "{0} Settings".format(payment_gateway)
doc = frappe.get_doc(doctype)
doc_meta = frappe.get_meta(doctype)
all_mandatory_fields_has_value = True

for d in doc_meta.fields:
if d.reqd and not doc.get(d.fieldname):
all_mandatory_fields_has_value = False
break

if all_mandatory_fields_has_value:
create_payment_gateway(payment_gateway)

+ 3
- 3
frappe/utils/oauth.py 查看文件

@@ -73,8 +73,8 @@ def get_oauth2_providers():
out['frappe'] = {
"flow_params": {
"name": "frappe",
"authorize_url": frappe_server_url + "/api/method/frappe.integration_broker.oauth2.authorize",
"access_token_url": frappe_server_url + "/api/method/frappe.integration_broker.oauth2.get_token",
"authorize_url": frappe_server_url + "/api/method/frappe.integrations.oauth2.authorize",
"access_token_url": frappe_server_url + "/api/method/frappe.integrations.oauth2.get_token",
"base_url": frappe_server_url
},

@@ -86,7 +86,7 @@ def get_oauth2_providers():
},

# relative to base_url
"api_endpoint": "/api/method/frappe.integration_broker.oauth2.openid_profile"
"api_endpoint": "/api/method/frappe.integrations.oauth2.openid_profile"
}

return out


+ 0
- 7
frappe/utils/scheduler.py 查看文件

@@ -23,7 +23,6 @@ from frappe.limits import has_expired
from frappe.utils.data import get_datetime, now_datetime
from frappe.core.doctype.user.user import STANDARD_USERS
from frappe.installer import update_site_config
from frappe.integration_broker.doctype.integration_service.integration_service import get_integration_service_events

DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'

@@ -158,21 +157,15 @@ def trigger(site, event, queued_jobs=(), now=False):
else:
scheduler_task(site=site, event=event, handler=handler, now=True)


def get_scheduler_events(event):
'''Get scheduler events from hooks and integrations'''
scheduler_events = frappe.cache().get_value('scheduler_events')
if not scheduler_events:
scheduler_events = frappe.get_hooks("scheduler_events")
integration_events = get_integration_service_events()
for key, handlers in integration_events.items():
scheduler_events.setdefault(key, []).extend(handlers)
frappe.cache().set_value('scheduler_events', scheduler_events)

return scheduler_events.get(event) or []



def log(method, message=None):
"""log error in patch_log"""
message = frappe.utils.cstr(message) + "\n" if message else ""


+ 2
- 2
frappe/website/doctype/web_form/web_form.json 查看文件

@@ -814,7 +814,7 @@
"label": "Payment Gateway",
"length": 0,
"no_copy": 0,
"options": "Integration Service",
"options": "Payment Gateway",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -1139,7 +1139,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-03-06 16:29:35.691485",
"modified": "2017-03-09 12:52:43.388176",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Form",


+ 2
- 2
frappe/website/doctype/web_form/web_form.py 查看文件

@@ -9,10 +9,10 @@ from frappe.utils import cstr
from frappe.utils.file_manager import save_file, remove_file_by_url
from frappe.website.utils import get_comment_list
from frappe.custom.doctype.customize_form.customize_form import docfield_properties
from frappe.integration_broker.doctype.integration_service.integration_service import get_integration_controller
from frappe.utils.file_manager import get_max_file_size
from frappe.modules.utils import export_module_json, get_doc_module
from urllib import urlencode
from frappe.integrations.utils import get_payment_gateway_controller

class WebForm(WebsiteGenerator):
website = frappe._dict(
@@ -221,7 +221,7 @@ def get_context(context):

def get_payment_gateway_url(self, doc):
if self.accept_payment:
controller = get_integration_controller(self.payment_gateway)
controller = get_payment_gateway_controller(self.payment_gateway)

title = "Payment for {0} {1}".format(doc.doctype, doc.name)
amount = self.amount


Loading…
取消
儲存