2014-05-14 08:28:10 +00:00
# -*- coding: utf-8 -*-
2013-12-02 14:31:33 +00:00
2013-12-10 16:45:25 +00:00
import operator
2013-12-02 14:31:33 +00:00
import simplejson
2014-05-14 08:28:10 +00:00
import urllib2
2013-12-02 14:31:33 +00:00
2014-05-14 08:28:10 +00:00
import openerp
2013-12-02 14:31:33 +00:00
from openerp import tools
2013-12-18 17:49:31 +00:00
from openerp import SUPERUSER_ID
2014-10-03 15:52:31 +00:00
from openerp . tools import DEFAULT_SERVER_DATE_FORMAT , DEFAULT_SERVER_DATETIME_FORMAT , exception_to_unicode
2014-05-14 08:28:10 +00:00
from openerp . tools . translate import _
from openerp . http import request
2014-02-24 22:02:22 +00:00
from datetime import datetime , timedelta
2013-12-09 14:08:19 +00:00
from dateutil import parser
import pytz
2013-12-02 14:31:33 +00:00
from openerp . osv import fields , osv
2014-02-18 17:15:08 +00:00
import logging
_logger = logging . getLogger ( __name__ )
2014-05-14 08:28:10 +00:00
def status_response ( status , substr = False ) :
if substr :
return int ( str ( status ) [ 0 ] )
else :
return status_response ( status , substr = True ) == 2
2014-02-18 17:15:08 +00:00
class Meta ( type ) :
2014-02-24 22:02:22 +00:00
""" This Meta class allow to define class as a structure, and so instancied variable
2014-02-18 17:15:08 +00:00
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 ( )
if callable ( v ) )
attrs = dict ( ( k , v ) for k , v in attrs . iteritems ( )
if not callable ( v ) )
def init ( self , * * kw ) :
for k , v in attrs . iteritems ( ) :
setattr ( self , k , v )
for k , v in kw . iteritems ( ) :
assert k in attrs
setattr ( self , k , v )
methods [ ' __init__ ' ] = init
methods [ ' __getitem__ ' ] = getattr
return type . __new__ ( typ , name , parents , methods )
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class Struct ( object ) :
__metaclass__ = Meta
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class OpenerpEvent ( Struct ) :
event = False
found = False
event_id = False
isRecurrence = False
isInstance = False
update = False
status = False
attendee_id = False
synchro = False
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class GmailEvent ( Struct ) :
event = False
found = False
isRecurrence = False
isInstance = False
update = False
status = False
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class SyncEvent ( object ) :
def __init__ ( self ) :
self . OE = OpenerpEvent ( )
2014-02-24 22:02:22 +00:00
self . GG = GmailEvent ( )
2014-02-18 17:15:08 +00:00
self . OP = None
2014-02-24 22:02:22 +00:00
def __getitem__ ( self , key ) :
return getattr ( self , key )
2014-02-18 17:15:08 +00:00
2014-05-14 08:28:10 +00:00
def compute_OP ( self , modeFull = True ) :
2014-02-24 22:02:22 +00:00
#If event are already in Gmail and in OpenERP
2014-02-18 17:15:08 +00:00
if self . OE . found and self . GG . found :
2015-06-11 11:55:10 +00:00
is_owner = self . OE . event . env . user . id == self . OE . event . user_id . id
2014-02-18 17:15:08 +00:00
#If the event has been deleted from one side, we delete on other side !
2015-06-02 13:04:00 +00:00
if self . OE . status != self . GG . status and is_owner :
2014-02-18 17:15:08 +00:00
self . OP = Delete ( ( self . OE . status and " OE " ) or ( self . GG . status and " GG " ) ,
2014-02-24 22:02:22 +00:00
' The event has been deleted from one side, we delete on other side ! ' )
#If event is not deleted !
2015-06-02 13:04:00 +00:00
elif self . OE . status and ( self . GG . status or not is_owner ) :
2014-02-18 17:15:08 +00:00
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 '
2014-02-24 22:02:22 +00:00
assert tmpSrc in [ ' GG ' , ' OE ' ]
2014-02-18 17:15:08 +00:00
#if self.OP.action == None:
if self [ tmpSrc ] . isRecurrence :
if self [ tmpSrc ] . status :
2014-02-24 22:02:22 +00:00
self . OP = Update ( tmpSrc , ' Only need to update, because i \' m active ' )
2014-02-18 17:15:08 +00:00
else :
self . OP = Exclude ( tmpSrc , ' Need to Exclude (Me = First event from recurrence) from recurrence ' )
elif self [ tmpSrc ] . isInstance :
2014-02-24 22:02:22 +00:00
self . OP = Update ( tmpSrc , ' Only need to update, because already an exclu ' )
2014-02-18 17:15:08 +00:00
else :
2014-02-24 22:02:22 +00:00
self . OP = Update ( tmpSrc , ' Simply Update... I \' m a single event ' )
2014-02-18 17:15:08 +00:00
else :
if not self . OE . synchro or self . OE . synchro . split ( ' . ' ) [ 0 ] < self . OE . update . split ( ' . ' ) [ 0 ] :
2014-02-24 22:02:22 +00:00
self . OP = Update ( ' OE ' , ' Event already updated by another user, but not synchro with my google calendar ' )
2014-02-18 17:15:08 +00:00
else :
2014-02-24 22:02:22 +00:00
self . OP = NothingToDo ( " " , ' Not update needed ' )
2014-02-18 17:15:08 +00:00
else :
2014-02-24 22:02:22 +00:00
self . OP = NothingToDo ( " " , " Both are already deleted " )
2014-02-18 17:15:08 +00:00
# New in openERP... Create on create_events of synchronize function
elif self . OE . found and not self . GG . found :
if self . OE . status :
2014-05-14 08:28:10 +00:00
self . OP = Delete ( ' OE ' , ' Update or delete from GOOGLE ' )
2014-02-18 17:15:08 +00:00
else :
2014-05-14 08:28:10 +00:00
if not modeFull :
2014-07-09 11:39:38 +00:00
self . OP = Delete ( ' GG ' , ' Deleted from Odoo, need to delete it from Gmail if already created ' )
2014-05-14 08:28:10 +00:00
else :
2014-07-09 11:39:38 +00:00
self . OP = NothingToDo ( " " , " Already Deleted in gmail and unlinked in Odoo " )
2014-02-18 17:15:08 +00:00
elif self . GG . found and not self . OE . found :
tmpSrc = ' GG '
if not self . GG . status and not self . GG . isInstance :
2014-02-24 22:02:22 +00:00
# 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 ' )
2014-02-18 17:15:08 +00:00
else :
2014-02-24 22:02:22 +00:00
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 ' )
2014-02-18 17:15:08 +00:00
def __str__ ( self ) :
return self . __repr__ ( )
def __repr__ ( self ) :
2014-05-14 08:28:10 +00:00
myPrint = " \n \n ---- A SYNC EVENT --- "
2014-02-24 22:02:22 +00:00
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 ) )
2014-05-14 08:28:10 +00:00
myPrint + = " \n Name OE: %s " % ( self . OE . event and self . OE . event . name . encode ( ' utf8 ' ) )
myPrint + = " \n Name GG: %s " % ( self . GG . event and self . GG . event . get ( ' summary ' , ' ' ) . encode ( ' utf8 ' ) )
2014-02-24 22:02:22 +00:00
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 )
2014-02-18 17:15:08 +00:00
if ( self . OP is None ) :
2014-02-24 22:02:22 +00:00
myPrint + = " \n Action %s " % " ---!!!---NONE---!!!--- "
2014-02-18 17:15:08 +00:00
else :
2014-02-24 22:02:22 +00:00
myPrint + = " \n Action %s " % type ( self . OP ) . __name__
myPrint + = " \n Source %s " % ( self . OP . src )
myPrint + = " \n comment %s " % ( self . OP . info )
2014-02-18 17:15:08 +00:00
return myPrint
class SyncOperation ( object ) :
2014-02-24 22:02:22 +00:00
def __init__ ( self , src , info , * * kw ) :
2014-02-18 17:15:08 +00:00
self . src = src
self . info = info
2014-02-24 22:02:22 +00:00
for k , v in kw . items ( ) :
setattr ( self , k , v )
2014-02-18 17:15:08 +00:00
def __str__ ( self ) :
return ' in__STR__ '
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class Create ( SyncOperation ) :
pass
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class Update ( SyncOperation ) :
pass
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class Delete ( SyncOperation ) :
pass
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class NothingToDo ( SyncOperation ) :
pass
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
class Exclude ( SyncOperation ) :
pass
2013-12-02 14:31:33 +00:00
2014-01-13 17:41:57 +00:00
class google_calendar ( osv . AbstractModel ) :
2013-12-02 14:31:33 +00:00
STR_SERVICE = ' calendar '
2013-12-13 10:35:17 +00:00
_name = ' google. %s ' % STR_SERVICE
2014-05-14 08:28:10 +00:00
def generate_data ( self , cr , uid , event , isCreating = False , context = None ) :
2015-06-26 09:14:59 +00:00
if not context :
context = { }
2013-12-02 14:31:33 +00:00
if event . allday :
2014-05-14 08:28:10 +00:00
start_date = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( event . start , tools . DEFAULT_SERVER_DATETIME_FORMAT ) , context = context ) . isoformat ( ' T ' ) . split ( ' T ' ) [ 0 ]
final_date = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( event . start , tools . DEFAULT_SERVER_DATETIME_FORMAT ) + timedelta ( hours = event . duration ) + timedelta ( days = isCreating and 1 or 0 ) , context = context ) . isoformat ( ' T ' ) . split ( ' T ' ) [ 0 ]
2013-12-02 14:31:33 +00:00
type = ' date '
2014-02-18 17:15:08 +00:00
vstype = ' dateTime '
2013-12-02 14:31:33 +00:00
else :
2014-05-14 08:28:10 +00:00
start_date = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( event . start , tools . DEFAULT_SERVER_DATETIME_FORMAT ) , context = context ) . isoformat ( ' T ' )
final_date = fields . datetime . context_timestamp ( cr , uid , datetime . strptime ( event . stop , tools . DEFAULT_SERVER_DATETIME_FORMAT ) , context = context ) . isoformat ( ' T ' )
2013-12-02 14:31:33 +00:00
type = ' dateTime '
2014-02-18 17:15:08 +00:00
vstype = ' date '
2013-12-02 14:31:33 +00:00
attendee_list = [ ]
for attendee in event . attendee_ids :
2015-08-04 16:51:22 +00:00
email = tools . email_split ( attendee . email )
email = email [ 0 ] if email else ' NoEmail@mail.com '
2013-12-02 14:31:33 +00:00
attendee_list . append ( {
2015-08-04 16:51:22 +00:00
' email ' : email ,
2014-02-24 22:02:22 +00:00
' displayName ' : attendee . partner_id . name ,
' responseStatus ' : attendee . state or ' needsAction ' ,
2013-12-02 14:31:33 +00:00
} )
2015-02-12 21:16:41 +00:00
reminders = [ ]
for alarm in event . alarm_ids :
reminders . append ( {
" method " : " email " if alarm . type == " email " else " popup " ,
" minutes " : alarm . duration_minutes
} )
2013-12-02 14:31:33 +00:00
data = {
" summary " : event . name or ' ' ,
" description " : event . description or ' ' ,
2014-02-24 22:02:22 +00:00
" start " : {
type : start_date ,
vstype : None ,
2015-06-26 09:14:59 +00:00
' timeZone ' : context . get ( ' tz ' , ' UTC ' ) ,
2014-02-24 22:02:22 +00:00
} ,
" end " : {
2014-05-14 08:28:10 +00:00
type : final_date ,
2014-02-24 22:02:22 +00:00
vstype : None ,
2015-06-26 09:14:59 +00:00
' timeZone ' : context . get ( ' tz ' , ' UTC ' ) ,
2014-02-24 22:02:22 +00:00
} ,
" attendees " : attendee_list ,
2015-02-13 15:09:18 +00:00
" reminders " : {
" overrides " : reminders ,
" useDefault " : " false "
} ,
2014-02-24 22:02:22 +00:00
" location " : event . location or ' ' ,
" visibility " : event [ ' class ' ] or ' public ' ,
2013-12-02 14:31:33 +00:00
}
if event . recurrency and event . rrule :
2014-02-24 22:02:22 +00:00
data [ " recurrence " ] = [ " RRULE: " + event . rrule ]
2013-12-09 14:08:19 +00:00
if not event . active :
data [ " state " ] = " cancelled "
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
if not self . get_need_synchro_attendee ( cr , uid , context = context ) :
2014-02-18 17:15:08 +00:00
data . pop ( " attendees " )
2013-12-02 14:31:33 +00:00
return data
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def create_an_event ( self , cr , uid , event , context = None ) :
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-05-14 08:28:10 +00:00
data = self . generate_data ( cr , uid , event , isCreating = True , context = context )
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
url = " /calendar/v3/calendars/ %s /events?fields= %s &access_token= %s " % ( ' primary ' , urllib2 . quote ( ' id,updated ' ) , self . get_token ( cr , uid , context ) )
2013-12-02 14:31:33 +00:00
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
data_json = simplejson . dumps ( data )
2014-01-14 13:37:36 +00:00
2013-12-11 13:06:35 +00:00
return gs_pool . _do_request ( cr , uid , url , data_json , headers , type = ' POST ' , context = context )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def delete_an_event ( self , cr , uid , event_id , context = None ) :
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
params = {
2014-02-24 22:02:22 +00:00
' access_token ' : self . get_token ( cr , uid , context )
}
2013-12-09 14:08:19 +00:00
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
2014-02-24 22:02:22 +00:00
url = " /calendar/v3/calendars/ %s /events/ %s " % ( ' primary ' , event_id )
2013-12-13 10:35:17 +00:00
return gs_pool . _do_request ( cr , uid , url , params , headers , type = ' DELETE ' , context = context )
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
def get_calendar_primary_id ( self , cr , uid , context = None ) :
params = {
' fields ' : ' id ' ,
' access_token ' : self . get_token ( cr , uid , context )
}
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
url = " /calendar/v3/calendars/primary "
try :
2014-08-05 08:59:02 +00:00
st , content , ask_time = self . pool [ ' google.service ' ] . _do_request ( cr , uid , url , params , headers , type = ' GET ' , context = context )
2014-05-14 08:28:10 +00:00
except Exception , e :
if ( e . code == 401 ) : # Token invalid / Acces unauthorized
error_msg = " Your token is invalid or has been revoked ! "
registry = openerp . modules . registry . RegistryManager . get ( request . session . db )
with registry . cursor ( ) as cur :
2015-02-16 13:54:52 +00:00
self . pool [ ' res.users ' ] . write ( cur , SUPERUSER_ID , [ uid ] , { ' google_calendar_token ' : False , ' google_calendar_token_validity ' : False } , context = context )
2014-05-14 08:28:10 +00:00
raise self . pool . get ( ' res.config.settings ' ) . get_config_warning ( cr , _ ( error_msg ) , context = context )
raise
2014-08-05 08:59:02 +00:00
return ( status_response ( st ) , content [ ' id ' ] or False , ask_time )
2014-05-14 08:28:10 +00:00
def get_event_synchro_dict ( self , cr , uid , lastSync = False , token = False , nextPageToken = False , context = None ) :
2013-12-09 14:08:19 +00:00
if not token :
2014-02-24 22:02:22 +00:00
token = self . get_token ( cr , uid , context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
params = {
2014-02-24 22:02:22 +00:00
' fields ' : ' items,nextPageToken ' ,
' access_token ' : token ,
' maxResults ' : 1000 ,
2014-05-14 08:28:10 +00:00
#'timeMin': self.get_minTime(cr, uid, context=context).strftime("%Y-%m-%dT%H:%M:%S.%fz"),
2013-12-20 14:18:55 +00:00
}
2014-05-14 08:28:10 +00:00
if lastSync :
params [ ' updatedMin ' ] = lastSync . strftime ( " % Y- % m- %d T % H: % M: % S. %f z " )
params [ ' showDeleted ' ] = True
else :
params [ ' timeMin ' ] = self . get_minTime ( cr , uid , context = context ) . strftime ( " % Y- % m- %d T % H: % M: % S. %f z " )
2013-12-09 14:08:19 +00:00
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
2014-01-14 13:37:36 +00:00
url = " /calendar/v3/calendars/ %s /events " % ' primary '
2013-12-09 14:08:19 +00:00
if nextPageToken :
params [ ' pageToken ' ] = nextPageToken
2014-01-14 13:37:36 +00:00
2014-08-05 08:59:02 +00:00
status , content , ask_time = self . pool [ ' google.service ' ] . _do_request ( cr , uid , url , params , headers , type = ' GET ' , context = context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
google_events_dict = { }
for google_event in content [ ' items ' ] :
google_events_dict [ google_event [ ' id ' ] ] = google_event
2013-12-13 10:35:17 +00:00
2014-05-14 08:28:10 +00:00
if content . get ( ' nextPageToken ' ) :
google_events_dict . update (
self . get_event_synchro_dict ( cr , uid , lastSync = lastSync , token = token , nextPageToken = content [ ' nextPageToken ' ] , context = context )
)
2014-02-24 22:02:22 +00:00
return google_events_dict
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
def get_one_event_synchro ( self , cr , uid , google_id , context = None ) :
token = self . get_token ( cr , uid , context )
params = {
' access_token ' : token ,
' maxResults ' : 1000 ,
' showDeleted ' : True ,
}
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
url = " /calendar/v3/calendars/ %s /events/ %s " % ( ' primary ' , google_id )
try :
2014-08-05 08:59:02 +00:00
status , content , ask_time = self . pool [ ' google.service ' ] . _do_request ( cr , uid , url , params , headers , type = ' GET ' , context = context )
2014-05-14 08:28:10 +00:00
except :
_logger . info ( " Calendar Synchro - In except of get_one_event_synchro " )
pass
return status_response ( status ) and content or False
2013-12-09 14:08:19 +00:00
def update_to_google ( self , cr , uid , oe_event , google_event , context ) :
2014-01-15 09:38:05 +00:00
calendar_event = self . pool [ ' calendar.event ' ]
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
url = " /calendar/v3/calendars/ %s /events/ %s ?fields= %s &access_token= %s " % ( ' primary ' , google_event [ ' id ' ] , ' id,updated ' , self . get_token ( cr , uid , context ) )
2013-12-09 14:08:19 +00:00
headers = { ' Content-type ' : ' application/json ' , ' Accept ' : ' text/plain ' }
2015-06-26 09:14:59 +00:00
data = self . generate_data ( cr , uid , oe_event , context = context )
2013-12-09 14:08:19 +00:00
data [ ' sequence ' ] = google_event . get ( ' sequence ' , 0 )
data_json = simplejson . dumps ( data )
2014-01-14 13:37:36 +00:00
2014-08-05 08:59:02 +00:00
status , content , ask_time = self . pool [ ' google.service ' ] . _do_request ( cr , uid , url , data_json , headers , type = ' PATCH ' , context = context )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
update_date = datetime . strptime ( content [ ' updated ' ] , " % Y- % m- %d T % H: % M: % S. %f z " )
calendar_event . write ( cr , uid , [ oe_event . id ] , { ' oe_update_date ' : update_date } )
2014-01-14 13:37:36 +00:00
2013-12-17 20:42:38 +00:00
if context [ ' curr_attendee ' ] :
2014-02-24 22:02:22 +00:00
self . pool [ ' calendar.attendee ' ] . write ( cr , uid , [ context [ ' curr_attendee ' ] ] , { ' oe_synchro_date ' : update_date } , context )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def update_an_event ( self , cr , uid , event , context = None ) :
data = self . generate_data ( cr , uid , event , context = context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
url = " /calendar/v3/calendars/ %s /events/ %s " % ( ' primary ' , event . google_internal_event_id )
headers = { }
2014-02-24 22:02:22 +00:00
data [ ' access_token ' ] = self . get_token ( cr , uid , context )
2014-01-14 13:37:36 +00:00
2014-08-05 08:59:02 +00:00
status , response , ask_time = self . pool [ ' google.service ' ] . _do_request ( cr , uid , url , data , headers , type = ' GET ' , context = context )
2013-12-20 14:18:55 +00:00
#TO_CHECK : , if http fail, no event, do DELETE ?
2013-12-09 14:08:19 +00:00
return response
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def update_recurrent_event_exclu ( self , cr , uid , instance_id , event_ori_google_id , event_new , context = None ) :
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
data = self . generate_data ( cr , uid , event_new , context = context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
data [ ' recurringEventId ' ] = event_ori_google_id
data [ ' originalStartTime ' ] = event_new . recurrent_id_date
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
url = " /calendar/v3/calendars/ %s /events/ %s ?access_token= %s " % ( ' primary ' , instance_id , self . get_token ( cr , uid , context ) )
headers = { ' Content-type ' : ' application/json ' }
2014-01-14 13:37:36 +00:00
data [ ' sequence ' ] = self . get_sequence ( cr , uid , instance_id , context )
2013-12-09 14:08:19 +00:00
data_json = simplejson . dumps ( data )
2013-12-13 10:35:17 +00:00
return gs_pool . _do_request ( cr , uid , url , data_json , headers , type = ' PUT ' , context = context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
def update_from_google ( self , cr , uid , event , single_event_dict , type , context ) :
2013-12-10 16:45:25 +00:00
if context is None :
2014-02-24 22:02:22 +00:00
context = [ ]
2014-01-14 13:37:36 +00:00
2014-01-15 09:38:05 +00:00
calendar_event = self . pool [ ' calendar.event ' ]
2013-12-09 14:08:19 +00:00
res_partner_obj = self . pool [ ' res.partner ' ]
calendar_attendee_obj = self . pool [ ' calendar.attendee ' ]
2015-02-12 21:16:41 +00:00
calendar_alarm_obj = self . pool [ ' calendar.alarm ' ]
2014-02-18 17:15:08 +00:00
user_obj = self . pool [ ' res.users ' ]
2014-02-24 22:02:22 +00:00
myPartnerID = user_obj . browse ( cr , uid , uid , context ) . partner_id . id
2013-12-10 16:45:25 +00:00
attendee_record = [ ]
2015-05-15 12:03:48 +00:00
alarm_record = set ( )
2014-02-24 22:02:22 +00:00
partner_record = [ ( 4 , myPartnerID ) ]
2013-12-09 14:08:19 +00:00
result = { }
2013-12-10 16:45:25 +00:00
2015-02-12 21:16:41 +00:00
if self . get_need_synchro_attendee ( cr , uid , context = context ) :
for google_attendee in single_event_dict . get ( ' attendees ' , [ ] ) :
2015-07-22 11:22:35 +00:00
partner_email = google_attendee . get ( ' email ' , False )
2013-12-09 14:08:19 +00:00
if type == " write " :
for oe_attendee in event [ ' attendee_ids ' ] :
2015-07-22 11:22:35 +00:00
if oe_attendee . email == partner_email :
[FIX] google_calendar: event duplication during sync to google
With User A <a@gmail.com> and user B <b@gmail.com> both syncing
their calendar with Google.
If User a created an event X, adding as attendee himself and user B,
and then synced his calendar to Google, a new event was
created in User B Google Agenda automatically, representing the
invitation.
At this stage, X appears only once, in the four calendars
(Odoo cal for A, Odoo cal for B, Google Cal for A, Google Cal for B)
If user B then synced his calendar to Odoo, the event X was
duplicated in three of the calendars (Odoo cal for A and B, Google cal for B)
If then user A synced again his calendar with Google, the event X
was duplicated in the four calendars.
From then, a duplicate loop began, at each sync of the both user calendars.
opw-639419
2015-06-01 16:14:50 +00:00
calendar_attendee_obj . write ( cr , uid , [ oe_attendee . id ] , { ' state ' : google_attendee [ ' responseStatus ' ] , ' google_internal_event_id ' : single_event_dict . get ( ' id ' ) } , context = context )
2013-12-09 14:08:19 +00:00
google_attendee [ ' found ' ] = True
2013-12-10 16:45:25 +00:00
continue
2014-01-14 13:37:36 +00:00
2015-02-12 21:16:41 +00:00
if google_attendee . get ( ' found ' ) :
2013-12-09 14:08:19 +00:00
continue
2015-02-12 21:16:41 +00:00
2015-07-22 11:22:35 +00:00
attendee_id = res_partner_obj . search ( cr , uid , [ ( ' email ' , ' = ' , partner_email ) ] , context = context )
2015-02-12 21:16:41 +00:00
if not attendee_id :
data = {
2015-07-22 11:22:35 +00:00
' email ' : partner_email ,
2015-02-12 21:16:41 +00:00
' customer ' : False ,
2015-07-22 11:22:35 +00:00
' name ' : google_attendee . get ( " displayName " , False ) or partner_email
2015-02-12 21:16:41 +00:00
}
attendee_id = [ res_partner_obj . create ( cr , uid , data , 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 ' ]
[FIX] google_calendar: event duplication during sync to google
With User A <a@gmail.com> and user B <b@gmail.com> both syncing
their calendar with Google.
If User a created an event X, adding as attendee himself and user B,
and then synced his calendar to Google, a new event was
created in User B Google Agenda automatically, representing the
invitation.
At this stage, X appears only once, in the four calendars
(Odoo cal for A, Odoo cal for B, Google Cal for A, Google Cal for B)
If user B then synced his calendar to Odoo, the event X was
duplicated in three of the calendars (Odoo cal for A and B, Google cal for B)
If then user A synced again his calendar with Google, the event X
was duplicated in the four calendars.
From then, a duplicate loop began, at each sync of the both user calendars.
opw-639419
2015-06-01 16:14:50 +00:00
attendee [ ' google_internal_event_id ' ] = single_event_dict . get ( ' id ' )
2015-02-12 21:16:41 +00:00
attendee_record . append ( ( 0 , 0 , attendee ) )
for google_alarm in single_event_dict . get ( ' reminders ' , { } ) . get ( ' overrides ' , [ ] ) :
alarm_id = calendar_alarm_obj . search (
cr ,
uid ,
[
( ' type ' , ' = ' , google_alarm [ ' method ' ] if google_alarm [ ' method ' ] == ' email ' else ' notification ' ) ,
( ' duration_minutes ' , ' = ' , google_alarm [ ' minutes ' ] )
] ,
context = context
)
if not alarm_id :
data = {
' type ' : google_alarm [ ' method ' ] if google_alarm [ ' method ' ] == ' email ' else ' notification ' ,
' duration ' : google_alarm [ ' minutes ' ] ,
' interval ' : ' minutes ' ,
' name ' : " %s minutes - %s " % ( google_alarm [ ' minutes ' ] , google_alarm [ ' method ' ] )
}
alarm_id = [ calendar_alarm_obj . create ( cr , uid , data , context = context ) ]
2015-05-15 12:03:48 +00:00
alarm_record . add ( alarm_id [ 0 ] )
2014-02-24 22:02:22 +00:00
2013-12-10 16:45:25 +00:00
UTC = pytz . timezone ( ' UTC ' )
2014-02-24 22:02:22 +00:00
if single_event_dict . get ( ' start ' ) and single_event_dict . get ( ' end ' ) : # If not cancelled
2014-05-14 08:28:10 +00:00
2014-02-24 22:02:22 +00:00
if single_event_dict [ ' start ' ] . get ( ' dateTime ' , False ) and single_event_dict [ ' end ' ] . get ( ' dateTime ' , False ) :
2013-12-10 16:45:25 +00:00
date = parser . parse ( single_event_dict [ ' start ' ] [ ' dateTime ' ] )
2014-05-14 08:28:10 +00:00
stop = parser . parse ( single_event_dict [ ' end ' ] [ ' dateTime ' ] )
2013-12-10 16:45:25 +00:00
date = str ( date . astimezone ( UTC ) ) [ : - 6 ]
2014-05-14 08:28:10 +00:00
stop = str ( stop . astimezone ( UTC ) ) [ : - 6 ]
2013-12-10 16:45:25 +00:00
allday = False
2014-01-14 13:37:36 +00:00
else :
2014-05-14 08:28:10 +00:00
date = ( single_event_dict [ ' start ' ] [ ' date ' ] )
stop = ( single_event_dict [ ' end ' ] [ ' date ' ] )
d_end = datetime . strptime ( stop , DEFAULT_SERVER_DATE_FORMAT )
2013-12-10 16:45:25 +00:00
allday = True
2014-05-14 08:28:10 +00:00
d_end = d_end + timedelta ( days = - 1 )
stop = d_end . strftime ( DEFAULT_SERVER_DATE_FORMAT )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
update_date = datetime . strptime ( single_event_dict [ ' updated ' ] , " % Y- % m- %d T % H: % M: % S. %f z " )
2013-12-10 16:45:25 +00:00
result . update ( {
2014-05-14 08:28:10 +00:00
' start ' : date ,
' stop ' : stop ,
2013-12-10 16:45:25 +00:00
' allday ' : allday
} )
2013-12-09 14:08:19 +00:00
result . update ( {
' attendee_ids ' : attendee_record ,
2013-12-10 16:45:25 +00:00
' partner_ids ' : list ( set ( partner_record ) ) ,
2015-05-15 12:03:48 +00:00
' alarm_ids ' : [ ( 6 , 0 , list ( alarm_record ) ) ] ,
2013-12-10 16:45:25 +00:00
2014-02-24 22:02:22 +00:00
' 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 ,
2013-12-09 14:08:19 +00:00
} )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
if single_event_dict . get ( " recurrence " , False ) :
2013-12-09 14:08:19 +00:00
rrule = [ rule for rule in single_event_dict [ " recurrence " ] if rule . startswith ( " RRULE: " ) ] [ 0 ] [ 6 : ]
2014-02-24 22:02:22 +00:00
result [ ' rrule ' ] = rrule
2014-01-14 13:37:36 +00:00
2015-02-24 17:18:25 +00:00
context = dict ( context or { } , no_mail_to_attendees = True )
2013-12-09 14:08:19 +00:00
if type == " write " :
2014-01-15 09:38:05 +00:00
res = calendar_event . write ( cr , uid , event [ ' id ' ] , result , context = context )
2013-12-09 14:08:19 +00:00
elif type == " copy " :
2013-12-10 16:45:25 +00:00
result [ ' recurrence ' ] = True
2014-01-15 09:38:05 +00:00
res = calendar_event . write ( cr , uid , [ event [ ' id ' ] ] , result , context = context )
2013-12-13 16:27:52 +00:00
elif type == " create " :
2014-01-15 09:38:05 +00:00
res = calendar_event . create ( cr , uid , result , context = context )
2014-01-14 13:37:36 +00:00
2013-12-13 16:27:52 +00:00
if context [ ' curr_attendee ' ] :
2014-02-24 22:02:22 +00:00
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 )
2014-01-14 13:37:36 +00:00
return res
2014-05-14 08:28:10 +00:00
def remove_references ( self , cr , uid , context = None ) :
2014-09-24 13:30:11 +00:00
current_user = self . pool [ ' res.users ' ] . browse ( cr , SUPERUSER_ID , uid , context = context )
2014-05-14 08:28:10 +00:00
reset_data = {
' google_calendar_rtoken ' : False ,
' google_calendar_token ' : False ,
' google_calendar_token_validity ' : False ,
' google_calendar_last_sync_date ' : False ,
' google_calendar_cal_id ' : False ,
}
all_my_attendees = self . pool [ ' calendar.attendee ' ] . search ( cr , uid , [ ( ' partner_id ' , ' = ' , current_user . partner_id . id ) ] , context = context )
self . pool [ ' calendar.attendee ' ] . write ( cr , uid , all_my_attendees , { ' oe_synchro_date ' : False , ' google_internal_event_id ' : False } , context = context )
2014-11-13 11:30:26 +00:00
current_user . write ( reset_data )
2014-05-14 08:28:10 +00:00
return True
2014-10-03 15:52:31 +00:00
def synchronize_events_cron ( self , cr , uid , context = None ) :
ids = self . pool [ ' res.users ' ] . search ( cr , uid , [ ( ' google_calendar_last_sync_date ' , ' != ' , False ) ] , context = context )
_logger . info ( " Calendar Synchro - Started by cron " )
for user_to_sync in ids :
_logger . info ( " Calendar Synchro - Starting synchronization for a new user [ %s ] " % user_to_sync )
try :
2015-02-18 12:00:39 +00:00
resp = self . synchronize_events ( cr , user_to_sync , False , lastSync = True , context = None )
2014-10-03 15:52:31 +00:00
if resp . get ( " status " ) == " need_reset " :
_logger . info ( " [ %s ] Calendar Synchro - Failed - NEED RESET ! " % user_to_sync )
else :
_logger . info ( " [ %s ] Calendar Synchro - Done with status : %s ! " % ( user_to_sync , resp . get ( " status " ) ) )
except Exception , e :
2014-10-06 12:32:28 +00:00
_logger . info ( " [ %s ] Calendar Synchro - Exception : %s ! " % ( user_to_sync , exception_to_unicode ( e ) ) )
2014-10-03 15:52:31 +00:00
_logger . info ( " Calendar Synchro - Ended by cron " )
2014-05-14 08:28:10 +00:00
def synchronize_events ( self , cr , uid , ids , lastSync = True , context = None ) :
if context is None :
context = { }
# def isValidSync(syncToken):
# gs_pool = self.pool['google.service']
# params = {
# 'maxResults': 1,
# 'fields': 'id',
# 'access_token': self.get_token(cr, uid, context),
# 'syncToken': syncToken,
# }
# url = "/calendar/v3/calendars/primary/events"
# status, response = gs_pool._do_request(cr, uid, url, params, type='GET', context=context)
# return int(status) != 410
2014-01-14 13:37:36 +00:00
2014-10-03 15:52:31 +00:00
user_to_sync = ids and ids [ 0 ] or uid
current_user = self . pool [ ' res.users ' ] . browse ( cr , SUPERUSER_ID , user_to_sync , context = context )
2014-05-14 08:28:10 +00:00
2015-02-18 12:00:39 +00:00
st , current_google , ask_time = self . get_calendar_primary_id ( cr , user_to_sync , context = context )
2014-05-14 08:28:10 +00:00
if current_user . google_calendar_cal_id :
if current_google != current_user . google_calendar_cal_id :
return {
" status " : " need_reset " ,
" info " : {
" old_name " : current_user . google_calendar_cal_id ,
" new_name " : current_google
} ,
" url " : ' '
}
2015-02-18 12:00:39 +00:00
if lastSync and self . get_last_sync_date ( cr , user_to_sync , context = context ) and not self . get_disable_since_synchro ( cr , user_to_sync , context = context ) :
lastSync = self . get_last_sync_date ( cr , user_to_sync , context )
2014-10-03 15:52:31 +00:00
_logger . info ( " [ %s ] Calendar Synchro - MODE SINCE_MODIFIED : %s ! " % ( user_to_sync , lastSync . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) )
2014-05-14 08:28:10 +00:00
else :
lastSync = False
2014-10-03 15:52:31 +00:00
_logger . info ( " [ %s ] Calendar Synchro - MODE FULL SYNCHRO FORCED " % user_to_sync )
2014-05-14 08:28:10 +00:00
else :
2014-11-13 11:30:26 +00:00
current_user . write ( { ' google_calendar_cal_id ' : current_google } )
2014-05-14 08:28:10 +00:00
lastSync = False
2014-10-03 15:52:31 +00:00
_logger . info ( " [ %s ] Calendar Synchro - MODE FULL SYNCHRO - NEW CAL ID " % user_to_sync )
2014-05-14 08:28:10 +00:00
new_ids = [ ]
2015-02-18 12:00:39 +00:00
new_ids + = self . create_new_events ( cr , user_to_sync , context = context )
new_ids + = self . bind_recurring_events_to_google ( cr , user_to_sync , context )
2014-05-14 08:28:10 +00:00
2015-02-18 12:00:39 +00:00
res = self . update_events ( cr , user_to_sync , lastSync , context )
2014-05-14 08:28:10 +00:00
2014-11-13 11:30:26 +00:00
current_user . write ( { ' google_calendar_last_sync_date ' : ask_time } )
2013-12-09 14:08:19 +00:00
return {
2015-02-18 12:00:39 +00:00
" status " : res and " need_refresh " or " no_new_event_from_google " ,
2014-02-24 22:02:22 +00:00
" url " : ' '
}
2014-01-14 13:37:36 +00:00
2014-02-18 17:15:08 +00:00
def create_new_events ( self , cr , uid , context = None ) :
2014-05-14 08:28:10 +00:00
if context is None :
context = { }
new_ids = [ ]
2014-02-18 17:15:08 +00:00
ev_obj = self . pool [ ' calendar.event ' ]
2013-12-13 16:27:52 +00:00
att_obj = self . pool [ ' calendar.attendee ' ]
2013-12-09 14:08:19 +00:00
user_obj = self . pool [ ' res.users ' ]
2014-02-24 22:02:22 +00:00
myPartnerID = user_obj . browse ( cr , uid , uid , context = context ) . partner_id . id
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
context_norecurrent = context . copy ( )
context_norecurrent [ ' virtual_id ' ] = False
2014-02-24 22:02:22 +00:00
my_att_ids = att_obj . search ( cr , uid , [ ( ' partner_id ' , ' = ' , myPartnerID ) ,
( ' google_internal_event_id ' , ' = ' , False ) ,
' | ' ,
2014-05-14 08:28:10 +00:00
( ' event_id.stop ' , ' > ' , self . get_minTime ( cr , uid , context = context ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) ,
( ' event_id.final_date ' , ' > ' , self . get_minTime ( cr , uid , context = context ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) ,
2014-02-24 22:02:22 +00:00
] , context = context_norecurrent )
for att in att_obj . browse ( cr , uid , my_att_ids , context = context ) :
2013-12-13 16:27:52 +00:00
if not att . event_id . recurrent_id or att . event_id . recurrent_id == 0 :
2014-08-05 08:59:02 +00:00
st , response , ask_time = self . create_an_event ( cr , uid , att . event_id , context = context )
2014-05-14 08:28:10 +00:00
if status_response ( st ) :
update_date = datetime . strptime ( response [ ' updated ' ] , " % Y- % m- %d T % H: % M: % S. %f z " )
ev_obj . write ( cr , uid , att . event_id . id , { ' oe_update_date ' : update_date } )
new_ids . append ( response [ ' id ' ] )
[FIX] google_calendar: event duplication during sync to google
With User A <a@gmail.com> and user B <b@gmail.com> both syncing
their calendar with Google.
If User a created an event X, adding as attendee himself and user B,
and then synced his calendar to Google, a new event was
created in User B Google Agenda automatically, representing the
invitation.
At this stage, X appears only once, in the four calendars
(Odoo cal for A, Odoo cal for B, Google Cal for A, Google Cal for B)
If user B then synced his calendar to Odoo, the event X was
duplicated in three of the calendars (Odoo cal for A and B, Google cal for B)
If then user A synced again his calendar with Google, the event X
was duplicated in the four calendars.
From then, a duplicate loop began, at each sync of the both user calendars.
opw-639419
2015-06-01 16:14:50 +00:00
att_obj . write ( cr , uid , [ att . id for att in att . event_id . attendee_ids ] , { ' google_internal_event_id ' : response [ ' id ' ] , ' oe_synchro_date ' : update_date } )
2014-05-14 08:28:10 +00:00
cr . commit ( )
else :
_logger . warning ( " Impossible to create event %s . [ %s ] " % ( att . event_id . id , st ) )
_logger . warning ( " Response : %s " % response )
return new_ids
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
def get_context_no_virtual ( self , context ) :
context_norecurrent = context . copy ( )
context_norecurrent [ ' virtual_id ' ] = False
context_norecurrent [ ' active_test ' ] = False
return context_norecurrent
def bind_recurring_events_to_google ( self , cr , uid , context = None ) :
if context is None :
context = { }
new_ids = [ ]
2014-02-18 17:15:08 +00:00
ev_obj = self . pool [ ' calendar.event ' ]
att_obj = self . pool [ ' calendar.attendee ' ]
user_obj = self . pool [ ' res.users ' ]
2014-02-24 22:02:22 +00:00
myPartnerID = user_obj . browse ( cr , uid , uid , context = context ) . partner_id . id
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
context_norecurrent = self . get_context_no_virtual ( context )
2014-02-24 22:02:22 +00:00
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 ) :
2014-02-18 17:15:08 +00:00
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 )
2014-02-24 22:02:22 +00:00
source_attendee_record_id = att_obj . search ( cr , uid , [ ( ' partner_id ' , ' = ' , myPartnerID ) , ( ' event_id ' , ' = ' , source_event_record . id ) ] , context = context )
2014-12-09 15:34:35 +00:00
if not source_attendee_record_id :
continue
2014-02-18 17:15:08 +00:00
source_attendee_record = att_obj . browse ( cr , uid , source_attendee_record_id , context ) [ 0 ]
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
if att . event_id . recurrent_id_date and source_event_record . allday and source_attendee_record . google_internal_event_id :
2014-02-24 22:02:22 +00:00
new_google_internal_event_id = source_attendee_record . google_internal_event_id + ' _ ' + att . event_id . recurrent_id_date . split ( ' ' ) [ 0 ] . replace ( ' - ' , ' ' )
2014-02-18 17:15:08 +00:00
elif att . event_id . recurrent_id_date and source_attendee_record . google_internal_event_id :
2014-02-24 22:02:22 +00:00
new_google_internal_event_id = source_attendee_record . google_internal_event_id + ' _ ' + att . event_id . recurrent_id_date . replace ( ' - ' , ' ' ) . replace ( ' ' , ' T ' ) . replace ( ' : ' , ' ' ) + ' Z '
2014-02-18 17:15:08 +00:00
if new_google_internal_event_id :
#TODO WARNING, NEED TO CHECK THAT EVENT and ALL instance NOT DELETE IN GMAIL BEFORE !
2014-05-14 08:28:10 +00:00
try :
2014-08-05 08:59:02 +00:00
st , response , ask_time = self . update_recurrent_event_exclu ( cr , uid , new_google_internal_event_id , source_attendee_record . google_internal_event_id , att . event_id , context = context )
2014-05-14 08:28:10 +00:00
if status_response ( st ) :
att_obj . write ( cr , uid , [ att . id ] , { ' google_internal_event_id ' : new_google_internal_event_id } , context = context )
new_ids . append ( new_google_internal_event_id )
cr . commit ( )
else :
_logger . warning ( " Impossible to create event %s . [ %s ] " % ( att . event_id . id , st ) )
_logger . warning ( " Response : %s " % response )
except :
pass
return new_ids
2014-02-18 17:15:08 +00:00
2014-05-14 08:28:10 +00:00
def update_events ( self , cr , uid , lastSync = False , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-01-14 13:37:36 +00:00
2014-01-15 09:38:05 +00:00
calendar_event = self . pool [ ' calendar.event ' ]
2013-12-10 16:45:25 +00:00
user_obj = self . pool [ ' res.users ' ]
2013-12-13 16:27:52 +00:00
att_obj = self . pool [ ' calendar.attendee ' ]
2014-02-18 17:15:08 +00:00
myPartnerID = user_obj . browse ( cr , uid , uid , context = context ) . partner_id . id
2014-05-14 08:28:10 +00:00
context_novirtual = self . get_context_no_virtual ( context )
if lastSync :
try :
all_event_from_google = self . get_event_synchro_dict ( cr , uid , lastSync = lastSync , context = context )
except urllib2 . HTTPError , e :
if e . code == 410 : # GONE, Google is lost.
# we need to force the rollback from this cursor, because it locks my res_users but I need to write in this tuple before to raise.
cr . rollback ( )
registry = openerp . modules . registry . RegistryManager . get ( request . session . db )
with registry . cursor ( ) as cur :
2015-02-16 13:54:52 +00:00
self . pool [ ' res.users ' ] . write ( cur , SUPERUSER_ID , [ uid ] , { ' google_calendar_last_sync_date ' : False } , context = context )
2014-12-10 16:29:14 +00:00
error_key = simplejson . loads ( str ( e ) )
2014-05-14 08:28:10 +00:00
error_key = error_key . get ( ' error ' , { } ) . get ( ' message ' , ' nc ' )
2014-12-10 16:30:34 +00:00
error_msg = " Google is lost... the next synchro will be a full synchro. \n \n %s " % error_key
2014-05-14 08:28:10 +00:00
raise self . pool . get ( ' res.config.settings ' ) . get_config_warning ( cr , _ ( error_msg ) , context = context )
my_google_att_ids = att_obj . search ( cr , uid , [
( ' partner_id ' , ' = ' , myPartnerID ) ,
( ' google_internal_event_id ' , ' in ' , all_event_from_google . keys ( ) )
] , context = context_novirtual )
my_openerp_att_ids = att_obj . search ( cr , uid , [
( ' partner_id ' , ' = ' , myPartnerID ) ,
( ' event_id.oe_update_date ' , ' > ' , lastSync and lastSync . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) or self . get_minTime ( cr , uid , context ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) ,
( ' google_internal_event_id ' , ' != ' , False ) ,
] , context = context_novirtual )
my_openerp_googleinternal_ids = att_obj . read ( cr , uid , my_openerp_att_ids , [ ' google_internal_event_id ' , ' event_id ' ] , context = context_novirtual )
if self . get_print_log ( cr , uid , context = context ) :
_logger . info ( " Calendar Synchro - \n \n UPDATE IN GOOGLE \n %s \n \n RETRIEVE FROM OE \n %s \n \n UPDATE IN OE \n %s \n \n RETRIEVE FROM GG \n %s \n \n " % ( all_event_from_google , my_google_att_ids , my_openerp_att_ids , my_openerp_googleinternal_ids ) )
for giid in my_openerp_googleinternal_ids :
active = True # if not sure, we request google
if giid . get ( ' event_id ' ) :
active = calendar_event . browse ( cr , uid , int ( giid . get ( ' event_id ' ) [ 0 ] ) , context = context_novirtual ) . active
if giid . get ( ' google_internal_event_id ' ) and not all_event_from_google . get ( giid . get ( ' google_internal_event_id ' ) ) and active :
one_event = self . get_one_event_synchro ( cr , uid , giid . get ( ' google_internal_event_id ' ) , context = context )
if one_event :
all_event_from_google [ one_event [ ' id ' ] ] = one_event
my_att_ids = list ( set ( my_google_att_ids + my_openerp_att_ids ) )
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
else :
domain = [
( ' partner_id ' , ' = ' , myPartnerID ) ,
( ' google_internal_event_id ' , ' != ' , False ) ,
' | ' ,
( ' event_id.stop ' , ' > ' , self . get_minTime ( cr , uid , context ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) ,
( ' event_id.final_date ' , ' > ' , self . get_minTime ( cr , uid , context ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT ) ) ,
]
# Select all events from OpenERP which have been already synchronized in gmail
my_att_ids = att_obj . search ( cr , uid , domain , context = context_novirtual )
all_event_from_google = self . get_event_synchro_dict ( cr , uid , lastSync = False , context = context )
2014-02-24 22:02:22 +00:00
2013-12-10 16:45:25 +00:00
event_to_synchronize = { }
2014-02-24 22:02:22 +00:00
for att in att_obj . browse ( cr , uid , my_att_ids , context = context ) :
2013-12-13 16:27:52 +00:00
event = att . event_id
2014-01-14 13:37:36 +00:00
2014-06-13 15:57:01 +00:00
base_event_id = att . google_internal_event_id . rsplit ( ' _ ' , 1 ) [ 0 ]
2014-01-14 13:37:36 +00:00
2013-12-10 16:45:25 +00:00
if base_event_id not in event_to_synchronize :
event_to_synchronize [ base_event_id ] = { }
2014-01-14 13:37:36 +00:00
2013-12-13 16:27:52 +00:00
if att . google_internal_event_id not in event_to_synchronize [ base_event_id ] :
2014-02-18 17:15:08 +00:00
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 ]
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
ev_to_sync . OE . attendee_id = att . id
ev_to_sync . OE . event = event
ev_to_sync . OE . found = True
ev_to_sync . OE . event_id = event . id
ev_to_sync . OE . isRecurrence = event . recurrency
ev_to_sync . OE . isInstance = bool ( event . recurrent_id and event . recurrent_id > 0 )
ev_to_sync . OE . update = event . oe_update_date
ev_to_sync . OE . status = event . active
ev_to_sync . OE . synchro = att . oe_synchro_date
2014-01-14 13:37:36 +00:00
2013-12-10 16:45:25 +00:00
for event in all_event_from_google . values ( ) :
event_id = event . get ( ' id ' )
2014-06-13 15:57:01 +00:00
base_event_id = event_id . rsplit ( ' _ ' , 1 ) [ 0 ]
2014-01-14 13:37:36 +00:00
2013-12-10 16:45:25 +00:00
if base_event_id not in event_to_synchronize :
event_to_synchronize [ base_event_id ] = { }
2014-01-14 13:37:36 +00:00
2013-12-10 16:45:25 +00:00
if event_id not in event_to_synchronize [ base_event_id ] :
2014-02-18 17:15:08 +00:00
event_to_synchronize [ base_event_id ] [ event_id ] = SyncEvent ( )
ev_to_sync = event_to_synchronize [ base_event_id ] [ event_id ]
2014-02-24 22:02:22 +00:00
2014-02-18 17:15:08 +00:00
ev_to_sync . GG . event = event
ev_to_sync . GG . found = True
2014-02-24 22:02:22 +00:00
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
2014-02-18 17:15:08 +00:00
if ev_to_sync . GG . update :
2014-02-24 22:02:22 +00:00
ev_to_sync . GG . update = ev_to_sync . GG . update . replace ( ' T ' , ' ' ) . replace ( ' Z ' , ' ' )
2014-02-18 17:15:08 +00:00
ev_to_sync . GG . status = ( event . get ( ' status ' ) != ' cancelled ' )
2014-02-24 22:02:22 +00:00
######################
2013-12-13 16:27:52 +00:00
# PRE-PROCESSING #
######################
2013-12-10 16:45:25 +00:00
for base_event in event_to_synchronize :
for current_event in event_to_synchronize [ base_event ] :
2014-05-14 08:28:10 +00:00
event_to_synchronize [ base_event ] [ current_event ] . compute_OP ( modeFull = not lastSync )
if self . get_print_log ( cr , uid , context = context ) :
if not isinstance ( event_to_synchronize [ base_event ] [ current_event ] . OP , NothingToDo ) :
_logger . info ( event_to_synchronize [ base_event ] )
2014-02-24 22:02:22 +00:00
2013-12-13 16:27:52 +00:00
######################
# DO ACTION #
2014-02-24 22:02:22 +00:00
######################
2013-12-10 16:45:25 +00:00
for base_event in event_to_synchronize :
2014-02-24 22:02:22 +00:00
event_to_synchronize [ base_event ] = sorted ( event_to_synchronize [ base_event ] . iteritems ( ) , key = operator . itemgetter ( 0 ) )
2013-12-10 16:45:25 +00:00
for current_event in event_to_synchronize [ base_event ] :
2013-12-13 10:35:17 +00:00
cr . commit ( )
2014-02-24 22:02:22 +00:00
event = current_event [ 1 ] # event is an Sync Event !
2014-02-18 17:15:08 +00:00
actToDo = event . OP
actSrc = event . OP . src
2013-12-09 14:08:19 +00:00
2014-02-18 17:15:08 +00:00
context [ ' curr_attendee ' ] = event . OE . attendee_id
2014-01-14 13:37:36 +00:00
2014-02-18 17:15:08 +00:00
if isinstance ( actToDo , NothingToDo ) :
continue
elif isinstance ( actToDo , Create ) :
context_tmp = context . copy ( )
context_tmp [ ' NewMeeting ' ] = True
2014-02-24 22:02:22 +00:00
if actSrc == ' GG ' :
2014-02-18 17:15:08 +00:00
res = self . update_from_google ( cr , uid , False , event . GG . event , " create " , context = context_tmp )
event . OE . event_id = res
2014-02-24 22:02:22 +00:00
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 ' :
2014-02-18 17:15:08 +00:00
raise " Should be never here, creation for OE is done before update ! "
#TODO Add to batch
elif isinstance ( actToDo , Update ) :
2014-02-24 22:02:22 +00:00
if actSrc == ' GG ' :
2014-02-18 17:15:08 +00:00
self . update_from_google ( cr , uid , event . OE . event , event . GG . event , ' write ' , context )
2014-02-24 22:02:22 +00:00
elif actSrc == ' OE ' :
2014-02-18 17:15:08 +00:00
self . update_to_google ( cr , uid , event . OE . event , event . GG . event , context )
elif isinstance ( actToDo , Exclude ) :
if actSrc == ' OE ' :
2014-02-24 22:02:22 +00:00
self . delete_an_event ( cr , uid , current_event [ 0 ] , context = context )
elif actSrc == ' GG ' :
2014-06-19 14:13:35 +00:00
new_google_event_id = event . GG . event [ ' id ' ] . rsplit ( ' _ ' , 1 ) [ 1 ]
2014-05-14 08:28:10 +00:00
if ' T ' in new_google_event_id :
new_google_event_id = new_google_event_id . replace ( ' T ' , ' ' ) [ : - 1 ]
else :
new_google_event_id = new_google_event_id + " 000000 "
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
if event . GG . status :
parent_event = { }
if not event_to_synchronize [ base_event ] [ 0 ] [ 1 ] . OE . event_id :
2014-06-19 14:13:35 +00:00
main_ev = att_obj . search_read ( cr , uid , [ ( ' google_internal_event_id ' , ' = ' , event . GG . event [ ' id ' ] . rsplit ( ' _ ' , 1 ) [ 0 ] ) ] , fields = [ ' event_id ' ] , context = context_novirtual )
event_to_synchronize [ base_event ] [ 0 ] [ 1 ] . OE . event_id = main_ev [ 0 ] . get ( ' event_id ' ) [ 0 ]
2014-05-14 08:28:10 +00:00
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 :
parent_oe_id = event_to_synchronize [ base_event ] [ 0 ] [ 1 ] . OE . event_id
2014-12-09 16:13:26 +00:00
if parent_oe_id :
calendar_event . unlink ( cr , uid , " %s - %s " % ( parent_oe_id , new_google_event_id ) , can_be_deleted = True , context = context )
2014-02-18 17:15:08 +00:00
elif isinstance ( actToDo , Delete ) :
if actSrc == ' GG ' :
2014-05-14 08:28:10 +00:00
try :
self . delete_an_event ( cr , uid , current_event [ 0 ] , context = context )
except Exception , e :
error = simplejson . loads ( e . read ( ) )
error_nr = error . get ( ' error ' , { } ) . get ( ' code ' )
# if already deleted from gmail or never created
if error_nr in ( 404 , 410 , ) :
pass
else :
raise e
2014-02-24 22:02:22 +00:00
elif actSrc == ' OE ' :
2014-04-30 09:36:13 +00:00
calendar_event . unlink ( cr , uid , event . OE . event_id , can_be_deleted = False , context = context )
2014-02-18 17:15:08 +00:00
return True
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
def check_and_sync ( self , cr , uid , oe_event , google_event , context ) :
2014-02-24 22:02:22 +00:00
if datetime . strptime ( oe_event . oe_update_date , " % Y- % m- %d % H: % M: % S. %f " ) > datetime . strptime ( google_event [ ' updated ' ] , " % Y- % m- %d T % H: % M: % S. %f z " ) :
2013-12-09 14:08:19 +00:00
self . update_to_google ( cr , uid , oe_event , google_event , context )
2014-02-24 22:02:22 +00:00
elif datetime . strptime ( oe_event . oe_update_date , " % Y- % m- %d % H: % M: % S. %f " ) < datetime . strptime ( google_event [ ' updated ' ] , " % Y- % m- %d T % H: % M: % S. %f z " ) :
2013-12-09 14:08:19 +00:00
self . update_from_google ( cr , uid , oe_event , google_event , ' write ' , context )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def get_sequence ( self , cr , uid , instance_id , context = None ) :
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-01-14 13:37:36 +00:00
params = {
2014-02-24 22:02:22 +00:00
' fields ' : ' sequence ' ,
' access_token ' : self . get_token ( cr , uid , context )
}
2014-01-14 13:37:36 +00:00
headers = { ' Content-type ' : ' application/json ' }
2014-02-24 22:02:22 +00:00
url = " /calendar/v3/calendars/ %s /events/ %s " % ( ' primary ' , instance_id )
2014-01-14 13:37:36 +00:00
2014-08-05 08:59:02 +00:00
st , content , ask_time = gs_pool . _do_request ( cr , uid , url , params , headers , type = ' GET ' , context = context )
2014-02-24 22:02:22 +00:00
return content . get ( ' sequence ' , 0 )
#################################
2013-12-09 14:08:19 +00:00
## MANAGE CONNEXION TO GMAIL ##
#################################
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def get_token ( self , cr , uid , context = None ) :
current_user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
2014-05-14 08:28:10 +00:00
if not current_user . google_calendar_token_validity or \
datetime . strptime ( current_user . google_calendar_token_validity . split ( ' . ' ) [ 0 ] , DEFAULT_SERVER_DATETIME_FORMAT ) < ( datetime . now ( ) + timedelta ( minutes = 1 ) ) :
2014-02-24 22:02:22 +00:00
self . do_refresh_token ( cr , uid , context = context )
2013-12-02 14:31:33 +00:00
current_user . refresh ( )
return current_user . google_calendar_token
2014-05-14 08:28:10 +00:00
def get_last_sync_date ( self , cr , uid , context = None ) :
current_user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
return current_user . google_calendar_last_sync_date and datetime . strptime ( current_user . google_calendar_last_sync_date , DEFAULT_SERVER_DATETIME_FORMAT ) + timedelta ( minutes = 0 ) or False
2014-02-24 22:02:22 +00:00
def do_refresh_token ( self , cr , uid , context = None ) :
current_user = self . pool [ ' res.users ' ] . browse ( cr , uid , uid , context = context )
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-01-14 13:37:36 +00:00
2014-02-18 17:15:08 +00:00
all_token = gs_pool . _refresh_google_token_json ( cr , uid , current_user . google_calendar_rtoken , self . STR_SERVICE , context = context )
2014-01-14 13:37:36 +00:00
2013-12-02 14:31:33 +00:00
vals = { }
2014-01-14 13:37:36 +00:00
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 ' )
2014-02-24 22:02:22 +00:00
self . pool [ ' res.users ' ] . write ( cr , SUPERUSER_ID , uid , vals , context = context )
2013-12-02 14:31:33 +00:00
2014-02-24 22:02:22 +00:00
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
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def get_calendar_scope ( self , RO = False ) :
2014-01-14 13:37:36 +00:00
readonly = RO and ' .readonly ' or ' '
return ' https://www.googleapis.com/auth/calendar %s ' % ( readonly )
2013-12-02 14:31:33 +00:00
2014-02-24 22:02:22 +00:00
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 )
2014-01-14 13:37:36 +00:00
return url
2014-02-24 22:02:22 +00:00
def can_authorize_google ( self , cr , uid , context = None ) :
2013-12-19 16:50:11 +00:00
return self . pool [ ' res.users ' ] . has_group ( cr , uid , ' base.group_erp_manager ' )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
def set_all_tokens ( self , cr , uid , authorization_code , context = None ) :
2014-02-18 17:15:08 +00:00
gs_pool = self . pool [ ' google.service ' ]
2014-02-24 22:02:22 +00:00
all_token = gs_pool . _get_google_token_json ( cr , uid , authorization_code , self . STR_SERVICE , context = context )
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
vals = { }
vals [ ' google_ %s _rtoken ' % self . STR_SERVICE ] = all_token . get ( ' refresh_token ' )
2013-12-19 14:25:14 +00:00
vals [ ' google_ %s _token_validity ' % self . STR_SERVICE ] = datetime . now ( ) + timedelta ( seconds = all_token . get ( ' expires_in ' ) )
2014-01-14 13:37:36 +00:00
vals [ ' google_ %s _token ' % self . STR_SERVICE ] = all_token . get ( ' access_token ' )
2014-02-24 22:02:22 +00:00
self . pool [ ' res.users ' ] . write ( cr , SUPERUSER_ID , uid , vals , context = context )
2014-01-14 13:37:36 +00:00
2014-05-14 08:28:10 +00:00
def get_minTime ( self , cr , uid , context = None ) :
2015-05-28 14:01:42 +00:00
number_of_week = int ( self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' calendar.week_synchro ' , default = 13 ) )
2014-02-24 22:02:22 +00:00
return datetime . now ( ) - timedelta ( weeks = number_of_week )
2014-02-18 17:15:08 +00:00
def get_need_synchro_attendee ( self , cr , uid , context = None ) :
2014-05-14 08:28:10 +00:00
return self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' calendar.block_synchro_attendee ' , default = True )
def get_disable_since_synchro ( self , cr , uid , context = None ) :
return self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' calendar.block_since_synchro ' , default = False )
def get_print_log ( self , cr , uid , context = None ) :
return self . pool [ ' ir.config_parameter ' ] . get_param ( cr , uid , ' calendar.debug_print ' , default = False )
2014-01-14 13:37:36 +00:00
2014-02-24 22:02:22 +00:00
class res_users ( osv . Model ) :
2013-12-02 14:31:33 +00:00
_inherit = ' res.users '
2014-01-14 13:37:36 +00:00
2013-12-02 14:31:33 +00:00
_columns = {
' google_calendar_rtoken ' : fields . char ( ' Refresh Token ' ) ,
2014-02-24 22:02:22 +00:00
' google_calendar_token ' : fields . char ( ' User token ' ) ,
2014-01-14 13:37:36 +00:00
' google_calendar_token_validity ' : fields . datetime ( ' Token Validity ' ) ,
2014-05-14 08:28:10 +00:00
' google_calendar_last_sync_date ' : fields . datetime ( ' Last synchro date ' ) ,
' google_calendar_cal_id ' : fields . char ( ' Calendar ID ' , help = ' Last Calendar ID who has been synchronized. If it is changed, we remove \
2014-07-09 11:39:38 +00:00
all links between GoogleID and Odoo Google Internal ID ' )
2014-02-24 22:02:22 +00:00
}
2013-12-02 14:31:33 +00:00
2014-01-15 09:38:05 +00:00
class calendar_event ( osv . Model ) :
_inherit = " calendar.event "
2013-12-20 16:08:18 +00:00
2014-05-14 08:28:10 +00:00
def get_fields_need_update_google ( self , cr , uid , context = None ) :
2015-05-18 12:17:20 +00:00
return [ ' name ' , ' description ' , ' allday ' , ' start ' , ' date_end ' , ' stop ' ,
' attendee_ids ' , ' alarm_ids ' , ' location ' , ' class ' , ' active ' ,
' start_date ' , ' start_datetime ' , ' stop_date ' , ' stop_datetime ' ]
2014-05-14 08:28:10 +00:00
2013-12-02 14:31:33 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2013-12-20 09:57:20 +00:00
if context is None :
2014-02-24 22:02:22 +00:00
context = { }
2014-05-14 08:28:10 +00:00
sync_fields = set ( self . get_fields_need_update_google ( cr , uid , context ) )
2013-12-20 09:57:20 +00:00
if ( set ( vals . keys ( ) ) & sync_fields ) and ' oe_update_date ' not in vals . keys ( ) and ' NewMeeting ' not in context :
2013-12-02 14:31:33 +00:00
vals [ ' oe_update_date ' ] = datetime . now ( )
2013-12-20 16:08:18 +00:00
2014-01-15 09:38:05 +00:00
return super ( calendar_event , self ) . write ( cr , uid , ids , vals , context = context )
2014-01-14 13:37:36 +00:00
2013-12-02 14:31:33 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
default = default or { }
if default . get ( ' write_type ' , False ) :
del default [ ' write_type ' ]
elif default . get ( ' recurrent_id ' , False ) :
default [ ' oe_update_date ' ] = datetime . now ( )
else :
default [ ' oe_update_date ' ] = False
2014-01-15 09:38:05 +00:00
return super ( calendar_event , self ) . copy ( cr , uid , id , default , context )
2014-01-14 13:37:36 +00:00
2014-04-30 09:36:13 +00:00
def unlink ( self , cr , uid , ids , can_be_deleted = False , context = None ) :
return super ( calendar_event , self ) . unlink ( cr , uid , ids , can_be_deleted = can_be_deleted , context = context )
2014-01-14 13:37:36 +00:00
_columns = {
2014-07-09 11:39:38 +00:00
' oe_update_date ' : fields . datetime ( ' Odoo Update Date ' ) ,
2013-12-02 14:31:33 +00:00
}
2014-01-14 13:37:36 +00:00
2014-01-13 17:41:57 +00:00
class calendar_attendee ( osv . Model ) :
2013-12-02 14:31:33 +00:00
_inherit = ' calendar.attendee '
2014-01-14 13:37:36 +00:00
2013-12-13 16:27:52 +00:00
_columns = {
2014-05-14 08:28:10 +00:00
' google_internal_event_id ' : fields . char ( ' Google Calendar Event Id ' ) ,
2014-07-09 11:39:38 +00:00
' oe_synchro_date ' : fields . datetime ( ' Odoo Synchro Date ' ) ,
2013-12-13 16:27:52 +00:00
}
2014-02-24 22:02:22 +00:00
_sql_constraints = [ ( ' google_id_uniq ' , ' unique(google_internal_event_id,partner_id,event_id) ' , ' Google ID should be unique! ' ) ]
2014-01-14 13:37:36 +00:00
2013-12-02 14:31:33 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2013-12-13 16:27:52 +00:00
if context is None :
context = { }
2014-01-14 13:37:36 +00:00
2013-12-09 14:08:19 +00:00
for id in ids :
2014-02-24 22:02:22 +00:00
ref = vals . get ( ' event_id ' , self . browse ( cr , uid , id , context = context ) . event_id . id )
2014-01-14 13:37:36 +00:00
2013-12-20 16:08:18 +00:00
# If attendees are updated, we need to specify that next synchro need an action
2014-01-14 13:37:36 +00:00
# Except if it come from an update_from_google
2013-12-20 09:57:20 +00:00
if not context . get ( ' curr_attendee ' , False ) and not context . get ( ' NewMeeting ' , False ) :
2014-02-24 22:02:22 +00:00
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 )