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