commit
807e39efe1
3 changed files with 6 additions and 255 deletions
|
|
@ -1,249 +0,0 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.data_migration.doctype.data_migration_connector.connectors.base import BaseConnection
|
||||
import googleapiclient.discovery
|
||||
import google.oauth2.credentials
|
||||
from googleapiclient.errors import HttpError
|
||||
import time
|
||||
from datetime import datetime
|
||||
from frappe.utils import add_days, add_years
|
||||
from frappe.desk.doctype.event.event import has_permission
|
||||
|
||||
class CalendarConnector(BaseConnection):
|
||||
def __init__(self, connector):
|
||||
self.connector = connector
|
||||
settings = frappe.get_doc("GCalendar Settings", None)
|
||||
|
||||
self.account = frappe.get_doc("GCalendar Account", connector.username)
|
||||
|
||||
self.credentials_dict = {
|
||||
'token': self.account.get_password(fieldname='session_token', raise_exception=False),
|
||||
'refresh_token': self.account.get_password(fieldname='refresh_token', raise_exception=False),
|
||||
'token_uri': 'https://www.googleapis.com/oauth2/v4/token',
|
||||
'client_id': settings.client_id,
|
||||
'client_secret': settings.get_password(fieldname='client_secret', raise_exception=False),
|
||||
'scopes':'https://www.googleapis.com/auth/calendar'
|
||||
}
|
||||
|
||||
self.name_field = 'id'
|
||||
|
||||
self.credentials = google.oauth2.credentials.Credentials(**self.credentials_dict)
|
||||
self.gcalendar = googleapiclient.discovery.build('calendar', 'v3', credentials=self.credentials)
|
||||
|
||||
self.check_remote_calendar()
|
||||
|
||||
def check_remote_calendar(self):
|
||||
def _create_calendar():
|
||||
timezone = frappe.db.get_value("System Settings", None, "time_zone")
|
||||
calendar = {
|
||||
'summary': self.account.calendar_name,
|
||||
'timeZone': timezone
|
||||
}
|
||||
try:
|
||||
created_calendar = self.gcalendar.calendars().insert(body=calendar).execute()
|
||||
frappe.db.set_value("GCalendar Account", self.account.name, "gcalendar_id", created_calendar["id"])
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
try:
|
||||
if self.account.gcalendar_id is not None:
|
||||
try:
|
||||
self.gcalendar.calendars().get(calendarId=self.account.gcalendar_id).execute()
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
else:
|
||||
_create_calendar()
|
||||
except HttpError as err:
|
||||
if err.resp.status in [403, 500, 503]:
|
||||
time.sleep(5)
|
||||
elif err.resp.status in [404]:
|
||||
_create_calendar()
|
||||
else: raise
|
||||
|
||||
|
||||
def get(self, remote_objectname, fields=None, filters=None, start=0, page_length=10):
|
||||
return self.get_events(remote_objectname, filters, page_length)
|
||||
|
||||
def insert(self, doctype, doc):
|
||||
if doctype == 'Events':
|
||||
d = frappe.get_doc("Event", doc["name"])
|
||||
if has_permission(d, self.account.name):
|
||||
try:
|
||||
doctype = "Event"
|
||||
e = self.insert_events(doctype, doc)
|
||||
return e
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), "GCalendar Synchronization Error")
|
||||
|
||||
|
||||
def update(self, doctype, doc, migration_id):
|
||||
if doctype == 'Events':
|
||||
d = frappe.get_doc("Event", doc["name"])
|
||||
if has_permission(d, self.account.name):
|
||||
if migration_id is not None:
|
||||
try:
|
||||
doctype = "Event"
|
||||
return self.update_events(doctype, doc, migration_id)
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), "GCalendar Synchronization Error")
|
||||
|
||||
def delete(self, doctype, migration_id):
|
||||
if doctype == 'Events':
|
||||
try:
|
||||
return self.delete_events(migration_id)
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), "GCalendar Synchronization Error")
|
||||
|
||||
def get_events(self, remote_objectname, filters, page_length):
|
||||
page_token = None
|
||||
results = []
|
||||
events = {"items": []}
|
||||
while True:
|
||||
try:
|
||||
events = self.gcalendar.events().list(calendarId=self.account.gcalendar_id, maxResults=page_length,
|
||||
singleEvents=False, showDeleted=True, syncToken=self.account.next_sync_token or None).execute()
|
||||
except HttpError as err:
|
||||
if err.resp.status in [410]:
|
||||
events = self.gcalendar.events().list(calendarId=self.account.gcalendar_id, maxResults=page_length,
|
||||
singleEvents=False, showDeleted=True, timeMin=add_years(None, -1).strftime('%Y-%m-%dT%H:%M:%SZ')).execute()
|
||||
else:
|
||||
frappe.log_error(err.resp, "GCalendar Events Fetch Error")
|
||||
for event in events['items']:
|
||||
event.update({'account': self.account.name})
|
||||
event.update({'calendar_tz': events['timeZone']})
|
||||
results.append(event)
|
||||
|
||||
page_token = events.get('nextPageToken')
|
||||
if not page_token:
|
||||
if events.get('nextSyncToken'):
|
||||
frappe.db.set_value("GCalendar Account", self.connector.username, "next_sync_token", events.get('nextSyncToken'))
|
||||
break
|
||||
return list(results)
|
||||
|
||||
def insert_events(self, doctype, doc, migration_id=None):
|
||||
event = {
|
||||
'summary': doc.summary,
|
||||
'description': doc.description
|
||||
}
|
||||
|
||||
dates = self.return_dates(doc)
|
||||
event.update(dates)
|
||||
|
||||
if migration_id:
|
||||
event.update({"id": migration_id})
|
||||
|
||||
if doc.repeat_this_event != 0:
|
||||
recurrence = self.return_recurrence(doctype, doc)
|
||||
if not not recurrence:
|
||||
event.update({"recurrence": ["RRULE:" + str(recurrence)]})
|
||||
|
||||
try:
|
||||
remote_event = self.gcalendar.events().insert(calendarId=self.account.gcalendar_id, body=event).execute()
|
||||
return {self.name_field: remote_event["id"]}
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), "GCalendar Synchronization Error")
|
||||
|
||||
def update_events(self, doctype, doc, migration_id):
|
||||
try:
|
||||
event = self.gcalendar.events().get(calendarId=self.account.gcalendar_id, eventId=migration_id).execute()
|
||||
event = {
|
||||
'summary': doc.summary,
|
||||
'description': doc.description
|
||||
}
|
||||
|
||||
if doc.event_type == "Cancel":
|
||||
event.update({"status": "cancelled"})
|
||||
|
||||
dates = self.return_dates(doc)
|
||||
event.update(dates)
|
||||
|
||||
if doc.repeat_this_event != 0:
|
||||
recurrence = self.return_recurrence(doctype, doc)
|
||||
if recurrence:
|
||||
event.update({"recurrence": ["RRULE:" + str(recurrence)]})
|
||||
|
||||
try:
|
||||
updated_event = self.gcalendar.events().update(calendarId=self.account.gcalendar_id, eventId=migration_id, body=event).execute()
|
||||
return {self.name_field: updated_event["id"]}
|
||||
except Exception as e:
|
||||
frappe.log_error(e, "GCalendar Synchronization Error")
|
||||
except HttpError as err:
|
||||
if err.resp.status in [404]:
|
||||
self.insert_events(doctype, doc, migration_id)
|
||||
else:
|
||||
frappe.log_error(err.resp, "GCalendar Synchronization Error")
|
||||
|
||||
def delete_events(self, migration_id):
|
||||
try:
|
||||
self.gcalendar.events().delete(calendarId=self.account.gcalendar_id, eventId=migration_id).execute()
|
||||
except HttpError as err:
|
||||
if err.resp.status in [410]:
|
||||
pass
|
||||
|
||||
def return_dates(self, doc):
|
||||
timezone = frappe.db.get_value("System Settings", None, "time_zone")
|
||||
if doc.end_datetime is None:
|
||||
doc.end_datetime = doc.start_datetime
|
||||
if doc.all_day == 1:
|
||||
return {
|
||||
'start': {
|
||||
'date': doc.start_datetime.date().isoformat(),
|
||||
'timeZone': timezone,
|
||||
},
|
||||
'end': {
|
||||
'date': add_days(doc.end_datetime.date(), 1).isoformat(),
|
||||
'timeZone': timezone,
|
||||
}
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'start': {
|
||||
'dateTime': doc.start_datetime.isoformat(),
|
||||
'timeZone': timezone,
|
||||
},
|
||||
'end': {
|
||||
'dateTime': doc.end_datetime.isoformat(),
|
||||
'timeZone': timezone,
|
||||
}
|
||||
}
|
||||
|
||||
def return_recurrence(self, doctype, doc):
|
||||
e = frappe.get_doc(doctype, doc.name)
|
||||
if e.repeat_till is not None:
|
||||
end_date = datetime.combine(e.repeat_till, datetime.min.time()).strftime('UNTIL=%Y%m%dT%H%M%SZ')
|
||||
else:
|
||||
end_date = None
|
||||
|
||||
day = []
|
||||
if e.repeat_on == "Daily":
|
||||
frequency = "FREQ=DAILY"
|
||||
elif e.repeat_on == "Weekly":
|
||||
if e.monday == 1:
|
||||
day.append("MO")
|
||||
if e.tuesday == 1:
|
||||
day.append("TU")
|
||||
if e.wednesday == 1:
|
||||
day.append("WE")
|
||||
if e.thursday == 1:
|
||||
day.append("TH")
|
||||
if e.friday == 1:
|
||||
day.append("FR")
|
||||
if e.saturday == 1:
|
||||
day.append("SA")
|
||||
if e.sunday == 1:
|
||||
day.append("SU")
|
||||
|
||||
day = "BYDAY=" + ",".join(str(d) for d in day)
|
||||
frequency = "FREQ=WEEKLY"
|
||||
elif e.repeat_on == "Monthly":
|
||||
frequency = "FREQ=MONTHLY;BYDAY=SU,MO,TU,WE,TH,FR,SA;BYSETPOS=-1"
|
||||
end_date = datetime.combine(add_days(e.repeat_till, 1), datetime.min.time()).strftime('UNTIL=%Y%m%dT%H%M%SZ')
|
||||
elif e.repeat_on == "Yearly":
|
||||
frequency = "FREQ=YEARLY"
|
||||
else:
|
||||
return None
|
||||
|
||||
wst = "WKST=SU"
|
||||
|
||||
elements = [frequency, end_date, wst, day]
|
||||
|
||||
return ";".join(str(e) for e in elements if e is not None and not not e)
|
||||
|
|
@ -75,12 +75,12 @@ frappe.ui.EnergyPointsNotifications = class {
|
|||
return frappe.db.get_list('Energy Point Log', {
|
||||
filters: {
|
||||
user: frappe.session.user,
|
||||
type: ['not in',['Review']]
|
||||
type: ['not in', ['Review']],
|
||||
},
|
||||
fields:
|
||||
['name','user', 'points', 'reference_doctype', 'reference_name', 'reason', 'type', 'seen', 'rule', 'owner', 'creation'],
|
||||
['name', 'user', 'points', 'reference_doctype', 'reference_name', 'reason', 'type', 'seen', 'rule', 'owner', 'creation'],
|
||||
limit: limit,
|
||||
order_by:'creation desc'
|
||||
order_by: 'creation desc'
|
||||
}).then((energy_points_list) => {
|
||||
return energy_points_list;
|
||||
});
|
||||
|
|
@ -116,7 +116,7 @@ frappe.ui.EnergyPointsNotifications = class {
|
|||
}
|
||||
|
||||
get_dropdown_item_html(field) {
|
||||
let doc_link = frappe.utils.get_form_link(field.reference_doctype,field.reference_name);
|
||||
let doc_link = frappe.utils.get_form_link(field.reference_doctype, field.reference_name);
|
||||
let link_html_string = field.seen ? `<a href=${doc_link}>`: `<a href=${doc_link} class="unseen">`;
|
||||
let points_html = `<div class="points-update">${frappe.energy_points.get_points(field.points)}</div>`;
|
||||
let message_html = this.get_message_html(field);
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ export default class WebForm extends frappe.ui.FieldGroup {
|
|||
}
|
||||
|
||||
add_button_to_footer(name, type, action) {
|
||||
this.add_button(name, type, action, '.web-form-footer')
|
||||
this.add_button(name, type, action, '.web-form-footer');
|
||||
}
|
||||
|
||||
add_button_to_header(name, type, action) {
|
||||
this.add_button(name, type, action, '.web-form-actions')
|
||||
this.add_button(name, type, action, '.web-form-actions');
|
||||
}
|
||||
|
||||
setup_primary_action() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue