[TYPO] PEP7 - Module calendar (no E501)

bzr revid: jke@openerp.com-20140224220222-dp26lvbv2bfljxvt
This commit is contained in:
Kersten Jeremy 2014-02-24 23:02:22 +01:00
parent bfaa40266d
commit 2907c8dd66
5 changed files with 324 additions and 342 deletions

View File

@ -37,8 +37,6 @@ from openerp.tools.translate import _
from openerp.http import request from openerp.http import request
from operator import itemgetter from operator import itemgetter
from werkzeug.exceptions import BadRequest
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -63,6 +61,7 @@ def calendar_id2real_id(calendar_id=None, with_date=False):
return int(real_id) return int(real_id)
return calendar_id and int(calendar_id) or calendar_id return calendar_id and int(calendar_id) or calendar_id
def get_real_ids(ids): def get_real_ids(ids):
if isinstance(ids, (str, int, long)): if isinstance(ids, (str, int, long)):
return calendar_id2real_id(ids) return calendar_id2real_id(ids)
@ -76,6 +75,7 @@ class calendar_attendee(osv.Model):
Calendar Attendee Information Calendar Attendee Information
""" """
_name = 'calendar.attendee' _name = 'calendar.attendee'
_rec_name = 'cn'
_description = 'Attendee information' _description = 'Attendee information'
def _compute_data(self, cr, uid, ids, name, arg, context=None): def _compute_data(self, cr, uid, ids, name, arg, context=None):
@ -388,14 +388,12 @@ class calendar_alarm_manager(osv.AbstractModel):
SELECT SELECT
* *
FROM ( FROM (
""" %s
+ base_request
+ """
) AS ALL_EVENTS ) AS ALL_EVENTS
WHERE WHERE
ALL_EVENTS.first_alarm < (now() at time zone 'utc' + interval '%s' second ) 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 ) 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(): for event_id, first_alarm, last_alarm, first_meeting, last_meeting, min_duration, max_duration, rule in cr.fetchall():
res[event_id].update({ res[event_id].update({
@ -433,87 +431,86 @@ class calendar_alarm_manager(osv.AbstractModel):
res.append(alert) res.append(alert)
return res return res
def get_next_mail(self, cr, uid, context=None):
def get_next_mail(self,cr,uid,context=None): cron = self.pool.get('ir.cron').search(cr, uid, [('model', 'ilike', self._name)], context=context)
cron = self.pool.get('ir.cron').search(cr,uid,[('model','ilike',self._name)],context=context)
if cron and len(cron) == 1: 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: else:
raise ("Cron for " + self._name + " not identified :( !") 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 cron_interval = cron.interval_number * 7 * 24 * 60 * 60
elif cron.interval_type=="days": elif cron.interval_type == "days":
cron_interval = cron.interval_number * 24 * 60 * 60 cron_interval = cron.interval_number * 24 * 60 * 60
elif cron.interval_type=="hours": elif cron.interval_type == "hours":
cron_interval = cron.interval_number * 60 * 60 cron_interval = cron.interval_number * 60 * 60
elif cron.interval_type=="minutes": elif cron.interval_type == "minutes":
cron_interval = cron.interval_number * 60 cron_interval = cron.interval_number * 60
elif cron.interval_type=="seconds": elif cron.interval_type == "seconds":
cron_interval = cron.interval_number cron_interval = cron.interval_number
if not cron_interval: if not cron_interval:
raise ("Cron delay for " + self._name + " can not be calculated :( !") 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() for event in all_events: # .values()
max_delta = all_events[event]['max_duration']; max_delta = all_events[event]['max_duration']
curEvent = self.pool.get('calendar.event').browse(cr,uid,event,context=context) curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context)
if curEvent.recurrency: if curEvent.recurrency:
bFound = False bFound = False
LastFound = False LastFound = False
for one_date in self.pool.get('calendar.event').get_recurrent_date_by_event(cr,uid,curEvent, 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'); 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) LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
if LastFound: if LastFound:
for alert in 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 if not bFound: # if it's the first alarm for this recurrent event
bFound = True 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 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 break
else: else:
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S'); 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) LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
if LastFound: if LastFound:
for alert in 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 ajax_check_every_seconds = 300
partner = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id partner = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id
all_notif = [] all_notif = []
if not partner or not partner.id: # If user is disconnected if not partner:
return [] 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() for event in all_events: # .values()
max_delta = all_events[event]['max_duration']; max_delta = all_events[event]['max_duration']
curEvent = self.pool.get('calendar.event').browse(cr,uid,event,context=context) curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context)
if curEvent.recurrency: if curEvent.recurrency:
bFound = False bFound = False
LastFound = False LastFound = False
for one_date in self.pool.get("calendar.event").get_recurrent_date_by_event(cr,uid,curEvent, 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'); 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) 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: if LastFound:
for alert in LastFound: for alert in LastFound:
all_notif.append(self.do_notif_reminder(cr,uid,alert,context=context)) 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 if not bFound: # if it's the first alarm for this recurrent event
bFound = True 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 if bFound and not LastFound: # if the precedent event had alarm but not this one, we can stop the search fot this event
break break
else: else:
in_date_format = datetime.strptime(curEvent.date, '%Y-%m-%d %H:%M:%S'); 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) 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: if LastFound:
for alert in LastFound: for alert in LastFound:
all_notif.append(self.do_notif_reminder(cr,uid,alert,context=context)) all_notif.append(self.do_notif_reminder(cr, uid, alert, context=context))
return all_notif return all_notif
def do_mail_reminder(self, cr, uid, alert, context=None): def do_mail_reminder(self, cr, uid, alert, context=None):
if context is None: if context is None:
@ -781,7 +778,7 @@ class calendar_event(osv.Model):
else: else:
result[event] = "" result[event] = ""
return result return result
def _rrule_write(self, cr, uid, ids, field_name, field_value, args, context=None): def _rrule_write(self, cr, uid, ids, field_name, field_value, args, context=None):
if not isinstance(ids, list): if not isinstance(ids, list):
ids = [ids] ids = [ids]
@ -794,7 +791,7 @@ class calendar_event(osv.Model):
data.update(update_data) data.update(update_data)
self.write(cr, uid, ids, data, context=context) self.write(cr, uid, ids, data, context=context)
return True return True
def _tz_get(self, cr, uid, context=None): def _tz_get(self, cr, uid, context=None):
return [(x.lower(), x) for x in pytz.all_timezones] return [(x.lower(), x) for x in pytz.all_timezones]
@ -802,7 +799,7 @@ class calendar_event(osv.Model):
'location': { 'location': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, 'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
}, },
'date': { 'date': {
'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True, 'calendar.subtype_invitation': lambda self, cr, uid, obj, ctx=None: True,
}, },
} }
@ -983,7 +980,7 @@ class calendar_event(osv.Model):
} }
return res 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 = {} sort_fields = {}
for ord in order_fields: for ord in order_fields:
if ord == 'id' and r_date: 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 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: if type(browse_event[ord]) is openerp.osv.orm.browse_record:
name_get = browse_event[ord].name_get() 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] sort_fields[ord] = name_get[0][1]
return sort_fields return sort_fields
def get_recurrent_ids(self, cr, uid, event_id, domain, order=None, context=None): 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 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: if not context:
@ -1028,7 +1025,7 @@ class calendar_event(osv.Model):
for ev in self.browse(cr, uid, ids_to_browse, context=context): for ev in self.browse(cr, uid, ids_to_browse, context=context):
if not ev.recurrency or not ev.rrule: if not ev.recurrency or not ev.rrule:
result.append(ev.id) 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 continue
rdates = self.get_recurrent_date_by_event(cr, uid, ev, context=context) 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]: if [True for item in new_pile if not item]:
continue 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: if order_fields:
def comparer(left, right): def comparer(left, right):
@ -1085,7 +1082,7 @@ class calendar_event(osv.Model):
return 0 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(',')] 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)] ids = [r['id'] for r in sorted(result_data, cmp=comparer)]
if isinstance(event_id, (str, int, long)): if isinstance(event_id, (str, int, long)):
@ -1093,7 +1090,6 @@ class calendar_event(osv.Model):
else: else:
return ids return ids
def compute_rule_string(self, data): def compute_rule_string(self, data):
""" """
Compute rule string according to value type RECUR of iCalendar from the values given. 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' 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 '') +\ 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 freq = data.get('rrule_type', False) # day/week/month/year
res = '' res = ''
@ -1223,12 +1219,12 @@ class calendar_event(osv.Model):
res.update(self.check_partners_email(cr, uid, value[0][2], context=context)) res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
return res 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""" """ set the start date according to the first occurence of rrule"""
rrule_obj = self._get_empty_rrule_data() rrule_obj = self._get_empty_rrule_data()
rrule_obj.update({ rrule_obj.update({
'byday':True, 'byday': True,
'rrule_type':'weekly', 'rrule_type': 'weekly',
'mo': mo, 'mo': mo,
'tu': tu, 'tu': tu,
'we': we, 'we': we,
@ -1236,12 +1232,11 @@ class calendar_event(osv.Model):
'fr': fr, 'fr': fr,
'sa': sa, 'sa': sa,
'su': su, 'su': su,
'interval':1 'interval': 1
}) })
str_rrule = self.compute_rule_string(rrule_obj) 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] 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' } } return {'value': {'date': first_occurence.strftime("%Y-%m-%d") + ' 00:00:00'}}
def check_partners_email(self, cr, uid, partner_ids, context=None): def check_partners_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined. """ 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 :') warning_msg = _('The following contacts have no email address :')
for partner in partner_wo_email_lst: for partner in partner_wo_email_lst:
warning_msg += '\n- %s' % (partner.name) warning_msg += '\n- %s' % (partner.name)
return {'warning': return {'warning': {
{ 'title': _('Email addresses not found'),
'title': _('Email addresses not found'), 'message': warning_msg,
'message': warning_msg, }}
}
}
# ---------------------------------------- # ----------------------------------------
# OpenChatter # OpenChatter
@ -1369,8 +1362,7 @@ class calendar_event(osv.Model):
rrule_type=False, rrule_type=False,
rrule='', rrule='',
recurrency=False, recurrency=False,
end_date = datetime.strptime(values.get('date', False) or data.get('date'),"%Y-%m-%d %H:%M:%S") 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'))
+ timedelta(hours=values.get('duration', False) or data.get('duration'))
) )
#do not copy the id #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) new_id = self._detach_one_event(cr, uid, ids[0], context=context)
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'res_model': 'calendar.event', 'res_model': 'calendar.event',
'view_mode': 'form', 'view_mode': 'form',
'res_id': new_id, 'res_id': new_id,
'target': 'current', 'target': 'current',
'flags': {'form': {'action_buttons': True, 'options' : { 'mode' : 'edit' } } } 'flags': {'form': {'action_buttons': True, 'options': {'mode': 'edit'}}}
} }
def write(self, cr, uid, ids, values, context=None): def write(self, cr, uid, ids, values, context=None):
def _only_changes_to_apply_on_real_ids(field_names): 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: for field in field_names:
if field in ['date','active']: if field in ['date', 'active']:
return True return True
return False return False
context = context or {} context = context or {}
if isinstance(ids, (str,int, long)): if isinstance(ids, (str, int, long)):
if len(str(ids).split('-')) == 1: if len(str(ids).split('-')) == 1:
ids = [int(ids)] ids = [int(ids)]
else: else:
@ -1432,9 +1420,9 @@ class calendar_event(osv.Model):
continue continue
else: else:
data = self.read(cr, uid, event_id, ['date', 'date_deadline', 'rrule', 'duration']) 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) 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) res = super(calendar_event, self).write(cr, uid, ids, values, context=context)
# set end_date for calendar searching # set end_date for calendar searching
@ -1558,7 +1546,7 @@ class calendar_event(osv.Model):
ids_to_unlink = [] 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 # 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 unlink_level == 1 and len(str(event_id).split('-')) == 1: # if ID REAL
if self.browse(cr, uid, event_id).recurrent_id: if self.browse(cr, uid, event_id).recurrent_id:
ids_to_exclure.append(event_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): def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None):
if doc_model == 'calendar.event': 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): 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)]) 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) 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): def _auth_method_calendar(self):
token = request.params['token'] token = request.params['token']
db = request.params['db'] db = request.params['db']
registry = openerp.modules.registry.RegistryManager.get(db) registry = openerp.modules.registry.RegistryManager.get(db)
attendee_pool = registry.get('calendar.attendee') attendee_pool = registry.get('calendar.attendee')
error_message = False error_message = False
with registry.cursor() as cr: 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: if not attendee_id:
error_message = """Invalid Invitation Token.""" error_message = """Invalid Invitation Token."""
elif request.session.uid and request.session.login != 'anonymous': elif request.session.uid and request.session.login != 'anonymous':
# if valid session but user is not match # if valid session but user is not match
attendee = attendee_pool.browse(cr, openerp.SUPERUSER_ID, attendee_id[0]) attendee = attendee_pool.browse(cr, openerp.SUPERUSER_ID, attendee_id[0])
user = registry.get('res.users').browse(cr, openerp.SUPERUSER_ID, request.session.uid) user = registry.get('res.users').browse(cr, openerp.SUPERUSER_ID, request.session.uid)
if attendee.partner_id.id != user.partner_id.id: 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) 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: if error_message:
raise BadRequest(error_message) raise BadRequest(error_message)
return True return True
class invite_wizard(osv.osv_memory): class invite_wizard(osv.osv_memory):
_inherit = 'mail.wizard.invite' _inherit = 'mail.wizard.invite'

View File

@ -20,7 +20,7 @@
<record id="calendar_event_1" model="calendar.event"> <record id="calendar_event_1" model="calendar.event">
<field eval="1" name="active"/> <field eval="1" name="active"/>
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root"/>
<field name="partner_ids" eval="[(6,0,[ref('base.partner_root'),ref('base.res_partner_1'),ref('base.res_partner_6')])]"/> <field name="partner_ids" eval="[(6,0,[ref('base.res_partner_6')])]"/>
<field name="name">Follow-up for Project proposal</field> <field name="name">Follow-up for Project proposal</field>
<field name="description">Meeting to discuss project plan and hash out the details of implementation.</field> <field name="description">Meeting to discuss project plan and hash out the details of implementation.</field>
<field eval="time.strftime('%Y-%m-03 10:20:00')" name="date"/> <field eval="time.strftime('%Y-%m-03 10:20:00')" name="date"/>

View File

@ -1,10 +1,13 @@
openerp.calendar = function(instance) { openerp.calendar = function(instance) {
var _t = instance.web._t; var _t = instance.web._t;
var QWeb = instance.web.qweb; var QWeb = instance.web.qweb;
instance.calendar = {}; instance.calendar = {};
instance.web.WebClient = instance.web.WebClient.extend({ instance.web.WebClient = instance.web.WebClient.extend({
get_notif_box: function(me) { get_notif_box: function(me) {
return $(me).closest(".ui-notify-message-style"); return $(me).closest(".ui-notify-message-style");
}, },
@ -55,7 +58,7 @@ openerp.calendar = function(instance) {
check_notifications: function() { check_notifications: function() {
var self= this; var self= this;
self.get_next_notif(); self.get_next_notif();
setInterval(function(){ self.intervalNotif = setInterval(function(){
self.get_next_notif(); self.get_next_notif();
}, 5 * 60 * 1000 ); }, 5 * 60 * 1000 );
}, },
@ -63,7 +66,12 @@ openerp.calendar = function(instance) {
//Override the show_application of addons/web/static/src/js/chrome.js //Override the show_application of addons/web/static/src/js/chrome.js
show_application: function() { show_application: function() {
this._super(); this._super();
this.check_notifications(); this.check_notifications();
},
//Override addons/web/static/src/js/chrome.js
on_logout: function() {
this._super();
clearInterval(self.intervalNotif);
}, },
}); });

View File

@ -23,15 +23,13 @@ from openerp.osv import fields, osv
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
#
# calendar.event is defined in module calendar
#
class calendar_event(osv.Model): class calendar_event(osv.Model):
""" Model for Calendar Event """ """ Model for Calendar Event """
_inherit = 'calendar.event' _inherit = 'calendar.event'
_columns = { _columns = {
'phonecall_id': fields.many2one ('crm.phonecall', 'Phonecall'), 'phonecall_id': fields.many2one('crm.phonecall', 'Phonecall'),
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"), 'opportunity_id': fields.many2one('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
} }
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
@ -49,7 +47,7 @@ class calendar_attendee(osv.osv):
_description = 'Calendar Attendee' _description = 'Calendar Attendee'
def _noop(self, cr, uid, ids, name, arg, context=None): def _noop(self, cr, uid, ids, name, arg, context=None):
return dict.fromkeys(ids,False) return dict.fromkeys(ids, False)
_columns = { _columns = {
'categ_id': fields.function(_noop, string='Event Type', deprecated="Unused Field - TODO : Remove it in trunk", type="many2one", relation="crm.case.categ"), 'categ_id': fields.function(_noop, string='Event Type', deprecated="Unused Field - TODO : Remove it in trunk", type="many2one", relation="crm.case.categ"),

View File

@ -21,30 +21,22 @@
import operator import operator
import simplejson import simplejson
import re
import urllib import urllib
import warnings
from openerp import tools from openerp import tools
from openerp import SUPERUSER_ID from openerp import SUPERUSER_ID
from openerp.tools.translate import _
from openerp.addons.web.http import request from datetime import datetime, timedelta
import werkzeug.utils
from datetime import datetime, timedelta, date
from dateutil import parser from dateutil import parser
import pytz import pytz
from openerp.osv import fields, osv from openerp.osv import fields, osv
from openerp.osv import osv
from collections import namedtuple
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class Meta(type): 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 """ in __init__ to avoid to have side effect alike 'static' variable """
def __new__(typ, name, parents, attrs): def __new__(typ, name, parents, attrs):
methods = dict((k, v) for k, v in attrs.iteritems() methods = dict((k, v) for k, v in attrs.iteritems()
@ -63,9 +55,11 @@ class Meta(type):
methods['__getitem__'] = getattr methods['__getitem__'] = getattr
return type.__new__(typ, name, parents, methods) return type.__new__(typ, name, parents, methods)
class Struct(object): class Struct(object):
__metaclass__ = Meta __metaclass__ = Meta
class OpenerpEvent(Struct): class OpenerpEvent(Struct):
event = False event = False
found = False found = False
@ -77,6 +71,7 @@ class OpenerpEvent(Struct):
attendee_id = False attendee_id = False
synchro = False synchro = False
class GmailEvent(Struct): class GmailEvent(Struct):
event = False event = False
found = False found = False
@ -85,53 +80,51 @@ class GmailEvent(Struct):
update = False update = False
status = False status = False
class SyncEvent(object): class SyncEvent(object):
def __init__(self): def __init__(self):
self.OE = OpenerpEvent() self.OE = OpenerpEvent()
self.GG = GmailEvent() self.GG = GmailEvent()
self.OP = None self.OP = None
def __getitem__(self, key): def __getitem__(self, key):
return getattr(self,key) return getattr(self, key)
def compute_OP(self): 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 self.OE.found and self.GG.found:
#If the event has been deleted from one side, we delete on other side ! #If the event has been deleted from one side, we delete on other side !
if self.OE.status != self.GG.status: if self.OE.status != self.GG.status:
self.OP = Delete((self.OE.status and "OE") or (self.GG.status and "GG"), 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 !' ) 'The event has been deleted from one side, we delete on other side !')
#If event is not deleted ! #If event is not deleted !
elif self.OE.status and self.GG.status: elif self.OE.status and self.GG.status:
if self.OE.update.split('.')[0] != self.GG.update.split('.')[0]: if self.OE.update.split('.')[0] != self.GG.update.split('.')[0]:
if self.OE.update < self.GG.update: if self.OE.update < self.GG.update:
tmpSrc = 'GG' tmpSrc = 'GG'
elif self.OE.update > self.GG.update: elif self.OE.update > self.GG.update:
tmpSrc = 'OE' tmpSrc = 'OE'
assert tmpSrc in ['GG','OE'] assert tmpSrc in ['GG', 'OE']
#if self.OP.action == None: #if self.OP.action == None:
if self[tmpSrc].isRecurrence: if self[tmpSrc].isRecurrence:
if self[tmpSrc].status: 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: else:
self.OP = Exclude(tmpSrc, 'Need to Exclude (Me = First event from recurrence) from recurrence') self.OP = Exclude(tmpSrc, 'Need to Exclude (Me = First event from recurrence) from recurrence')
elif self[tmpSrc].isInstance: 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: else:
self.OP = Update(tmpSrc, 'Simply Update... I\'m a single event'); self.OP = Update(tmpSrc, 'Simply Update... I\'m a single event')
#end-if self.OP.action == None:
else: else:
if not self.OE.synchro or self.OE.synchro.split('.')[0] < self.OE.update.split('.')[0]: 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(); #import ipdb; ipdb.set_trace();
else: else:
self.OP = NothingToDo("",'Not update needed') self.OP = NothingToDo("", 'Not update needed')
else: 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 # New in openERP... Create on create_events of synchronize function
elif self.OE.found and not self.GG.found: elif self.OE.found and not self.GG.found:
@ -139,64 +132,73 @@ class SyncEvent(object):
if self.OE.status: if self.OE.status:
self.OP = Delete('OE', 'Removed from GOOGLE') self.OP = Delete('OE', 'Removed from GOOGLE')
else: 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: elif self.GG.found and not self.OE.found:
tmpSrc = 'GG' tmpSrc = 'GG'
if not self.GG.status and not self.GG.isInstance: 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 # 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') self.OP = NothingToDo("", 'Nothing to do... Create and Delete directly')
else: else:
if self.GG.isInstance: if self.GG.isInstance:
if self[tmpSrc].status: if self[tmpSrc].status:
self.OP = Exclude(tmpSrc, 'Need to create the new exclu') self.OP = Exclude(tmpSrc, 'Need to create the new exclu')
else: else:
self.OP = Exclude(tmpSrc, 'Need to copy and Exclude') self.OP = Exclude(tmpSrc, 'Need to copy and Exclude')
else: else:
self.OP = Create(tmpSrc, 'New EVENT CREATE from GMAIL') self.OP = Create(tmpSrc, 'New EVENT CREATE from GMAIL')
def __str__(self): def __str__(self):
return self.__repr__() return self.__repr__()
def __repr__(self): def __repr__(self):
myPrint = "---- A SYNC EVENT ---" myPrint = "---- A SYNC EVENT ---"
myPrint += "\n ID OE: %s " % (self.OE.event and self.OE.event.id) 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 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 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 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 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 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 Instance OE:%5s vs GG: %5s" % (self.OE.isInstance, self.GG.isInstance)
myPrint += "\n Synchro OE: %10s " % (self.OE.synchro) myPrint += "\n Synchro OE: %10s " % (self.OE.synchro)
myPrint += "\n Update OE: %10s " % (self.OE.update) myPrint += "\n Update OE: %10s " % (self.OE.update)
myPrint += "\n Update GG: %10s " % (self.GG.update) myPrint += "\n Update GG: %10s " % (self.GG.update)
myPrint += "\n Status OE:%5s vs GG: %5s" % (self.OE.status, self.GG.status) myPrint += "\n Status OE:%5s vs GG: %5s" % (self.OE.status, self.GG.status)
if (self.OP is None): if (self.OP is None):
myPrint += "\n Action %s" % "---!!!---NONE---!!!---" myPrint += "\n Action %s" % "---!!!---NONE---!!!---"
else: else:
myPrint += "\n Action %s" % type(self.OP).__name__ myPrint += "\n Action %s" % type(self.OP).__name__
myPrint += "\n Source %s" % (self.OP.src) myPrint += "\n Source %s" % (self.OP.src)
myPrint += "\n comment %s" % (self.OP.info) myPrint += "\n comment %s" % (self.OP.info)
return myPrint return myPrint
class SyncOperation(object): class SyncOperation(object):
def __init__(self, src,info, **kw): def __init__(self, src, info, **kw):
self.src = src self.src = src
self.info = info self.info = info
for k,v in kw.items(): for k, v in kw.items():
setattr(self,k,v) setattr(self, k, v)
def __str__(self): def __str__(self):
return 'in__STR__' return 'in__STR__'
class Create(SyncOperation): class Create(SyncOperation):
pass pass
class Update(SyncOperation): class Update(SyncOperation):
pass pass
class Delete(SyncOperation): class Delete(SyncOperation):
pass pass
class NothingToDo(SyncOperation): class NothingToDo(SyncOperation):
pass pass
class Exclude(SyncOperation): class Exclude(SyncOperation):
pass pass
@ -205,9 +207,9 @@ class google_calendar(osv.AbstractModel):
STR_SERVICE = 'calendar' STR_SERVICE = 'calendar'
_name = 'google.%s' % STR_SERVICE _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: 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] 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' type = 'date'
vstype = 'dateTime' vstype = 'dateTime'
@ -220,72 +222,71 @@ class google_calendar(osv.AbstractModel):
for attendee in event.attendee_ids: for attendee in event.attendee_ids:
attendee_list.append({ attendee_list.append({
'email':attendee.email or 'NoEmail@mail.com', 'email': attendee.email or 'NoEmail@mail.com',
'displayName':attendee.partner_id.name, 'displayName': attendee.partner_id.name,
'responseStatus':attendee.state or 'needsAction', 'responseStatus': attendee.state or 'needsAction',
}) })
data = { data = {
"summary": event.name or '', "summary": event.name or '',
"description": event.description or '', "description": event.description or '',
"start":{ "start": {
type:start_date, type: start_date,
vstype:None, vstype: None,
'timeZone':'UTC' 'timeZone': 'UTC'
}, },
"end":{ "end": {
type:end_date, type: end_date,
vstype:None, vstype: None,
'timeZone':'UTC' 'timeZone': 'UTC'
}, },
"attendees":attendee_list, "attendees": attendee_list,
"location":event.location or '', "location": event.location or '',
"visibility":event['class'] or 'public', "visibility": event['class'] or 'public',
} }
if event.recurrency and event.rrule: if event.recurrency and event.rrule:
data["recurrence"]=["RRULE:"+event.rrule] data["recurrence"] = ["RRULE:" + event.rrule]
if not event.active: if not event.active:
data["state"] = "cancelled" 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") data.pop("attendees")
return data 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'] 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'} headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
data_json = simplejson.dumps(data) data_json = simplejson.dumps(data)
return gs_pool._do_request(cr, uid, url, data_json, headers, type='POST', context=context) 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'] gs_pool = self.pool['google.service']
params = { 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'} 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) 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: if not token:
token = self.get_token(cr,uid,context) token = self.get_token(cr, uid, context)
gs_pool = self.pool['google.service'] gs_pool = self.pool['google.service']
params = { params = {
'fields': 'items,nextPageToken', 'fields': 'items,nextPageToken',
'access_token' : token, 'access_token': token,
'maxResults':1000, 'maxResults': 1000,
'timeMin': self.get_start_time_to_synchro(cr,uid,context=context).strftime("%Y-%m-%dT%H:%M:%S.%fz"), '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'} 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 google_events_dict[google_event['id']] = google_event
if content.get('nextPageToken', False): if content.get('nextPageToken', False):
google_events_dict.update(self.get_event_dict(cr,uid,token,content['nextPageToken'],context=context)) google_events_dict.update(self.get_event_dict(cr, uid, token, content['nextPageToken'], context=context))
return google_events_dict return google_events_dict
def update_to_google(self, cr, uid, oe_event, google_event, context): def update_to_google(self, cr, uid, oe_event, google_event, context):
calendar_event = self.pool['calendar.event'] calendar_event = self.pool['calendar.event']
gs_pool = self.pool['google.service'] 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'} 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['sequence'] = google_event.get('sequence', 0)
data_json = simplejson.dumps(data) data_json = simplejson.dumps(data)
content = gs_pool._do_request(cr, uid, url, data_json, headers, type='PATCH', context=context) 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") 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}) calendar_event.write(cr, uid, [oe_event.id], {'oe_update_date': update_date})
if context['curr_attendee']: 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'] 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) url = "/calendar/v3/calendars/%s/events/%s" % ('primary', event.google_internal_event_id)
headers = {} 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) response = gs_pool._do_request(cr, uid, url, data, headers, type='GET', context=context)
#TO_CHECK : , if http fail, no event, do DELETE ? #TO_CHECK : , if http fail, no event, do DELETE ?
return response 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'] 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['recurringEventId'] = event_ori_google_id
data['originalStartTime'] = event_new.recurrent_id_date 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)) url = "/calendar/v3/calendars/%s/events/%s?access_token=%s" % ('primary', instance_id, self.get_token(cr, uid, context))
headers = { 'Content-type': 'application/json'} headers = {'Content-type': 'application/json'}
data['sequence'] = self.get_sequence(cr, uid, instance_id, context) 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): def update_from_google(self, cr, uid, event, single_event_dict, type, context):
if context is None: if context is None:
context= [] context = []
calendar_event = self.pool['calendar.event'] calendar_event = self.pool['calendar.event']
res_partner_obj = self.pool['res.partner'] res_partner_obj = self.pool['res.partner']
calendar_attendee_obj = self.pool['calendar.attendee'] calendar_attendee_obj = self.pool['calendar.attendee']
user_obj = self.pool['res.users'] 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 = [] attendee_record = []
partner_record = [(4,myPartnerID)] partner_record = [(4, myPartnerID)]
result = {} result = {}
if single_event_dict.get('attendees',False): if single_event_dict.get('attendees', False):
for google_attendee in single_event_dict['attendees']: for google_attendee in single_event_dict['attendees']:
if type == "write": if type == "write":
for oe_attendee in event['attendee_ids']: for oe_attendee in event['attendee_ids']:
if oe_attendee.email == google_attendee['email']: 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 google_attendee['found'] = True
continue continue
if google_attendee.get('found',False): if google_attendee.get('found', False):
continue continue
if self.get_need_synchro_attendee(cr,uid,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) attendee_id = res_partner_obj.search(cr, uid, [('email', '=', google_attendee['email'])], context=context)
if not attendee_id: 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_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) attendee = res_partner_obj.read(cr, uid, attendee_id[0], ['email'], context=context)
partner_record.append((4, attendee.get('id'))) partner_record.append((4, attendee.get('id')))
attendee['partner_id'] = attendee.pop('id') attendee['partner_id'] = attendee.pop('id')
attendee['state'] = google_attendee['responseStatus'] attendee['state'] = google_attendee['responseStatus']
attendee_record.append((0, 0, attendee)) attendee_record.append((0, 0, attendee))
UTC = pytz.timezone('UTC') UTC = pytz.timezone('UTC')
if single_event_dict.get('start') and single_event_dict.get('end'): # If not cancelled 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['start'].get('dateTime', False) and single_event_dict['end'].get('dateTime', False):
date = parser.parse(single_event_dict['start']['dateTime']) date = parser.parse(single_event_dict['start']['dateTime'])
date_deadline = parser.parse(single_event_dict['end']['dateTime']) date_deadline = parser.parse(single_event_dict['end']['dateTime'])
delta = date_deadline.astimezone(UTC) - date.astimezone(UTC) delta = date_deadline.astimezone(UTC) - date.astimezone(UTC)
@ -402,8 +403,8 @@ class google_calendar(osv.AbstractModel):
delta = (d_end - d_start) delta = (d_end - d_start)
allday = True allday = True
result['duration'] = (delta.seconds / 60) / 60.0 + delta.days *24 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") update_date = datetime.strptime(single_event_dict['updated'], "%Y-%m-%dT%H:%M:%S.%fz")
result.update({ result.update({
'date': date, 'date': date,
'date_deadline': date_deadline, 'date_deadline': date_deadline,
@ -413,17 +414,17 @@ class google_calendar(osv.AbstractModel):
'attendee_ids': attendee_record, 'attendee_ids': attendee_record,
'partner_ids': list(set(partner_record)), 'partner_ids': list(set(partner_record)),
'name': single_event_dict.get('summary','Event'), 'name': single_event_dict.get('summary', 'Event'),
'description': single_event_dict.get('description',False), 'description': single_event_dict.get('description', False),
'location':single_event_dict.get('location',False), 'location': single_event_dict.get('location', False),
'class':single_event_dict.get('visibility','public'), 'class': single_event_dict.get('visibility', 'public'),
'oe_update_date':update_date, 'oe_update_date': update_date,
# 'google_internal_event_id': single_event_dict.get('id',False), # '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:] rrule = [rule for rule in single_event_dict["recurrence"] if rule.startswith("RRULE:")][0][6:]
result['rrule']=rrule result['rrule'] = rrule
if type == "write": if type == "write":
res = calendar_event.write(cr, uid, event['id'], result, context=context) 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) res = calendar_event.create(cr, uid, result, context=context)
if context['curr_attendee']: 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 return res
def synchronize_events(self, cr, uid, ids, context=None): 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 # Create all new events from OpenERP into Gmail, if that is not recurrent event
self.create_new_events(cr, uid, context=context) self.create_new_events(cr, uid, context=context)
self.bind_recurring_events_to_google(cr, uid, context) self.bind_recurring_events_to_google(cr, uid, context)
res = self.update_events(cr, uid, context) res = self.update_events(cr, uid, context)
return { return {
"status" : res and "need_refresh" or "no_new_event_form_google", "status": res and "need_refresh" or "no_new_event_form_google",
"url" : '' "url": ''
} }
def create_new_events(self, cr, uid, context=None): def create_new_events(self, cr, uid, context=None):
gc_pool = self.pool['google.calendar']
ev_obj = self.pool['calendar.event'] ev_obj = self.pool['calendar.event']
att_obj = self.pool['calendar.attendee'] att_obj = self.pool['calendar.attendee']
user_obj = self.pool['res.users'] 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 = context.copy()
context_norecurrent['virtual_id'] = False context_norecurrent['virtual_id'] = False
my_att_ids = att_obj.search(cr, uid,[ ('partner_id', '=', myPartnerID), my_att_ids = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID),
('google_internal_event_id', '=', False), ('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.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")), ('event_id.end_date', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")),
], context=context_norecurrent) ], 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: 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) 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") 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}) 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}) att_obj.write(cr, uid, [att.id], {'google_internal_event_id': response['id'], 'oe_synchro_date': update_date})
cr.commit() 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'] ev_obj = self.pool['calendar.event']
att_obj = self.pool['calendar.attendee'] att_obj = self.pool['calendar.attendee']
user_obj = self.pool['res.users'] 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 = context.copy()
context_norecurrent['virtual_id'] = False context_norecurrent['virtual_id'] = False
context_norecurrent['active_test'] = 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) 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): 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: if att.event_id.recurrent_id and att.event_id.recurrent_id > 0:
new_google_internal_event_id = False new_google_internal_event_id = False
source_event_record = ev_obj.browse(cr, uid, att.event_id.recurrent_id, context) 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] 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: 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: 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: if new_google_internal_event_id:
#TODO WARNING, NEED TO CHECK THAT EVENT and ALL instance NOT DELETE IN GMAIL BEFORE ! #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) att_obj.write(cr, uid, [att.id], {'google_internal_event_id': new_google_internal_event_id}, context=context)
cr.commit() cr.commit()
@ -523,16 +518,16 @@ class google_calendar(osv.AbstractModel):
context_novirtual['active_test'] = False context_novirtual['active_test'] = False
all_event_from_google = self.get_event_dict(cr, uid, context=context) all_event_from_google = self.get_event_dict(cr, uid, context=context)
# Select all events from OpenERP which have been already synchronized in gmail # Select all events from OpenERP which have been already synchronized in gmail
my_att_ids = att_obj.search(cr, uid,[ ('partner_id', '=', myPartnerID), my_att_ids = att_obj.search(cr, uid, [('partner_id', '=', myPartnerID),
('google_internal_event_id', '!=', False), ('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.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")), ('event_id.end_date', '>', self.get_start_time_to_synchro(cr, uid, context).strftime("%Y-%m-%d %H:%M:%S")),
], context=context_novirtual) ], context=context_novirtual)
event_to_synchronize = {} 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 event = att.event_id
base_event_id = att.google_internal_event_id.split('_')[0] 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() 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 = event_to_synchronize[base_event_id][att.google_internal_event_id]
ev_to_sync.OE.attendee_id = att.id ev_to_sync.OE.attendee_id = att.id
ev_to_sync.OE.event = event ev_to_sync.OE.event = event
ev_to_sync.OE.found = True ev_to_sync.OE.found = True
@ -566,40 +561,35 @@ class google_calendar(osv.AbstractModel):
event_to_synchronize[base_event_id][event_id] = SyncEvent() event_to_synchronize[base_event_id][event_id] = SyncEvent()
ev_to_sync = event_to_synchronize[base_event_id][event_id] ev_to_sync = event_to_synchronize[base_event_id][event_id]
ev_to_sync.GG.event = event ev_to_sync.GG.event = event
ev_to_sync.GG.found = True ev_to_sync.GG.found = True
ev_to_sync.GG.isRecurrence = bool(event.get('recurrence','')) ev_to_sync.GG.isRecurrence = bool(event.get('recurrence', ''))
ev_to_sync.GG.isInstance = bool(event.get('recurringEventId',0)) 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.update = event.get('updated', None) # if deleted, no date without browse event
if ev_to_sync.GG.update: 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') ev_to_sync.GG.status = (event.get('status') != 'cancelled')
###################### ######################
# PRE-PROCESSING # # PRE-PROCESSING #
###################### ######################
for base_event in event_to_synchronize: for base_event in event_to_synchronize:
for current_event in event_to_synchronize[base_event]: 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 event_to_synchronize[base_event]
#print "========================================================"
###################### ######################
# DO ACTION # # DO ACTION #
###################### ######################
for base_event in event_to_synchronize: 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]: for current_event in event_to_synchronize[base_event]:
cr.commit() cr.commit()
event = current_event[1] # event is an Sync Event ! event = current_event[1] # event is an Sync Event !
actToDo = event.OP actToDo = event.OP
actSrc = event.OP.src actSrc = event.OP.src
# if not isinstance(actToDo, NothingToDo):
# print event
context['curr_attendee'] = event.OE.attendee_id context['curr_attendee'] = event.OE.attendee_id
if isinstance(actToDo, NothingToDo): if isinstance(actToDo, NothingToDo):
@ -607,135 +597,134 @@ class google_calendar(osv.AbstractModel):
elif isinstance(actToDo, Create): elif isinstance(actToDo, Create):
context_tmp = context.copy() context_tmp = context.copy()
context_tmp['NewMeeting'] = True 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) res = self.update_from_google(cr, uid, False, event.GG.event, "create", context=context_tmp)
event.OE.event_id = res event.OE.event_id = res
meeting = calendar_event.browse(cr,uid,res,context=context) 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) 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) 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': elif actSrc == 'OE':
raise "Should be never here, creation for OE is done before update !" raise "Should be never here, creation for OE is done before update !"
#TODO Add to batch #TODO Add to batch
elif isinstance(actToDo, Update): elif isinstance(actToDo, Update):
if actSrc == 'GG': if actSrc == 'GG':
self.update_from_google(cr, uid, event.OE.event, event.GG.event, 'write', context) 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) self.update_to_google(cr, uid, event.OE.event, event.GG.event, context)
elif isinstance(actToDo, Exclude): elif isinstance(actToDo, Exclude):
if actSrc == 'OE': if actSrc == 'OE':
self.delete_an_event(cr,uid,current_event[0],context=context) self.delete_an_event(cr, uid, current_event[0], context=context)
elif actSrc == 'GG': elif actSrc == 'GG':
new_google_event_id = event.GG.event['id'].split('_')[1] new_google_event_id = event.GG.event['id'].split('_')[1]
if 'T' in new_google_event_id: 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: else:
new_google_event_id = new_google_event_id + "000000" new_google_event_id = new_google_event_id + "000000"
if event.GG.status: if event.GG.status:
parent_event = {} 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) res = self.update_from_google(cr, uid, parent_event, event.GG.event, "copy", context)
else: else:
if event_to_synchronize[base_event][0][1].OE.event_id: if event_to_synchronize[base_event][0][1].OE.event_id:
parent_oe_id = 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) calendar_event.unlink(cr, uid, "%s-%s" % (parent_oe_id, new_google_event_id), unlink_level=1, context=context)
elif isinstance(actToDo, Delete): elif isinstance(actToDo, Delete):
if actSrc == 'GG': if actSrc == 'GG':
self.delete_an_event(cr,uid,current_event[0],context=context) self.delete_an_event(cr, uid, current_event[0], context=context)
elif actSrc == 'OE': elif actSrc == 'OE':
calendar_event.unlink(cr,uid,event.OE.event_id,unlink_level=0,context=context) calendar_event.unlink(cr, uid, event.OE.event_id, unlink_level=0, context=context)
return True return True
def check_and_sync(self, cr, uid, oe_event, google_event, context): 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) 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) 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'] gs_pool = self.pool['google.service']
params = { params = {
'fields': 'sequence', 'fields': 'sequence',
'access_token' : self.get_token(cr,uid,context) 'access_token': self.get_token(cr, uid, context)
} }
headers = {'Content-type': 'application/json'} 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) 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 ## ## MANAGE CONNEXION TO GMAIL ##
################################# #################################
def get_token(self,cr,uid,context=None): def get_token(self, cr, uid, context=None):
current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) 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)): 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() current_user.refresh()
return current_user.google_calendar_token return current_user.google_calendar_token
def do_refresh_token(self,cr,uid,context=None): def do_refresh_token(self, cr, uid, context=None):
current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) current_user = self.pool['res.users'].browse(cr, uid, uid, context=context)
gs_pool = self.pool['google.service'] 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) all_token = gs_pool._refresh_google_token_json(cr, uid, current_user.google_calendar_rtoken, self.STR_SERVICE, context=context)
vals = {} vals = {}
vals['google_%s_token_validity' % self.STR_SERVICE] = datetime.now() + timedelta(seconds=all_token.get('expires_in')) 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') 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): def need_authorize(self, cr, uid, context=None):
current_user = self.pool['res.users'].browse(cr,uid,uid,context=context) current_user = self.pool['res.users'].browse(cr, uid, uid, context=context)
return current_user.google_calendar_rtoken == False 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 '' readonly = RO and '.readonly' or ''
return 'https://www.googleapis.com/auth/calendar%s' % (readonly) return 'https://www.googleapis.com/auth/calendar%s' % (readonly)
def authorize_google_uri(self,cr,uid,from_url='http://www.openerp.com',context=None): 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) url = self.pool['google.service']._get_authorize_uri(cr, uid, from_url, self.STR_SERVICE, scope=self.get_calendar_scope(), context=context)
return url 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') 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'] 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 = {}
vals['google_%s_rtoken' % self.STR_SERVICE] = all_token.get('refresh_token') 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_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') 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 # WILL BE AN IR CONFIG PARAMETER - beginning from SAAS4
number_of_week = 13 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): def get_need_synchro_attendee(self, cr, uid, context=None):
# WILL BE AN IR CONFIG PARAMETER - beginning from SAAS4 # WILL BE AN IR CONFIG PARAMETER - beginning from SAAS4
return True return True
class res_users(osv.Model):
class res_users(osv.Model):
_inherit = 'res.users' _inherit = 'res.users'
_columns = { _columns = {
'google_calendar_rtoken': fields.char('Refresh Token'), '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'), 'google_calendar_token_validity': fields.datetime('Token Validity'),
} }
class calendar_event(osv.Model): class calendar_event(osv.Model):
@ -743,7 +732,7 @@ class calendar_event(osv.Model):
def write(self, cr, uid, ids, vals, context=None): def write(self, cr, uid, ids, vals, context=None):
if context is None: if context is None:
context= {} context = {}
sync_fields = set(['name', 'description', 'date', 'date_closed', 'date_deadline', 'attendee_ids', 'location', 'class']) 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: 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() 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), 'google_internal_event_id': fields.char('Google Calendar Event Id', size=256),
'oe_synchro_date': fields.datetime('OpenERP Synchro Date'), '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): def write(self, cr, uid, ids, vals, context=None):
if context is None: if context is None:
context = {} context = {}
for id in ids: 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 # If attendees are updated, we need to specify that next synchro need an action
# Except if it come from an update_from_google # Except if it come from an update_from_google
if not context.get('curr_attendee', False) and not context.get('NewMeeting', False): 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) 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)
return super(calendar_attendee, self).write(cr, uid, ids, vals, context=context)