[IMP]: Intregate history and email and bug to import_base module.
[odoo/odoo.git] / addons / import_sugarcrm / import_sugarcrm.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 from osv import fields, osv
22 import sugar
23 from tools.translate import _
24 from import_base.import_framework import *
25 from import_base.mapper import *
26 from datetime import datetime
27 import base64
28 import pprint
29 pp = pprint.PrettyPrinter(indent=4)
30
31 #copy old import here
32 class related_ref(dbmapper):
33     def __init__(self, type):
34         self.type = type
35         
36     def __call__(self, external_val):
37         if external_val.get('parent_type') in self.type and external_val.get('parent_id'):
38             return self.parent.xml_id_exist(external_val['parent_type'], external_val['parent_id'])
39         return ''
40
41
42 class sugar_import(import_framework):
43     TABLE_CONTACT = 'Contacts'
44     TABLE_ACCOUNT = 'Accounts'
45     TABLE_USER = 'Users'
46     TABLE_EMPLOYEE = 'Employees'
47     TABLE_RESSOURCE = "resource"
48     TABLE_OPPORTUNITY = 'Opportunities'
49     TABLE_LEAD = 'Leads'
50     TABLE_STAGE = 'crm_stage'
51     TABLE_CALL = 'Calls'
52     TABLE_MEETING = 'Meetings'
53     TABLE_TASK = 'Tasks'
54     TABLE_PROJECT = 'Project'
55     TABLE_PROJECT_TASK = 'ProjectTask'
56     TABLE_BUG = 'Bugs'
57     TABLE_CASE = 'Cases'
58     TABLE_NOTE = 'Notes'
59     TABLE_EMAIL = 'Emails'
60     TABLE_DOCUMENT = 'DocumentRevisions'
61     
62     
63     def initialize(self):
64         #login
65         PortType,sessionid = sugar.login(self.context.get('username',''), self.context.get('password',''), self.context.get('url',''))
66         self.context['port'] = PortType
67         self.context['session_id'] = sessionid
68         
69     def get_data(self, table):
70         return sugar.search(self.context.get('port'), self.context.get('session_id'), table)
71     """
72         Common import method
73     """
74     def get_category(self, val, model, name):
75         fields = ['name', 'object_id']
76         data = [name, model]
77         return self.import_object(fields, data, 'crm.case.categ', 'crm_categ', name, [('object_id.model','=',model), ('name', 'ilike', name)])
78
79     def get_job_title(self, dict, salutation):
80         fields = ['shortcut', 'name', 'domain']
81         if salutation:
82             data = [salutation, salutation, 'Contact']
83             return self.import_object(fields, data, 'res.partner.title', 'contact_title', salutation, [('shortcut', '=', salutation)])
84
85     def get_campaign_id(self, dict, val):
86         fields = ['name']
87         data = [val]
88         return self.import_object(fields, data, 'crm.case.resource.type', 'crm_campaign', val)
89     
90     def get_all_states(self, external_val, country_id):
91         """Get states or create new state unless country_id is False"""
92         state_code = external_val[0:3] #take the tree first char
93         fields = ['country_id/id', 'name', 'code']
94         data = [country_id, external_val, state_code]
95         if country_id:
96             return self.import_object(fields, data, 'res.country.state', 'country_state', external_val) 
97         return False
98
99     def get_all_countries(self, val):
100         """Get Country, if no country match do not create anything, to avoid duplicate country code"""
101         return self.mapped_id_if_exist('res.country', [('name', 'ilike', val)], 'country', val)
102     
103     def get_float_time(self, dict, hour, min):
104         min = int(min) * 100 / 60
105         return "%s.%i" % (hour, min)
106     
107     """
108     import Documents
109     """
110     
111     def import_document(self, val):
112         
113         filepath = '/var/www/sugarcrm/cache/upload/'+ val.get('id')
114         f = open(filepath, "r")
115         datas = f.read()
116         f.close()
117         val['datas'] = base64.encodestring(datas)
118         val['datas_fname'] = val.get('filename')
119         return val   
120         
121     def get_document_mapping(self): 
122         return { 
123                 'model' : 'ir.attachment',
124                 'dependencies' : [self.TABLE_USER],
125                 'hook' : self.import_document,
126                 'map' : {'name':'filename',
127                          'description': 'description',
128                          'datas': 'datas',
129                          'datas_fname': 'datas_fname',
130                 }
131             }     
132
133     """
134     import Emails
135     """
136     
137     def import_email(self, val):
138         model_obj =  self.obj.pool.get('ir.model.data')
139         xml_id = self.xml_id_exist(val.get('parent_type'), val.get('parent_type'))
140         xml_id = self.xml_id_exist(history_attachment, val.get('parent_type'))
141         model_ids = model_obj.search(self.cr, self.uid, [('name', 'like', xml_id)])
142         if model_ids:
143               model = model_obj.browse(self.cr, self.uid, model_ids)[0]
144               if model.model == 'res.partner':
145                     val['partner_id/.id'] = model.res_id
146               else:    
147                     val['res_id'] = model.res_id
148                     val['model'] = model.model
149         return val   
150         
151     def get_email_mapping(self): 
152         return { 
153                 'model' : 'mailgate.message',
154                 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT, self.TABLE_PROJECT_TASK, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD, self.TABLE_OPPORTUNITY, self.TABLE_MEETING, self.TABLE_CALL],
155                 'hook' : self.import_email,
156                 'map' : {'name':'name',
157                         'date':'date_sent',
158                         'email_from': 'from_addr_name',
159                         'email_to': 'reply_to_addr',
160                         'email_cc': 'cc_addrs_names',
161                         'email_bcc': 'bcc_addrs_names',
162                         'message_id': 'message_id',
163                         'res_id': 'res_id',
164                         'model': 'model',
165                         'partner_id/.id': 'partner_id/.id',                         
166                         'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
167                         'description': ppconcat('__prettyprint__','description', 'description_html'),
168                 }
169             } 
170     
171     
172     """
173     import History(Notes)
174     """
175     def get_attachment(self, val):
176         File, Filename = sugar.attachment_search(self.context.get('port'), self.context.get('session_id'), self.TABLE_NOTE, val.get('id'))    
177         attachment_obj = self.obj.pool.get('ir.attachment')
178         model_obj = self.obj.pool.get('ir.model.data')
179         mailgate_obj = self.obj.pool.get('mailgate.message')
180         fields = ['name', 'datas', 'res_id', 'res_model']
181         datas = [val.get('name'), File, val.get('res_id'),val.get('model',False)]
182         self.import_object(fields, datas, 'ir.attachment', 'history_attachment', val.get('name'), [('res_id', '=', val.get('res_id'), ('model', '=', val.get('model')))])
183         return True    
184
185     def import_history(self, val):
186         model_obj =  self.obj.pool.get('ir.model.data')
187         xml_id = self.xml_id_exist(val.get('parent_type'), val.get('parent_id'))
188         model_ids = model_obj.search(self.cr, self.uid, [('name', 'like', xml_id)])
189         if model_ids:
190               model = model_obj.browse(self.cr, self.uid, model_ids)[0]
191               if model.model == 'res.partner':
192                     val['partner_id/.id'] = model.res_id
193               else:    
194                     val['res_id'] = model.res_id
195                     val['model'] = model.model
196         get_attachment(val)            
197         return val    
198     
199     def get_history_mapping(self): 
200         return { 
201                 'model' : 'mailgate.message',
202                 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT, self.TABLE_PROJECT_TASK, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD, self.TABLE_OPPORTUNITY, self.TABLE_MEETING, self.TABLE_CALL],
203                 'hook' : self.import_history,
204                 'map' : {
205                       'name':'name',
206                       'date': 'date_entered',
207                       'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
208                       'description': ppconcat('__prettyprint__','description', 'description_html'),
209                       'res_id': 'res_id',
210                       'model': 'model',
211                       'partner_id/.id' : 'partner_id/.id',
212                 }
213             }     
214     
215     """
216     import Claims(Cases)
217     """
218     def get_claim_priority(self, val):
219         priority_dict = {            
220                 'High': '2',
221                 'Medium': '3',
222                 'Low': '4'
223         }
224         return priority_dict.get(val.get('priority'), '')
225         
226     def get_contact_info_from_account(self, val):
227         partner_id = self.get_mapped_id(self.TABLE_ACCOUNT, val.get('account_id'))
228         partner_address_id = False
229         partner_phone = False
230         partner_email = False
231         partner = self.obj.pool.get('res.partner').browse(self.cr, self.uid, [partner_id])[0]
232         if partner.address and partner.address[0]:
233             address = partner.address[0]
234             partner_address_id = address.id
235             partner_phone = address.phone
236             partner_email = address.email
237         return partner_address_id, partner_phone,partner_email
238     
239     def import_crm_claim(self, val):
240         partner_address_id, partner_phone,partner_email =  self.get_contact_info_from_account(val)
241         val['partner_address_id/.id'] = partner_address_id
242         val['partner_address_id/.id'] = partner_address_id
243         val['partner_phone'] = partner_phone
244         val['email_from'] = partner_email
245         return val
246     
247     def get_crm_claim_mapping(self): 
248         return { 
249                 'model' : 'crm.claim',
250                 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD],
251                 'hook' : self.import_crm_claim,
252                 'map' : {
253                     'name': 'name',
254                     'date': 'date_entered',
255                     'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
256                     'description': 'description',
257                     'partner_id/id': ref(self.TABLE_ACCOUNT, 'account_id'),
258                     'partner_address_id/.id': 'partner_address_id/.id',
259                     'partner_phone': 'partner_phone',
260                     'email_from': 'email_from',                                        
261                     'priority': self.get_claim_priority,
262                     'state': map_val('status', self.project_issue_state)
263                 }
264             }    
265     """
266     Import Project Issue(Bugs)
267     """
268     project_issue_state = {
269             'New' : 'draft',
270             'Assigned':'open',
271             'Closed': 'done',
272             'Pending': 'pending',
273             'Rejected': 'cancel',
274     }
275      
276     def get_project_issue_priority(self, val):
277         priority_dict = {
278                 'Urgent': '1',
279                 'High': '2',
280                 'Medium': '3',
281                 'Low': '4'
282          }
283         return priority_dict.get(val.get('priority'), '')     
284       
285     def get_bug_project_id(self, dict, val):
286         fields = ['name']
287         data = [val]
288         return self.import_object(fields, data, 'project.project', 'project_issue', val)    
289     
290     def get_project_issue_mapping(self):
291         return { 
292                 'model' : 'project.issue',
293                 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT, self.TABLE_PROJECT_TASK],
294                 'map' : {
295                     'name': 'name',
296                     'project_id/id': call(self.get_bug_project_id, 'sugarcrm_bugs'),
297                     'categ_id/id': call(self.get_category, 'project.issue', value('type')),
298                     'description': ppconcat('__prettyprint__','description', 'bug_number', 'fixed_in_release_name', 'source', 'fixed_in_release', 'work_log', 'found_in_release', 'release_name', 'resolution'),
299                     'priority': self.get_project_issue_priority,
300                     'state': map_val('status', self.project_issue_state)
301                 }
302             }
303     
304     """
305     import Project Tasks
306     """
307     project_task_state = {
308             'Not Started': 'draft',
309             'In Progress': 'open',
310             'Completed': 'done',
311             'Pending Input': 'pending',
312             'Deferred': 'cancelled',
313      }
314     
315     def get_project_task_priority(self, val):
316       priority_dict = {
317             'High': '0',
318             'Medium': '2',
319             'Low': '3'
320         }
321       return priority_dict.get(val.get('priority'), '')
322
323     def get_project_task_mapping(self):
324         return { 
325                 'model' : 'project.task',
326                 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT],
327                 'map' : {
328                     'name': 'name',
329                     'date_start': 'date_start',
330                     'date_end': 'date_finish',
331                     'progress': 'progress',
332                     'project_id/id': ref(self.TABLE_PROJECT, 'project_id'),
333                     'planned_hours': 'planned_hours',
334                     'total_hours': 'total_hours',        
335                     'priority': self.get_project_task_priority,
336                     'description': 'description',
337                     'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
338                     'partner_id/id': 'partner_id/id',
339                     'contact_id/id': 'contact_id/id',
340                     'state': map_val('status', self.project_task_state)
341                 }
342             }
343
344     """
345     import Projects
346     """
347     project_state = {
348             'Draft' : 'draft',
349             'In Review': 'open',
350             'Published': 'close'
351      }
352     def import_project_account(self, val):
353         partner_id = False
354         partner_invoice_id = False        
355         model_obj = self.obj.pool.get('ir.model.data')
356         partner_obj = self.obj.pool.get('res.partner')
357         partner_address_obj = self.obj.pool.get('res.partner.address')
358         sugar_project_account = sugar.relation_search(self.context.get('port'), self.context.get('session_id'), 'Project', module_id=val.get('id'), related_module=self.TABLE_ACCOUNT, query=None, deleted=None)
359         sugar_project_contact = sugar.relation_search(self.context.get('port'), self.context.get('session_id'), 'Project', module_id=val.get('id'), related_module=self.TABLE_CONTACT, query=None, deleted=None)
360         for contact_id in sugar_project_contact:
361             partner_invoice_id = self.get_mapped_id(self.TABLE_CONTACT, contact_id)
362         for account_id in sugar_project_account:
363             partner_id = self.get_mapped_id(self.TABLE_ACCOUNT, account_id)
364         return partner_id, partner_invoice_id      
365            
366     def import_project(self, val):
367         partner_id, partner_invoice_id  = self.import_project_account(val)    
368         val['partner_id/.id'] = partner_id
369         val['contact_id/.id'] = partner_invoice_id
370         return val
371     
372     def get_project_mapping(self):
373         return { 
374                 'model' : 'project.project',
375                 'dependencies' : [self.TABLE_CONTACT, self.TABLE_ACCOUNT, self.TABLE_USER],
376                 'hook' : self.import_project,
377                 'map' : {
378                     'name': 'name',
379                     'date_start': 'estimated_start_date',
380                     'date': 'estimated_end_date',
381                     'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
382                     'partner_id/.id': 'partner_id/.id',
383                     'contact_id/.id': 'contact_id/.id',
384                     'state': map_val('status', self.project_state)
385                 }
386             }
387     
388     """
389     import Tasks
390     """
391     task_state = {
392             'Completed' : 'done',
393             'Not Started':'draft',
394             'In Progress': 'open',
395             'Pending Input': 'draft',
396             'deferred': 'cancel'
397         }
398
399     def import_task(self, val):
400         val['date'] = val.get('date_start') or datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
401         val['date_deadline'] = val.get('date_due') or datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
402         return val
403
404     def get_task_mapping(self):
405         return { 
406                 'model' : 'crm.meeting',
407                 'dependencies' : [self.TABLE_CONTACT, self.TABLE_ACCOUNT, self.TABLE_USER],
408                 'hook' : self.import_task,
409                 'map' : {
410                     'name': 'name',
411                     'date': 'date',
412                     'date_deadline': 'date_deadline',
413                     'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
414                     'categ_id/id': call(self.get_category, 'crm.meeting', const('Tasks')),
415                     'partner_id/id': related_ref(self.TABLE_ACCOUNT),
416                     'partner_address_id/id': ref(self.TABLE_CONTACT,'contact_id'),
417                     'state': map_val('status', self.task_state)
418                 }
419             }
420        
421     """
422     import Calls
423     """     
424     call_state = {   
425             'Planned' : 'open',
426             'Held':'done',
427             'Not Held': 'pending',
428         }
429
430     def get_calls_mapping(self):
431         return { 
432                 'model' : 'crm.phonecall',
433                 'dependencies' : [self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_OPPORTUNITY, self.TABLE_LEAD],
434                 'map' : {
435                     'name': 'name',
436                     'date': 'date_start',
437                     'duration': call(self.get_float_time, value('duration_hours'), value('duration_minutes')),
438                     'user_id/id':  ref(self.TABLE_USER, 'assigned_user_id'),
439                     'partner_id/id': related_ref(self.TABLE_ACCOUNT),
440                     'partner_address_id/id': related_ref(self.TABLE_CONTACT),
441                     'categ_id/id': call(self.get_category, 'crm.phonecall', value('direction')),
442                     'opportunity_id/id': related_ref(self.TABLE_OPPORTUNITY),
443                     'description': 'description',   
444                     'state': map_val('status', self.call_state)                      
445                 }
446             }        
447         
448     """
449         import meeting
450     """
451     meeting_state = {
452             'Planned' : 'draft',
453             'Held': 'open',
454             'Not Held': 'draft', 
455         }
456     
457     def get_alarm_id(self, dict_val, val):
458         alarm_dict = {
459             '60': '1 minute before',
460             '300': '5 minutes before',
461             '600': '10 minutes before',
462             '900': '15 minutes before',
463             '1800':'30 minutes before',
464             '3600': '1 hour before',
465         }
466         return self.mapped_id_if_exist('res.alarm', [('name', 'like', alarm_dict.get(val))], 'alarm', val)
467     
468     #TODO attendees
469     def get_meeting_mapping(self):
470         return { 
471                 'model' : 'crm.meeting',
472                 'dependencies' : [self.TABLE_CONTACT, self.TABLE_OPPORTUNITY, self.TABLE_LEAD],
473                 'map' : {
474                     'name': 'name',
475                     'date': 'date_start',
476                     'duration': call(self.get_float_time, value('duration_hours'), value('duration_minutes')),
477                     'location': 'location',
478                     'alarm_id/id': call(self.get_alarm_id, value('reminder_time')),
479                     'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
480                     'partner_id/id': related_ref(self.TABLE_ACCOUNT),
481                     'partner_address_id/id': related_ref(self.TABLE_CONTACT),
482                     'state': map_val('status', self.meeting_state)
483                 }
484             }
485     
486     """
487         import Opportunity
488     """
489     def get_opportunity_status(self, sugar_val):
490         fields = ['name', 'type']
491         name = 'Opportunity_' + sugar_val['sales_stage']
492         data = [sugar_val['sales_stage'], 'Opportunity']
493         return self.import_object(fields, data, 'crm.case.stage', self.TABLE_STAGE, name, [('type', '=', 'opportunity'), ('name', 'ilike', sugar_val['sales_stage'])])
494     
495     def import_opportunity_contact(self, val):
496         sugar_opportunities_contact = set(sugar.relation_search(self.context.get('port'), self.context.get('session_id'), 'Opportunities', module_id=val.get('id'), related_module='Contacts', query=None, deleted=None))
497             
498         partner_contact_id = False 
499         partner_contact_email = False       
500         partner_address_obj = self.obj.pool.get('res.partner.address')
501         partner_xml_id = self.name_exist(self.TABLE_ACCOUNT, val['account_name'], 'res.partner')
502         
503         for contact in sugar_opportunities_contact:
504             address_id = self.get_mapped_id(self.TABLE_CONTACT, contact)
505             if address_id:                    
506                 address = partner_address_obj.browse(self.cr, self.uid, address_id)
507                 partner_name = address.partner_id and address.partner_id.name or False
508                 if not partner_name: #link with partner id 
509                     fields = ['partner_id/id']
510                     data = [partner_xml_id]
511                     self.import_object(fields, data, 'res.partner.address', self.TABLE_CONTACT, contact, self.DO_NOT_FIND_DOMAIN)
512                 if not partner_name or partner_name == val.get('account_name'):
513                     partner_contact_id = self.xml_id_exist(self.TABLE_CONTACT, contact)
514                     partner_contact_email = address.email
515         return partner_contact_id, partner_contact_email
516
517     def import_opp(self, val):    
518         partner_contact_name, partner_contact_email = self.import_opportunity_contact(val)
519         val['partner_address_id/id'] = partner_contact_name
520         val['email_from'] = partner_contact_email
521         return val
522     
523     def get_opp_mapping(self):
524         return {
525             'model' : 'crm.lead',
526             'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT],
527             'hook' : self.import_opp,
528             'map' :  {
529                 'name': 'name',
530                 'probability': 'probability',
531                 'partner_id/id': refbyname(self.TABLE_ACCOUNT, 'account_name', 'res.partner'),
532                 'title_action': 'next_step',
533                 'partner_address_id/id': 'partner_address_id/id',
534                 'planned_revenue': 'amount',
535                 'date_deadline': 'date_closed',
536                 'user_id/id' : ref(self.TABLE_USER, 'assigned_user_id'),
537                 'stage_id/id' : self.get_opportunity_status,
538                 'type' : const('opportunity'),
539                 'categ_id/id': call(self.get_category, 'crm.lead', value('opportunity_type')),
540                 'email_from': 'email_from',
541                 'state' : const('open'), #TODO
542             }
543         }
544     
545     """
546         import lead
547     """
548     def get_lead_status(self, sugar_val):
549         fields = ['name', 'type']
550         name = 'lead_' + sugar_val.get('status', '')
551         data = [sugar_val.get('status', ''), 'lead']
552         return self.import_object(fields, data, 'crm.case.stage', self.TABLE_STAGE, name, [('type', '=', 'lead'), ('name', 'ilike', sugar_val.get('status', ''))])
553
554     lead_state = {
555         'New' : 'draft',
556         'Assigned':'open',
557         'In Progress': 'open',
558         'Recycled': 'cancel',
559         'Dead': 'done',
560         'Converted': 'done',
561     }
562
563     
564     def import_lead(self, val):
565         if val.get('opportunity_id'): #if lead is converted into opp, don't import as lead
566             return False
567         if val.get('primary_address_country'):
568             country_id = self.get_all_countries(val.get('primary_address_country'))
569             val['country_id/id'] =  country_id
570             val['state_id/id'] =  self.get_all_states(val.get('primary_address_state'), country_id)
571         return val
572     
573     def get_lead_mapping(self):
574         return {
575             'model' : 'crm.lead',
576             'hook' : self.import_lead,
577             'map' : {
578                 'name': concat('first_name', 'last_name'),
579                 'contact_name': concat('first_name', 'last_name'),
580                 'description': ppconcat('description', 'refered_by', 'lead_source', 'lead_source_description', 'website', 'email2', 'status_description', 'lead_source_description', 'do_not_call'),
581                 'partner_name': 'account_name',
582                 'email_from': 'email1',
583                 'phone': 'phone_work',
584                 'mobile': 'phone_mobile',
585                 'title/id': call(self.get_job_title, value('salutation')),
586                 'function':'title',
587                 'street': 'primary_address_street',
588                 'street2': 'alt_address_street',
589                 'zip': 'primary_address_postalcode',
590                 'city':'primary_address_city',
591                 'user_id/id' : ref(self.TABLE_USER, 'assigned_user_id'),
592                 'stage_id/id' : self.get_lead_status,
593                 'type' : const('lead'),
594                 'state': map_val('status', self.lead_state) ,
595                 'fax': 'phone_fax',
596                 'referred': 'refered_by',
597                 'optout': 'do_not_call',
598                 'type_id/id': call(self.get_campaign_id, value('lead_source')),
599                 'country_id/id': 'country_id/id',
600                 'state_id/id': 'state_id/id'
601                 } 
602         }
603     
604     """
605         import contact
606     """
607     def get_email(self, val):
608         return val.get('email1') + ','+ val.get('email2')
609     
610     def import_contact(self, val):
611         if val.get('primary_address_country'):
612             country_id = self.get_all_countries(val.get('primary_address_country'))
613             state = self.get_all_states(val.get('primary_address_state'), country_id)
614             val['country_id/id'] =  country_id
615             val['state_id/id'] =  state  
616         return val    
617         
618     def get_contact_mapping(self):
619         return { 
620             'model' : 'res.partner.address',
621             'dependencies' : [self.TABLE_ACCOUNT],
622             'hook' : self.import_contact,
623             'map' :  {
624                 'name': concat('first_name', 'last_name'),
625                 'partner_id/id': ref(self.TABLE_ACCOUNT,'account_id'),
626                 'phone': 'phone_work',
627                 'mobile': 'phone_mobile',
628                 'fax': 'phone_fax',
629                 'function': 'title',
630                 'street': 'primary_address_street',
631                 'zip': 'primary_address_postalcode',
632                 'city': 'primary_address_city',
633                 'country_id/id': 'country_id/id',
634                 'state_id/id': 'state_id/id',
635                 'email': self.get_email,
636                 'type': const('contact')
637             }
638         }
639     
640     """ 
641         import Account
642     """
643     def get_address_type(self, val, type):
644         if type == 'invoice':
645             type_address = 'billing'
646         else:
647             type_address = 'shipping'     
648     
649         map_partner_address = {
650             'name': 'name',
651             'phone': 'phone_office',
652             'mobile': 'phone_mobile',
653             'fax': 'phone_fax',
654             'type': 'type',
655             'street': type_address + '_address_street',
656             'zip': type_address +'_address_postalcode',
657             'city': type_address +'_address_city',
658              'country_id/id': 'country_id/id',
659              'type': 'type',
660             }
661         
662         if val.get(type_address +'_address_country'):
663             country_id = self.get_all_countries(val.get(type_address +'_address_country'))
664             state = self.get_all_states(val.get(type_address +'_address_state'), country_id)
665             val['country_id/id'] =  country_id
666             val['state_id/id'] =  state
667         val['type'] = type
668         val['id_new'] = val['id'] + '_address_' + type
669         return self.import_object_mapping(map_partner_address, val, 'res.partner.address', self.TABLE_CONTACT, val['id_new'], self.DO_NOT_FIND_DOMAIN) 
670     
671     def get_partner_address(self, val):
672         address_id=[]
673         type_dict = {'billing_address_street' : 'invoice', 'shipping_address_street' : 'delivery'}
674         for key, type_value in type_dict.items():
675             if val.get(key):
676                 id = self.get_address_type(val, type_value)
677                 address_id.append(id)
678           
679         return ','.join(address_id)
680     
681     def get_partner_mapping(self):
682         return {
683                 'model' : 'res.partner',
684                 'dependencies' : [self.TABLE_USER],
685                 'map' : {
686                     'name': 'name',
687                     'website': 'website',
688                     'user_id/id': ref(self.TABLE_USER,'assigned_user_id'),
689                     'ref': 'sic_code',
690                     'comment': ppconcat('description', 'employees', 'ownership', 'annual_revenue', 'rating', 'industry', 'ticker_symbol'),
691                     'customer': const('1'),
692                     'supplier': const('0'),
693                     'address/id':'address/id', 
694                     'parent_id/id_parent' : 'parent_id',
695                     'address/id' : self.get_partner_address,
696                 }
697         }
698
699     """
700         import Employee
701     """
702     def get_ressource(self, val):
703         map_resource = { 
704             'name': concat('first_name', 'last_name'),
705         }        
706         return self.import_object_mapping(map_resource, val, 'resource.resource', self.TABLE_RESSOURCE, val['id'], self.DO_NOT_FIND_DOMAIN)
707     
708     def get_job_id(self, val):
709         fields = ['name']
710         data = [val.get('title')]
711         return self.import_object(fields, data, 'hr.job', 'hr_job', val.get('title'))
712
713     def get_user_address(self, val):
714         map_user_address = {
715             'name': concat('first_name', 'last_name'),
716             'city': 'address_city',
717             'country_id/id': 'country_id/id',
718             'state_id/id': 'state_id/id',
719             'street': 'address_street',
720             'zip': 'address_postalcode',
721             'fax': 'fax',
722         }
723         
724         if val.get('address_country'):
725             country_id = self.get_all_countries(val.get('address_country'))
726             state_id = self.get_all_states(val.get('address_state'), country_id)
727             val['country_id/id'] =  country_id
728             val['state_id/id'] =  state_id
729             
730         return self.import_object_mapping(map_user_address, val, 'res.partner.address', self.TABLE_CONTACT, val['id'], self.DO_NOT_FIND_DOMAIN)
731     
732     def get_employee_mapping(self):
733         return {
734             'model' : 'hr.employee',
735             'dependencies' : [self.TABLE_USER],
736             'map' : {
737                 'resource_id/id': self.get_ressource, 
738                 'name': concat('first_name', 'last_name'),
739                 'work_phone': 'phone_work',
740                 'mobile_phone':  'phone_mobile',
741                 'user_id/id': ref(self.TABLE_USER, 'id'), 
742                 'address_home_id/id': self.get_user_address,
743                 'notes': 'description',
744                 'job_id/id': self.get_job_id,
745             }
746      }
747     
748     """
749         import user
750     """  
751     def import_user(self, val):
752         user_obj = self.obj.pool.get('res.users')
753         user_ids = user_obj.search(self.cr, self.uid, [('login', '=', val.get('user_name'))])
754         if user_ids: 
755             val['.id'] = str(user_ids[0])
756         else:
757             val['password'] = 'sugarcrm' #default password for all user #TODO needed in documentation
758             
759         val['context_lang'] = self.context.get('lang','en_US')
760         return val
761     
762     def get_users_department(self, val):
763         dep = val.get('department')
764         fields = ['name']
765         data = [dep]
766         if not dep:
767             return False
768         return self.import_object(fields, data, 'hr.department', 'hr_department_user', dep)
769
770     def get_user_mapping(self):
771         return {
772             'model' : 'res.users',
773             'hook' : self.import_user,
774             'map' : { 
775                 'name': concat('first_name', 'last_name'),
776                 'login': 'user_name',
777                 'context_lang' : 'context_lang',
778                 'password' : 'password',
779                 '.id' : '.id',
780                 'context_department_id/id': self.get_users_department,
781             }
782         }
783
784     def get_mapping(self):
785         return {
786             self.TABLE_USER : self.get_user_mapping(),
787             self.TABLE_EMPLOYEE : self.get_employee_mapping(),
788             self.TABLE_ACCOUNT : self.get_partner_mapping(),
789             self.TABLE_CONTACT : self.get_contact_mapping(),
790             self.TABLE_LEAD : self.get_lead_mapping(),
791             self.TABLE_OPPORTUNITY : self.get_opp_mapping(),
792             self.TABLE_MEETING : self.get_meeting_mapping(),
793             self.TABLE_CALL : self.get_calls_mapping(),
794             self.TABLE_TASK : self.get_task_mapping(),
795             self.TABLE_PROJECT : self.get_project_mapping(),
796             self.TABLE_PROJECT_TASK: self.get_project_task_mapping(),
797             self.TABLE_BUG: self.get_project_issue_mapping(),
798             self.TABLE_CASE: self.get_crm_claim_mapping(),
799             self.TABLE_NOTE: self.get_history_mapping(),
800             self.TABLE_EMAIL: self.get_email_mapping(),
801             self.TABLE_DOCUMENT: self.get_document_mapping()
802             
803         }
804
805
806
807
808
809 class import_sugarcrm(osv.osv):
810     """Import SugarCRM DATA"""
811     
812     _name = "import.sugarcrm"
813     _description = __doc__
814     _columns = {
815                 
816         'opportunity': fields.boolean('Leads and Opportunities', help="If Opportunities are checked, SugarCRM opportunities data imported in OpenERP crm-Opportunity form"),
817         'user': fields.boolean('Users', help="If Users  are checked, SugarCRM Users data imported in OpenERP Users form"),
818         'contact': fields.boolean('Contacts', help="If Contacts are checked, SugarCRM Contacts data imported in OpenERP partner address form"),
819         'account': fields.boolean('Accounts', help="If Accounts are checked, SugarCRM  Accounts data imported in OpenERP partners form"),
820         'employee': fields.boolean('Employee', help="If Employees is checked, SugarCRM Employees data imported in OpenERP employees form"),
821         'meeting': fields.boolean('Meetings', help="If Meetings is checked, SugarCRM Meetings data imported in OpenERP meetings form"),
822         'call': fields.boolean('Calls', help="If Calls is checked, SugarCRM Calls data imported in OpenERP phonecalls form"),
823         'claim': fields.boolean('Claims', help="If Claims is checked, SugarCRM Claims data imported in OpenERP Claims form"),
824         'email': fields.boolean('Emails', help="If Emails is checked, SugarCRM Emails data imported in OpenERP Emails form"),
825         'project': fields.boolean('Projects', help="If Projects is checked, SugarCRM Projects data imported in OpenERP Projects form"),
826         'project_task': fields.boolean('Project Tasks', help="If Project Tasks is checked, SugarCRM Project Tasks data imported in OpenERP Project Tasks form"),
827         'task': fields.boolean('Tasks', help="If Tasks is checked, SugarCRM Tasks data imported in OpenERP Meetings form"),
828         'bug': fields.boolean('Bugs', help="If Bugs is checked, SugarCRM Bugs data imported in OpenERP Project Issues form"),
829         'attachment': fields.boolean('Attachments', help="If Attachments is checked, SugarCRM Notes data imported in OpenERP's Related module's History with attachment"),
830         'document': fields.boolean('Documents', help="If Documents is checked, SugarCRM Documents data imported in OpenERP Document Form"),
831         'username': fields.char('User Name', size=64),
832         'password': fields.char('Password', size=24),
833     }
834     _defaults = {#to be set to true, but easier for debugging
835        'opportunity': False,
836        'user' : False,
837        'contact' : False,
838        'account' : False,
839         'employee' : False,
840         'meeting' : False,
841         'task' : False,
842         'call' : False,
843         'claim' : False,    
844         'email' : False, 
845         'project' : False,   
846         'project_task': False,     
847         'bug': False,
848         'document': False
849     }
850     
851     def get_key(self, cr, uid, ids, context=None):
852         """Select Key as For which Module data we want import data."""
853         if not context:
854             context = {}
855         key_list = []
856         for current in self.browse(cr, uid, ids, context):
857             if current.opportunity:
858                 key_list.append('Leads')
859                 key_list.append('Opportunities')
860             if current.user:
861                 key_list.append('Users')
862             if current.contact:
863                 key_list.append('Contacts')
864             if current.account:
865                 key_list.append('Accounts') 
866             if current.employee:
867                 key_list.append('Employees')  
868             if current.meeting:
869                 key_list.append('Meetings')
870             if current.task:
871                 key_list.append('Tasks')
872             if current.call:
873                 key_list.append('Calls')
874             if current.claim:
875                 key_list.append('Cases')                
876             if current.email:
877                 key_list.append('Emails') 
878             if current.project:
879                 key_list.append('Project')
880             if current.project_task:
881                 key_list.append('ProjectTask')
882             if current.bug:
883                 key_list.append('Bugs')
884             if current.attachment:
885                 key_list.append('Notes')     
886             if current.document:
887                 key_list.append('DocumentRevisions')                                                  
888         return key_list
889
890     def import_all(self, cr, uid, ids, context=None):
891         
892 #        """Import all sugarcrm data into openerp module"""
893         keys = self.get_key(cr, uid, ids, context)
894         imp = sugar_import(self, cr, uid, "sugarcrm", "import_sugarcrm", ["tfr@openerp.com"], context)
895         imp.set_table_list(keys)
896         imp.start()
897         
898         obj_model = self.pool.get('ir.model.data')
899         model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','import.message.form')])
900         resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])
901         return {
902                 'view_type': 'form',
903                 'view_mode': 'form',
904                 'res_model': 'import.message',
905                 'views': [(resource_id,'form')],
906                 'type': 'ir.actions.act_window',
907                 'target': 'new',
908             }
909         
910 import_sugarcrm()