diff --git a/addons/base_setup/base_setup_installer.xml b/addons/base_setup/base_setup_installer.xml index e8168a69ea9..a92f84c20db 100644 --- a/addons/base_setup/base_setup_installer.xml +++ b/addons/base_setup/base_setup_installer.xml @@ -73,7 +73,6 @@ - 2 normal_recurring @@ -124,7 +123,6 @@ - normal skip @@ -144,7 +142,6 @@ - normal current skip @@ -199,7 +196,6 @@ - normal skip @@ -219,7 +215,6 @@ - normal current 1000 @@ -230,7 +225,6 @@ @@ -281,7 +275,6 @@ - normal skip @@ -299,7 +292,6 @@ - 1 normal skip diff --git a/addons/import_base/import_framework.py b/addons/import_base/import_framework.py index b6d22f42012..6f350dfb97a 100644 --- a/addons/import_base/import_framework.py +++ b/addons/import_base/import_framework.py @@ -22,11 +22,13 @@ import pprint import mapper import pooler import tools - +from tools.translate import _ from threading import Thread import datetime import logging +import StringIO +import traceback pp = pprint.PrettyPrinter(indent=4) @@ -58,6 +60,7 @@ class import_framework(Thread): self.context = context or {} self.email = email_to_notify self.table_list = [] + self.logger = logging.getLogger('import_framework') """ Abstract Method to be implemented in @@ -175,8 +178,9 @@ class import_framework(Thread): model_obj = self.obj.pool.get(model) if not model_obj: - raise ValueError("%s is not a valid model name" % model) - + raise ValueError(_("%s is not a valid model name") % model) + self.logger.debug(_("fields imported : ")) + self.logger.debug(fields) (p, r, warning, s) = model_obj.import_data(self.cr, self.uid, fields, res, mode='update', current_module=self.module_name, noupdate=True, context=self.context) for (field, field_name) in self_dependencies: self._import_self_dependencies(model_obj, field, datas) @@ -311,6 +315,9 @@ class import_framework(Thread): """ domain_search = not domain_search and [('name', 'ilike', name)] or domain_search obj = self.obj.pool.get(model) + if not obj: #if the model doesn't exist + return False + xml_id = self._generate_xml_id(name, table) xml_ref = self.mapped_id_if_exist(model, domain_search, table, name) fields.append('id') @@ -359,6 +366,7 @@ class import_framework(Thread): """ self.data_started = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.cr = pooler.get_db(self.cr.dbname).cursor() + error = False try: self.initialize() result = [] @@ -369,16 +377,22 @@ class import_framework(Thread): res = self._resolve_dependencies(self.get_mapping()[table].get('dependencies', []), imported) result.extend(res) if to_import: + self.logger.debug(_("import : ") + table ) (position, warning) = self._import_table(table) result.append((table, position, warning)) imported.add(table) self.cr.commit() - + + except Exception, err: + sh = StringIO.StringIO() + traceback.print_exc(file=sh) + error = sh.getvalue() + print error finally: self.cr.close() + self.date_ended = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - self._send_notification_email(result) - + self._send_notification_email(result, error) def _resolve_dependencies(self, dep, imported): """ @@ -392,26 +406,29 @@ class import_framework(Thread): res = self._resolve_dependencies(self.get_mapping()[dependency].get('dependencies', []), imported) result.extend(res) if to_import: + self.logger.debug("import dependency : " + dependency) r = self._import_table(dependency) (position, warning) = r result.append((dependency, position, warning)) imported.add(dependency) return result - def _send_notification_email(self, result): - if not self.email: + def _send_notification_email(self, result, error): + if not self.email or not self.email[0]: return False tools.email_send( 'import@module.openerp', self.email, - self.get_email_subject(result), - self.get_email_body(result), + self.get_email_subject(result, error), + self.get_email_body(result, error), ) - logger = logging.getLogger('import_sugarcam') - logger.info("Import finished, notification email sended") + if error: + self.logger.error(_("Import failed due to an unexpected error")) + else: + self.logger.info(_("Import finished, notification email sended")) - def get_email_subject(self, result): + def get_email_subject(self, result, error=False): """ This method define the subject of the email send by openerp at the end of import @param result: a list of tuple @@ -419,9 +436,11 @@ class import_framework(Thread): @return the subject of the mail """ - return "Import of your data finished at %s" % self.date_ended + if error: + return _("Data Import failed at %s due to an unexpected error") % self.date_ended + return _("Import of your data finished at %s") % self.date_ended - def get_email_body(self, result): + def get_email_body(self, result, error=False): """ This method define the body of the email send by openerp at the end of import. The body is separated in two part the header (@see get_body_header), and the generate body with the list of table and number of record imported. @@ -432,20 +451,23 @@ class import_framework(Thread): """ - body = "started at %s and finished at %s \n" % (self.data_started, self.date_ended) + body = _("started at %s and finished at %s \n") % (self.data_started, self.date_ended) + if error: + body += _("but failed, in consequence no data were imported to keep database consistency \n error : \n") + error + for (table, nb, warning) in result: if not warning: - warning = "with no warning" + warning = _("with no warning") else: - warning = "with warning : %s" % warning - body += "%s records were imported from table %s, %s \n" % (nb, table, warning) + warning = _("with warning : %s") % warning + body += _("%s records were imported from table %s, %s \n") % (nb, table, warning) return self.get_body_header(result) + "\n\n" + body def get_body_header(self, result): """ @return the first sentences written in the mail's body """ - return "The import of data \n instance name : %s \n" % self.instance_name + return _("The import of data \n instance name : %s \n") % self.instance_name #TODO documentation test diff --git a/addons/import_sugarcrm/__openerp__.py b/addons/import_sugarcrm/__openerp__.py index 3d264facd0c..071f58099b3 100644 --- a/addons/import_sugarcrm/__openerp__.py +++ b/addons/import_sugarcrm/__openerp__.py @@ -27,7 +27,7 @@ "Contacts", "Employees", Meetings, Phonecalls, Emails, and Project, Project Tasks Data into OpenERP Module.""", 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', - 'depends': ['import_base', 'crm_claim', 'project', 'project_issue', 'hr', 'document'], + 'depends': ['import_base','crm', 'document'], 'init_xml': [], 'update_xml': ["wizard/import_message_view.xml", "import_sugarcrm_view.xml"], diff --git a/addons/import_sugarcrm/import_sugarcrm.py b/addons/import_sugarcrm/import_sugarcrm.py index 2fd5b5acbbe..71c37865f80 100644 --- a/addons/import_sugarcrm/import_sugarcrm.py +++ b/addons/import_sugarcrm/import_sugarcrm.py @@ -75,7 +75,6 @@ class sugar_import(import_framework): def get_data(self, table): offset = 0 - res = [] while True: r = sugar.search(self.context.get('port'), self.context.get('session_id'), table, offset, self.MAX_RESULT_PER_PAGE) @@ -157,6 +156,7 @@ class sugar_import(import_framework): def import_document(self, val): File,Filename = sugar.get_document_revision_search(self.context.get('port'), self.context.get('session_id'), val.get('document_revision_id')) + #File = base64.encodestring(File) res_id, res_model = self.import_related_document(val) val['res_id'] = res_id val['res_model'] = res_model @@ -168,9 +168,10 @@ class sugar_import(import_framework): def get_document_mapping(self): return { 'model' : 'ir.attachment', - 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT,self.TABLE_CONTACT, self.TABLE_OPPORTUNITY, self.TABLE_CASE, self.TABLE_BUG], + 'dependencies' : [self.TABLE_USER], 'hook' : self.import_document, - 'map' : {'name':'document_name', + 'map' : { + 'name':'document_name', 'description': ppconcat('description'), 'datas': 'datas', 'datas_fname': 'datas_fname', @@ -203,10 +204,11 @@ class sugar_import(import_framework): def get_email_mapping(self): return { 'model' : 'mailgate.message', - '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], + 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD, self.TABLE_OPPORTUNITY, self.TABLE_MEETING, self.TABLE_CALL], 'hook' : self.import_email, - 'map' : {'name':'name', - 'history' : const("1"), + 'map' : { + 'name':'name', + 'history' : const("1"), 'date':'date_sent', 'email_from': 'from_addr_name', 'email_to': 'to_addrs_names', @@ -245,7 +247,7 @@ class sugar_import(import_framework): def get_history_mapping(self): return { 'model' : 'ir.attachment', - '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, self.TABLE_EMAIL], + 'dependencies' : [self.TABLE_USER, self.TABLE_ACCOUNT, self.TABLE_CONTACT, self.TABLE_LEAD, self.TABLE_OPPORTUNITY, self.TABLE_MEETING, self.TABLE_CALL, self.TABLE_EMAIL], 'hook' : self.import_history, 'map' : { 'name':'name', @@ -880,7 +882,7 @@ class sugar_import(import_framework): 'hook' : self.import_user, 'map' : { 'name': concat('first_name', 'last_name'), - 'login': 'user_name', + 'login': value('user_name', fallback='last_name'), 'context_lang' : 'context_lang', 'password' : 'password', '.id' : '.id', @@ -914,7 +916,9 @@ class sugar_import(import_framework): """ Email notification """ - def get_email_subject(self, result): + def get_email_subject(self, result, error=False): + if error: + return "Sugarcrm data import failed at %s due to an unexpected error" % self.date_ended return "your sugarcrm data were successfully imported at %s" % self.date_ended def get_body_header(self, result): @@ -948,23 +952,42 @@ class import_sugarcrm(osv.osv): } def _get_email_id(self, cr, uid, context=None): - return self.pool.get('res.users').browse(cr, uid, uid, context=context).user_email + return self.pool.get('res.users').browse(cr, uid, uid, context=context).user_email + + def _module_installed(self, cr, uid, model, context=None): + module_id = self.pool.get('ir.module.module').search(cr, uid, [('name', '=', model), ('state', "=", "installed")], context=context) + return bool(module_id) + + def _project_installed(self, cr, uid, context=None): + return self._module_installed(cr,uid,'project',context=context) + + def _crm_claim_installed(self, cr, uid, context=None): + return self._module_installed(cr,uid,'crm_claim',context=context) + + def _project_issue_installed(self, cr, uid, context=None): + return self._module_installed(cr,uid,'project_issue',context=context) + + def _hr_installed(self, cr, uid, context=None): + return self._module_installed(cr,uid,'hr',context=context) _defaults = {#to be set to true, but easier for debugging 'opportunity': True, 'contact' : True, 'account' : True, - 'employee' : False, + 'employee' : _hr_installed, 'meeting' : True, 'call' : True, - 'claim' : True, + 'claim' : _crm_claim_installed, 'email_history' : True, - 'project' : True, - 'project_task': True, - 'bug': True, - 'document': False, + 'project' : _project_installed, + 'project_task': _project_installed, + 'bug': _project_issue_installed, + 'document': True, 'instance_name': 'sugarcrm', 'email_from': _get_email_id, + #'username' : 'admin', + #'password' : '', + #'url': "http://sugarcrm.example.com/soap.php" 'username' : 'tfr', 'password' : 'a', 'url': "http://localhost/sugarcrm/soap.php" @@ -987,8 +1010,6 @@ class import_sugarcrm(osv.osv): if not context: context = {} url = context.get('url') - - url_split = str(url).split('/') while len(url_split) >= 3: #3 case, soap.php is already at the end of url should be valid @@ -1011,35 +1032,41 @@ class import_sugarcrm(osv.osv): if not context: context = {} key_list = [] + module = {} for current in self.browse(cr, uid, ids, context): 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}) - if current.opportunity: - key_list.append('Leads') - key_list.append('Opportunities') if current.contact: key_list.append('Contacts') if current.account: - key_list.append('Accounts') + key_list.append('Accounts') + if current.opportunity: + key_list.append('Leads') + key_list.append('Opportunities') if current.employee: - key_list.append('Employees') + key_list.append('Employees') + module.update({'Employees':'hr'}) if current.meeting: key_list.append('Meetings') if current.call: key_list.append('Calls') if current.claim: - key_list.append('Cases') + key_list.append('Cases') + module.update({'Cases':'crm_claim'}) if current.email_history: key_list.append('Emails') key_list.append('Notes') if current.project: key_list.append('Project') + module.update({'Project':'project'}) if current.project_task: key_list.append('ProjectTask') + module.update({'ProjectTask':'project'}) if current.bug: key_list.append('Bugs') + module.update({'Bugs':'project_issue'}) if current.document: key_list.append('Documents') - return key_list + return key_list,module def do_import_all(self, cr, uid, *args): @@ -1053,9 +1080,16 @@ class import_sugarcrm(osv.osv): return True def import_from_scheduler_all(self, cr, uid, ids, context=None): - keys = self.get_key(cr, uid, ids, context) + keys, module_list = self.get_key(cr, uid, ids, context) if not keys: raise osv.except_osv(_('Warning !'), _('Select Module to Import.')) + key_list = module_list.keys() + for module in key_list : + module = module_list[module] + state = self.get_all(cr,uid,module,context=context) + if state == False: + keys = ', '.join(key_list) + raise osv.except_osv(_('Error !!'), _("%s data required %s Module to be installed, Please install %s module") %(keys,module,module)) cron_obj = self.pool.get('ir.cron') url = self.parse_valid_url(context) args = (keys,context.get('email_user'), context.get('instance_name'), url, context.get('username'), context.get('password') ) @@ -1068,18 +1102,25 @@ class import_sugarcrm(osv.osv): 'res_id': new_create_id, 'type': 'ir.actions.act_window', } - - + def import_all(self, cr, uid, ids, context=None): # """Import all sugarcrm data into openerp module""" - keys = self.get_key(cr, uid, ids, context) + keys, module_list = self.get_key(cr, uid, ids, context) + if not keys: + raise osv.except_osv(_('Warning !'), _('Select Module to Import.')) + key_list = module_list.keys() + for module in key_list : + module = module_list[module] + state = self._module_installed(cr,uid,module,context=context) + if state == False: + keys = ', '.join(key_list) + raise osv.except_osv(_('Error !!'), _("%s data required %s Module to be installed, Please install %s module") %(keys,module,module)) url = self.parse_valid_url(context) context.update({'url': url}) imp = sugar_import(self, cr, uid, context.get('instance_name'), "import_sugarcrm", [context.get('email_user')], context) imp.set_table_list(keys) imp.start() - obj_model = self.pool.get('ir.model.data') model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','import.message.form')]) resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id']) diff --git a/addons/import_sugarcrm/import_sugarcrm_view.xml b/addons/import_sugarcrm/import_sugarcrm_view.xml index 350b35a128d..8ab250fe6c1 100644 --- a/addons/import_sugarcrm/import_sugarcrm_view.xml +++ b/addons/import_sugarcrm/import_sugarcrm_view.xml @@ -13,13 +13,13 @@