[REF] Add order fix on calendar list view, flake google_calendar, undelete function get_sequence needed for google synchro

bzr revid: jke@openerp.com-20140114133736-cvvftr4hmaa3w3ad
This commit is contained in:
jke-openerp 2014-01-14 14:37:36 +01:00
parent facb8547db
commit 53264da08a
6 changed files with 260 additions and 216 deletions

View File

@ -36,6 +36,7 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp import http from openerp import http
from openerp.http import request from openerp.http import request
from operator import itemgetter
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -61,7 +62,6 @@ 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)
@ -297,7 +297,7 @@ class calendar_attendee(osv.Model):
class res_partner(osv.Model): class res_partner(osv.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
_columns = { _columns = {
'calendar_last_notif': fields.datetime('Last Notification from base Calendar'), 'calendar_last_notif_ack': fields.datetime('Last notification marked as read from base Calendar'),
} }
def get_attendee_detail(self, cr, uid, ids, meeting_id, context=None): def get_attendee_detail(self, cr, uid, ids, meeting_id, context=None):
@ -314,9 +314,9 @@ class res_partner(osv.Model):
datas.append(data) datas.append(data)
return datas return datas
def calendar_last_event(self, cr, uid, context=None): def calendar_last_notif_ack(self, cr, uid, context=None):
partner = self.pool['res.users'].browse(cr, uid, uid, context=context).partner_id partner = self.pool['res.users'].browse(cr, uid, uid, context=context).partner_id
self.write(cr, uid, partner.id, {'calendar_last_notif': datetime.now()}, context=context) self.write(cr, uid, partner.id, {'calendar_last_notif_ack': datetime.now()}, context=context)
return return
@ -974,23 +974,52 @@ class crm_meeting(osv.Model):
} }
return res return res
def get_recurrent_ids(self, cr, uid, select, domain, limit=100, context=None): def get_search_fields(self,browse_event,order_fields,r_date=None):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule sort_fields = {}
This method gives ids of dates that comes between start date and end date of calendar views for ord in order_fields:
if ord == 'id' and r_date:
sort_fields[ord] = '%s-%s' % (browse_event[ord], r_date.strftime("%Y%m%d%H%M%S"))
else:
sort_fields[ord] = browse_event[ord]
'If we sort on FK, we obtain a browse_record, so we need to sort on name_get'
if type(browse_event[ord]) is openerp.osv.orm.browse_record:
name_get = browse_event[ord].name_get()
if len(name_get) and len(name_get[0])>=2:
sort_fields[ord] = name_get[0][1]
@param limit: The Number of Results to Return """ return sort_fields
def get_recurrent_ids(self, cr, uid, event_id, domain, order=None, context=None):
"""Gives virtual event ids for recurring events
This method gives ids of dates that comes between start date and end date of calendar views
@param order: The fields (comma separated, format "FIELD {DESC|ASC}") on which the events should be sorted
"""
if not context: if not context:
context = {} context = {}
if isinstance(select, (str, int, long)): if isinstance(event_id, (str, int, long)):
ids_to_browse = [select] # keep select for return ids_to_browse = [event_id] # keep select for return
else: else:
ids_to_browse = select ids_to_browse = event_id
if order:
order_fields = [field.split()[0] for field in order.split(',')]
else:
# fallback on self._order defined on the model
order_fields = [field.split()[0] for field in self._order.split(',')]
if 'id' not in order_fields:
order_fields.append('id')
result_data = []
result = [] result = []
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))
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)
@ -1036,15 +1065,25 @@ class crm_meeting(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))
idval = '%d-%s' % (ev.id, r_date.strftime("%Y%m%d%H%M%S")) if order_fields:
result.append(idval) def comparer(left, right):
for fn, mult in comparers:
result = cmp(fn(left), fn(right))
if result:
return mult * result
return 0
if isinstance(select, (str, int, long)): sort_params = [key.split()[0] if key[-4:].lower() != 'desc' else '-%s' % key.split()[0] for key in (order or self._order).split(',')]
return result and result[0] or False comparers = [ ((itemgetter(col[1:]), -1) if col[0] == '-' else (itemgetter(col), 1)) for col in sort_params]
ids = [r['id'] for r in sorted(result_data, cmp=comparer)]
if isinstance(event_id, (str, int, long)):
return ids and ids[0] or False
else: else:
ids = list(set(result)) return ids
return ids
def compute_rule_string(self, data): def compute_rule_string(self, data):
""" """
@ -1268,10 +1307,11 @@ class crm_meeting(osv.Model):
new_args.append(new_arg) new_args.append(new_arg)
#offset, limit and count must be treated separately as we may need to deal with virtual ids #offset, limit and count must be treated separately as we may need to deal with virtual ids
res = super(crm_meeting, self).search(cr, uid, new_args, offset=0, limit=0, order=order, context=context, count=False)
if context.get('virtual_id', True): if context.get('virtual_id', True):
res = self.get_recurrent_ids(cr, uid, res, args, limit, context=context) res = super(crm_meeting, self).search(cr, uid, new_args, offset=0, limit=0, order=None, context=context, count=False)
res = self.get_recurrent_ids(cr, uid, res, args, order=order, context=context)
else:
res = super(crm_meeting, self).search(cr, uid, new_args, offset=0, limit=0, order=order, context=context, count=False)
if count: if count:
return len(res) return len(res)
elif limit: elif limit:
@ -1297,7 +1337,14 @@ class crm_meeting(osv.Model):
return True return True
context = context or {} context = context or {}
if isinstance(ids, (str, int, long)):
if isinstance(ids, (str)):
if len(str(ids).split('-')) == 1:
ids = [int(ids)]
else:
ids = [ids]
if isinstance(ids, (int, long)):
ids = [ids] ids = [ids]
res = False res = False
new_id = False new_id = False
@ -1460,7 +1507,7 @@ class crm_meeting(osv.Model):
ids_to_exclure = [] ids_to_exclure = []
ids_to_unlink = [] ids_to_unlink = []
# One time moved to google_Calendar, we can specify, an 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:
@ -1494,7 +1541,8 @@ 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 == 'crm.meeting': if doc_model == 'crm.meeting':
for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], context=context): order = context.get('order', self._order)
for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context):
doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)]) 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)

View File

@ -78,7 +78,7 @@
<field name="name">Run Event Reminder</field> <field name="name">Run Event Reminder</field>
<field eval="True" name="active" /> <field eval="True" name="active" />
<field name="user_id" ref="base.user_root" /> <field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field> <field name="interval_number">30</field>
<field name="interval_type">minutes</field> <field name="interval_type">minutes</field>
<field name="numbercall">-1</field> <field name="numbercall">-1</field>
<field eval="False" name="doall" /> <field eval="False" name="doall" />

View File

@ -58,7 +58,7 @@ class meeting_invitation(http.Controller):
uid = request.session.uid uid = request.session.uid
context = request.session.context context = request.session.context
with registry.cursor() as cr: with registry.cursor() as cr:
res = registry.get("calendar.alarm_manager").do_run_next_event(cr,uid,context=context) res = registry.get("calendar.alarm_manager").get_next_notif(cr,uid,context=context)
return res return res
@http.route('/calendar/notify_ack', type='json', auth="none") @http.route('/calendar/notify_ack', type='json', auth="none")
@ -67,6 +67,6 @@ class meeting_invitation(http.Controller):
uid = request.session.uid uid = request.session.uid
context = request.session.context context = request.session.context
with registry.cursor() as cr: with registry.cursor() as cr:
res = registry.get("res.partner").calendar_last_event(cr,uid,context=context) res = registry.get("res.partner").calendar_last_notif(cr,uid,context=context)
return res return res

View File

@ -60,21 +60,19 @@ class google_service(osv.osv_memory):
'redirect_uri': ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri'), 'redirect_uri': ir_config.get_param(cr, SUPERUSER_ID, 'google_redirect_uri'),
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service), 'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
'response_type': 'code', 'response_type': 'code',
'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service), 'client_id': ir_config.get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % service),
} }
uri = 'https://accounts.google.com/o/oauth2/auth?%s' % urllib.urlencode(params) uri = 'https://accounts.google.com/o/oauth2/auth?%s' % urllib.urlencode(params)
return uri return uri
#If no scope is passed, we use service by default to get a default scope #If no scope is passed, we use service by default to get a default scope
def _get_authorize_uri(self, cr, uid, from_url, service, scope = False, context=None): def _get_authorize_uri(self, cr, uid, from_url, service, scope = False, context=None):
""" This method return the url needed to allow this instance of OpenErp to access to the scope of gmail specified as parameters """ """ This method return the url needed to allow this instance of OpenErp to access to the scope of gmail specified as parameters """
state_obj = dict(d=cr.dbname, s=service, f=from_url) state_obj = dict(d=cr.dbname, s=service, f=from_url)
base_url = self.get_base_url(cr, uid, context) base_url = self.get_base_url(cr, uid, context)
client_id = self.get_client_id(cr, uid, service, context) client_id = self.get_client_id(cr, uid, service, context)
params = { params = {
'response_type': 'code', 'response_type': 'code',
'client_id': client_id, 'client_id': client_id,
@ -84,16 +82,16 @@ class google_service(osv.osv_memory):
'approval_prompt':'force', 'approval_prompt':'force',
'access_type':'offline' 'access_type':'offline'
} }
uri = self.get_uri_oauth(a='auth') + "?%s" % urllib.urlencode(params) uri = self.get_uri_oauth(a='auth') + "?%s" % urllib.urlencode(params)
return uri return uri
def _get_google_token_json(self, cr, uid, authorize_code, service, context=None): def _get_google_token_json(self, cr, uid, authorize_code, service, context=None):
res = False res = False
base_url = self.get_base_url(cr, uid, context) base_url = self.get_base_url(cr, uid, context)
client_id = self.get_client_id(cr, uid, service, context) client_id = self.get_client_id(cr, uid, service, context)
client_secret = self.get_client_secret(cr, uid, service, context) client_secret = self.get_client_secret(cr, uid, service, context)
params = { params = {
'code': authorize_code, 'code': authorize_code,
'client_id': client_id, 'client_id': client_id,
@ -101,34 +99,34 @@ class google_service(osv.osv_memory):
'grant_type' : 'authorization_code', 'grant_type' : 'authorization_code',
'redirect_uri': base_url + '/google_account/authentication' 'redirect_uri': base_url + '/google_account/authentication'
} }
headers = {"content-type": "application/x-www-form-urlencoded"} headers = {"content-type": "application/x-www-form-urlencoded"}
try: try:
data = urllib.urlencode(params) data = urllib.urlencode(params)
req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers) req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers)
content = urllib2.urlopen(req).read() content = urllib2.urlopen(req).read()
res = simplejson.loads(content) res = simplejson.loads(content)
except urllib2.HTTPError,e: except urllib2.HTTPError,e:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid"), context=context) raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid"), context=context)
return res return res
def _refresh_google_token_json(self, cr, uid, refresh_token, service, context=None): #exchange_AUTHORIZATION vs Token (service = calendar) def _refresh_google_token_json(self, cr, uid, refresh_token, service, context=None): #exchange_AUTHORIZATION vs Token (service = calendar)
res = False res = False
base_url = self.get_base_url(cr, uid, context) base_url = self.get_base_url(cr, uid, context)
client_id = self.get_client_id(cr, uid, service, context) client_id = self.get_client_id(cr, uid, service, context)
client_secret = self.get_client_secret(cr, uid, service, context) client_secret = self.get_client_secret(cr, uid, service, context)
params = { params = {
'refresh_token': refresh_token, 'refresh_token': refresh_token,
'client_id': client_id, 'client_id': client_id,
'client_secret': client_secret, 'client_secret': client_secret,
'grant_type' : 'refresh_token' 'grant_type' : 'refresh_token'
} }
headers = {"content-type": "application/x-www-form-urlencoded"} headers = {"content-type": "application/x-www-form-urlencoded"}
try: try:
data = urllib.urlencode(params) data = urllib.urlencode(params)
req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers) req = urllib2.Request(self.get_uri_oauth(a='token'), data, headers)
@ -136,25 +134,26 @@ class google_service(osv.osv_memory):
res = simplejson.loads(content) res = simplejson.loads(content)
except urllib2.HTTPError: except urllib2.HTTPError:
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"), context=context) raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired"), context=context)
return res return res
def _do_request(self,cr,uid,uri,params={},headers={},type='POST', context=None): def _do_request(self,cr,uid,uri,params={},headers={},type='POST', context=None):
_logger.debug("Uri: %s - Type : %s - Headers: %s - Params : %s !" % (uri,type,headers,urllib.urlencode(params) if type =='GET' else params)) _logger.debug("Uri: %s - Type : %s - Headers: %s - Params : %s !" % (uri,type,headers,urllib.urlencode(params) if type =='GET' else params))
res = False res = False
try: try:
if type.upper() == 'GET' or type.upper() == 'DELETE': if type.upper() == 'GET' or type.upper() == 'DELETE':
data = urllib.urlencode(params) data = urllib.urlencode(params)
req = urllib2.Request(self.get_uri_api() + uri + "?" + data) req = urllib2.Request(self.get_uri_api() + uri + "?" + data)
elif type.upper() == 'POST' or type.upper() == 'PATCH' or type.upper() == 'PUT': elif type.upper() == 'POST' or type.upper() == 'PATCH' or type.upper() == 'PUT':
req = urllib2.Request(self.get_uri_api() + uri, params, headers) req = urllib2.Request(self.get_uri_api() + uri, params, headers)
else: else:
raise ('Method not supported [%s] not in [GET, POST, PUT, PATCH or DELETE]!' % (type)) raise ('Method not supported [%s] not in [GET, POST, PUT, PATCH or DELETE]!' % (type))
req.get_method = lambda: type.upper() req.get_method = lambda: type.upper()
request = urllib2.urlopen(req) request = urllib2.urlopen(req)
if request.getcode() == 204: #No content returned, (ex: POST calendar/event/clear) if request.getcode() == 204: #No content returned, (ex: POST calendar/event/clear)
res = True res = True
elif request.getcode() == 404: #Page not found elif request.getcode() == 404: #Page not found
@ -164,20 +163,20 @@ class google_service(osv.osv_memory):
res = simplejson.loads(content) res = simplejson.loads(content)
except urllib2.HTTPError,e: except urllib2.HTTPError,e:
_logger.exception("Bad google request : %s !" % e.read()) _logger.exception("Bad google request : %s !" % e.read())
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong with your request to google"), context=context) raise self.pool.get('res.config.settings').get_config_warning(cr, _("Something went wrong with your request to google"), context=context)
return res return res
def get_base_url(self, cr, uid, context=None): def get_base_url(self, cr, uid, context=None):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url',default='http://www.openerp.com?NoBaseUrl',context=context) return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url',default='http://www.openerp.com?NoBaseUrl',context=context)
def get_client_id(self, cr, uid, service, context=None): def get_client_id(self, cr, uid, service, context=None):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_id' % (service,),default=False,context=context) return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_id' % (service,),default=False,context=context)
def get_client_secret(self, cr, uid, service, context=None): def get_client_secret(self, cr, uid, service, context=None):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_secret' % (service,),default=False,context=context) return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_secret' % (service,),default=False,context=context)
def get_uri_oauth(self,a=''): #a = optional action def get_uri_oauth(self,a=''): #a = optional action
return "https://accounts.google.com/o/oauth2/%s" % (a,) return "https://accounts.google.com/o/oauth2/%s" % (a,)
def get_uri_api(self): def get_uri_api(self):
return 'https://www.googleapis.com' return 'https://www.googleapis.com'

View File

@ -38,11 +38,9 @@ from openerp.osv import fields, osv
from openerp.osv import osv from openerp.osv import osv
class google_calendar(osv.AbstractModel): 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:
@ -69,7 +67,7 @@ class google_calendar(osv.AbstractModel):
'timeZone':'UTC' 'timeZone':'UTC'
}, },
"end":{ "end":{
type:end_date, type:end_date,
'timeZone':'UTC' 'timeZone':'UTC'
}, },
"attendees":attendee_list, "attendees":attendee_list,
@ -81,23 +79,23 @@ class google_calendar(osv.AbstractModel):
if not event.active: if not event.active:
data["state"] = "cancelled" data["state"] = "cancelled"
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.get('google.service') gs_pool = self.pool.get('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.get('google.service') gs_pool = self.pool.get('google.service')
params = { params = {
'access_token' : self.get_token(cr,uid,context) 'access_token' : self.get_token(cr,uid,context)
} }
@ -105,93 +103,93 @@ class google_calendar(osv.AbstractModel):
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.get('google.service') gs_pool = self.pool.get('google.service')
params = { params = {
'fields': 'items,nextPageToken', 'fields': 'items,nextPageToken',
'access_token' : token, 'access_token' : token,
'maxResults':1000 'maxResults':1000
} }
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
url = "/calendar/v3/calendars/%s/events" % 'primary' url = "/calendar/v3/calendars/%s/events" % 'primary'
if nextPageToken: if nextPageToken:
params['pageToken'] = nextPageToken params['pageToken'] = nextPageToken
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)
google_events_dict = {} google_events_dict = {}
for google_event in content['items']: for google_event in content['items']:
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):
crm_meeting = self.pool['crm.meeting'] crm_meeting = self.pool['crm.meeting']
gs_pool = self.pool.get('google.service') gs_pool = self.pool.get('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")
crm_meeting.write(cr, uid, [oe_event.id], {'oe_update_date':update_date}) crm_meeting.write(cr, uid, [oe_event.id], {'oe_update_date':update_date})
if context['curr_attendee']: if context['curr_attendee']:
self.pool.get('calendar.attendee').write(cr,uid,[context['curr_attendee']], {'oe_synchro_date':update_date},context) self.pool.get('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.get('google.service') gs_pool = self.pool.get('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.get('google.service') gs_pool = self.pool.get('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_json = simplejson.dumps(data) data_json = simplejson.dumps(data)
return gs_pool._do_request(cr, uid, url, data_json, headers, type='PUT', context=context) return gs_pool._do_request(cr, uid, url, data_json, headers, type='PUT', context=context)
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= []
crm_meeting = self.pool['crm.meeting'] crm_meeting = self.pool['crm.meeting']
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.get('res.users') user_obj = self.pool.get('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):
@ -202,7 +200,7 @@ class google_calendar(osv.AbstractModel):
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
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)
@ -210,9 +208,9 @@ class google_calendar(osv.AbstractModel):
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):
@ -222,16 +220,15 @@ class google_calendar(osv.AbstractModel):
date = str(date.astimezone(UTC))[:-6] date = str(date.astimezone(UTC))[:-6]
date_deadline = str(date_deadline.astimezone(UTC))[:-6] date_deadline = str(date_deadline.astimezone(UTC))[:-6]
allday = False allday = False
else: else:
date = (single_event_dict['start']['date'] + ' 00:00:00') date = (single_event_dict['start']['date'] + ' 00:00:00')
date_deadline = (single_event_dict['end']['date'] + ' 00:00:00') date_deadline = (single_event_dict['end']['date'] + ' 00:00:00')
d_start = datetime.strptime(date, "%Y-%m-%d %H:%M:%S") d_start = datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
d_end = datetime.strptime(date_deadline, "%Y-%m-%d %H:%M:%S") d_end = datetime.strptime(date_deadline, "%Y-%m-%d %H:%M:%S")
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,
@ -249,12 +246,11 @@ class google_calendar(osv.AbstractModel):
'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 = crm_meeting.write(cr, uid, event['id'], result, context=context) res = crm_meeting.write(cr, uid, event['id'], result, context=context)
elif type == "copy": elif type == "copy":
@ -263,38 +259,37 @@ class google_calendar(osv.AbstractModel):
elif type == "create": elif type == "create":
res = crm_meeting.create(cr, uid, result, context=context) res = crm_meeting.create(cr, uid, result, context=context)
if context['curr_attendee']: if context['curr_attendee']:
self.pool.get('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.get('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.get('google.calendar') gc_obj = self.pool.get('google.calendar')
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)
cr.commit() cr.commit()
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): def create_new_events(self, cr, uid, context):
gc_pool = self.pool.get('google.calendar') gc_pool = self.pool.get('google.calendar')
crm_meeting = self.pool['crm.meeting'] crm_meeting = self.pool['crm.meeting']
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),('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 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:
@ -304,7 +299,7 @@ class google_calendar(osv.AbstractModel):
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()
return True return True
def get_empty_synchro_summarize(self) : def get_empty_synchro_summarize(self) :
return { return {
#OPENERP #OPENERP
@ -317,16 +312,15 @@ class google_calendar(osv.AbstractModel):
'OE_status':False, 'OE_status':False,
'OE_attendee_id': False, 'OE_attendee_id': False,
'OE_synchro':False, 'OE_synchro':False,
#GOOGLE #GOOGLE
'GG_event' : False, 'GG_event' : False,
'GG_found' : False, 'GG_found' : False,
'GG_isRecurrence':False, 'GG_isRecurrence':False,
'GG_isInstance':False, 'GG_isInstance':False,
'GG_update':False, 'GG_update':False,
'GG_status':False, 'GG_status':False,
#TO_DO_IN_GOOGLE #TO_DO_IN_GOOGLE
'td_action':'', # create, update, delete, None 'td_action':'', # create, update, delete, None
#If 'td_action' in (create , update), #If 'td_action' in (create , update),
@ -342,43 +336,41 @@ class google_calendar(osv.AbstractModel):
# We delete in Gmail the event # We delete in Gmail the event
# If td_source == ALL # If td_source == ALL
# We delete in openERP AND in Gmail the event # We delete in openERP AND in Gmail the event
'td_source': '', # OE, GG, ALL 'td_source': '', # OE, GG, ALL
'td_comment':'' 'td_comment':''
} }
def update_events(self, cr, uid, context): def update_events(self, cr, uid, context):
if context is None: if context is None:
context = {} context = {}
crm_meeting = self.pool['crm.meeting'] crm_meeting = self.pool['crm.meeting']
user_obj = self.pool['res.users'] user_obj = self.pool['res.users']
att_obj = self.pool['calendar.attendee'] att_obj = self.pool['calendar.attendee']
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_novirtual = context.copy() context_novirtual = context.copy()
context_novirtual['virtual_id'] = False context_novirtual['virtual_id'] = False
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)
all_new_event_from_google = all_event_from_google.copy() all_new_event_from_google = all_event_from_google.copy()
# Select all events from OpenERP which have been already synchronized in gmail # Select all events from OpenERP which have been already synchronized in gmail
# events_ids = crm_meeting.search(cr, uid,[('partner_ids', 'in', myPartnerID),('google_internal_event_id', '!=', False),('oe_update_date','!=', False)],order='google_internal_event_id',context=context_novirtual)
my_att_ids = att_obj.search(cr, uid,[('partner_id', '=', myPartnerID),('google_internal_event_id', '!=', False)], context=context_novirtual) my_att_ids = att_obj.search(cr, uid,[('partner_id', '=', myPartnerID),('google_internal_event_id', '!=', False)], 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]
if base_event_id not in event_to_synchronize: if base_event_id not in event_to_synchronize:
event_to_synchronize[base_event_id] = {} event_to_synchronize[base_event_id] = {}
if att.google_internal_event_id not in event_to_synchronize[base_event_id]: if att.google_internal_event_id not in event_to_synchronize[base_event_id]:
event_to_synchronize[base_event_id][att.google_internal_event_id] = self.get_empty_synchro_summarize() event_to_synchronize[base_event_id][att.google_internal_event_id] = self.get_empty_synchro_summarize()
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_attendee_id'] = att.id event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_attendee_id'] = att.id
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_event'] = event event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_event'] = event
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_found'] = True event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_found'] = True
@ -388,15 +380,15 @@ class google_calendar(osv.AbstractModel):
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_update'] = event.oe_update_date event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_update'] = event.oe_update_date
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_status'] = event.active event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_status'] = event.active
event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_synchro'] = att.oe_synchro_date event_to_synchronize[base_event_id][att.google_internal_event_id]['OE_synchro'] = att.oe_synchro_date
for event in all_event_from_google.values(): for event in all_event_from_google.values():
event_id = event.get('id') event_id = event.get('id')
base_event_id = event_id.split('_')[0] base_event_id = event_id.split('_')[0]
if base_event_id not in event_to_synchronize: if base_event_id not in event_to_synchronize:
event_to_synchronize[base_event_id] = {} event_to_synchronize[base_event_id] = {}
if event_id not in event_to_synchronize[base_event_id]: if event_id not in event_to_synchronize[base_event_id]:
event_to_synchronize[base_event_id][event_id] = self.get_empty_synchro_summarize() event_to_synchronize[base_event_id][event_id] = self.get_empty_synchro_summarize()
@ -408,16 +400,16 @@ class google_calendar(osv.AbstractModel):
if event_to_synchronize[base_event_id][event_id]['GG_update']: if event_to_synchronize[base_event_id][event_id]['GG_update']:
event_to_synchronize[base_event_id][event_id]['GG_update'] =event_to_synchronize[base_event_id][event_id]['GG_update'].replace('T',' ').replace('Z','') event_to_synchronize[base_event_id][event_id]['GG_update'] =event_to_synchronize[base_event_id][event_id]['GG_update'].replace('T',' ').replace('Z','')
event_to_synchronize[base_event_id][event_id]['GG_status'] = (event.get('status') != 'cancelled') event_to_synchronize[base_event_id][event_id]['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 = event_to_synchronize[base_event][current_event] event = event_to_synchronize[base_event][current_event]
#If event are already in Gmail and in OpenERP #If event are already in Gmail and in OpenERP
if event['OE_found'] and event['GG_found']: if event['OE_found'] and event['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 !
@ -433,33 +425,33 @@ class google_calendar(osv.AbstractModel):
event['td_source'] = 'OE' event['td_source'] = 'OE'
if event['td_action'] != "None": if event['td_action'] != "None":
if event['%s_isRecurrence' % event['td_source']]: if event['%s_isRecurrence' % event['td_source']]:
if event['%s_status' % event['td_source']]: if event['%s_status' % event['td_source']]:
event['td_action'] = "UPDATE" event['td_action'] = "UPDATE"
event['td_comment'] = 'Only need to update, because i\'m active' event['td_comment'] = 'Only need to update, because i\'m active'
else: else:
event['td_action'] = "EXCLUDE" event['td_action'] = "EXCLUDE"
event['td_comment'] = 'Need to Exclude (Me = First event from recurrence) from recurrence' event['td_comment'] = 'Need to Exclude (Me = First event from recurrence) from recurrence'
elif event['%s_isInstance' % event['td_source']]: elif event['%s_isInstance' % event['td_source']]:
event['td_action'] = "UPDATE" event['td_action'] = "UPDATE"
event['td_comment'] = 'Only need to update, because already an exclu' event['td_comment'] = 'Only need to update, because already an exclu'
else: else:
event['td_action'] = "UPDATE" event['td_action'] = "UPDATE"
event['td_comment'] = 'Simply Update... I\'m a single event' event['td_comment'] = 'Simply Update... I\'m a single event'
else: else:
if not event['OE_synchro'] or event['OE_synchro'].split('.')[0] < event['OE_update'].split('.')[0]: if not event['OE_synchro'] or event['OE_synchro'].split('.')[0] < event['OE_update'].split('.')[0]:
event['td_source'] = 'OE' event['td_source'] = 'OE'
event['td_action'] = "UPDATE" event['td_action'] = "UPDATE"
event['td_comment'] = 'Event already updated by another user, but not synchro with my google calendar' event['td_comment'] = 'Event already updated by another user, but not synchro with my google calendar'
else: else:
event['td_action'] = "None" event['td_action'] = "None"
event['td_comment'] = 'Not update needed' event['td_comment'] = 'Not update needed'
else: else:
event['td_action'] = "None" event['td_action'] = "None"
event['td_comment'] = "Both are already deleted" event['td_comment'] = "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 event['OE_found'] and not event['GG_found']: elif event['OE_found'] and not event['GG_found']:
@ -474,10 +466,10 @@ class google_calendar(osv.AbstractModel):
elif event['GG_found'] and not event['OE_found']: elif event['GG_found'] and not event['OE_found']:
event['td_source'] = 'GG' event['td_source'] = 'GG'
if not event['GG_status'] and not event['GG_isInstance']: if not event['GG_status'] and not event['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
event['td_action'] = 'None' event['td_action'] = 'None'
event['td_comment'] = 'Nothing to do... Create and Delete directly' event['td_comment'] = 'Nothing to do... Create and Delete directly'
else: else:
if event['GG_isInstance']: if event['GG_isInstance']:
if event['%s_status' % event['td_source']]: if event['%s_status' % event['td_source']]:
@ -486,11 +478,9 @@ class google_calendar(osv.AbstractModel):
else: else:
event['td_action'] = "EXCLUDE" event['td_action'] = "EXCLUDE"
event['td_comment'] = 'Need to copy and Exclude' event['td_comment'] = 'Need to copy and Exclude'
else: else:
event['td_action'] = "CREATE" event['td_action'] = "CREATE"
event['td_comment'] = 'New EVENT CREATE from GMAIL' event['td_comment'] = 'New EVENT CREATE from GMAIL'
###################### ######################
# DO ACTION # # DO ACTION #
@ -515,14 +505,13 @@ class google_calendar(osv.AbstractModel):
# print " Action %s" % (event['td_action']) # print " Action %s" % (event['td_action'])
# print " Source %s" % (event['td_source']) # print " Source %s" % (event['td_source'])
# print " comment %s" % (event['td_comment']) # print " comment %s" % (event['td_comment'])
context['curr_attendee'] = event.get('OE_attendee_id',False) context['curr_attendee'] = event.get('OE_attendee_id',False)
actToDo = event['td_action'] actToDo = event['td_action']
actSrc = event['td_source'] actSrc = event['td_source']
if not actToDo: if not actToDo:
raise ("#!? WHAT I NEED TO DO ????") raise ("#!? WHAT I NEED TO DO ????")
else: else:
if actToDo == 'None': if actToDo == 'None':
continue continue
@ -545,7 +534,7 @@ class google_calendar(osv.AbstractModel):
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 actToDo == 'EXCLUDE' : elif 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:
@ -558,13 +547,13 @@ class google_calendar(osv.AbstractModel):
parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].get('OE_event_id') , new_google_event_id) parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].get('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].get('OE_event_id'): if event_to_synchronize[base_event][0][1].get('OE_event_id'):
parent_oe_id = event_to_synchronize[base_event][0][1].get('OE_event_id') parent_oe_id = event_to_synchronize[base_event][0][1].get('OE_event_id')
crm_meeting.unlink(cr,uid,"%s-%s" % (parent_oe_id,new_google_event_id),unlink_level=1,context=context) crm_meeting.unlink(cr,uid,"%s-%s" % (parent_oe_id,new_google_event_id),unlink_level=1,context=context)
elif actToDo == 'DELETE': elif 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':
crm_meeting.unlink(cr,uid,event['OE_event_id'],unlink_level=0,context=context) crm_meeting.unlink(cr,uid,event['OE_event_id'],unlink_level=0,context=context)
return True return True
@ -574,13 +563,11 @@ class google_calendar(osv.AbstractModel):
att_obj = self.pool.get('calendar.attendee') att_obj = self.pool.get('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
#new_events_ids = crm_meeting.search(cr, uid,[('partner_ids', 'in', myPartnerID),('google_internal_event_id', '=', False),('recurrent_id', '>', 0),'|',('active', '=', False),('active', '=', True)], context=context_norecurrent)
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:
@ -590,86 +577,96 @@ class google_calendar(osv.AbstractModel):
source_attendee_record = att_obj.browse(cr, uid, source_attendee_record_id, context) source_attendee_record = att_obj.browse(cr, uid, source_attendee_record_id, context)
if source_attendee_record: if source_attendee_record:
source_attendee_record = source_attendee_record[0] source_attendee_record = source_attendee_record[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 event.recurrent_id_date and source_attendee_record.google_internal_event_id: elif event.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) 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)
att_obj.write(cr, uid, [att.event_id.id], {'google_internal_event_id': new_google_internal_event_id}) att_obj.write(cr, uid, [att.event_id.id], {'google_internal_event_id': new_google_internal_event_id})
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):
gs_pool = self.pool.get('google.service')
params = {
'fields': 'sequence',
'access_token' : self.get_token(cr,uid,context)
}
headers = {'Content-type': 'application/json'}
url = "/calendar/v3/calendars/%s/events/%s" % ('primary',instance_id)
content = gs_pool._do_request(cr, uid, url, params, headers, type='GET', context=context)
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.get('res.users').browse(cr,uid,uid,context=context) current_user = self.pool.get('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.get('res.users').browse(cr,uid,uid,context=context) current_user = self.pool.get('res.users').browse(cr,uid,uid,context=context)
gs_pool = self.pool.get('google.service') gs_pool = self.pool.get('google.service')
refresh = current_user.google_calendar_rtoken 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.get('res.users').write(cr,SUPERUSER_ID,uid,vals,context=context) self.pool.get('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.get('res.users').browse(cr,uid,uid,context=context) current_user = self.pool.get('res.users').browse(cr,uid,uid,context=context)
return current_user.google_calendar_rtoken == False return current_user.google_calendar_rtoken == 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.get('google.service')._get_authorize_uri(cr,uid,from_url,self.STR_SERVICE,scope=self.get_calendar_scope(),context=context) url = self.pool.get('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.get('google.service') gs_pool = self.pool.get('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.get('res.users').write(cr,SUPERUSER_ID,uid,vals,context=context) self.pool.get('res.users').write(cr,SUPERUSER_ID,uid,vals,context=context)
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'),
} }
@ -684,7 +681,7 @@ class crm_meeting(osv.Model):
vals['oe_update_date'] = datetime.now() vals['oe_update_date'] = datetime.now()
return super(crm_meeting, self).write(cr, uid, ids, vals, context=context) return super(crm_meeting, self).write(cr, uid, ids, vals, context=context)
def copy(self, cr, uid, id, default=None, context=None): def copy(self, cr, uid, id, default=None, context=None):
default = default or {} default = default or {}
default['attendee_ids'] = False default['attendee_ids'] = False
@ -695,33 +692,33 @@ class crm_meeting(osv.Model):
else: else:
default['oe_update_date'] = False default['oe_update_date'] = False
return super(crm_meeting, self).copy(cr, uid, id, default, context) return super(crm_meeting, self).copy(cr, uid, id, default, context)
_columns = { _columns = {
'oe_update_date': fields.datetime('OpenERP Update Date'), 'oe_update_date': fields.datetime('OpenERP Update Date'),
} }
class calendar_attendee(osv.Model): class calendar_attendee(osv.Model):
_inherit = 'calendar.attendee' _inherit = 'calendar.attendee'
_columns = { _columns = {
'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 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.get('crm.meeting').write(cr, uid, ref, {'oe_update_date':datetime.now()},context) self.pool.get('crm.meeting').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)

View File

@ -30,7 +30,7 @@ openerp.google_calendar = function(instance) {
} }
else if (o.status == "need_config_from_admin") { else if (o.status == "need_config_from_admin") {
if (!_.IsUndefined(o.action) && parseInt(o.action)) { if (!_.isUndefined(o.action) && parseInt(o.action)) {
if (confirm(_t("An admin need to configure Google Synchronization before to use it, do you want to configure it now ? !"))) { if (confirm(_t("An admin need to configure Google Synchronization before to use it, do you want to configure it now ? !"))) {
self.do_action(o.action); self.do_action(o.action);
} }