@@ -9,11 +9,13 @@ | |||
"doctype": "DocType", | |||
"document_type": "", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "integration_type", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
@@ -40,6 +42,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "integration_request_service", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
@@ -66,6 +69,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "Queued", | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
@@ -73,7 +77,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"in_list_view": 1, | |||
"label": "Status", | |||
"length": 0, | |||
"no_copy": 0, | |||
@@ -93,6 +97,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "data", | |||
"fieldtype": "Code", | |||
"hidden": 0, | |||
@@ -118,6 +123,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "output", | |||
"fieldtype": "Code", | |||
"hidden": 0, | |||
@@ -143,6 +149,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "error", | |||
"fieldtype": "Code", | |||
"hidden": 0, | |||
@@ -175,7 +182,7 @@ | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-08-11 10:40:32.231331", | |||
"modified": "2016-10-13 05:01:14.913553", | |||
"modified_by": "Administrator", | |||
"module": "Integration Broker", | |||
"name": "Integration Request", | |||
@@ -192,6 +199,7 @@ | |||
"export": 1, | |||
"if_owner": 0, | |||
"import": 0, | |||
"is_custom": 0, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
@@ -208,5 +216,6 @@ | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"title_field": "integration_request_service", | |||
"track_seen": 0 | |||
} |
@@ -6,7 +6,6 @@ from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.model.document import Document | |||
from frappe.utils.background_jobs import enqueue, get_jobs | |||
import json, urlparse | |||
from frappe.utils import get_request_session | |||
@@ -17,6 +16,8 @@ class IntegrationService(Document): | |||
self.enable_service() | |||
self.install_fixtures() | |||
frappe.cache().delete_value('scheduler_events') | |||
def install_fixtures(self): | |||
pass | |||
@@ -96,13 +97,15 @@ def get_integration_services(): | |||
return services | |||
def trigger_integration_service_events(): | |||
for service in frappe.get_all("Integration Service", filters={"enabled": 1}, fields=["name"]): | |||
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, "scheduled_jobs"): | |||
for job in controller.scheduled_jobs: | |||
for event, handlers in job.items(): | |||
for handler in handlers: | |||
if handler not in get_jobs(): | |||
enqueue(handler, queue='short', event=event) | |||
if hasattr(controller, "scheduler_events"): | |||
for key, handlers in controller.scheduler_events: | |||
events.setdefault(key, []).extend(handlers) | |||
return events |
@@ -5,8 +5,16 @@ 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): | |||
pass | |||
def test_scheudler_events(self): | |||
dropbox_settings = frappe.get_doc('Dropbox Settings') | |||
dropbox_settings.db_set('enabled', 1) | |||
events = get_scheduler_events('daily_long') | |||
self.assertTrue('frappe.integrations.dropbox_integration.take_backups_daily' in events) | |||
dropbox_settings.db_set('enabled', 0) |
@@ -15,17 +15,15 @@ from frappe.integration_broker.doctype.integration_service.integration_service i | |||
ignore_list = [".DS_Store"] | |||
class DropboxSettings(IntegrationService): | |||
scheduled_jobs = [ | |||
{ | |||
"daily_long": [ | |||
"frappe.integrations.dropbox_integration.take_backups_daily" | |||
], | |||
"weekly_long": [ | |||
"frappe.integrations.dropbox_integration.take_backups_weekly" | |||
] | |||
} | |||
] | |||
scheduler_events = { | |||
"daily_long": [ | |||
"frappe.integrations.dropbox_integration.take_backups_daily" | |||
], | |||
"weekly_long": [ | |||
"frappe.integrations.dropbox_integration.take_backups_weekly" | |||
] | |||
} | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_dropbox_credentails() | |||
@@ -49,10 +47,10 @@ class DropboxSettings(IntegrationService): | |||
from dropbox import session | |||
except: | |||
raise Exception(_("Please install dropbox python module")) | |||
if not (self.app_access_key or self.app_secret_key): | |||
raise Exception(_("Please set Dropbox access keys in your site config")) | |||
sess = session.DropboxSession(self.app_access_key, | |||
self.get_password(fieldname="app_secret_key", raise_exception=False), "app_folder") | |||
@@ -64,13 +62,13 @@ def get_service_details(): | |||
<div> | |||
Steps to enable dropbox backup service: | |||
<ol> | |||
<li> Create a dropbox app then get App Key and App Secret, | |||
<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. | |||
<li> Setup credentials on Dropbox Settings doctype. | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> Dropbox Settings </button> | |||
top right corner | |||
@@ -109,7 +107,7 @@ def get_dropbox_authorize_url(): | |||
"dropbox_access_key": request_token.key, | |||
"dropbox_access_secret": request_token.secret | |||
}) | |||
doc.save(ignore_permissions=False) | |||
return_address = get_request_site_address(True) \ | |||
@@ -61,28 +61,26 @@ For razorpay payment status is Authorized | |||
class RazorpaySettings(IntegrationService): | |||
service_name = "Razorpay" | |||
supported_currencies = ["INR"] | |||
scheduled_jobs = [ | |||
{ | |||
"all": [ | |||
"frappe.integrations.razorpay.capture_payment" | |||
] | |||
} | |||
] | |||
scheduler_events = { | |||
"all": [ | |||
"frappe.integrations.razorpay.capture_payment" | |||
] | |||
} | |||
def validate(self): | |||
if not self.flags.ignore_mandatory: | |||
self.validate_razorpay_credentails() | |||
def on_update(self): | |||
pass | |||
def enable(self): | |||
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: | |||
@@ -90,14 +88,14 @@ class RazorpaySettings(IntegrationService): | |||
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)) | |||
def get_payment_url(self, **kwargs): | |||
return get_url("./integrations/razorpay_checkout?{0}".format(urllib.urlencode(kwargs))) | |||
def create_request(self, data): | |||
self.data = frappe._dict(data) | |||
@@ -168,7 +166,7 @@ class RazorpaySettings(IntegrationService): | |||
"redirect_to": redirect_url, | |||
"status": status | |||
} | |||
def get_settings(self): | |||
return frappe._dict({ | |||
"api_key": self.api_key, | |||
@@ -212,7 +210,7 @@ def get_checkout_url(**kwargs): | |||
_("Looks like something is wrong with this site's Razorpay configuration. Don't worry! No payment has been made."), | |||
success=False, | |||
http_status_code=frappe.ValidationError.http_status_code) | |||
@frappe.whitelist() | |||
def get_service_details(): | |||
@@ -220,13 +218,13 @@ def get_service_details(): | |||
<div> | |||
<p> Steps to configure Service | |||
<ol> | |||
<li> Get Razorpay api credentials by login to: | |||
<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. | |||
<li> Setup credentials on Razorpay Settings doctype. | |||
Click on | |||
<button class="btn btn-default btn-xs disabled"> Razorpay Settings </button> | |||
top right corner | |||
@@ -22,6 +22,8 @@ def get_controller(doctype): | |||
:param doctype: DocType name as string.""" | |||
from frappe.model.document import Document | |||
global _classes | |||
if not doctype in _classes: | |||
module_name, custom = frappe.db.get_value("DocType", doctype, ["module", "custom"]) \ | |||
or ["Core", False] | |||
@@ -48,7 +48,8 @@ def clear_cache(user=None): | |||
def clear_global_cache(): | |||
frappe.model.meta.clear_cache() | |||
frappe.cache().delete_value(["app_hooks", "installed_apps", | |||
"app_modules", "module_app", "notification_config", 'system_settings']) | |||
"app_modules", "module_app", "notification_config", 'system_settings' | |||
'scheduler_events']) | |||
frappe.setup_module_map() | |||
def clear_sessions(user=None, keep_current=False, device=None): | |||
@@ -23,6 +23,7 @@ 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' | |||
@@ -142,7 +143,11 @@ def trigger(site, event, queued_jobs=(), now=False): | |||
if not queued_jobs and not now: | |||
queued_jobs = get_jobs(site=site, queue=queue) | |||
for handler in frappe.get_hooks("scheduler_events").get(event, []): | |||
events = get_scheduler_events(event) | |||
if not events: | |||
return | |||
for handler in events: | |||
if not now: | |||
if handler not in queued_jobs: | |||
enqueue(handler, queue, timeout, event) | |||
@@ -152,6 +157,20 @@ def trigger(site, event, queued_jobs=(), now=False): | |||
if frappe.flags.in_test: | |||
frappe.flags.ran_schedulers.append(event) | |||
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: | |||
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 "" | |||