summaryrefslogtreecommitdiff
path: root/addons/import_google/wizard/import_google.py
diff options
context:
space:
mode:
authorMeera Trambadia (OpenERP) <mtr@tinyerp.com>2011-09-16 11:11:38 +0530
committerMeera Trambadia (OpenERP) <mtr@tinyerp.com>2011-09-16 11:11:38 +0530
commitd979aad3de95ae24aa1db52cf17c4eecf3d3ce6b (patch)
tree592698c8e0dab53fcd157dd456a800bd4a80b5bf /addons/import_google/wizard/import_google.py
parenteea80125f7d1c739260929fb1f38866ef21439e1 (diff)
parentd101d3fbaaffe2d0219ac6cfeef50338a2501664 (diff)
[MERGE] branch merged with lp:openobject-addons
bzr revid: mtr@tinyerp.com-20110916054138-93b3caomaij5dyp4
Diffstat (limited to 'addons/import_google/wizard/import_google.py')
-rw-r--r--addons/import_google/wizard/import_google.py355
1 files changed, 355 insertions, 0 deletions
diff --git a/addons/import_google/wizard/import_google.py b/addons/import_google/wizard/import_google.py
new file mode 100644
index 00000000000..87155c806c6
--- /dev/null
+++ b/addons/import_google/wizard/import_google.py
@@ -0,0 +1,355 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import re
+import urllib
+import dateutil
+import pytz
+from dateutil import *
+from pytz import timezone
+from datetime import datetime
+import time
+from osv import *
+try:
+ import gdata
+ import gdata.contacts.service
+ import gdata.calendar.service
+ import gdata.contacts
+ import gdata.calendar
+except ImportError:
+ raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
+from import_base.import_framework import *
+from import_base.mapper import *
+
+class google_import(import_framework):
+
+ gd_client = False
+ calendars = False
+ contact = False
+ DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
+ TABLE_CONTACT = 'Contact'
+ TABLE_ADDRESS ='Address'
+ TABLE_EVENT = 'Events'
+
+ def initialize(self):
+ google = self.obj.pool.get('google.login')
+ self.external_id_field = 'Id'
+ self.gd_client = google.google_login(self.context.get('user'),
+ self.context.get('password'),
+ self.context.get('instance'))
+
+ if self.context.get('instance') and self.context.get('instance') == 'contact':
+ self.contact = self.context.get('contact')
+ if self.context.get('instance') and self.context.get('instance') == 'calendar':
+ self.calendars = self.context.get('calendars')
+
+ def get_mapping(self):
+ return {
+ self.TABLE_EVENT: self.get_event_mapping(),
+ self.TABLE_CONTACT: self.get_contact_mapping(),
+ self.TABLE_ADDRESS: self.get_address_mapping(),
+ }
+
+ def get_data(self, table):
+ data_fetching_function = {
+ self.TABLE_CONTACT: self.get_contact,
+ self.TABLE_ADDRESS: self.get_contact,
+ self.TABLE_EVENT: self.get_events,
+ }
+
+ return data_fetching_function.get(table)()
+
+
+ def _get_tinydates(self, stime, etime, au_tz):
+ stime = dateutil.parser.parse(stime)
+ etime = dateutil.parser.parse(etime)
+ try:
+ au_dt = au_tz.normalize(stime.replace(tzinfo=pytz.utc).astimezone(au_tz))
+ timestring = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
+ au_dt = au_tz.normalize(etime.replace(tzinfo=pytz.utc).astimezone(au_tz))
+ timestring_end = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
+ except:
+ timestring = datetime.datetime(*stime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
+ timestring_end = datetime.datetime(*etime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
+ return (timestring, timestring_end)
+
+ def _get_rules(self, datas):
+ new_val = {}
+ if datas['FREQ'] == 'WEEKLY' and datas.get('BYDAY'):
+ for day in datas['BYDAY'].split(','):
+ new_val[day.lower()] = True
+ datas.pop('BYDAY')
+
+ if datas.get('UNTIL'):
+ until = parser.parse(''.join((re.compile('\d')).findall(datas.get('UNTIL'))))
+ new_val['end_date'] = until.strftime('%Y-%m-%d')
+ new_val['end_type'] = 'end_date'
+ datas.pop('UNTIL')
+
+ if datas.get('COUNT'):
+ new_val['count'] = datas.get('COUNT')
+ new_val['end_type'] = 'count'
+ datas.pop('COUNT')
+
+ if datas.get('INTERVAL'):
+ new_val['interval'] = datas.get('INTERVAL')
+ else:
+ new_val['interval'] = 1
+
+ if datas.get('BYMONTHDAY'):
+ new_val['day'] = datas.get('BYMONTHDAY')
+ datas.pop('BYMONTHDAY')
+ new_val['select1'] = 'date'
+
+ if datas.get('BYDAY'):
+ d = datas.get('BYDAY')
+ if '-' in d:
+ new_val['byday'] = d[:2]
+ new_val['week_list'] = d[2:4].upper()
+ else:
+ new_val['byday'] = d[:1]
+ new_val['week_list'] = d[1:3].upper()
+ new_val['select1'] = 'day'
+
+ if datas.get('BYMONTH'):
+ new_val['month_list'] = datas.get('BYMONTH')
+ datas.pop('bymonth')
+ return new_val
+
+
+ def _get_repeat_status(self, str_google):
+ rrule = str_google[str_google.find('FREQ'):str_google.find('\nBEGIN')]
+ status = {}
+ for rule in rrule.split(';'):
+ status[rule.split('=')[0]] = rule.split('=')[-1:] and rule.split('=')[-1:][0] or ''
+ rules = self._get_rules(status)
+ if status.get('FREQ') == 'WEEKLY':
+ status.update({'rrule_type': 'weekly'})
+ status.pop('FREQ')
+ elif status.get('FREQ') == 'DAILY':
+ status.update({'rrule_type': 'daily'})
+ status.pop('FREQ')
+ elif status.get('FREQ') == 'MONTHLY':
+ status.update({'rrule_type': 'monthly'})
+ status.pop('FREQ')
+ elif status.get('FREQ') == 'YEARLY':
+ status.update({'rrule_type': 'yearly'})
+ status.pop('FREQ')
+ status.update(rules)
+ return status
+
+
+ def _get_repeat_dates(self, x):
+ if len(x) > 4:
+ if x[3].startswith('BY'):
+ zone_time = x[4].split('+')[-1:][0].split(':')[0][:4]
+ else:
+ zone_time = x[3].split('+')[-1:][0].split(':')[0][:4]
+ else:
+ zone_time = x[2].split('+')[-1:][0].split(':')[0][:4]
+ tz_format = zone_time[:2]+':'+zone_time[2:]
+ repeat_start = x[1].split('\n')[0].split(':')[1]
+ repeat_end = x[2].split('\n')[0].split(':')[1]
+ o = repeat_start.split('T')
+ repeat_start = str(o[0][:4]) + '-' + str(o[0][4:6]) + '-' + str(o[0][6:8])
+ if len(o) == 2:
+ repeat_start += ' ' + str(o[1][:2]) + ':' + str(o[1][2:4]) + ':' + str(o[1][4:6])
+ else:
+ repeat_start += ' ' + '00' + ':' + '00' + ':' + '00'
+ p = repeat_end.split('T')
+ repeat_end = str(p[0][:4]) + '-' + str(p[0][4:6]) + '-' + str(p[0][6:8])
+ if len(p) == 2:
+ repeat_end += ' ' + str(p[1][:2]) + ':' + str(p[1][2:4]) + ':' + str(p[1][4:6])
+ else:
+ repeat_end += ' ' + '00' + ':' + '00' + ':' + '00'
+ return (repeat_start, repeat_end, tz_format)
+
+ def get_events(self):
+ if 'tz' in self.context and self.context['tz']:
+ time_zone = self.context['tz']
+ else:
+ time_zone = tools.get_server_timezone()
+ au_tz = timezone(time_zone)
+ event_vals = []
+ for cal in self.calendars:
+ events_query = gdata.calendar.service.CalendarEventQuery(user=urllib.unquote(cal.split('/')[~0]))
+ events_query.start_index = 1
+ events_query.max_results = 1000
+ event_feed = self.gd_client.GetCalendarEventFeed(events_query.ToUri())
+ for feed in event_feed.entry:
+ event = {
+ 'recurrency': False,
+ 'end_date' : False,
+ 'end_type' : False,
+ 'byday': 0,
+ 'count' : 0,
+ 'interval': 1,
+ 'day': False,
+ 'select1': False,
+ 'week_list': "",
+ 'month_list': False,
+ 'rrule_type': False,
+ }
+
+ timestring = timestring_end = datetime.datetime.now().strftime(self.DATETIME_FORMAT)
+ if feed.when:
+ timestring, timestring_end = self._get_tinydates(feed.when[0].start_time, feed.when[0].end_time, au_tz)
+ else:
+ x = feed.recurrence.text.split(';')
+ repeat_status = self._get_repeat_status(feed.recurrence.text)
+ repeat_start, repeat_end, zone_time = self._get_repeat_dates(x)
+ timestring = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_start, "%Y-%m-%d %H:%M:%S"))
+ timestring_end = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_end, "%Y-%m-%d %H:%M:%S"))
+ if repeat_status:
+ repeat_status.update({'recurrency': True})
+ event.update(repeat_status)
+
+ event.update({'id' : feed.id.text,
+ 'DateStart': timestring,
+ 'DateEnd': timestring_end,
+ 'Category':event_feed.title.text,
+ 'Name': feed.title.text or 'No title',
+ 'Description': feed.content.text,
+ })
+ event_vals.append(event)
+ return event_vals
+
+
+ def get_event_category(self, val, name):
+ fields = ['name', 'object_id']
+ nameid = 'event_category_'+name
+ data = [name, 'crm.meeting']
+ return self.import_object(fields, data, 'crm.case.categ', "crm_case_categ", nameid, [('name', 'ilike', name)])
+
+ def get_rec(self, val):
+ if val.get("recurrency"):
+ return "1"
+ return "0"
+
+ def get_event_mapping(self):
+ return {
+ 'model': 'crm.meeting',
+ 'map': {
+ 'id': 'id',
+ 'name': 'Name',
+ 'description': 'Description',
+ 'email_from': 'Email',
+ 'date': 'DateStart',
+ 'date_deadline': 'DateEnd',
+ 'categ_id/id': call(self.get_event_category, value('Category')),
+ 'recurrency': self.get_rec,
+ 'end_date' : 'end_date',
+ 'end_type' : 'end_type',
+ 'byday':'byday',
+ 'count' : 'count',
+ 'interval': 'interval',
+ 'day': 'day',
+ 'select1': 'date',
+ 'week_list': 'week_list',
+ 'month_list':'month_list',
+ 'rrule_type': 'rrule_type',
+ }
+ }
+
+
+ def get_contact(self):
+ table = self.context.get('table')[0]
+ datas = []
+ if self.context.get('group_name'):
+ query = gdata.contacts.service.ContactsQuery()
+ query.group = self.context.get('group_name')
+ self.contact = self.gd_client.GetContactsFeed(query.ToUri())
+ else:
+ self.contact = self.gd_client.GetContactsFeed()
+ while self.contact:
+ for entry in self.contact.entry:
+ data = {}
+ data['id'] = entry.id.text
+ name = tools.ustr(entry.title.text)
+ if name == "None":
+ name = entry.email[0].address
+ data['name'] = name
+ emails = ','.join(email.address for email in entry.email)
+ data['email'] = emails
+ if table == 'Contact':
+ data.update({'customer': str(self.context.get('customer')),
+ 'supplier': str(self.context.get('supplier'))})
+ if entry.organization:
+ if entry.organization.org_name:
+ data.update({'company': entry.organization.org_name.text})
+ if entry.organization.org_title:
+ data.update ({'function': entry.organization.org_title.text})
+ if entry.phone_number:
+ for phone in entry.phone_number:
+ if phone.rel == gdata.contacts.REL_WORK:
+ data['phone'] = phone.text
+ if phone.rel == gdata.contacts.PHONE_MOBILE:
+ data['mobile'] = phone.text
+ if phone.rel == gdata.contacts.PHONE_WORK_FAX:
+ data['fax'] = phone.text
+ datas.append(data)
+ next = self.contact.GetNextLink()
+ self.contact = next and self.gd_client.GetContactsFeed(next.href) or None
+ return datas
+
+
+
+ def get_contact_mapping(self):
+ return {
+ 'model': 'res.partner',
+ 'dependencies': [self.TABLE_ADDRESS],
+ 'map': {
+ 'id':'id',
+ 'name': value('company', fallback='name'),
+ 'customer': 'customer',
+ 'supplier': 'supplier',
+ 'address/id': ref(self.TABLE_ADDRESS, 'id'),
+ }
+ }
+
+ def get_partner_id(self, val):
+ partner_id = False
+ company_pool = self.obj.pool.get('res.partner')
+ if 'company' in val:
+ partner_ids = company_pool.search(self.cr, self.uid, [('name', '=', val.get('company'))])
+ return partner_ids and partner_ids[0] or False
+ contact = self.xml_id_exist(self.TABLE_CONTACT, val.get('id'))
+ if contact:
+ partner_id = self.get_mapped_id(self.TABLE_CONTACT, val.get('id'))
+ return partner_id
+
+ def get_address_mapping(self):
+ return {
+ 'model': 'res.partner.address',
+ 'dependencies': [],
+ 'map': {
+ 'id':'id',
+ 'partner_id/.id': self.get_partner_id,
+ 'name': 'name',
+ 'city': 'city',
+ 'phone': 'phone',
+ 'mobile': 'mobile',
+ 'email': 'email',
+ 'fax': 'fax',
+ 'function': 'function'
+ }
+
+ }