1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
21 from osv import fields, osv
23 from tools.translate import _
24 from import_base.import_framework import *
25 from import_base.mapper import *
26 from datetime import datetime
29 pp = pprint.PrettyPrinter(indent=4)
32 class related_ref(dbmapper):
33 def __init__(self, type):
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'])
42 class sugar_import(import_framework):
43 TABLE_CONTACT = 'Contacts'
44 TABLE_ACCOUNT = 'Accounts'
46 TABLE_EMPLOYEE = 'Employees'
47 TABLE_RESSOURCE = "resource"
48 TABLE_OPPORTUNITY = 'Opportunities'
50 TABLE_STAGE = 'crm_stage'
51 TABLE_ATTENDEE = 'calendar_attendee'
53 TABLE_MEETING = 'Meetings'
55 TABLE_PROJECT = 'Project'
56 TABLE_PROJECT_TASK = 'ProjectTask'
60 TABLE_EMAIL = 'Emails'
61 TABLE_DOCUMENT = 'DocumentRevisions'
62 TABLE_COMPAIGN = 'Campaigns'
63 TABLE_HISTORY_ATTACHMNET = 'history_attachment'
67 PortType,sessionid = sugar.login(self.context.get('username',''), self.context.get('password',''), self.context.get('url',''))
69 raise osv.except_osv(_('Error !'), _('Authentication error !\nBad Username or Password !'))
70 self.context['port'] = PortType
71 self.context['session_id'] = sessionid
73 def get_data(self, table):
75 return sugar.search(self.context.get('port'), self.context.get('session_id'), table)
80 def get_category(self, val, model, name):
81 fields = ['name', 'object_id']
83 return self.import_object(fields, data, 'crm.case.categ', 'crm_categ', name, [('object_id.model','=',model), ('name', 'ilike', name)])
85 def get_job_title(self, dict, salutation):
86 fields = ['shortcut', 'name', 'domain']
88 data = [salutation, salutation, 'Contact']
89 return self.import_object(fields, data, 'res.partner.title', 'contact_title', salutation, [('shortcut', '=', salutation)])
91 def get_channel_id(self, dict, val):
94 return self.import_object(fields, data, 'res.partner.canal', 'crm_channel', val)
96 def get_all_states(self, external_val, country_id):
97 """Get states or create new state unless country_id is False"""
98 state_code = external_val[0:3] #take the tree first char
99 fields = ['country_id/id', 'name', 'code']
100 data = [country_id, external_val, state_code]
102 return self.import_object(fields, data, 'res.country.state', 'country_state', external_val)
105 def get_all_countries(self, val):
106 """Get Country, if no country match do not create anything, to avoid duplicate country code"""
107 return self.mapped_id_if_exist('res.country', [('name', 'ilike', val)], 'country', val)
109 def get_float_time(self, dict, hour, min):
110 min = int(min) * 100 / 60
111 return "%s.%i" % (hour, min)
117 def import_document(self, val):
118 filepath = '/var/www/sugarcrm/cache/upload/'+ val.get('id')
119 f = open(filepath, "r")
122 val['datas'] = base64.encodestring(datas)
123 val['datas_fname'] = val.get('filename')
126 def get_document_mapping(self):
128 'model' : 'ir.attachment',
129 'dependencies' : [self.TABLE_USER],
130 'hook' : self.import_document,
131 'map' : {'name':'filename',
132 'description': ppconcat('description'),
134 'datas_fname': 'datas_fname',
142 def import_email(self, val):
143 model_obj = self.obj.pool.get('ir.model.data')
144 xml_id = self.xml_id_exist(val.get('parent_type'), val.get('parent_id'))
145 model_ids = model_obj.search(self.cr, self.uid, [('name', 'like', xml_id)])
147 model = model_obj.browse(self.cr, self.uid, model_ids)[0]
148 if model.model == 'res.partner':
149 val['partner_id/.id'] = model.res_id
151 val['res_id'] = model.res_id
152 val['model'] = model.model
153 attach_id = self.get_attachment(val)
154 val['attachment_ids/id'] = attach_id
157 def get_email_mapping(self):
159 'model' : 'mailgate.message',
160 '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],
161 'hook' : self.import_email,
162 'map' : {'name':'name',
164 'email_from': 'from_addr_name',
165 'email_to': 'reply_to_addr',
166 'email_cc': 'cc_addrs_names',
167 'email_bcc': 'bcc_addrs_names',
168 'message_id': 'message_id',
171 'partner_id/.id': 'partner_id/.id',
172 'attachment_ids/id': 'attachment_ids/id',
173 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
174 'description': ppconcat('description', 'description_html'),
179 import History(Notes)
181 def get_attachment(self, val):
182 File, Filename = sugar.attachment_search(self.context.get('port'), self.context.get('session_id'), self.TABLE_NOTE, val.get('id'))
183 attachment_obj = self.obj.pool.get('ir.attachment')
184 model_obj = self.obj.pool.get('ir.model.data')
185 mailgate_obj = self.obj.pool.get('mailgate.message')
186 fields = ['name', 'datas', 'datas_fname','res_id', 'res_model']
187 name = 'attachment_'+ (Filename or val.get('name'))
188 datas = [Filename or val.get('name'), File, Filename, val.get('res_id'),val.get('model',False)]
189 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')))])
192 def import_history(self, val):
193 model_obj = self.obj.pool.get('ir.model.data')
194 xml_id = self.xml_id_exist(val.get('parent_type'), val.get('parent_id'))
195 model_ids = model_obj.search(self.cr, self.uid, [('name', 'like', xml_id)])
197 model = model_obj.browse(self.cr, self.uid, model_ids)[0]
198 if model.model == 'res.partner':
199 val['partner_id/.id'] = model.res_id
201 val['res_id'] = model.res_id
202 val['model'] = model.model
203 attach_id = self.get_attachment(val)
204 val['attachment_ids/id'] = attach_id
207 def get_history_mapping(self):
209 'model' : 'mailgate.message',
210 '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],
211 'hook' : self.import_history,
214 'date': 'date_entered',
215 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
216 'description': ppconcat('description', 'description_html'),
219 'attachment_ids/id': 'attachment_ids/id',
220 'partner_id/.id' : 'partner_id/.id',
227 def get_claim_priority(self, val):
233 return priority_dict.get(val.get('priority'), '')
235 def get_contact_info_from_account(self, val):
236 partner_id = self.get_mapped_id(self.TABLE_ACCOUNT, val.get('account_id'))
237 partner_address_id = False
238 partner_phone = False
239 partner_email = False
240 partner = self.obj.pool.get('res.partner').browse(self.cr, self.uid, [partner_id])[0]
241 if partner.address and partner.address[0]:
242 address = partner.address[0]
243 partner_address_id = address.id
244 partner_phone = address.phone
245 partner_email = address.email
246 return partner_address_id, partner_phone,partner_email
248 def import_crm_claim(self, val):
249 partner_address_id, partner_phone,partner_email = self.get_contact_info_from_account(val)
250 val['partner_address_id/.id'] = partner_address_id
251 val['partner_address_id/.id'] = partner_address_id
252 val['partner_phone'] = partner_phone
253 val['email_from'] = partner_email
256 def get_crm_claim_mapping(self):
258 'model' : 'crm.claim',
259 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD],
260 'hook' : self.import_crm_claim,
263 'date': 'date_entered',
264 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
265 'description': ppconcat('description'),
266 'partner_id/id': ref(self.TABLE_ACCOUNT, 'account_id'),
267 'partner_address_id/.id': 'partner_address_id/.id',
268 'partner_phone': 'partner_phone',
269 'email_from': 'email_from',
270 'priority': self.get_claim_priority,
271 'state': map_val('status', self.project_issue_state)
275 Import Project Issue(Bugs)
277 project_issue_state = {
281 'Pending': 'pending',
282 'Rejected': 'cancel',
285 def get_project_issue_priority(self, val):
292 return priority_dict.get(val.get('priority'), '')
294 def get_bug_project_id(self, dict, val):
297 return self.import_object(fields, data, 'project.project', 'project_issue', val)
299 def get_project_issue_mapping(self):
301 'model' : 'project.issue',
302 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT, self.TABLE_PROJECT_TASK],
305 'project_id/id': call(self.get_bug_project_id, 'sugarcrm_bugs'),
306 'categ_id/id': call(self.get_category, 'project.issue', value('type')),
307 'description': ppconcat('description', 'bug_number', 'fixed_in_release_name', 'source', 'fixed_in_release', 'work_log', 'found_in_release', 'release_name', 'resolution'),
308 'priority': self.get_project_issue_priority,
309 'state': map_val('status', self.project_issue_state)
316 project_task_state = {
317 'Not Started': 'draft',
318 'In Progress': 'open',
320 'Pending Input': 'pending',
321 'Deferred': 'cancelled',
324 def get_project_task_priority(self, val):
330 return priority_dict.get(val.get('priority'), '')
332 def get_project_task_mapping(self):
334 'model' : 'project.task',
335 'dependencies' : [self.TABLE_USER, self.TABLE_PROJECT],
338 'date_start': 'date_start',
339 'date_end': 'date_finish',
340 'progress': 'progress',
341 'project_id/id': ref(self.TABLE_PROJECT, 'project_id'),
342 'planned_hours': 'planned_hours',
343 'total_hours': 'total_hours',
344 'priority': self.get_project_task_priority,
345 'description': ppconcat('description','milestone_flag', 'project_task_id', 'task_number'),
346 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
347 'partner_id/id': 'partner_id/id',
348 'contact_id/id': 'contact_id/id',
349 'state': map_val('status', self.project_task_state)
361 def import_project_account(self, val):
363 partner_invoice_id = False
364 model_obj = self.obj.pool.get('ir.model.data')
365 partner_obj = self.obj.pool.get('res.partner')
366 partner_address_obj = self.obj.pool.get('res.partner.address')
367 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)
368 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)
369 for contact_id in sugar_project_contact:
370 partner_invoice_id = self.get_mapped_id(self.TABLE_CONTACT, contact_id)
371 for account_id in sugar_project_account:
372 partner_id = self.get_mapped_id(self.TABLE_ACCOUNT, account_id)
373 return partner_id, partner_invoice_id
375 def import_project(self, val):
376 partner_id, partner_invoice_id = self.import_project_account(val)
377 val['partner_id/.id'] = partner_id
378 val['contact_id/.id'] = partner_invoice_id
381 def get_project_mapping(self):
383 'model' : 'project.project',
384 'dependencies' : [self.TABLE_CONTACT, self.TABLE_ACCOUNT, self.TABLE_USER],
385 'hook' : self.import_project,
388 'date_start': 'estimated_start_date',
389 'date': 'estimated_end_date',
390 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
391 'partner_id/.id': 'partner_id/.id',
392 'contact_id/.id': 'contact_id/.id',
393 'state': map_val('status', self.project_state)
401 'Completed' : 'done',
402 'Not Started':'draft',
403 'In Progress': 'open',
404 'Pending Input': 'draft',
408 def import_task(self, val):
409 val['date'] = val.get('date_start') or datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
410 val['date_deadline'] = val.get('date_due') or datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
413 def get_task_mapping(self):
415 'model' : 'crm.meeting',
416 'dependencies' : [self.TABLE_CONTACT, self.TABLE_ACCOUNT, self.TABLE_USER],
417 'hook' : self.import_task,
421 'date_deadline': 'date_deadline',
422 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
423 'categ_id/id': call(self.get_category, 'crm.meeting', const('Tasks')),
424 'partner_id/id': related_ref(self.TABLE_ACCOUNT),
425 'partner_address_id/id': ref(self.TABLE_CONTACT,'contact_id'),
426 'state': map_val('status', self.task_state)
436 'Not Held': 'pending',
439 def get_calls_mapping(self):
441 'model' : 'crm.phonecall',
442 'dependencies' : [self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_OPPORTUNITY, self.TABLE_LEAD],
445 'date': 'date_start',
446 'duration': call(self.get_float_time, value('duration_hours'), value('duration_minutes')),
447 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
448 'partner_id/id': related_ref(self.TABLE_ACCOUNT),
449 'partner_address_id/id': related_ref(self.TABLE_CONTACT),
450 'categ_id/id': call(self.get_category, 'crm.phonecall', value('direction')),
451 'opportunity_id/id': related_ref(self.TABLE_OPPORTUNITY),
452 'description': ppconcat('description'),
453 'state': map_val('status', self.call_state)
466 def get_attendee_id(self, cr, uid, module_name, module_id):
470 model_obj = self.obj.pool.get('ir.model.data')
471 address_obj = self.obj.pool.get('res.partner.address')
472 att_obj = self.obj.pool.get('calendar.attendee')
473 attendee_dict = sugar.user_get_attendee_list(self.context.get('port'), self.context.get('session_id'), module_name, module_id)
474 for attendee in attendee_dict:
475 user_id = self.xml_id_exist(self.TABLE_USER, attendee.get('id', False))
479 contact_id = self.xml_id_exist(self.TABLE_CONTACT, attendee.get('id', False))
480 fields = ['user_id/id', 'email', 'partner_address_id/id']
481 data = [user_id or False, attendee.get('email1'), contact_id]
482 attendee_xml_id = self.import_object(fields, data, 'calendar.attendee', self.TABLE_ATTENDEE, user_id or contact_id or attendee.get('email1'), ['|',('user_id', '=', attendee.get('id')),('partner_address_id','=',attendee.get('id')),('email', '=', attendee.get('email1'))])
483 attendee_id.append(attendee_xml_id)
484 return ','.join(attendee_id)
486 def get_alarm_id(self, dict_val, val):
488 '60': '1 minute before',
489 '300': '5 minutes before',
490 '600': '10 minutes before',
491 '900': '15 minutes before',
492 '1800':'30 minutes before',
493 '3600': '1 hour before',
495 return self.mapped_id_if_exist('res.alarm', [('name', 'like', alarm_dict.get(val))], 'alarm', val)
498 def import_meeting(self, val):
499 attendee_id = self.get_attendee_id(self.cr, self.uid, 'Meetings', val.get('id')) #TODO
500 val['attendee_ids/id'] = attendee_id
503 def get_meeting_mapping(self):
505 'model' : 'crm.meeting',
506 'dependencies' : [self.TABLE_CONTACT, self.TABLE_OPPORTUNITY, self.TABLE_LEAD],
507 'hook': self.import_meeting,
510 'date': 'date_start',
511 'duration': call(self.get_float_time, value('duration_hours'), value('duration_minutes')),
512 'location': 'location',
513 'attendee_ids/id':'attendee_ids/id',
514 'alarm_id/id': call(self.get_alarm_id, value('reminder_time')),
515 'user_id/id': ref(self.TABLE_USER, 'assigned_user_id'),
516 'partner_id/id': related_ref(self.TABLE_ACCOUNT),
517 'partner_address_id/id': related_ref(self.TABLE_CONTACT),
518 'state': map_val('status', self.meeting_state)
526 'Need Analysis' : 'New',
527 'Closed Lost': 'Lost',
529 'Value Proposition': 'Proposition',
530 'Negotiation/Review': 'Negotiation'
533 def get_opportunity_status(self, sugar_val):
534 fields = ['name', 'type']
535 name = 'Opportunity_' + sugar_val['sales_stage']
536 data = [sugar_val['sales_stage'], 'Opportunity']
537 return self.import_object(fields, data, 'crm.case.stage', self.TABLE_STAGE, name, [('type', '=', 'opportunity'), ('name', 'ilike', sugar_val['sales_stage'])])
539 def import_opportunity_contact(self, val):
540 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))
542 partner_contact_id = False
543 partner_contact_email = False
544 partner_address_obj = self.obj.pool.get('res.partner.address')
545 partner_xml_id = self.name_exist(self.TABLE_ACCOUNT, val['account_name'], 'res.partner')
547 for contact in sugar_opportunities_contact:
548 address_id = self.get_mapped_id(self.TABLE_CONTACT, contact)
550 address = partner_address_obj.browse(self.cr, self.uid, address_id)
551 partner_name = address.partner_id and address.partner_id.name or False
552 if not partner_name: #link with partner id
553 fields = ['partner_id/id']
554 data = [partner_xml_id]
555 self.import_object(fields, data, 'res.partner.address', self.TABLE_CONTACT, contact, self.DO_NOT_FIND_DOMAIN)
556 if not partner_name or partner_name == val.get('account_name'):
557 partner_contact_id = self.xml_id_exist(self.TABLE_CONTACT, contact)
558 partner_contact_email = address.email
559 return partner_contact_id, partner_contact_email
561 def import_opp(self, val):
562 partner_contact_name, partner_contact_email = self.import_opportunity_contact(val)
563 val['partner_address_id/id'] = partner_contact_name
564 val['email_from'] = partner_contact_email
567 def get_opp_mapping(self):
569 'model' : 'crm.lead',
570 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT,self.TABLE_COMPAIGN],
571 'hook' : self.import_opp,
574 'probability': 'probability',
575 'partner_id/id': refbyname(self.TABLE_ACCOUNT, 'account_name', 'res.partner'),
576 'title_action': 'next_step',
577 'partner_address_id/id': 'partner_address_id/id',
578 'planned_revenue': 'amount',
579 'date_deadline': 'date_closed',
580 'user_id/id' : ref(self.TABLE_USER, 'assigned_user_id'),
581 'stage_id/id' : self.get_opportunity_status,
582 'type' : const('opportunity'),
583 'categ_id/id': call(self.get_category, 'crm.lead', value('opportunity_type')),
584 'email_from': 'email_from',
585 'state': map_val('status', self.opp_state) , #TODO
593 def get_compaign_mapping(self):
595 'model' : 'crm.case.resource.type',
604 def get_lead_status(self, sugar_val):
605 fields = ['name', 'type']
606 name = 'lead_' + sugar_val.get('status', '')
607 data = [sugar_val.get('status', ''), 'lead']
608 return self.import_object(fields, data, 'crm.case.stage', self.TABLE_STAGE, name, [('type', '=', 'lead'), ('name', 'ilike', sugar_val.get('status', ''))])
613 'In Progress': 'open',
614 'Recycled': 'cancel',
620 def import_lead(self, val):
621 if val.get('opportunity_id'): #if lead is converted into opp, don't import as lead
623 if val.get('primary_address_country'):
624 country_id = self.get_all_countries(val.get('primary_address_country'))
625 val['country_id/id'] = country_id
626 val['state_id/id'] = self.get_all_states(val.get('primary_address_state'), country_id)
629 def get_lead_mapping(self):
631 'model' : 'crm.lead',
632 'dependencies' : [self.TABLE_COMPAIGN],
633 'hook' : self.import_lead,
635 'name': concat('first_name', 'last_name'),
636 'contact_name': concat('first_name', 'last_name'),
637 'description': ppconcat('description', 'refered_by', 'lead_source', 'lead_source_description', 'website', 'email2', 'status_description', 'lead_source_description', 'do_not_call'),
638 'partner_name': 'account_name',
639 'email_from': 'email1',
640 'phone': 'phone_work',
641 'mobile': 'phone_mobile',
642 'title/id': call(self.get_job_title, value('salutation')),
644 'street': 'primary_address_street',
645 'street2': 'alt_address_street',
646 'zip': 'primary_address_postalcode',
647 'city':'primary_address_city',
648 'user_id/id' : ref(self.TABLE_USER, 'assigned_user_id'),
649 'stage_id/id' : self.get_lead_status,
650 'type' : const('lead'),
651 'state': map_val('status', self.lead_state) ,
653 'referred': 'refered_by',
654 'optout': 'do_not_call',
655 'channel_id/id': call(self.get_channel_id, value('lead_source')),
656 'type_id/id': ref(self.TABLE_COMPAIGN, 'campaign_id'),
657 'country_id/id': 'country_id/id',
658 'state_id/id': 'state_id/id'
665 def get_email(self, val):
666 return val.get('email1') + ','+ val.get('email2')
668 def import_contact(self, val):
669 if val.get('primary_address_country'):
670 country_id = self.get_all_countries(val.get('primary_address_country'))
671 state = self.get_all_states(val.get('primary_address_state'), country_id)
672 val['country_id/id'] = country_id
673 val['state_id/id'] = state
676 def get_contact_mapping(self):
678 'model' : 'res.partner.address',
679 'dependencies' : [self.TABLE_ACCOUNT],
680 'hook' : self.import_contact,
682 'name': concat('first_name', 'last_name'),
683 'partner_id/id': ref(self.TABLE_ACCOUNT,'account_id'),
684 'phone': 'phone_work',
685 'mobile': 'phone_mobile',
688 'street': 'primary_address_street',
689 'zip': 'primary_address_postalcode',
690 'city': 'primary_address_city',
691 'country_id/id': 'country_id/id',
692 'state_id/id': 'state_id/id',
693 'email': self.get_email,
694 'type': const('contact')
701 def get_address_type(self, val, type):
702 if type == 'invoice':
703 type_address = 'billing'
705 type_address = 'shipping'
707 map_partner_address = {
709 'phone': 'phone_office',
710 'mobile': 'phone_mobile',
713 'street': type_address + '_address_street',
714 'zip': type_address +'_address_postalcode',
715 'city': type_address +'_address_city',
716 'country_id/id': 'country_id/id',
720 if val.get(type_address +'_address_country'):
721 country_id = self.get_all_countries(val.get(type_address +'_address_country'))
722 state = self.get_all_states(val.get(type_address +'_address_state'), country_id)
723 val['country_id/id'] = country_id
724 val['state_id/id'] = state
726 val['id_new'] = val['id'] + '_address_' + type
727 return self.import_object_mapping(map_partner_address, val, 'res.partner.address', self.TABLE_CONTACT, val['id_new'], self.DO_NOT_FIND_DOMAIN)
729 def get_partner_address(self, val):
731 type_dict = {'billing_address_street' : 'invoice', 'shipping_address_street' : 'delivery'}
732 for key, type_value in type_dict.items():
734 id = self.get_address_type(val, type_value)
735 address_id.append(id)
737 return ','.join(address_id)
739 def get_partner_mapping(self):
741 'model' : 'res.partner',
742 'dependencies' : [self.TABLE_USER],
745 'website': 'website',
746 'user_id/id': ref(self.TABLE_USER,'assigned_user_id'),
748 'comment': ppconcat('description', 'employees', 'ownership', 'annual_revenue', 'rating', 'industry', 'ticker_symbol'),
749 'customer': const('1'),
750 'supplier': const('0'),
751 'address/id':'address/id',
752 'parent_id/id_parent' : 'parent_id',
753 'address/id' : self.get_partner_address,
760 def get_ressource(self, val):
762 'name': concat('first_name', 'last_name'),
764 return self.import_object_mapping(map_resource, val, 'resource.resource', self.TABLE_RESSOURCE, val['id'], self.DO_NOT_FIND_DOMAIN)
766 def get_job_id(self, val):
768 data = [val.get('title')]
769 return self.import_object(fields, data, 'hr.job', 'hr_job', val.get('title'))
771 def get_user_address(self, val):
773 'name': concat('first_name', 'last_name'),
774 'city': 'address_city',
775 'country_id/id': 'country_id/id',
776 'state_id/id': 'state_id/id',
777 'street': 'address_street',
778 'zip': 'address_postalcode',
780 'phone': 'phone_work',
781 'mobile':'phone_mobile',
785 if val.get('address_country'):
786 country_id = self.get_all_countries(val.get('address_country'))
787 state_id = self.get_all_states(val.get('address_state'), country_id)
788 val['country_id/id'] = country_id
789 val['state_id/id'] = state_id
791 return self.import_object_mapping(map_user_address, val, 'res.partner.address', self.TABLE_CONTACT, val['id'], self.DO_NOT_FIND_DOMAIN)
793 def get_employee_mapping(self):
795 'model' : 'hr.employee',
796 'dependencies' : [self.TABLE_USER],
798 'resource_id/id': self.get_ressource,
799 'name': concat('first_name', 'last_name'),
800 'work_phone': 'phone_work',
801 'mobile_phone': 'phone_mobile',
802 'user_id/id': ref(self.TABLE_USER, 'id'),
803 'address_home_id/id': self.get_user_address,
804 'notes': ppconcat('messenger_type', 'messenger_id', 'description'),
805 'job_id/id': self.get_job_id,
812 def import_user(self, val):
813 user_obj = self.obj.pool.get('res.users')
814 user_ids = user_obj.search(self.cr, self.uid, [('login', '=', val.get('user_name'))])
816 val['.id'] = str(user_ids[0])
818 val['password'] = 'sugarcrm' #default password for all user #TODO needed in documentation
820 val['context_lang'] = self.context.get('lang','en_US')
823 def get_users_department(self, val):
824 dep = val.get('department')
829 return self.import_object(fields, data, 'hr.department', 'hr_department_user', dep)
831 def get_user_mapping(self):
833 'model' : 'res.users',
834 'hook' : self.import_user,
836 'name': concat('first_name', 'last_name'),
837 'login': 'user_name',
838 'context_lang' : 'context_lang',
839 'password' : 'password',
841 'context_department_id/id': self.get_users_department,
845 def get_mapping(self):
847 self.TABLE_USER : self.get_user_mapping(),
848 self.TABLE_EMPLOYEE : self.get_employee_mapping(),
849 self.TABLE_ACCOUNT : self.get_partner_mapping(),
850 self.TABLE_CONTACT : self.get_contact_mapping(),
851 self.TABLE_LEAD : self.get_lead_mapping(),
852 self.TABLE_OPPORTUNITY : self.get_opp_mapping(),
853 self.TABLE_MEETING : self.get_meeting_mapping(),
854 self.TABLE_CALL : self.get_calls_mapping(),
855 self.TABLE_TASK : self.get_task_mapping(),
856 self.TABLE_PROJECT : self.get_project_mapping(),
857 self.TABLE_PROJECT_TASK: self.get_project_task_mapping(),
858 self.TABLE_BUG: self.get_project_issue_mapping(),
859 self.TABLE_CASE: self.get_crm_claim_mapping(),
860 self.TABLE_NOTE: self.get_history_mapping(),
861 self.TABLE_EMAIL: self.get_email_mapping(),
862 self.TABLE_DOCUMENT: self.get_document_mapping(),
863 self.TABLE_COMPAIGN: self.get_compaign_mapping()
868 class import_sugarcrm(osv.osv):
869 """Import SugarCRM DATA"""
871 _name = "import.sugarcrm"
872 _description = __doc__
875 'username': fields.char('User Name', size=64, required=True),
876 'password': fields.char('Password', size=24,required=True),
877 '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."),
879 'opportunity': fields.boolean('Leads and Opportunities', help="If Opportunities are checked, SugarCRM opportunities data imported in OpenERP crm-Opportunity form"),
880 'user': fields.boolean('Users', help="If Users are checked, SugarCRM Users data imported in OpenERP Users form"),
881 'contact': fields.boolean('Contacts', help="If Contacts are checked, SugarCRM Contacts data imported in OpenERP partner address form"),
882 'account': fields.boolean('Accounts', help="If Accounts are checked, SugarCRM Accounts data imported in OpenERP partners form"),
883 'employee': fields.boolean('Employee', help="If Employees is checked, SugarCRM Employees data imported in OpenERP employees form"),
884 'meeting': fields.boolean('Meetings', help="If Meetings is checked, SugarCRM Meetings data imported in OpenERP meetings form"),
885 'call': fields.boolean('Calls', help="If Calls is checked, SugarCRM Calls data imported in OpenERP phonecalls form"),
886 'claim': fields.boolean('Claims', help="If Claims is checked, SugarCRM Claims data imported in OpenERP Claims form"),
887 'email': fields.boolean('Emails', help="If Emails is checked, SugarCRM Emails data imported in OpenERP Emails form"),
888 'project': fields.boolean('Projects', help="If Projects is checked, SugarCRM Projects data imported in OpenERP Projects form"),
889 'project_task': fields.boolean('Project Tasks', help="If Project Tasks is checked, SugarCRM Project Tasks data imported in OpenERP Project Tasks form"),
890 'task': fields.boolean('Tasks', help="If Tasks is checked, SugarCRM Tasks data imported in OpenERP Meetings form"),
891 'bug': fields.boolean('Bugs', help="If Bugs is checked, SugarCRM Bugs data imported in OpenERP Project Issues form"),
892 'attachment': fields.boolean('Attachments', help="If Attachments is checked, SugarCRM Notes data imported in OpenERP's Related module's History with attachment"),
893 'document': fields.boolean('Documents', help="If Documents is checked, SugarCRM Documents data imported in OpenERP Document Form"),
894 'email_from': fields.char('Notify End Of Import To:', size=128),
895 '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."),
898 _defaults = {#to be set to true, but easier for debugging
899 'opportunity': False,
910 'project_task': False,
913 'instance_name': 'sugarcrm',
914 'email_from': 'tfr@tinyerp.com',
917 'url': "http://localhost/sugarcrm/soap.php"
920 def get_key(self, cr, uid, ids, context=None):
921 """Select Key as For which Module data we want import data."""
925 for current in self.browse(cr, uid, ids, context):
926 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})
927 if current.opportunity:
928 key_list.append('Leads')
929 key_list.append('Opportunities')
931 key_list.append('Users')
933 key_list.append('Contacts')
935 key_list.append('Accounts')
937 key_list.append('Employees')
939 key_list.append('Meetings')
941 key_list.append('Tasks')
943 key_list.append('Calls')
945 key_list.append('Cases')
947 key_list.append('Emails')
949 key_list.append('Project')
950 if current.project_task:
951 key_list.append('ProjectTask')
953 key_list.append('Bugs')
954 if current.attachment:
955 key_list.append('Notes')
957 key_list.append('DocumentRevisions')
961 def do_import_all(self, cr, uid, *args):
967 login_obj = self.pool.get('sugarcrm.login')
969 login_id = login_obj.browse(cr, uid, args[1])
970 context.update({'username': login_id.username, 'password': login_id.password, 'url': login_id.url, 'instance_name': args[3]})
972 imp = sugar_import(self, cr, uid, context.get('instance_name'), "import_sugarcrm", [context.get('email_from', 'tfr@openerp.com')], context)
973 imp.set_table_list(keys)
977 def import_from_scheduler_all(self, cr, uid, ids, context=None):
978 keys = self.get_key(cr, uid, ids, context)
980 raise osv.except_osv(_('Warning !'), _('Select Module to Import.'))
981 cron_obj = self.pool.get('ir.cron')
982 mod_obj = self.pool.get('ir.model.data')
983 login_obj = self.pool.get('sugarcrm.login')
984 field = ['username', 'password', 'url']
985 datas = [context.get('username'), context.get('password'), context.get('url')]
986 name = 'login_user_'+ context.get('username')
987 login_ids = login_obj.search(cr, uid, [('username', '=', context.get('username'))])
989 login_id = login_ids[0]
991 login_id = login_obj.create(cr, uid, {'username': context.get('username'), 'password': context.get('password'), 'url': context.get('url')})
992 args = (keys, login_id, context.get('email_user'), context.get('instance_name'))
993 for current in self.browse(cr, uid, ids):
994 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})
996 'name': 'SugarCRM Scheduler',
998 'view_mode': 'form,tree',
999 'res_model': 'ir.cron',
1000 'res_id': new_create_id,
1001 'type': 'ir.actions.act_window',
1004 def import_all(self, cr, uid, ids, context=None):
1006 # """Import all sugarcrm data into openerp module"""
1007 keys = self.get_key(cr, uid, ids, context)
1008 imp = sugar_import(self, cr, uid, context.get('instance_name'), "import_sugarcrm", [context.get('email_from', 'tfr@openerp.com')], context)
1009 imp.set_table_list(keys)
1012 obj_model = self.pool.get('ir.model.data')
1013 model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','import.message.form')])
1014 resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])
1016 'view_type': 'form',
1017 'view_mode': 'form',
1018 'res_model': 'import.message',
1019 'views': [(resource_id,'form')],
1020 'type': 'ir.actions.act_window',