diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 65af3f9e530..238029a3f58 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -21,6 +21,7 @@ import base64 import time +from lxml import etree from osv import fields from osv import osv import tools @@ -97,6 +98,7 @@ class crm_case_stage(osv.osv): class crm_case_section(osv.osv): """ Model for sales teams. """ _name = "crm.case.section" + _inherits = {'mail.alias': 'alias_id'} _description = "Sales Teams" _order = "complete_name" @@ -120,6 +122,7 @@ class crm_case_section(osv.osv): 'note': fields.text('Description'), 'working_hours': fields.float('Working Hours', digits=(16,2 )), 'stage_ids': fields.many2many('crm.case.stage', 'section_stage_rel', 'section_id', 'stage_id', 'Stages'), + 'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True), } def _get_stage_common(self, cr, uid, context): @@ -155,6 +158,33 @@ class crm_case_section(osv.osv): name = record['parent_id'][1] + ' / ' + name res.append((record['id'], name)) return res + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + res = super(crm_case_section,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) + if view_type == 'form': + domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", context=context) + if not domain: + doc = etree.XML(res['arch']) + alias_node = doc.xpath("//field[@name='alias_id']")[0] + parent = alias_node.getparent() + parent.remove(alias_node) + res['arch'] = etree.tostring(doc) + return res + + def create(self, cr, uid, vals, context=None): + model_pool = self.pool.get('ir.model.data') + alias_pool = self.pool.get('mail.alias') + if not vals.get('alias_id'): + model, res_id = model_pool.get_object_reference( cr, uid, "crm", "model_crm_lead") + vals.update({'alias_name': "sales", + 'alias_model_id': res_id}) + alias_pool.create_unique_alias(cr, uid, vals, context=context) + res = super(crm_case_section, self).create(cr, uid, vals, context) + record = self.read(cr, uid, res, context) + alias_pool.write(cr, uid, [record['alias_id']],{'alias_defaults':{'section_id':record['id'],'type':'lead'}},context) + return res + return super(crm_case_section, self).create(cr, uid, vals, context) + class crm_case_categ(osv.osv): """ Category of Case """ diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml index 4ca40a691f5..9192b52e7b8 100644 --- a/addons/crm/crm_data.xml +++ b/addons/crm/crm_data.xml @@ -13,9 +13,17 @@ email + + sales + + + {'type':'lead'} + + Sales Department Sales + diff --git a/addons/crm/crm_demo.xml b/addons/crm/crm_demo.xml index f345d86d030..c53b05df811 100644 --- a/addons/crm/crm_demo.xml +++ b/addons/crm/crm_demo.xml @@ -1,28 +1,37 @@ + + + info + + + {'type':'lead'} + + + - - Meetings - ir.ui.menu - - - + + Meetings + ir.ui.menu + + + - - Sales Marketing Department - Sales Marketing - - - - - OpenERP partners - True - - + + Sales Marketing Department + Sales Marketing + + + + + OpenERP partners + True + + diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index 257d1cd93f7..7f41df641b3 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -71,6 +71,7 @@ + diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py index cddcf642dc4..55923c3043a 100644 --- a/addons/fetchmail/fetchmail.py +++ b/addons/fetchmail/fetchmail.py @@ -151,7 +151,7 @@ openerp_mailgate.py -u %(uid)d -p PASSWORD -o %(model)s -d %(dbname)s --host=HOS connection = server.connect() server.write({'state':'done'}) except Exception, e: - logger.exception("Failed to connect to %s server %s", server.type, server.name) + _logger.exception("Failed to connect to %s server %s", server.type, server.name) raise osv.except_osv(_("Connection test failed!"), _("Here is what we got instead:\n %s") % tools.ustr(e)) finally: try: @@ -177,7 +177,7 @@ openerp_mailgate.py -u %(uid)d -p PASSWORD -o %(model)s -d %(dbname)s --host=HOS mail_thread = self.pool.get('mail.thread') action_pool = self.pool.get('ir.actions.server') for server in self.browse(cr, uid, ids, context=context): - logger.info('start checking for new emails on %s server %s', server.type, server.name) + _logger.info('start checking for new emails on %s server %s', server.type, server.name) context.update({'fetchmail_server_id': server.id, 'server_type': server.type}) count = 0 imap_server = False @@ -198,9 +198,9 @@ openerp_mailgate.py -u %(uid)d -p PASSWORD -o %(model)s -d %(dbname)s --host=HOS imap_server.store(num, '+FLAGS', '\\Seen') cr.commit() count += 1 - logger.info("fetched/processed %s email(s) on %s server %s", count, server.type, server.name) + _logger.info("fetched/processed %s email(s) on %s server %s", count, server.type, server.name) except Exception, e: - logger.exception("Failed to fetch mail from %s server %s", server.type, server.name) + _logger.exception("Failed to fetch mail from %s server %s", server.type, server.name) finally: if imap_server: imap_server.close() @@ -222,9 +222,9 @@ openerp_mailgate.py -u %(uid)d -p PASSWORD -o %(model)s -d %(dbname)s --host=HOS action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]}) pop_server.dele(num) cr.commit() - logger.info("fetched/processed %s email(s) on %s server %s", numMsgs, server.type, server.name) + _logger.info("fetched/processed %s email(s) on %s server %s", numMsgs, server.type, server.name) except Exception, e: - logger.exception("Failed to fetch mail from %s server %s", server.type, server.name) + _logger.exception("Failed to fetch mail from %s server %s", server.type, server.name) finally: if pop_server: pop_server.quit() diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index c893755c7c0..d000c0c07ae 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -22,7 +22,7 @@ from base_status.base_stage import base_stage import time from datetime import datetime, timedelta - +from lxml import etree from osv import fields, osv from crm import crm import tools @@ -549,10 +549,37 @@ class hr_applicant(base_stage, osv.Model): class hr_job(osv.osv): _inherit = "hr.job" _name = "hr.job" + _inherits = {'mail.alias': 'alias_id'} _columns = { 'survey_id': fields.many2one('survey', 'Interview Form', help="Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job"), + 'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True), } + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + res = super(hr_job,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) + if view_type == 'form': + domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", context=context) + if not domain: + doc = etree.XML(res['arch']) + alias_node = doc.xpath("//field[@name='alias_id']")[0] + parent = alias_node.getparent() + parent.remove(alias_node) + res['arch'] = etree.tostring(doc) + return res + + def create(self, cr, uid, vals, context=None): + model_pool = self.pool.get('ir.model.data') + alias_pool = self.pool.get('mail.alias') + res_id = model_pool.get_object( cr, uid, "hr_recruitment", "model_hr_applicant") + vals.update({'alias_name': "job", + 'alias_model_id': res_id.id}) + alias_pool.create_unique_alias(cr, uid, vals, context=context) + res = super( hr_job, self).create(cr, uid, vals, context) + record = self.read(cr, uid, res, context) + alias_pool.write(cr, uid, [record['alias_id']], {"alias_defaults": {'job_id': record['id']}}, context) + return res + + def action_print_survey(self, cr, uid, ids, context=None): if context is None: context = {} diff --git a/addons/hr_recruitment/hr_recruitment_data.xml b/addons/hr_recruitment/hr_recruitment_data.xml index 13436bef45a..aed3fe1667e 100644 --- a/addons/hr_recruitment/hr_recruitment_data.xml +++ b/addons/hr_recruitment/hr_recruitment_data.xml @@ -449,5 +449,13 @@ + + + Jobs + + + {} + + diff --git a/addons/hr_recruitment/hr_recruitment_demo.yml b/addons/hr_recruitment/hr_recruitment_demo.yml index 59508b83c28..c616e9e7e95 100644 --- a/addons/hr_recruitment/hr_recruitment_demo.yml +++ b/addons/hr_recruitment/hr_recruitment_demo.yml @@ -1,3 +1,99 @@ +- + !record {model: mail.alias, id: alias_job_devloper, view: False}: + alias_name: 'job-developer' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_devloper')], {"alias_defaults": {'job_id': ref('hr.job_developer')}}) +- + !record {model: hr.job, id: hr.job_developer, view: False}: + alias_id: alias_job_devloper +- + !record {model: mail.alias, id: alias_job_ceo, view: False}: + alias_name: 'job-ceo' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_ceo')], {'alias_defaults': {'job_id': ref('hr.job_ceo')}}) +- + !record {model: hr.job, id: hr.job_ceo, view: False}: + alias_id: alias_job_ceo +- + !record {model: mail.alias, id: alias_job_cto, view: False}: + alias_name: 'job-cto' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_cto')], {"alias_defaults": {'job_id': ref('hr.job_cto')}}) +- + !record {model: hr.job, id: hr.job_cto, view: False}: + alias_id: alias_job_cto +- + !record {model: mail.alias, id: alias_job_hr_manager, view: False}: + alias_name: 'job-hr-manager' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_hr_manager')], {"alias_defaults": {'job_id': ref('hr.job_hr_manager')}}) +- + !record {model: hr.job, id: hr.job_hr_manager, view: False}: + alias_id: alias_job_hr_manager +- + !record {model: mail.alias, id: alias_job_consultant, view: False}: + alias_name: 'job-consultant' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_consultant')], {"alias_defaults": {'job_id': ref('hr.job_consultant')}}) +- + !record {model: hr.job, id: hr.job_consultant, view: False}: + alias_id: alias_job_consultant +- + !record {model: mail.alias, id: alias_job_hrm, view: False}: + alias_name: 'job-hrm' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_hrm')], {"alias_defaults": {'job_id': ref('hr.job_hrm')}}) +- + !record {model: hr.job, id: hr.job_hrm, view: False}: + alias_id: alias_job_hrm +- + !record {model: mail.alias, id: alias_job_marketing, view: False}: + alias_name: 'job-marketing' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_marketing')], {"alias_defaults": {'job_id': ref('hr.job_marketing')}}) +- + !record {model: hr.job, id: hr.job_marketing, view: False}: + alias_id: alias_job_marketing +- + !record {model: mail.alias, id: alias_job_trainee, view: False}: + alias_name: 'job-trainees' + alias_model_id: model_hr_applicant + alias_user_id: base.user_root + alias_defaults: '{}' +- + !python {model: mail.alias}: | + self.write(cr, uid, [ref('alias_job_trainee')], {"alias_defaults": {'job_id': ref('hr.job_trainee')}}) +- + !record {model: hr.job, id: hr.job_trainee, view: False}: + alias_id: alias_job_trainee - !record {model: hr.applicant, id: hr_case_salesman0}: date: !eval time.strftime('%Y-%m-01 10:35:50') diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml index f31778b7874..56d0da979ee 100644 --- a/addons/hr_recruitment/hr_recruitment_view.xml +++ b/addons/hr_recruitment/hr_recruitment_view.xml @@ -348,6 +348,9 @@ attrs="{'invisible':[('survey_id','=',False)]}"/> + + + diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index 4c313338ceb..f06b4536040 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -19,11 +19,11 @@ # ############################################################################## +import mail_alias import mail_message import mail_thread import mail_group import mail_subscription -import mail_alias import res_users import res_partner import report diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index 95ce7d5619d..5c0afc27ec1 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -56,7 +56,9 @@ The main features are: 'depends': ['base', 'base_tools'], 'data': [ 'wizard/mail_compose_message_view.xml', + 'wizard/update_mail_alias_wizard.xml', 'mail_message_view.xml', + 'mail_alias_data.xml', 'mail_subscription_view.xml', 'mail_thread_view.xml', 'mail_group_view.xml', @@ -66,6 +68,10 @@ The main features are: 'mail_data.xml', 'mail_group_data.xml', 'res_users_view.xml', + 'mail_alias_view.xml', + ], + 'demo_xml': [ + 'user_mail_alias_demo.xml', ], 'installable': True, 'auto_install': False, diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index b5aa6f6d76a..292b2f742cd 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -20,6 +20,7 @@ ############################################################################## from openerp.osv import fields, osv +from tools.translate import _ class mail_alias(osv.Model): """A Mail Alias is a mapping of an email address with a given OpenERP Document @@ -39,8 +40,8 @@ class mail_alias(osv.Model): _rec_name = 'alias_name' _columns = { - 'alias_name': fields.char('Mailbox Alias', required=True, - help="The name of the mailbox alias, e.g. `jobs' " + 'alias_name': fields.char('Mailbox Alias', size=255, required=True, + help="The name of the mailbox alias, e.g. 'jobs' " "if you want to catch emails for ",), 'alias_model_id': fields.many2one('ir.model', 'Aliased Model', required=True, help="The model (OpenERP Document Kind) to which this alias " @@ -48,7 +49,9 @@ class mail_alias(osv.Model): "existing record will cause the creation of a new record " "of this model (e.g. a Project Task)", # only allow selecting mail_thread models! - domain="[('field_ids', 'in', 'message_ids')]"), + #TODO kept doamin temporarily in comment, need to redefine domain + #domain="[('field_id', 'in', 'message_ids')]" + ), 'alias_user_id': fields.many2one('res.users', 'Owner', help="The owner of records created upon receiving emails on this alias. " "If this field is kept empty the system will attempt to find the right owner " @@ -64,19 +67,54 @@ class mail_alias(osv.Model): } _defaults = { 'alias_defaults': '{}', - 'alias_user_id': lambda s,c,u,ctx: u + 'alias_user_id': lambda self,cr,uid, context: uid } - _sql_constraint = [ - ('mailbox_uniq', 'unique (alias_name)', 'Unfortunately this mail alias is already used, please choose a unique one') + _sql_constraints = [ + ('mailbox_uniq', 'UNIQUE(alias_name)', 'Unfortunately this mail alias is already used, please choose a unique one') ] - - def create_unique_alias(self, cr, uid, values, context=None): - # TODO: call create() with `values` after checking that `alias_name` - # is unique. If not unique, append a sequential number after it until - # a unique one if found. - # E.g if create_unique_alias is called with {'alias_name': 'abc'} - # and 'abc', 'abc1', 'abc2' alias exist, replace alias_name with 'abc3'. - return - - - \ No newline at end of file + + def _check_alias_defaults(self, cr, uid, ids, context=None): + """ + Strick constraints checking for the alias defaults values. + it must follow the python dict format. So message_catachall + will not face any issue. + """ + for record in self.browse(cr, uid, ids, context=context): + try: + dict(eval(record.alias_defaults)) + return True + except: + return False + + _constraints = [ + (_check_alias_defaults, "Default Values are in wrong format.\nIt must be in python dictionary format e.g.{'field_name': 'value' or {}}", ['alias_defaults']), + ] + + def name_get(self, cr, uid, ids, context=None): + """ + Return the mail alias display alias_name, inclusing the Implicit and dynamic + Email Alias Domain from config. + e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` + """ + if context is None: + context = {} + res = [] + config_parameter_pool = self.pool.get("ir.config_parameter") + domain = config_parameter_pool.get_param(cr, uid, "mail.catchall.domain", context=context) + for record in self.read(cr, uid, ids, ['alias_name'], context=context): + domain_alias = "%s@%s"%(record['alias_name'], domain) + res.append((record['id'], domain_alias)) + return res + + def create_unique_alias(self, cr, uid, values, sequence=1 ,context=None): + if sequence: + prob_alias = "%s%s"%(values['alias_name'], sequence) + search_alias = self.search(cr, uid, [('alias_name', '=', prob_alias)]) + if search_alias: + values = self.create_unique_alias(cr, uid, values, sequence+1, context) + else: + values.update({'alias_name': prob_alias}) + return values + else: + return values.update({'alias_name': "%s"%(values['alias_name'])}) + diff --git a/addons/mail/mail_alias_data.xml b/addons/mail/mail_alias_data.xml new file mode 100644 index 00000000000..041c1dd3316 --- /dev/null +++ b/addons/mail/mail_alias_data.xml @@ -0,0 +1,9 @@ + + + + + mail.catchall.domain + openerp.my.openerp.com + + + diff --git a/addons/mail/mail_alias_view.xml b/addons/mail/mail_alias_view.xml new file mode 100644 index 00000000000..e72143bdb9a --- /dev/null +++ b/addons/mail/mail_alias_view.xml @@ -0,0 +1,73 @@ + + + + + + + mail.alias.form + mail.alias + form + + +
+ + + + + + + + + +
+
+
+ + + + mail.alias.tree + mail.alias + tree + + + + + + + + + + + + + mail.alias.search + mail.alias + search + + + + + + + + + + + + + + Mail Alias + mail.alias + form + tree,form + + + + + +
+
diff --git a/addons/mail/mail_data.xml b/addons/mail/mail_data.xml index c8e8b1a488e..2448b89fcd6 100644 --- a/addons/mail/mail_data.xml +++ b/addons/mail/mail_data.xml @@ -12,5 +12,18 @@ + + + admin + + + + {} + + + + + + diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 0a8677d7862..41d2d0a148e 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -30,6 +30,7 @@ from PIL import Image import StringIO import tools from tools.translate import _ +from lxml import etree class mail_group(osv.osv): """ @@ -48,7 +49,7 @@ class mail_group(osv.osv): _description = 'Discussion group' _name = 'mail.group' _inherit = ['mail.thread'] - + _inherits = {'mail.alias': 'alias_id'} def action_group_join(self, cr, uid, ids, context={}): return self.message_subscribe(cr, uid, ids, context=context); @@ -129,6 +130,7 @@ class mail_group(osv.osv): 'member_count': fields.function(get_member_ids, type='integer', string='Member count', multi='get_member_ids'), 'is_subscriber': fields.function(get_member_ids, type='boolean', string='Joined', multi='get_member_ids'), 'last_month_msg_nbr': fields.function(get_last_month_msg_nbr, type='integer', string='Messages count for last month'), + 'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True) } _defaults = { @@ -136,3 +138,27 @@ class mail_group(osv.osv): 'responsible_id': (lambda s, cr, uid, ctx: uid), 'photo': _get_default_photo, } + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + res = super(mail_group,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) + if view_type == 'form': + domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", context=context) + if not domain: + doc = etree.XML(res['arch']) + alias_node = doc.xpath("//field[@name='alias_id']")[0] + parent = alias_node.getparent() + parent.remove(alias_node) + res['arch'] = etree.tostring(doc) + return res + + def create(self, cr, uid, vals, context=None): + model_pool = self.pool.get('ir.model.data') + alias_pool = self.pool.get('mail.alias') + model, res_id = model_pool.get_object_reference( cr, uid, "mail", "model_mail_group") + vals.update({'alias_name': "mailing-group", + 'alias_model_id': res_id}) + alias_pool.create_unique_alias(cr, uid, vals, context=context) + res = super( mail_group, self).create(cr, uid, vals, context) + record = self.read(cr, uid, res, context) + alias_pool.write(cr, uid, [record['alias_id']], {"alias_force_thread_id":record['id']}, context) + return res diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 921c3b528c4..b02447576e9 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -69,6 +69,9 @@ +
+ +