[MERGE]:Merging the google_contact
[odoo/odoo.git] / addons / import_google / wizard / import_google.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import re
23 import urllib
24 import dateutil
25 from dateutil import *
26 from pytz import timezone
27 from datetime import datetime
28 import time
29 try:
30     import gdata
31     import gdata.contacts.service
32     import gdata.calendar.service
33     import gdata.contacts
34     import gdata.calendar
35 except ImportError:
36     raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
37 from import_base.import_framework import *
38 from import_base.mapper import *
39
40 class import_contact(import_framework):
41     
42     gd_client = False
43     calendars = False
44     DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
45     TABLE_CONTACT = 'contact'
46     TABLE_EVENT = 'Events'
47    
48     def initialize(self):
49         google = self.obj.pool.get('google.login')
50         self.external_id_field = 'Id'
51         self.gclient=self.context.get('gd_client', False)
52         self.gd_client = google.google_login(self.context.get('user'), 
53                                        self.context.get('password'), 
54                                         type = self.context.get('instance'))
55         if self.context.get('instance') and self.context.get('instance') == 'calendar':
56             self.calendars = self.context.get('calendars') 
57         
58     def get_mapping(self):
59         return { 
60             self.TABLE_EVENT: self.get_event_mapping(),
61             self.TABLE_CONTACT: self.get_contact_mapping(),
62             self.TABLE_ADDRESS: self.get_address_mapping(),
63         }
64         
65     def get_data(self, table):
66         val = {
67             self.TABLE_EVENT: self.get_events(),
68             self.TABLE_CONTACT: self.get_contact(),
69         }
70         return val.get(table)
71     
72
73     def _get_tinydates(self, stime, etime):
74         stime = dateutil.parser.parse(stime)
75         etime = dateutil.parser.parse(etime)
76         try:
77             au_dt = au_tz.normalize(stime.astimezone(au_tz))
78             timestring = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
79             au_dt = au_tz.normalize(etime.astimezone(au_tz))
80             timestring_end = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
81         except:
82             timestring = datetime.datetime(*stime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
83             timestring_end = datetime.datetime(*etime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
84         return (timestring, timestring_end)
85
86     def _get_rules(self, datas):
87         new_val = {}
88         if  datas['FREQ'] == 'WEEKLY' and datas.get('BYDAY'):
89             for day in datas['BYDAY'].split(','):
90                 new_val[day.lower()] = True
91             datas.pop('BYDAY')
92
93         if datas.get('UNTIL'):
94             until = parser.parse(''.join((re.compile('\d')).findall(datas.get('UNTIL'))))
95             new_val['end_date'] = until.strftime('%Y-%m-%d')
96             new_val['end_type'] = 'end_date'
97             datas.pop('UNTIL')
98
99         if datas.get('COUNT'):
100             new_val['count'] = datas.get('COUNT')
101             new_val['end_type'] = 'count'
102             datas.pop('COUNT')
103
104         if datas.get('INTERVAL'):
105             new_val['interval'] = datas.get('INTERVAL')
106         else:
107             new_val['interval'] = 1
108
109         if datas.get('BYMONTHDAY'):
110             new_val['day'] = datas.get('BYMONTHDAY')
111             datas.pop('BYMONTHDAY')
112             new_val['select1'] = 'date'
113
114         if datas.get('BYDAY'):
115             d = datas.get('BYDAY')
116             if '-' in d:
117                 new_val['byday'] = d[:2]
118                 new_val['week_list'] = d[2:4].upper()
119             else:
120                 new_val['byday'] = d[:1]
121                 new_val['week_list'] = d[1:3].upper()
122             new_val['select1'] = 'day'
123
124         if datas.get('BYMONTH'):
125             new_val['month_list'] = datas.get('BYMONTH')
126             datas.pop('bymonth')
127         return new_val
128
129
130     def _get_repeat_status(self, str_google):
131         rrule = str_google[str_google.find('FREQ'):str_google.find('\nBEGIN')]
132         status = {}
133         for rule in rrule.split(';'):
134             status[rule.split('=')[0]] = rule.split('=')[-1:] and rule.split('=')[-1:][0] or ''
135         rules = self._get_rules(status)
136         if status.get('FREQ') == 'WEEKLY':
137             status.update({'rrule_type': 'weekly'})
138             status.pop('FREQ')
139         elif status.get('FREQ') == 'DAILY':
140             status.update({'rrule_type': 'daily'})
141             status.pop('FREQ')
142         elif status.get('FREQ') == 'MONTHLY':
143             status.update({'rrule_type': 'monthly'})
144             status.pop('FREQ')
145         elif status.get('FREQ') == 'YEARLY':
146             status.update({'rrule_type': 'yearly'})
147             status.pop('FREQ')
148         status.update(rules)
149         return status
150
151
152     def _get_repeat_dates(self, x):
153         if len(x) > 4:
154             if x[3].startswith('BY'):
155                 zone_time = x[4].split('+')[-1:][0].split(':')[0][:4]
156             else:
157                 zone_time = x[3].split('+')[-1:][0].split(':')[0][:4]
158         else:
159             zone_time = x[2].split('+')[-1:][0].split(':')[0][:4]
160         tz_format = zone_time[:2]+':'+zone_time[2:]
161         repeat_start = x[1].split('\n')[0].split(':')[1]
162         repeat_end = x[2].split('\n')[0].split(':')[1]
163         o = repeat_start.split('T')
164         repeat_start = str(o[0][:4]) + '-' + str(o[0][4:6]) + '-' + str(o[0][6:8])
165         if len(o) == 2:
166             repeat_start += ' ' + str(o[1][:2]) + ':' + str(o[1][2:4]) + ':' + str(o[1][4:6])
167         else:
168             repeat_start += ' ' + '00' + ':' + '00' + ':' + '00'
169         p = repeat_end.split('T')
170         repeat_end = str(p[0][:4]) + '-' + str(p[0][4:6]) + '-' + str(p[0][6:8])
171         if len(p) == 2:
172             repeat_end += ' ' + str(p[1][:2]) + ':' + str(p[1][2:4]) + ':' + str(p[1][4:6])
173         else:
174             repeat_end += ' ' + '00' + ':' + '00' + ':' + '00'
175         return (repeat_start, repeat_end, tz_format)
176
177     def get_events(self):
178         if 'tz' in self.context and self.context['tz']:
179             time_zone = self.context['tz']
180         else:
181             time_zone = tools.get_server_timezone()
182         au_tz = timezone(time_zone)
183         event_vals = []            
184         for cal in self.calendars:
185             events_query = gdata.calendar.service.CalendarEventQuery(user=urllib.unquote(cal.split('/')[~0]))
186             events_query.start_index = 1
187             events_query.max_results = 1000
188             event_feed = self.gd_client.GetCalendarEventFeed(events_query.ToUri())
189             for feed in event_feed.entry:
190                 event = {            
191                     'recurrency': "0",
192                     'end_date' : False,
193                     'end_type' : False,
194                     'byday': 0,
195                     'count' : 0,
196                     'interval': 1,
197                     'day': False,
198                     'select1': False,
199                     'week_list': "",
200                     'month_list': False,
201                     'rrule_type': False,
202                 }
203
204                 timestring = timestring_end = datetime.datetime.now().strftime(self.DATETIME_FORMAT)
205                 if feed.when:
206                     timestring, timestring_end = self._get_tinydates(feed.when[0].start_time, feed.when[0].end_time)
207                 else:
208                     x = feed.recurrence.text.split(';')
209                     repeat_status = self._get_repeat_status(feed.recurrence.text)
210                     repeat_start, repeat_end, zone_time = self._get_repeat_dates(x)
211                     timestring = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_start, "%Y-%m-%d %H:%M:%S"))
212                     timestring_end = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_end, "%Y-%m-%d %H:%M:%S"))
213                     if repeat_status:
214                         repeat_status.update({'recurrency': True})
215                         event.update(repeat_status)
216
217                 event.update({'id' : feed.id.text,
218                               'DateStart': timestring, 
219                               'DateEnd': timestring_end,
220                               'Category':event_feed.title.text,
221                               'Name': feed.title.text or 'No title',
222                               'Description': feed.content.text, 
223                               })
224                 event_vals.append(event)
225         return event_vals
226
227
228     def get_event_category(self, val, name):
229         fields = ['name', 'object_id']
230         nameid = 'event_category_'+name
231         data = [name, 'crm.meeting']
232         return self.import_object(fields, data, 'crm.case.categ', "crm_case_categ", nameid, [('name', 'ilike', name)])
233
234     def get_event(self, val):
235         if val.get("recurrency"):
236             val.update({"recurrency": "1"})
237         return val
238     
239     def get_event_mapping(self):
240         return {
241             'model': 'crm.meeting',
242             'hook': self.get_event,
243             'map': {
244                     'id': 'id',
245                     'name': 'Name',
246                     'description': 'Description',
247                     'email_from': 'Email',
248                     'date': 'DateStart',
249                     'date_deadline': 'DateEnd',
250                     'categ_id/id': call(self.get_event_category, value('Category')),
251                     'recurrency': 'recurrency',
252                     'end_date' : 'end_date',
253                     'end_type' : 'end_type',
254                     'byday':'byday',
255                     'count' : 'count',
256                     'interval': 'interval',
257                     'day': 'day',
258                     'select1': 'date',
259                     'week_list': 'week_list',
260                     'month_list':'month_list',
261                     'rrule_type': 'rrule_type',
262                 }
263         }
264
265
266     def get_contact(self):
267         contact=self.gclient
268         gclient=self.context.get('client',False)
269         datas = [] 
270         while contact:      
271             for entry in contact.entry:
272                 data = {}
273                 data['id'] = entry.id.text
274                 name = tools.ustr(entry.title.text)
275                 if name == "None":
276                     name = entry.email[0].address
277                 data['name'] = name
278                 emails = ','.join(email.address for email in entry.email)
279                 data['email'] = emails
280                 if entry.organization:
281                     if entry.organization.org_name:
282                         data.update({'company': entry.organization.org_name.text})
283                     if entry.organization.org_title:
284                         data.update ({'function': entry.organization.org_title.text})
285                 if entry.phone_number:
286                     for phone in entry.phone_number:
287                         if phone.rel == gdata.contacts.REL_WORK:
288                             data['phone'] = phone.text
289                         if phone.rel == gdata.contacts.PHONE_MOBILE:
290                             data['mobile'] = phone.text
291                         if phone.rel == gdata.contacts.PHONE_WORK_FAX:
292                             data['fax'] = phone.text  
293                 datas.append(data)        
294             next = contact.GetNextLink()
295             contact = next and gclient.GetContactsFeed(next.href) or None     
296         return datas
297     
298     
299     def get_partner_address(self,val):
300             field_map = {
301                 'name': 'name',
302                 'type': 'Type',
303                 'city': 'city',
304                 'phone': 'phone',
305                 'mobile': 'mobile',
306                 'email': 'email',
307                 'fax': 'fax',
308             }
309             val.update({'Type':'contact'})
310             val.update({'id_new': val['id']+'address_contact' })
311             return self.import_object_mapping(field_map , val, 'res.partner.address', self.context.get('table')[0], val['id_new'], self.DO_NOT_FIND_DOMAIN)
312         
313     def get_contact_mapping(self):
314         return {
315             'model': 'res.partner',
316             'dependencies': [],
317             'map': {
318                 'name': 'name',
319                 'customer': str(self.context.get('customer')),
320                 'supplier': str(self.context.get('supplier')),
321                 'address/id': self.get_partner_address,
322                 }
323             }   
324                     
325     def get_address_mapping(self):
326         print"RRRRRRRRRREEElated to Address ONLY......................"
327         return {
328             'model': 'res.partner.address',
329             'dependencies': [],
330             'map': {
331                'name': 'name',
332                 'city': 'city',
333                 'phone': 'phone',
334                 'mobile': 'mobile',
335                 'email': 'email',
336                 'fax': 'fax'
337                 }
338         
339         }
340