diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 96c1e2b68e9..fdd02e19c5c 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -37,8 +37,6 @@ from openerp.tools.translate import _ from openerp.http import request from operator import itemgetter -from werkzeug.exceptions import BadRequest - import logging _logger = logging.getLogger(__name__) @@ -63,6 +61,7 @@ def calendar_id2real_id(calendar_id=None, with_date=False): return int(real_id) return calendar_id and int(calendar_id) or calendar_id + def get_real_ids(ids): if isinstance(ids, (str, int, long)): return calendar_id2real_id(ids) @@ -76,6 +75,7 @@ class calendar_attendee(osv.Model): Calendar Attendee Information """ _name = 'calendar.attendee' + _rec_name = 'cn' _description = 'Attendee information' def _compute_data(self, cr, uid, ids, name, arg, context=None): @@ -388,14 +388,12 @@ class calendar_alarm_manager(osv.AbstractModel): SELECT * FROM ( - """ - + base_request - + """ + %s ) AS ALL_EVENTS WHERE ALL_EVENTS.first_alarm < (now() at time zone 'utc' + interval '%s' second ) AND ALL_EVENTS.last_alarm > (now() at time zone 'utc' - interval '%s' second ) - """, tuple_params) + """ % base_request, tuple_params) for event_id, first_alarm, last_alarm, first_meeting, last_meeting, min_duration, max_duration, rule in cr.fetchall(): res[event_id].update({ @@ -433,87 +431,86 @@ class calendar_alarm_manager(osv.AbstractModel): res.append(alert) return res - - def get_next_mail(self,cr,uid,context=None): - cron = self.pool.get('ir.cron').search(cr,uid,[('model','ilike',self._name)],context=context) + def get_next_mail(self, cr, uid, context=None): + cron = self.pool.get('ir.cron').search(cr, uid, [('model', 'ilike', self._name)], context=context) if cron and len(cron) == 1: - cron = self.pool.get('ir.cron').browse(cr,uid,cron[0],context=context) + cron = self.pool.get('ir.cron').browse(cr, uid, cron[0], context=context) else: raise ("Cron for " + self._name + " not identified :( !") - if cron.interval_type=="weeks": + if cron.interval_type == "weeks": cron_interval = cron.interval_number * 7 * 24 * 60 * 60 - elif cron.interval_type=="days": - cron_interval = cron.interval_number * 24 * 60 * 60 - elif cron.interval_type=="hours": + elif cron.interval_type == "days": + cron_interval = cron.interval_number * 24 * 60 * 60 + elif cron.interval_type == "hours": cron_interval = cron.interval_number * 60 * 60 - elif cron.interval_type=="minutes": + elif cron.interval_type == "minutes": cron_interval = cron.interval_number * 60 - elif cron.interval_type=="seconds": - cron_interval = cron.interval_number + elif cron.interval_type == "seconds": + cron_interval = cron.interval_number if not cron_interval: raise ("Cron delay for " + self._name + " can not be calculated :( !") - all_events = self.get_next_potential_limit_alarm(cr,uid,cron_interval,notif=False,context=context) + all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context) - for event in all_events: #.values() - max_delta = all_events[event]['max_duration']; - curEvent = self.pool.get('calendar.event').browse(cr,uid,event,context=context) + for event in all_events: # .values() + max_delta = all_events[event]['max_duration'] + curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context) if curEvent.recurrency: bFound = False LastFound = False - for one_date in self.pool.get('calendar.event').get_recurrent_date_by_event(cr,uid,curEvent, context=context) : - in_date_format = datetime.strptime(one_date, '%Y-%m-%d %H:%M:%S'); - LastFound = self.do_check_alarm_for_one_date(cr,uid,in_date_format,curEvent,max_delta,cron_interval,notif=False,context=context) + for one_date in self.pool.get('calendar.event').get_recurrent_date_by_event(cr, uid, curEvent, context=context): + in_date_format = datetime.strptime(one_date, '%Y-%m-%d %H:%M:%S') + LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context) if LastFound: for alert in LastFound: - self.do_mail_reminder(cr,uid,alert,context=context) + self.do_mail_reminder(cr, uid, alert, context=context) if not bFound: # if it's the first alarm for this recurrent event bFound = True if bFound and not LastFound: # if the precedent event had an alarm but not this one, we can stop the search for this event break else: - in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S'); - LastFound = self.do_check_alarm_for_one_date(cr,uid,in_date_format,curEvent,max_delta,cron_interval,notif=False,context=context) + in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S') + LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context) if LastFound: for alert in LastFound: - self.do_mail_reminder(cr,uid,alert,context=context) + self.do_mail_reminder(cr, uid, alert, context=context) - def get_next_notif(self,cr,uid,context=None): + def get_next_notif(self, cr, uid, context=None): ajax_check_every_seconds = 300 partner = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id all_notif = [] - if not partner or not partner.id: # If user is disconnected + if not partner: return [] - all_events = self.get_next_potential_limit_alarm(cr,uid,ajax_check_every_seconds,partner_id=partner.id,mail=False,context=context) + all_events = self.get_next_potential_limit_alarm(cr, uid, ajax_check_every_seconds, partner_id=partner.id, mail=False, context=context) for event in all_events: # .values() - max_delta = all_events[event]['max_duration']; - curEvent = self.pool.get('calendar.event').browse(cr,uid,event,context=context) + max_delta = all_events[event]['max_duration'] + curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context) if curEvent.recurrency: bFound = False LastFound = False - for one_date in self.pool.get("calendar.event").get_recurrent_date_by_event(cr,uid,curEvent, context=context) : - in_date_format = datetime.strptime(one_date, '%Y-%m-%d %H:%M:%S'); - LastFound = self.do_check_alarm_for_one_date(cr,uid,in_date_format,curEvent,max_delta,ajax_check_every_seconds,after=partner.cal_last_notif,mail=False,context=context) + for one_date in self.pool.get("calendar.event").get_recurrent_date_by_event(cr, uid, curEvent, context=context): + in_date_format = datetime.strptime(one_date, '%Y-%m-%d %H:%M:%S') + LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, after=partner.cal_last_notif, mail=False, context=context) if LastFound: for alert in LastFound: - all_notif.append(self.do_notif_reminder(cr,uid,alert,context=context)) - if not bFound: #if it's the first alarm for this recurrent event - bFound = True - if bFound and not LastFound: #if the precedent event had alarm but not this one, we can stop the search fot this event + all_notif.append(self.do_notif_reminder(cr, uid, alert, context=context)) + if not bFound: # if it's the first alarm for this recurrent event + bFound = True + if bFound and not LastFound: # if the precedent event had alarm but not this one, we can stop the search fot this event break else: - in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S'); - LastFound = self.do_check_alarm_for_one_date(cr,uid,in_date_format,curEvent,max_delta,ajax_check_every_seconds,partner.cal_last_notif,mail=False,context=context) + in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S') + LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, partner.cal_last_notif, mail=False, context=context) if LastFound: for alert in LastFound: - all_notif.append(self.do_notif_reminder(cr,uid,alert,context=context)) - return all_notif + all_notif.append(self.do_notif_reminder(cr, uid, alert, context=context)) + return all_notif def do_mail_reminder(self, cr, uid, alert, context=None): if context is None: @@ -781,7 +778,7 @@ class calendar_event(osv.Model): else: result[event] = "" return result - + def _rrule_write(self, cr, uid, ids, field_name, field_value, args, context=None): if not isinstance(ids, list): ids = [ids] @@ -794,7 +791,7 @@ class calendar_event(osv.Model): data.update(update_data) self.write(cr, uid, ids, data, context=context) return True - + def _tz_get(self, cr, uid, context=None): return [(x.lower(), x) for x in pytz.all_timezones] @@ -802,7 +799,7 @@ class calendar_event(osv.Model): 'location': { 'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, }, - 'date': { + 'date': { 'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, }, } @@ -983,7 +980,7 @@ class calendar_event(osv.Model): } return res - def get_search_fields(self,browse_event,order_fields,r_date=None): + def get_search_fields(self, browse_event, order_fields, r_date=None): sort_fields = {} for ord in order_fields: if ord == 'id' and r_date: @@ -993,17 +990,17 @@ class calendar_event(osv.Model): 'If we sort on FK, we obtain a browse_record, so we need to sort on name_get' if type(browse_event[ord]) is openerp.osv.orm.browse_record: name_get = browse_event[ord].name_get() - if len(name_get) and len(name_get[0])>=2: + if len(name_get) and len(name_get[0]) >= 2: sort_fields[ord] = name_get[0][1] return sort_fields def get_recurrent_ids(self, cr, uid, event_id, domain, order=None, context=None): - """Gives virtual event ids for recurring events + """Gives virtual event ids for recurring events This method gives ids of dates that comes between start date and end date of calendar views - - @param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted + + @param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted """ if not context: @@ -1028,7 +1025,7 @@ class calendar_event(osv.Model): for ev in self.browse(cr, uid, ids_to_browse, context=context): if not ev.recurrency or not ev.rrule: result.append(ev.id) - result_data.append(self.get_search_fields(ev,order_fields)) + result_data.append(self.get_search_fields(ev, order_fields)) continue rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context) @@ -1074,7 +1071,7 @@ class calendar_event(osv.Model): if [True for item in new_pile if not item]: continue - result_data.append(self.get_search_fields(ev,order_fields,r_date=r_date)) + result_data.append(self.get_search_fields(ev, order_fields, r_date=r_date)) if order_fields: def comparer(left, right): @@ -1085,7 +1082,7 @@ class calendar_event(osv.Model): return 0 sort_params = [key.split()[0] if key[-4:].lower() != 'desc' else '-%s' % key.split()[0] for key in (order or self._order).split(',')] - comparers = [ ((itemgetter(col[1:]), -1) if col[0] == '-' else (itemgetter(col), 1)) for col in sort_params] + comparers = [((itemgetter(col[1:]), -1) if col[0] == '-' else (itemgetter(col), 1)) for col in sort_params] ids = [r['id'] for r in sorted(result_data, cmp=comparer)] if isinstance(event_id, (str, int, long)): @@ -1093,7 +1090,6 @@ class calendar_event(osv.Model): else: return ids - def compute_rule_string(self, data): """ Compute rule string according to value type RECUR of iCalendar from the values given. @@ -1127,7 +1123,7 @@ class calendar_event(osv.Model): data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z' return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\ - ((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '') + ((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '') freq = data.get('rrule_type', False) # day/week/month/year res = '' @@ -1223,12 +1219,12 @@ class calendar_event(osv.Model): res.update(self.check_partners_email(cr, uid, value[0][2], context=context)) return res - def onchange_rec_day(self,cr,uid,id,date,mo,tu,we,th,fr,sa,su): + def onchange_rec_day(self, cr, uid, id, date, mo, tu, we, th, fr, sa, su): """ set the start date according to the first occurence of rrule""" rrule_obj = self._get_empty_rrule_data() rrule_obj.update({ - 'byday':True, - 'rrule_type':'weekly', + 'byday': True, + 'rrule_type': 'weekly', 'mo': mo, 'tu': tu, 'we': we, @@ -1236,12 +1232,11 @@ class calendar_event(osv.Model): 'fr': fr, 'sa': sa, 'su': su, - 'interval':1 + 'interval': 1 }) str_rrule = self.compute_rule_string(rrule_obj) - first_occurence = list(rrule.rrulestr(str_rrule + ";COUNT=1", dtstart=datetime.strptime(date, "%Y-%m-%d %H:%M:%S"), forceset=True))[0] - return {'value': { 'date' : first_occurence.strftime("%Y-%m-%d") + ' 00:00:00' } } - + first_occurence = list(rrule.rrulestr(str_rrule + ";COUNT=1", dtstart=datetime.strptime(date, "%Y-%m-%d %H:%M:%S"), forceset=True))[0] + return {'value': {'date': first_occurence.strftime("%Y-%m-%d") + ' 00:00:00'}} def check_partners_email(self, cr, uid, partner_ids, context=None): """ Verify that selected partner_ids have an email_address defined. @@ -1255,12 +1250,10 @@ class calendar_event(osv.Model): warning_msg = _('The following contacts have no email address :') for partner in partner_wo_email_lst: warning_msg += '\n- %s' % (partner.name) - return {'warning': - { - 'title': _('Email addresses not found'), - 'message': warning_msg, - } - } + return {'warning': { + 'title': _('Email addresses not found'), + 'message': warning_msg, + }} # ---------------------------------------- # OpenChatter @@ -1369,8 +1362,7 @@ class calendar_event(osv.Model): rrule_type=False, rrule='', recurrency=False, - end_date = datetime.strptime(values.get('date', False) or data.get('date'),"%Y-%m-%d %H:%M:%S") - + timedelta(hours=values.get('duration', False) or data.get('duration')) + end_date=datetime.strptime(values.get('date', False) or data.get('date'), "%Y-%m-%d %H:%M:%S") + timedelta(hours=values.get('duration', False) or data.get('duration')) ) #do not copy the id @@ -1385,29 +1377,25 @@ class calendar_event(osv.Model): new_id = self._detach_one_event(cr, uid, ids[0], context=context) return { - 'type': 'ir.actions.act_window', - 'res_model': 'calendar.event', - 'view_mode': 'form', - 'res_id': new_id, - 'target': 'current', - 'flags': {'form': {'action_buttons': True, 'options' : { 'mode' : 'edit' } } } + 'type': 'ir.actions.act_window', + 'res_model': 'calendar.event', + 'view_mode': 'form', + 'res_id': new_id, + 'target': 'current', + 'flags': {'form': {'action_buttons': True, 'options': {'mode': 'edit'}}} } - - - def write(self, cr, uid, ids, values, context=None): def _only_changes_to_apply_on_real_ids(field_names): - ''' return True if changes are only to be made on the real ids''' + ''' return True if changes are only to be made on the real ids''' for field in field_names: - if field in ['date','active']: - return True + if field in ['date', 'active']: + return True return False context = context or {} - - if isinstance(ids, (str,int, long)): + if isinstance(ids, (str, int, long)): if len(str(ids).split('-')) == 1: ids = [int(ids)] else: @@ -1432,9 +1420,9 @@ class calendar_event(osv.Model): continue else: data = self.read(cr, uid, event_id, ['date', 'date_deadline', 'rrule', 'duration']) - if data.get('rrule'): + if data.get('rrule'): new_id = self._detach_one_event(cr, uid, event_id, values, context=None) - + res = super(calendar_event, self).write(cr, uid, ids, values, context=context) # set end_date for calendar searching @@ -1558,7 +1546,7 @@ class calendar_event(osv.Model): ids_to_unlink = [] # One time moved to google_Calendar, we can specify, if not in google, and not rec or get_inst = 0, we delete it - for event_id in ids: + for event_id in ids: if unlink_level == 1 and len(str(event_id).split('-')) == 1: # if ID REAL if self.browse(cr, uid, event_id).recurrent_id: ids_to_exclure.append(event_id) @@ -1591,7 +1579,7 @@ class mail_message(osv.Model): def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): if doc_model == 'calendar.event': - order = context.get('order', self._order) + order = context.get('order', self._order) for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context): doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)]) return super(mail_message, self)._find_allowed_model_wise(cr, uid, doc_model, doc_dict, context=context) @@ -1623,26 +1611,27 @@ class ir_http(osv.AbstractModel): def _auth_method_calendar(self): token = request.params['token'] - db = request.params['db'] + db = request.params['db'] registry = openerp.modules.registry.RegistryManager.get(db) attendee_pool = registry.get('calendar.attendee') error_message = False with registry.cursor() as cr: - attendee_id = attendee_pool.search(cr, openerp.SUPERUSER_ID, [('access_token','=',token)]) + attendee_id = attendee_pool.search(cr, openerp.SUPERUSER_ID, [('access_token', '=', token)]) if not attendee_id: error_message = """Invalid Invitation Token.""" elif request.session.uid and request.session.login != 'anonymous': # if valid session but user is not match attendee = attendee_pool.browse(cr, openerp.SUPERUSER_ID, attendee_id[0]) user = registry.get('res.users').browse(cr, openerp.SUPERUSER_ID, request.session.uid) - if attendee.partner_id.id != user.partner_id.id: - error_message = """Invitation cannot be forwarded via email. This event/meeting belongs to %s and you are logged in as %s. Please ask organizer to add you.""" % (attendee.email, user.email) + if attendee.partner_id.id != user.partner_id.id: + error_message = """Invitation cannot be forwarded via email. This event/meeting belongs to %s and you are logged in as %s. Please ask organizer to add you.""" % (attendee.email, user.email) if error_message: raise BadRequest(error_message) return True + class invite_wizard(osv.osv_memory): _inherit = 'mail.wizard.invite' diff --git a/addons/calendar/calendar_demo.xml b/addons/calendar/calendar_demo.xml index 9e0b44c89cb..4ac308a29c2 100644 --- a/addons/calendar/calendar_demo.xml +++ b/addons/calendar/calendar_demo.xml @@ -20,7 +20,7 @@ - + Follow-up for Project proposal Meeting to discuss project plan and hash out the details of implementation. diff --git a/addons/calendar/static/src/js/base_calendar.js b/addons/calendar/static/src/js/base_calendar.js index 4384964575c..a1b14393dba 100644 --- a/addons/calendar/static/src/js/base_calendar.js +++ b/addons/calendar/static/src/js/base_calendar.js @@ -1,10 +1,13 @@ openerp.calendar = function(instance) { var _t = instance.web._t; var QWeb = instance.web.qweb; + instance.calendar = {}; instance.web.WebClient = instance.web.WebClient.extend({ + + get_notif_box: function(me) { return $(me).closest(".ui-notify-message-style"); }, @@ -55,7 +58,7 @@ openerp.calendar = function(instance) { check_notifications: function() { var self= this; self.get_next_notif(); - setInterval(function(){ + self.intervalNotif = setInterval(function(){ self.get_next_notif(); }, 5 * 60 * 1000 ); }, @@ -63,7 +66,12 @@ openerp.calendar = function(instance) { //Override the show_application of addons/web/static/src/js/chrome.js show_application: function() { this._super(); - this.check_notifications(); + this.check_notifications(); + }, + //Override addons/web/static/src/js/chrome.js + on_logout: function() { + this._super(); + clearInterval(self.intervalNotif); }, }); diff --git a/addons/crm/calendar_event.py b/addons/crm/calendar_event.py index 4f57e364282..d505be1b174 100644 --- a/addons/crm/calendar_event.py +++ b/addons/crm/calendar_event.py @@ -23,15 +23,13 @@ from openerp.osv import fields, osv import logging _logger = logging.getLogger(__name__) -# -# calendar.event is defined in module calendar -# + class calendar_event(osv.Model): """ Model for Calendar Event """ _inherit = 'calendar.event' _columns = { - 'phonecall_id': fields.many2one ('crm.phonecall', 'Phonecall'), - 'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"), + 'phonecall_id': fields.many2one('crm.phonecall', 'Phonecall'), + 'opportunity_id': fields.many2one('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"), } def create(self, cr, uid, vals, context=None): @@ -49,7 +47,7 @@ class calendar_attendee(osv.osv): _description = 'Calendar Attendee' def _noop(self, cr, uid, ids, name, arg, context=None): - return dict.fromkeys(ids,False) + return dict.fromkeys(ids, False) _columns = { 'categ_id': fields.function(_noop, string='Event Type', deprecated="Unused Field - TODO : Remove it in trunk", type="many2one", relation="crm.case.categ"), diff --git a/addons/google_calendar/google_calendar.py b/addons/google_calendar/google_calendar.py index 734710be4d0..f36062b6be2 100644 --- a/addons/google_calendar/google_calendar.py +++ b/addons/google_calendar/google_calendar.py @@ -21,30 +21,22 @@ import operator import simplejson -import re import urllib -import warnings from openerp import tools from openerp import SUPERUSER_ID -from openerp.tools.translate import _ -from openerp.addons.web.http import request -import werkzeug.utils - -from datetime import datetime, timedelta, date +from datetime import datetime, timedelta from dateutil import parser import pytz from openerp.osv import fields, osv -from openerp.osv import osv -from collections import namedtuple import logging _logger = logging.getLogger(__name__) class Meta(type): - """ This Meta class allow to define class as a structure, and so instancied variable + """ This Meta class allow to define class as a structure, and so instancied variable in __init__ to avoid to have side effect alike 'static' variable """ def __new__(typ, name, parents, attrs): methods = dict((k, v) for k, v in attrs.iteritems() @@ -63,9 +55,11 @@ class Meta(type): methods['__getitem__'] = getattr return type.__new__(typ, name, parents, methods) + class Struct(object): __metaclass__ = Meta + class OpenerpEvent(Struct): event = False found = False @@ -77,6 +71,7 @@ class OpenerpEvent(Struct): attendee_id = False synchro = False + class GmailEvent(Struct): event = False found = False @@ -85,53 +80,51 @@ class GmailEvent(Struct): update = False status = False + class SyncEvent(object): def __init__(self): self.OE = OpenerpEvent() - self.GG = GmailEvent() + self.GG = GmailEvent() self.OP = None - def __getitem__(self, key): - return getattr(self,key) + def __getitem__(self, key): + return getattr(self, key) def compute_OP(self): - #If event are already in Gmail and in OpenERP + #If event are already in Gmail and in OpenERP if self.OE.found and self.GG.found: #If the event has been deleted from one side, we delete on other side ! if self.OE.status != self.GG.status: self.OP = Delete((self.OE.status and "OE") or (self.GG.status and "GG"), - 'The event has been deleted from one side, we delete on other side !' ) - #If event is not deleted ! + 'The event has been deleted from one side, we delete on other side !') + #If event is not deleted ! elif self.OE.status and self.GG.status: if self.OE.update.split('.')[0] != self.GG.update.split('.')[0]: if self.OE.update < self.GG.update: tmpSrc = 'GG' elif self.OE.update > self.GG.update: tmpSrc = 'OE' - assert tmpSrc in ['GG','OE'] + assert tmpSrc in ['GG', 'OE'] - #if self.OP.action == None: if self[tmpSrc].isRecurrence: if self[tmpSrc].status: - self.OP = Update(tmpSrc, 'Only need to update, because i\'m active') + self.OP = Update(tmpSrc, 'Only need to update, because i\'m active') else: self.OP = Exclude(tmpSrc, 'Need to Exclude (Me = First event from recurrence) from recurrence') elif self[tmpSrc].isInstance: - self.OP= Update(tmpSrc, 'Only need to update, because already an exclu'); + self.OP = Update(tmpSrc, 'Only need to update, because already an exclu') else: - self.OP = Update(tmpSrc, 'Simply Update... I\'m a single event'); - #end-if self.OP.action == None: - + self.OP = Update(tmpSrc, 'Simply Update... I\'m a single event') else: if not self.OE.synchro or self.OE.synchro.split('.')[0] < self.OE.update.split('.')[0]: - self.OP = Update('OE','Event already updated by another user, but not synchro with my google calendar') + self.OP = Update('OE', 'Event already updated by another user, but not synchro with my google calendar') #import ipdb; ipdb.set_trace(); else: - self.OP = NothingToDo("",'Not update needed') + self.OP = NothingToDo("", 'Not update needed') else: - self.OP = NothingToDo("", "Both are already deleted"); + self.OP = NothingToDo("", "Both are already deleted") # New in openERP... Create on create_events of synchronize function elif self.OE.found and not self.GG.found: @@ -139,64 +132,73 @@ class SyncEvent(object): if self.OE.status: self.OP = Delete('OE', 'Removed from GOOGLE') else: - self.OP = NothingToDo("","Already Deleted in gmail and unlinked in OpenERP") + self.OP = NothingToDo("", "Already Deleted in gmail and unlinked in OpenERP") elif self.GG.found and not self.OE.found: tmpSrc = 'GG' if not self.GG.status and not self.GG.isInstance: - # don't need to make something... because event has been created and deleted before the synchronization - self.OP = NothingToDo("", 'Nothing to do... Create and Delete directly') + # don't need to make something... because event has been created and deleted before the synchronization + self.OP = NothingToDo("", 'Nothing to do... Create and Delete directly') else: - if self.GG.isInstance: - if self[tmpSrc].status: - self.OP = Exclude(tmpSrc, 'Need to create the new exclu') - else: - self.OP = Exclude(tmpSrc, 'Need to copy and Exclude') - else: - self.OP = Create(tmpSrc, 'New EVENT CREATE from GMAIL') + if self.GG.isInstance: + if self[tmpSrc].status: + self.OP = Exclude(tmpSrc, 'Need to create the new exclu') + else: + self.OP = Exclude(tmpSrc, 'Need to copy and Exclude') + else: + self.OP = Create(tmpSrc, 'New EVENT CREATE from GMAIL') def __str__(self): return self.__repr__() def __repr__(self): - myPrint = "---- A SYNC EVENT ---" - myPrint += "\n ID OE: %s " % (self.OE.event and self.OE.event.id) - myPrint += "\n ID GG: %s " % (self.GG.event and self.GG.event.get('id', False)) - myPrint += "\n Name OE: %s " % (self.OE.event and self.OE.event.name) - myPrint += "\n Name GG: %s " % (self.GG.event and self.GG.event.get('summary', False)) - myPrint += "\n Found OE:%5s vs GG: %5s" % (self.OE.found, self.GG.found) - myPrint += "\n Recurrence OE:%5s vs GG: %5s" % (self.OE.isRecurrence, self.GG.isRecurrence) - myPrint += "\n Instance OE:%5s vs GG: %5s" % (self.OE.isInstance, self.GG.isInstance) - myPrint += "\n Synchro OE: %10s " % (self.OE.synchro) - myPrint += "\n Update OE: %10s " % (self.OE.update) - myPrint += "\n Update GG: %10s " % (self.GG.update) - myPrint += "\n Status OE:%5s vs GG: %5s" % (self.OE.status, self.GG.status) + myPrint = "---- A SYNC EVENT ---" + myPrint += "\n ID OE: %s " % (self.OE.event and self.OE.event.id) + myPrint += "\n ID GG: %s " % (self.GG.event and self.GG.event.get('id', False)) + myPrint += "\n Name OE: %s " % (self.OE.event and self.OE.event.name) + myPrint += "\n Name GG: %s " % (self.GG.event and self.GG.event.get('summary', False)) + myPrint += "\n Found OE:%5s vs GG: %5s" % (self.OE.found, self.GG.found) + myPrint += "\n Recurrence OE:%5s vs GG: %5s" % (self.OE.isRecurrence, self.GG.isRecurrence) + myPrint += "\n Instance OE:%5s vs GG: %5s" % (self.OE.isInstance, self.GG.isInstance) + myPrint += "\n Synchro OE: %10s " % (self.OE.synchro) + myPrint += "\n Update OE: %10s " % (self.OE.update) + myPrint += "\n Update GG: %10s " % (self.GG.update) + myPrint += "\n Status OE:%5s vs GG: %5s" % (self.OE.status, self.GG.status) if (self.OP is None): - myPrint += "\n Action %s" % "---!!!---NONE---!!!---" + myPrint += "\n Action %s" % "---!!!---NONE---!!!---" else: - myPrint += "\n Action %s" % type(self.OP).__name__ - myPrint += "\n Source %s" % (self.OP.src) - myPrint += "\n comment %s" % (self.OP.info) + myPrint += "\n Action %s" % type(self.OP).__name__ + myPrint += "\n Source %s" % (self.OP.src) + myPrint += "\n comment %s" % (self.OP.info) return myPrint class SyncOperation(object): - def __init__(self, src,info, **kw): + def __init__(self, src, info, **kw): self.src = src self.info = info - for k,v in kw.items(): - setattr(self,k,v) + for k, v in kw.items(): + setattr(self, k, v) def __str__(self): return 'in__STR__' + class Create(SyncOperation): pass + + class Update(SyncOperation): pass + + class Delete(SyncOperation): pass + + class NothingToDo(SyncOperation): pass + + class Exclude(SyncOperation): pass @@ -205,9 +207,9 @@ class google_calendar(osv.AbstractModel): STR_SERVICE = 'calendar' _name = 'google.%s' % STR_SERVICE - def generate_data(self, cr, uid, event, context=None): + def generate_data(self, cr, uid, event, context=None): if event.allday: - start_date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(event.date, tools.DEFAULT_SERVER_DATETIME_FORMAT) , context=context).isoformat('T').split('T')[0] + start_date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(event.date, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context).isoformat('T').split('T')[0] end_date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(event.date, tools.DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(hours=event.duration), context=context).isoformat('T').split('T')[0] type = 'date' vstype = 'dateTime' @@ -220,72 +222,71 @@ class google_calendar(osv.AbstractModel): for attendee in event.attendee_ids: attendee_list.append({ - 'email':attendee.email or 'NoEmail@mail.com', - 'displayName':attendee.partner_id.name, - 'responseStatus':attendee.state or 'needsAction', + 'email': attendee.email or 'NoEmail@mail.com', + 'displayName': attendee.partner_id.name, + 'responseStatus': attendee.state or 'needsAction', }) data = { "summary": event.name or '', "description": event.description or '', - "start":{ - type:start_date, - vstype:None, - 'timeZone':'UTC' - }, - "end":{ - type:end_date, - vstype:None, - 'timeZone':'UTC' - }, - "attendees":attendee_list, - "location":event.location or '', - "visibility":event['class'] or 'public', + "start": { + type: start_date, + vstype: None, + 'timeZone': 'UTC' + }, + "end": { + type: end_date, + vstype: None, + 'timeZone': 'UTC' + }, + "attendees": attendee_list, + "location": event.location or '', + "visibility": event['class'] or 'public', } if event.recurrency and event.rrule: - data["recurrence"]=["RRULE:"+event.rrule] + data["recurrence"] = ["RRULE:" + event.rrule] if not event.active: data["state"] = "cancelled" - if not self.get_need_synchro_attendee(cr,uid,context=context): + if not self.get_need_synchro_attendee(cr, uid, context=context): data.pop("attendees") return data - def create_an_event(self, cr, uid,event, context=None): + def create_an_event(self, cr, uid, event, context=None): gs_pool = self.pool['google.service'] - data = self.generate_data(cr, uid,event, context=context) + data = self.generate_data(cr, uid, event, context=context) - url = "/calendar/v3/calendars/%s/events?fields=%s&access_token=%s" % ('primary',urllib.quote('id,updated'),self.get_token(cr,uid,context)) + url = "/calendar/v3/calendars/%s/events?fields=%s&access_token=%s" % ('primary', urllib.quote('id,updated'), self.get_token(cr, uid, context)) headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} data_json = simplejson.dumps(data) return gs_pool._do_request(cr, uid, url, data_json, headers, type='POST', context=context) - def delete_an_event(self, cr, uid,event_id, context=None): + def delete_an_event(self, cr, uid, event_id, context=None): gs_pool = self.pool['google.service'] params = { - 'access_token' : self.get_token(cr,uid,context) - } + 'access_token': self.get_token(cr, uid, context) + } headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} - url = "/calendar/v3/calendars/%s/events/%s" % ('primary',event_id) + url = "/calendar/v3/calendars/%s/events/%s" % ('primary', event_id) return gs_pool._do_request(cr, uid, url, params, headers, type='DELETE', context=context) - def get_event_dict(self,cr,uid,token=False,nextPageToken=False,context=None): + def get_event_dict(self, cr, uid, token=False, nextPageToken=False, context=None): if not token: - token = self.get_token(cr,uid,context) + token = self.get_token(cr, uid, context) gs_pool = self.pool['google.service'] params = { - 'fields': 'items,nextPageToken', - 'access_token' : token, - 'maxResults':1000, - 'timeMin': self.get_start_time_to_synchro(cr,uid,context=context).strftime("%Y-%m-%dT%H:%M:%S.%fz"), - + 'fields': 'items,nextPageToken', + 'access_token': token, + 'maxResults': 1000, + 'timeMin': self.get_start_time_to_synchro(cr, uid, context=context).strftime("%Y-%m-%dT%H:%M:%S.%fz"), } headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} @@ -301,50 +302,50 @@ class google_calendar(osv.AbstractModel): google_events_dict[google_event['id']] = google_event if content.get('nextPageToken', False): - google_events_dict.update(self.get_event_dict(cr,uid,token,content['nextPageToken'],context=context)) - return google_events_dict + google_events_dict.update(self.get_event_dict(cr, uid, token, content['nextPageToken'], context=context)) + return google_events_dict def update_to_google(self, cr, uid, oe_event, google_event, context): calendar_event = self.pool['calendar.event'] gs_pool = self.pool['google.service'] - url = "/calendar/v3/calendars/%s/events/%s?fields=%s&access_token=%s" % ('primary', google_event['id'],'id,updated', self.get_token(cr,uid,context)) + url = "/calendar/v3/calendars/%s/events/%s?fields=%s&access_token=%s" % ('primary', google_event['id'], 'id,updated', self.get_token(cr, uid, context)) headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} - data = self.generate_data(cr,uid ,oe_event, context) + data = self.generate_data(cr, uid, oe_event, context) data['sequence'] = google_event.get('sequence', 0) data_json = simplejson.dumps(data) content = gs_pool._do_request(cr, uid, url, data_json, headers, type='PATCH', context=context) - update_date = datetime.strptime(content['updated'],"%Y-%m-%dT%H:%M:%S.%fz") - calendar_event.write(cr, uid, [oe_event.id], {'oe_update_date':update_date}) + update_date = datetime.strptime(content['updated'], "%Y-%m-%dT%H:%M:%S.%fz") + calendar_event.write(cr, uid, [oe_event.id], {'oe_update_date': update_date}) if context['curr_attendee']: - self.pool['calendar.attendee'].write(cr,uid,[context['curr_attendee']], {'oe_synchro_date':update_date},context) + self.pool['calendar.attendee'].write(cr, uid, [context['curr_attendee']], {'oe_synchro_date': update_date}, context) - def update_an_event(self, cr, uid,event, context=None): + def update_an_event(self, cr, uid, event, context=None): gs_pool = self.pool['google.service'] - data = self.generate_data(cr, uid,event, context=context) + data = self.generate_data(cr, uid, event, context=context) url = "/calendar/v3/calendars/%s/events/%s" % ('primary', event.google_internal_event_id) headers = {} - data['access_token'] = self.get_token(cr,uid,context) + data['access_token'] = self.get_token(cr, uid, context) response = gs_pool._do_request(cr, uid, url, data, headers, type='GET', context=context) #TO_CHECK : , if http fail, no event, do DELETE ? return response - def update_recurrent_event_exclu(self, cr, uid,instance_id,event_ori_google_id,event_new, context=None): + def update_recurrent_event_exclu(self, cr, uid, instance_id, event_ori_google_id, event_new, context=None): gs_pool = self.pool['google.service'] - data = self.generate_data(cr, uid,event_new, context=context) + data = self.generate_data(cr, uid, event_new, context=context) data['recurringEventId'] = event_ori_google_id data['originalStartTime'] = event_new.recurrent_id_date - url = "/calendar/v3/calendars/%s/events/%s?access_token=%s" % ('primary', instance_id,self.get_token(cr,uid,context)) - headers = { 'Content-type': 'application/json'} + url = "/calendar/v3/calendars/%s/events/%s?access_token=%s" % ('primary', instance_id, self.get_token(cr, uid, context)) + headers = {'Content-type': 'application/json'} data['sequence'] = self.get_sequence(cr, uid, instance_id, context) @@ -353,41 +354,41 @@ class google_calendar(osv.AbstractModel): def update_from_google(self, cr, uid, event, single_event_dict, type, context): if context is None: - context= [] + context = [] calendar_event = self.pool['calendar.event'] res_partner_obj = self.pool['res.partner'] calendar_attendee_obj = self.pool['calendar.attendee'] user_obj = self.pool['res.users'] - myPartnerID = user_obj.browse(cr,uid,uid,context).partner_id.id + myPartnerID = user_obj.browse(cr, uid, uid, context).partner_id.id attendee_record = [] - partner_record = [(4,myPartnerID)] + partner_record = [(4, myPartnerID)] result = {} - if single_event_dict.get('attendees',False): + if single_event_dict.get('attendees', False): for google_attendee in single_event_dict['attendees']: if type == "write": for oe_attendee in event['attendee_ids']: if oe_attendee.email == google_attendee['email']: - calendar_attendee_obj.write(cr, uid,[oe_attendee.id] ,{'state' : google_attendee['responseStatus']},context=context) + calendar_attendee_obj.write(cr, uid, [oe_attendee.id], {'state': google_attendee['responseStatus']}, context=context) google_attendee['found'] = True continue - if google_attendee.get('found',False): + if google_attendee.get('found', False): continue - if self.get_need_synchro_attendee(cr,uid,context=context): - attendee_id = res_partner_obj.search(cr, uid,[('email', '=', google_attendee['email'])], context=context) - if not attendee_id: - attendee_id = [res_partner_obj.create(cr, uid,{'email': google_attendee['email'],'customer': False, 'name': google_attendee.get("displayName",False) or google_attendee['email'] }, context=context)] + if self.get_need_synchro_attendee(cr, uid, context=context): + attendee_id = res_partner_obj.search(cr, uid, [('email', '=', google_attendee['email'])], context=context) + if not attendee_id: + attendee_id = [res_partner_obj.create(cr, uid, {'email': google_attendee['email'], 'customer': False, 'name': google_attendee.get("displayName", False) or google_attendee['email']}, context=context)] attendee = res_partner_obj.read(cr, uid, attendee_id[0], ['email'], context=context) partner_record.append((4, attendee.get('id'))) attendee['partner_id'] = attendee.pop('id') attendee['state'] = google_attendee['responseStatus'] attendee_record.append((0, 0, attendee)) - + UTC = pytz.timezone('UTC') - if single_event_dict.get('start') and single_event_dict.get('end'): # If not cancelled - if single_event_dict['start'].get('dateTime',False) and single_event_dict['end'].get('dateTime',False): + if single_event_dict.get('start') and single_event_dict.get('end'): # If not cancelled + if single_event_dict['start'].get('dateTime', False) and single_event_dict['end'].get('dateTime', False): date = parser.parse(single_event_dict['start']['dateTime']) date_deadline = parser.parse(single_event_dict['end']['dateTime']) delta = date_deadline.astimezone(UTC) - date.astimezone(UTC) @@ -402,8 +403,8 @@ class google_calendar(osv.AbstractModel): delta = (d_end - d_start) allday = True - result['duration'] = (delta.seconds / 60) / 60.0 + delta.days *24 - update_date = datetime.strptime(single_event_dict['updated'],"%Y-%m-%dT%H:%M:%S.%fz") + result['duration'] = (delta.seconds / 60) / 60.0 + delta.days * 24 + update_date = datetime.strptime(single_event_dict['updated'], "%Y-%m-%dT%H:%M:%S.%fz") result.update({ 'date': date, 'date_deadline': date_deadline, @@ -413,17 +414,17 @@ class google_calendar(osv.AbstractModel): 'attendee_ids': attendee_record, 'partner_ids': list(set(partner_record)), - 'name': single_event_dict.get('summary','Event'), - 'description': single_event_dict.get('description',False), - 'location':single_event_dict.get('location',False), - 'class':single_event_dict.get('visibility','public'), - 'oe_update_date':update_date, + 'name': single_event_dict.get('summary', 'Event'), + 'description': single_event_dict.get('description', False), + 'location': single_event_dict.get('location', False), + 'class': single_event_dict.get('visibility', 'public'), + 'oe_update_date': update_date, # 'google_internal_event_id': single_event_dict.get('id',False), }) - if single_event_dict.get("recurrence",False): + if single_event_dict.get("recurrence", False): rrule = [rule for rule in single_event_dict["recurrence"] if rule.startswith("RRULE:")][0][6:] - result['rrule']=rrule + result['rrule'] = rrule if type == "write": res = calendar_event.write(cr, uid, event['id'], result, context=context) @@ -435,77 +436,71 @@ class google_calendar(osv.AbstractModel): res = calendar_event.create(cr, uid, result, context=context) if context['curr_attendee']: - self.pool['calendar.attendee'].write(cr,uid,[context['curr_attendee']], {'oe_synchro_date':update_date,'google_internal_event_id': single_event_dict.get('id',False)},context) + self.pool['calendar.attendee'].write(cr, uid, [context['curr_attendee']], {'oe_synchro_date': update_date, 'google_internal_event_id': single_event_dict.get('id', False)}, context) return res def synchronize_events(self, cr, uid, ids, context=None): - gc_obj = self.pool['google.calendar'] - # Create all new events from OpenERP into Gmail, if that is not recurrent event self.create_new_events(cr, uid, context=context) - self.bind_recurring_events_to_google(cr, uid, context) - - res = self.update_events(cr, uid, context) return { - "status" : res and "need_refresh" or "no_new_event_form_google", - "url" : '' - } + "status": res and "need_refresh" or "no_new_event_form_google", + "url": '' + } def create_new_events(self, cr, uid, context=None): - gc_pool = self.pool['google.calendar'] ev_obj = self.pool['calendar.event'] att_obj = self.pool['calendar.attendee'] user_obj = self.pool['res.users'] - myPartnerID = user_obj.browse(cr,uid,uid,context=context).partner_id.id + myPartnerID = user_obj.browse(cr, uid, uid, context=context).partner_id.id context_norecurrent = context.copy() context_norecurrent['virtual_id'] = False - my_att_ids = att_obj.search(cr, uid,[ ('partner_id', '=', myPartnerID), - ('google_internal_event_id', '=', False), - '|', - ('event_id.date_deadline','>',self.get_start_time_to_synchro(cr,uid,context).strftime("%Y-%m-%d %H:%M:%S")), - ('event_id.end_date','>',self.get_start_time_to_synchro(cr,uid,context).strftime("%Y-%m-%d %H:%M:%S")), - ], context=context_norecurrent) + my_att_ids = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID), + ('google_internal_event_id', '=', False), + '|', + ('event_id.date_deadline', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")), + ('event_id.end_date', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")), + ], context=context_norecurrent) - for att in att_obj.browse(cr,uid,my_att_ids,context=context): + for att in att_obj.browse(cr, uid, my_att_ids, context=context): if not att.event_id.recurrent_id or att.event_id.recurrent_id == 0: - response = self.create_an_event(cr,uid,att.event_id,context=context) - update_date = datetime.strptime(response['updated'],"%Y-%m-%dT%H:%M:%S.%fz") - ev_obj.write(cr, uid, att.event_id.id, {'oe_update_date':update_date}) - att_obj.write(cr, uid, [att.id], {'google_internal_event_id': response['id'], 'oe_synchro_date':update_date}) - cr.commit() + response = self.create_an_event(cr, uid, att.event_id, context=context) + update_date = datetime.strptime(response['updated'], "%Y-%m-%dT%H:%M:%S.%fz") + ev_obj.write(cr, uid, att.event_id.id, {'oe_update_date': update_date}) + att_obj.write(cr, uid, [att.id], {'google_internal_event_id': response['id'], 'oe_synchro_date': update_date}) + cr.commit() - def bind_recurring_events_to_google(self, cr, uid, context): + def bind_recurring_events_to_google(self, cr, uid, context): ev_obj = self.pool['calendar.event'] att_obj = self.pool['calendar.attendee'] user_obj = self.pool['res.users'] - myPartnerID = user_obj.browse(cr,uid,uid,context=context).partner_id.id + myPartnerID = user_obj.browse(cr, uid, uid, context=context).partner_id.id context_norecurrent = context.copy() context_norecurrent['virtual_id'] = False context_norecurrent['active_test'] = False - my_att_ids = att_obj.search(cr, uid,[('partner_id', '=', myPartnerID),('google_internal_event_id', '=', False)], context=context_norecurrent) - - for att in att_obj.browse(cr,uid,my_att_ids,context=context): + my_att_ids = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID), ('google_internal_event_id', '=', False)], context=context_norecurrent) + + for att in att_obj.browse(cr, uid, my_att_ids, context=context): if att.event_id.recurrent_id and att.event_id.recurrent_id > 0: new_google_internal_event_id = False source_event_record = ev_obj.browse(cr, uid, att.event_id.recurrent_id, context) - source_attendee_record_id = att_obj.search(cr, uid, [('partner_id','=', myPartnerID), ('event_id','=',source_event_record.id)], context=context) + source_attendee_record_id = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID), ('event_id', '=', source_event_record.id)], context=context) source_attendee_record = att_obj.browse(cr, uid, source_attendee_record_id, context)[0] - + if att.event_id.recurrent_id_date and source_event_record.allday and source_attendee_record.google_internal_event_id: - new_google_internal_event_id = source_attendee_record.google_internal_event_id +'_'+ att.event_id.recurrent_id_date.split(' ')[0].replace('-','') + new_google_internal_event_id = source_attendee_record.google_internal_event_id + '_' + att.event_id.recurrent_id_date.split(' ')[0].replace('-', '') elif att.event_id.recurrent_id_date and source_attendee_record.google_internal_event_id: - new_google_internal_event_id = source_attendee_record.google_internal_event_id +'_'+ att.event_id.recurrent_id_date.replace('-','').replace(' ','T').replace(':','') + 'Z' + new_google_internal_event_id = source_attendee_record.google_internal_event_id + '_' + att.event_id.recurrent_id_date.replace('-', '').replace(' ', 'T').replace(':', '') + 'Z' if new_google_internal_event_id: #TODO WARNING, NEED TO CHECK THAT EVENT and ALL instance NOT DELETE IN GMAIL BEFORE ! - res = self.update_recurrent_event_exclu(cr, uid,new_google_internal_event_id, source_attendee_record.google_internal_event_id,att.event_id, context=context) + self.update_recurrent_event_exclu(cr, uid, new_google_internal_event_id, source_attendee_record.google_internal_event_id, att.event_id, context=context) att_obj.write(cr, uid, [att.id], {'google_internal_event_id': new_google_internal_event_id}, context=context) cr.commit() @@ -523,16 +518,16 @@ class google_calendar(osv.AbstractModel): context_novirtual['active_test'] = False all_event_from_google = self.get_event_dict(cr, uid, context=context) - + # Select all events from OpenERP which have been already synchronized in gmail - my_att_ids = att_obj.search(cr, uid,[ ('partner_id', '=', myPartnerID), - ('google_internal_event_id', '!=', False), - '|', - ('event_id.date_deadline','>',self.get_start_time_to_synchro(cr,uid,context).strftime("%Y-%m-%d %H:%M:%S")), - ('event_id.end_date','>',self.get_start_time_to_synchro(cr,uid,context).strftime("%Y-%m-%d %H:%M:%S")), - ], context=context_novirtual) + my_att_ids = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID), + ('google_internal_event_id', '!=', False), + '|', + ('event_id.date_deadline', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")), + ('event_id.end_date', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")), + ], context=context_novirtual) event_to_synchronize = {} - for att in att_obj.browse(cr,uid,my_att_ids,context=context): + for att in att_obj.browse(cr, uid, my_att_ids, context=context): event = att.event_id base_event_id = att.google_internal_event_id.split('_')[0] @@ -544,7 +539,7 @@ class google_calendar(osv.AbstractModel): event_to_synchronize[base_event_id][att.google_internal_event_id] = SyncEvent() ev_to_sync = event_to_synchronize[base_event_id][att.google_internal_event_id] - + ev_to_sync.OE.attendee_id = att.id ev_to_sync.OE.event = event ev_to_sync.OE.found = True @@ -566,40 +561,35 @@ class google_calendar(osv.AbstractModel): event_to_synchronize[base_event_id][event_id] = SyncEvent() ev_to_sync = event_to_synchronize[base_event_id][event_id] - + ev_to_sync.GG.event = event ev_to_sync.GG.found = True - ev_to_sync.GG.isRecurrence = bool(event.get('recurrence','')) - ev_to_sync.GG.isInstance = bool(event.get('recurringEventId',0)) - ev_to_sync.GG.update = event.get('updated',None) # if deleted, no date without browse event + ev_to_sync.GG.isRecurrence = bool(event.get('recurrence', '')) + ev_to_sync.GG.isInstance = bool(event.get('recurringEventId', 0)) + ev_to_sync.GG.update = event.get('updated', None) # if deleted, no date without browse event if ev_to_sync.GG.update: - ev_to_sync.GG.update = ev_to_sync.GG.update.replace('T',' ').replace('Z','') + ev_to_sync.GG.update = ev_to_sync.GG.update.replace('T', ' ').replace('Z', '') ev_to_sync.GG.status = (event.get('status') != 'cancelled') - - ###################### + + ###################### # PRE-PROCESSING # ###################### for base_event in event_to_synchronize: for current_event in event_to_synchronize[base_event]: - event_to_synchronize[base_event][current_event].compute_OP() + event_to_synchronize[base_event][current_event].compute_OP() #print event_to_synchronize[base_event] - #print "========================================================" - + ###################### # DO ACTION # - ###################### + ###################### for base_event in event_to_synchronize: - event_to_synchronize[base_event] = sorted(event_to_synchronize[base_event].iteritems(),key=operator.itemgetter(0)) + event_to_synchronize[base_event] = sorted(event_to_synchronize[base_event].iteritems(), key=operator.itemgetter(0)) for current_event in event_to_synchronize[base_event]: cr.commit() - event = current_event[1] # event is an Sync Event ! - + event = current_event[1] # event is an Sync Event ! actToDo = event.OP actSrc = event.OP.src - # if not isinstance(actToDo, NothingToDo): - # print event - context['curr_attendee'] = event.OE.attendee_id if isinstance(actToDo, NothingToDo): @@ -607,135 +597,134 @@ class google_calendar(osv.AbstractModel): elif isinstance(actToDo, Create): context_tmp = context.copy() context_tmp['NewMeeting'] = True - if actSrc == 'GG': + if actSrc == 'GG': res = self.update_from_google(cr, uid, False, event.GG.event, "create", context=context_tmp) event.OE.event_id = res - meeting = calendar_event.browse(cr,uid,res,context=context) - attendee_record_id = att_obj.search(cr, uid, [('partner_id','=', myPartnerID), ('event_id','=',res)], context=context) - self.pool['calendar.attendee'].write(cr, uid, attendee_record_id, {'oe_synchro_date':meeting.oe_update_date, 'google_internal_event_id':event.GG.event['id']}, context=context_tmp) - elif actSrc == 'OE': + meeting = calendar_event.browse(cr, uid, res, context=context) + attendee_record_id = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID), ('event_id', '=', res)], context=context) + self.pool['calendar.attendee'].write(cr, uid, attendee_record_id, {'oe_synchro_date': meeting.oe_update_date, 'google_internal_event_id': event.GG.event['id']}, context=context_tmp) + elif actSrc == 'OE': raise "Should be never here, creation for OE is done before update !" #TODO Add to batch elif isinstance(actToDo, Update): - if actSrc == 'GG': + if actSrc == 'GG': self.update_from_google(cr, uid, event.OE.event, event.GG.event, 'write', context) - elif actSrc == 'OE': + elif actSrc == 'OE': self.update_to_google(cr, uid, event.OE.event, event.GG.event, context) elif isinstance(actToDo, Exclude): if actSrc == 'OE': - self.delete_an_event(cr,uid,current_event[0],context=context) - elif actSrc == 'GG': + self.delete_an_event(cr, uid, current_event[0], context=context) + elif actSrc == 'GG': new_google_event_id = event.GG.event['id'].split('_')[1] if 'T' in new_google_event_id: - new_google_event_id = new_google_event_id.replace('T','')[:-1] + new_google_event_id = new_google_event_id.replace('T', '')[:-1] else: new_google_event_id = new_google_event_id + "000000" if event.GG.status: parent_event = {} - parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id , new_google_event_id) + parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id, new_google_event_id) res = self.update_from_google(cr, uid, parent_event, event.GG.event, "copy", context) else: if event_to_synchronize[base_event][0][1].OE.event_id: - parent_oe_id = event_to_synchronize[base_event][0][1].OE.event_id - calendar_event.unlink(cr,uid,"%s-%s" % (parent_oe_id,new_google_event_id),unlink_level=1,context=context) + parent_oe_id = event_to_synchronize[base_event][0][1].OE.event_id + calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), unlink_level=1, context=context) elif isinstance(actToDo, Delete): if actSrc == 'GG': - self.delete_an_event(cr,uid,current_event[0],context=context) - elif actSrc == 'OE': - calendar_event.unlink(cr,uid,event.OE.event_id,unlink_level=0,context=context) + self.delete_an_event(cr, uid, current_event[0], context=context) + elif actSrc == 'OE': + calendar_event.unlink(cr, uid, event.OE.event_id, unlink_level=0, context=context) return True - def check_and_sync(self, cr, uid, oe_event, google_event, context): - if datetime.strptime(oe_event.oe_update_date,"%Y-%m-%d %H:%M:%S.%f") > datetime.strptime(google_event['updated'],"%Y-%m-%dT%H:%M:%S.%fz"): + if datetime.strptime(oe_event.oe_update_date, "%Y-%m-%d %H:%M:%S.%f") > datetime.strptime(google_event['updated'], "%Y-%m-%dT%H:%M:%S.%fz"): self.update_to_google(cr, uid, oe_event, google_event, context) - elif datetime.strptime(oe_event.oe_update_date,"%Y-%m-%d %H:%M:%S.%f") < datetime.strptime(google_event['updated'],"%Y-%m-%dT%H:%M:%S.%fz"): + elif datetime.strptime(oe_event.oe_update_date, "%Y-%m-%d %H:%M:%S.%f") < datetime.strptime(google_event['updated'], "%Y-%m-%dT%H:%M:%S.%fz"): self.update_from_google(cr, uid, oe_event, google_event, 'write', context) - def get_sequence(self,cr,uid,instance_id,context=None): + def get_sequence(self, cr, uid, instance_id, context=None): gs_pool = self.pool['google.service'] params = { - 'fields': 'sequence', - 'access_token' : self.get_token(cr,uid,context) - } + 'fields': 'sequence', + 'access_token': self.get_token(cr, uid, context) + } headers = {'Content-type': 'application/json'} - url = "/calendar/v3/calendars/%s/events/%s" % ('primary',instance_id) + url = "/calendar/v3/calendars/%s/events/%s" % ('primary', instance_id) content = gs_pool._do_request(cr, uid, url, params, headers, type='GET', context=context) - return content.get('sequence',0) -################################# + return content.get('sequence', 0) +################################# ## MANAGE CONNEXION TO GMAIL ## ################################# - def get_token(self,cr,uid,context=None): - current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) + def get_token(self, cr, uid, context=None): + current_user = self.pool['res.users'].browse(cr, uid, uid, context=context) if datetime.strptime(current_user.google_calendar_token_validity.split('.')[0], "%Y-%m-%d %H:%M:%S") < (datetime.now() + timedelta(minutes=1)): - self.do_refresh_token(cr,uid,context=context) + self.do_refresh_token(cr, uid, context=context) current_user.refresh() return current_user.google_calendar_token - def do_refresh_token(self,cr,uid,context=None): - current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) + def do_refresh_token(self, cr, uid, context=None): + current_user = self.pool['res.users'].browse(cr, uid, uid, context=context) gs_pool = self.pool['google.service'] - refresh = current_user.google_calendar_rtoken all_token = gs_pool._refresh_google_token_json(cr, uid, current_user.google_calendar_rtoken, self.STR_SERVICE, context=context) vals = {} vals['google_%s_token_validity' % self.STR_SERVICE] = datetime.now() + timedelta(seconds=all_token.get('expires_in')) vals['google_%s_token' % self.STR_SERVICE] = all_token.get('access_token') - self.pool['res.users'].write(cr,SUPERUSER_ID,uid,vals,context=context) + self.pool['res.users'].write(cr, SUPERUSER_ID, uid, vals, context=context) - def need_authorize(self,cr,uid,context=None): - current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) - return current_user.google_calendar_rtoken == False + def need_authorize(self, cr, uid, context=None): + current_user = self.pool['res.users'].browse(cr, uid, uid, context=context) + return current_user.google_calendar_rtoken is False - def get_calendar_scope(self,RO=False): + def get_calendar_scope(self, RO=False): readonly = RO and '.readonly' or '' return 'https://www.googleapis.com/auth/calendar%s' % (readonly) - def authorize_google_uri(self,cr,uid,from_url='http://www.openerp.com',context=None): - url = self.pool['google.service']._get_authorize_uri(cr,uid,from_url,self.STR_SERVICE,scope=self.get_calendar_scope(),context=context) + def authorize_google_uri(self, cr, uid, from_url='http://www.openerp.com', context=None): + url = self.pool['google.service']._get_authorize_uri(cr, uid, from_url, self.STR_SERVICE, scope=self.get_calendar_scope(), context=context) return url - def can_authorize_google(self,cr,uid,context=None): + def can_authorize_google(self, cr, uid, context=None): return self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager') - def set_all_tokens(self,cr,uid,authorization_code,context=None): + def set_all_tokens(self, cr, uid, authorization_code, context=None): gs_pool = self.pool['google.service'] - all_token = gs_pool._get_google_token_json(cr, uid, authorization_code,self.STR_SERVICE,context=context) + all_token = gs_pool._get_google_token_json(cr, uid, authorization_code, self.STR_SERVICE, context=context) vals = {} vals['google_%s_rtoken' % self.STR_SERVICE] = all_token.get('refresh_token') vals['google_%s_token_validity' % self.STR_SERVICE] = datetime.now() + timedelta(seconds=all_token.get('expires_in')) vals['google_%s_token' % self.STR_SERVICE] = all_token.get('access_token') - self.pool['res.users'].write(cr,SUPERUSER_ID,uid,vals,context=context) + self.pool['res.users'].write(cr, SUPERUSER_ID, uid, vals, context=context) - def get_start_time_to_synchro(self, cr, uid, context=None) : + def get_start_time_to_synchro(self, cr, uid, context=None): # WILL BE AN IR CONFIG PARAMETER - beginning from SAAS4 number_of_week = 13 - return datetime.now()-timedelta(weeks=number_of_week) + return datetime.now() - timedelta(weeks=number_of_week) def get_need_synchro_attendee(self, cr, uid, context=None): # WILL BE AN IR CONFIG PARAMETER - beginning from SAAS4 return True -class res_users(osv.Model): + +class res_users(osv.Model): _inherit = 'res.users' _columns = { 'google_calendar_rtoken': fields.char('Refresh Token'), - 'google_calendar_token': fields.char('User token'), + 'google_calendar_token': fields.char('User token'), 'google_calendar_token_validity': fields.datetime('Token Validity'), - } + } class calendar_event(osv.Model): @@ -743,7 +732,7 @@ class calendar_event(osv.Model): def write(self, cr, uid, ids, vals, context=None): if context is None: - context= {} + context = {} sync_fields = set(['name', 'description', 'date', 'date_closed', 'date_deadline', 'attendee_ids', 'location', 'class']) if (set(vals.keys()) & sync_fields) and 'oe_update_date' not in vals.keys() and 'NewMeeting' not in context: vals['oe_update_date'] = datetime.now() @@ -773,19 +762,17 @@ class calendar_attendee(osv.Model): 'google_internal_event_id': fields.char('Google Calendar Event Id', size=256), 'oe_synchro_date': fields.datetime('OpenERP Synchro Date'), } - - _sql_constraints = [('google_id_uniq','unique(google_internal_event_id,partner_id,event_id)', 'Google ID should be unique!')] + _sql_constraints = [('google_id_uniq', 'unique(google_internal_event_id,partner_id,event_id)', 'Google ID should be unique!')] def write(self, cr, uid, ids, vals, context=None): if context is None: context = {} for id in ids: - ref = vals.get('event_id',self.browse(cr,uid,id,context=context).event_id.id) + ref = vals.get('event_id', self.browse(cr, uid, id, context=context).event_id.id) # If attendees are updated, we need to specify that next synchro need an action # Except if it come from an update_from_google if not context.get('curr_attendee', False) and not context.get('NewMeeting', False): - self.pool['calendar.event'].write(cr, uid, ref, {'oe_update_date':datetime.now()},context) - - return super(calendar_attendee, self).write(cr, uid, ids, vals, context=context) \ No newline at end of file + self.pool['calendar.event'].write(cr, uid, ref, {'oe_update_date': datetime.now()}, context) + return super(calendar_attendee, self).write(cr, uid, ids, vals, context=context)