[MERGE] Implementation of mail.alias by Jigar Amin
bzr revid: odo@openerp.com-20120703160155-gw8po01vmm0q30ow
This commit is contained in:
@@ -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 """
|
||||
|
||||
@@ -13,9 +13,17 @@
|
||||
<record model="crm.case.channel">
|
||||
<field name="name">email</field>
|
||||
</record>
|
||||
<record id="mail_alias_sales_department" model="mail.alias">
|
||||
<field name="alias_name">sales</field>
|
||||
<field name="alias_model_id" ref="model_crm_lead"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_defaults">{'type':'lead'}</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.case.section" id="section_sales_department">
|
||||
<field name="name">Sales Department</field>
|
||||
<field name="code">Sales</field>
|
||||
<field name="alias_id" ref="mail_alias_sales_department"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
+26
-17
@@ -1,28 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="mail_alias_marketing_department" model="mail.alias">
|
||||
<field name="alias_name">info</field>
|
||||
<field name="alias_model_id" ref="model_crm_lead"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_defaults">{'type':'lead'}</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data>
|
||||
<record id="base.user_demo" model="res.users">
|
||||
<field name="groups_id" eval="[(4,ref('base.group_sale_salesman'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="ir_ui_view_sc_calendar_demo" model="ir.ui.view_sc">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="res_id" ref="crm.menu_crm_case_categ_meet"/>
|
||||
</record>
|
||||
<record id="ir_ui_view_sc_calendar_demo" model="ir.ui.view_sc">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="res_id" ref="crm.menu_crm_case_categ_meet"/>
|
||||
</record>
|
||||
|
||||
<record model="crm.case.section" id="section_sales_marketing_department">
|
||||
<field name="name">Sales Marketing Department</field>
|
||||
<field name="code">Sales Marketing</field>
|
||||
<field name="parent_id" ref="crm.section_sales_department"></field>
|
||||
</record>
|
||||
|
||||
<record model="crm.segmentation" id="crm_segmentation0">
|
||||
<field name="name">OpenERP partners</field>
|
||||
<field name="exclusif">True</field>
|
||||
<field name="categ_id" ref="base.res_partner_category_2"/>
|
||||
</record>
|
||||
<record model="crm.case.section" id="section_sales_marketing_department">
|
||||
<field name="name">Sales Marketing Department</field>
|
||||
<field name="code">Sales Marketing</field>
|
||||
<field name="parent_id" ref="crm.section_sales_department"></field>
|
||||
<field name="alias_id" ref="mail_alias_marketing_department"/>
|
||||
</record>
|
||||
|
||||
<record model="crm.segmentation" id="crm_segmentation0">
|
||||
<field name="name">OpenERP partners</field>
|
||||
<field name="exclusif">True</field>
|
||||
<field name="categ_id" ref="base.res_partner_category_2"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<field name="name" colspan="2"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="code"/>
|
||||
<field name="alias_id" required="0" domain="[('alias_model_id', '=','crm.lead')]"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -449,5 +449,13 @@
|
||||
<field name="question_id" ref="survey_question_job_1"/>
|
||||
<field eval="13" name="sequence"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_alias_jobs" model="mail.alias">
|
||||
<field name="alias_name">Jobs</field>
|
||||
<field name="alias_model_id" ref="model_hr_applicant"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_defaults">{}</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -348,6 +348,9 @@
|
||||
attrs="{'invisible':[('survey_id','=',False)]}"/>
|
||||
</div>
|
||||
</field>
|
||||
<field name="company_id" version="7.0" position="after">
|
||||
<field name="alias_id" required="0" domain="[('alias_model_id','=','hr.applicant')]"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
+55
-17
@@ -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 <jobs@example.my.openerp.com>",),
|
||||
'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
|
||||
|
||||
|
||||
|
||||
|
||||
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'])})
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record model="ir.config_parameter" id="user_mail_alias">
|
||||
<field name="key">mail.catchall.domain</field>
|
||||
<field name="value">openerp.my.openerp.com</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Alias Form View !-->
|
||||
<record model="ir.ui.view" id="view_mail_alias_form">
|
||||
<field name="name">mail.alias.form</field>
|
||||
<field name="model">mail.alias</field>
|
||||
<field name="type">form</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Alias" version="7.0">
|
||||
<sheet>
|
||||
<group colspan="4" col="4">
|
||||
<field name="alias_name"/>
|
||||
<field name="alias_model_id" readonly="1"/>
|
||||
<field name="alias_user_id"/>
|
||||
<field name="alias_force_thread_id"/>
|
||||
<field name="alias_defaults"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Alias List View !-->
|
||||
<record model="ir.ui.view" id="view_mail_alias_tree">
|
||||
<field name="name">mail.alias.tree</field>
|
||||
<field name="model">mail.alias</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Alias">
|
||||
<field name="alias_name"/>
|
||||
<field name="alias_model_id"/>
|
||||
<field name="alias_user_id"/>
|
||||
<field name="alias_defaults"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Alias Search View !-->
|
||||
<record model="ir.ui.view" id="view_mail_alias_search">
|
||||
<field name="name">mail.alias.search</field>
|
||||
<field name="model">mail.alias</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Alias">
|
||||
<field name="alias_name"/>
|
||||
<field name="alias_model_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="User" name="User" icon="terp-personal" context="{'group_by':'alias_user_id'}"/>
|
||||
<filter string="Model" name="Model" context="{'group_by':'alias_model_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_mail_alias" model="ir.actions.act_window">
|
||||
<field name="name">Mail Alias</field>
|
||||
<field name="res_model">mail.alias</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_mail_alias_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="mail_alias_menu"
|
||||
parent="base.menu_email"
|
||||
action="action_view_mail_alias"
|
||||
sequence="50"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -12,5 +12,18 @@
|
||||
<field eval="'process_email_queue'" name="function"/>
|
||||
<field eval="'()'" name="args"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_alias_root_user" model="mail.alias">
|
||||
<field name="alias_name">admin</field>
|
||||
<field name="alias_model_id" ref="model_res_users"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_force_thread_id" ref="base.user_root"/>
|
||||
<field name="alias_defaults">{}</field>
|
||||
</record>
|
||||
|
||||
<record model="res.users" id="base.user_root">
|
||||
<field name="alias_id" ref="mail_alias_root_user"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
<field name="public" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<div class="oe_edit_only">
|
||||
<field name="alias_id" required="0" domain="[('alias_model_id','=','mail.group')]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
|
||||
@@ -475,11 +475,57 @@ class mail_thread(osv.osv):
|
||||
return msgs
|
||||
|
||||
|
||||
def message_catchall(self, cr, uid, message, context=None):
|
||||
"""TODO proper docstring, inspired by messsage_process()"""
|
||||
# TODO
|
||||
pass
|
||||
def _get_user(self, cr, uid, alias, context):
|
||||
"""
|
||||
param alias: browse record of alias.
|
||||
return: int user_id.
|
||||
"""
|
||||
|
||||
user_obj = self.pool.get('res.user')
|
||||
user_id = 1
|
||||
if alias.alias_user_id:
|
||||
user_id = alias.alias_user_id.id
|
||||
#if user_id not defined in the alias then search related user using name of Email sender
|
||||
else:
|
||||
from_email = msg.get('from')
|
||||
user_ids = user_obj.search(cr, uid, [('name','=',from_email)], context)
|
||||
if user_ids:
|
||||
user_id = user_obj.browse(cr, uid, user_ids[0], context).id
|
||||
return user_id
|
||||
|
||||
def message_catchall(self, cr, uid, message, context=None):
|
||||
"""
|
||||
Process incoming mail and call messsage_process using details of the mail.alias model
|
||||
else raise Exception so that mailgate script will reject the mail and
|
||||
send notification mail sender that this mailbox does not exist so your mail have been rejected.
|
||||
"""
|
||||
|
||||
alias_pool = self.pool.get('mail.alias')
|
||||
user_pool = self.pool.get('res.users')
|
||||
mail_compose_pool = self.pool.get('mail.compose.message')
|
||||
mail_message_pool = self.pool.get('mail.message')
|
||||
if isinstance(message, xmlrpclib.Binary):
|
||||
message = str(message.data)
|
||||
if isinstance(message, unicode):
|
||||
message = message.encode('utf-8')
|
||||
msg_txt = email.message_from_string(message)
|
||||
msg = mail_message_pool.parse_message(msg_txt)
|
||||
alias_name = msg.get('to').split("@")[0]
|
||||
alias_ids = alias_pool.search(cr, uid, [('alias_name','=',alias_name)])
|
||||
#if alias found then call message_process method.
|
||||
if alias_ids:
|
||||
alias_id = alias_pool.browse(cr, uid, alias_ids[0], context)
|
||||
user_id = self._get_user( cr, uid, alias_id, context)
|
||||
alias_defaults = dict(eval(alias_id.alias_defaults or {}))
|
||||
self.message_process(cr, user_id, alias_id.alias_model_id.model, message,
|
||||
custom_values = alias_defaults,
|
||||
thread_id = alias_id.alias_force_thread_id or False,
|
||||
context=context)
|
||||
else:
|
||||
#if Mail box for the intended Mail Alias then give logger warning
|
||||
_logger.warning("No Mail Alias Found for the name '%s'."%(alias_name))
|
||||
raise
|
||||
return True
|
||||
|
||||
#------------------------------------------------------
|
||||
# Email specific
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
from lxml import etree
|
||||
|
||||
class res_users(osv.osv):
|
||||
""" Update of res.users class
|
||||
@@ -29,6 +30,7 @@ class res_users(osv.osv):
|
||||
"""
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users', 'mail.thread']
|
||||
_inherits = {'mail.alias': 'alias_id'}
|
||||
|
||||
_columns = {
|
||||
'notification_email_pref': fields.selection([
|
||||
@@ -38,6 +40,7 @@ class res_users(osv.osv):
|
||||
('none', 'Never')
|
||||
], 'Receive Feeds by Email', required=True,
|
||||
help="Choose in which case you want to receive an email when you receive new feeds."),
|
||||
'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -55,9 +58,28 @@ class res_users(osv.osv):
|
||||
self.SELF_WRITEABLE_FIELDS.append('notification_email_pref')
|
||||
return init_res
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
res = super(res_users,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, data, context=None):
|
||||
# create default alias same as the login
|
||||
model_pool = self.pool.get('ir.model.data')
|
||||
alias_pool = self.pool.get('mail.alias')
|
||||
res_id = model_pool.get_object( cr, uid, "mail", "model_res_users")
|
||||
data.update({'alias_name': data.get('login'),
|
||||
'alias_model_id': res_id.id})
|
||||
user_id = super(res_users, self).create(cr, uid, data, context=context)
|
||||
user = self.browse(cr, uid, [user_id], context=context)[0]
|
||||
user = self.browse(cr, uid, user_id, context=context)
|
||||
alias_pool.write(cr, uid, [user.alias_id.id], {"alias_force_thread_id": user.id}, context)
|
||||
# make user follow itself
|
||||
self.message_subscribe(cr, uid, [user_id], [user_id], context=context)
|
||||
# create a welcome message to broadcast
|
||||
@@ -66,7 +88,15 @@ class res_users(osv.osv):
|
||||
# TODO: clean the broadcast feature. As this is not cleany specified, temporarily remove the message broadcasting that is not buggy but not very nice.
|
||||
#self.message_broadcast(cr, uid, [user.id], 'Welcome notification', message, context=context)
|
||||
return user_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
# if login of user have been changed then change alias of user also.
|
||||
if 'login' in vals.keys():
|
||||
for user in self.browse(cr, uid, ids, context=context):
|
||||
self.pool.get('mail.alias').write(cr, uid, [user.alias_id.id], {'alias_name': vals['login']}, context=context)
|
||||
return super(res_users, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[False], context=None):
|
||||
""" Override of message_load_ids
|
||||
User discussion page :
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<field name="active" position="after">
|
||||
<field name="alias_id" readonly="1" required="0"/>
|
||||
</field>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,3 +5,5 @@ access_mail_thread,mail.thread,model_mail_thread,base.group_user,1,1,1,0
|
||||
access_mail_subscription,mail.subscription,model_mail_subscription,,1,1,1,1
|
||||
access_mail_notification,mail.notification,model_mail_notification,,1,1,1,1
|
||||
access_mail_group,mail.group,model_mail_group,base.group_user,1,1,1,1
|
||||
access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0
|
||||
access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1
|
||||
|
||||
|
@@ -94,22 +94,23 @@ class RPCProxy(object):
|
||||
return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request, **kwargs)
|
||||
|
||||
class EmailParser(object):
|
||||
def __init__(self, uid, password, model, email_default, dbname, host, port):
|
||||
def __init__(self, uid, password, dbname, host, port, model=False, email_default=False):
|
||||
self.rpc = RPCProxy(uid, password, host=host, port=port, dbname=dbname)
|
||||
try:
|
||||
self.model_id = int(model)
|
||||
self.model = str(model)
|
||||
except:
|
||||
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
|
||||
self.model = str(model)
|
||||
self.email_default = email_default
|
||||
if model:
|
||||
try:
|
||||
self.model_id = int(model)
|
||||
self.model = str(model)
|
||||
except:
|
||||
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
|
||||
self.model = str(model)
|
||||
self.email_default = email_default
|
||||
|
||||
|
||||
def parse(self, message, custom_values=None, save_original=None):
|
||||
def parse(self, method, message, custom_values=None, save_original=None):
|
||||
# pass message as bytes because we don't know its encoding until we parse its headers
|
||||
# and hence can't convert it to utf-8 for transport
|
||||
res_id = self.rpc('mail.thread',
|
||||
'message_process',
|
||||
method,
|
||||
self.model,
|
||||
xmlrpclib.Binary(message),
|
||||
custom_values or {},
|
||||
@@ -156,30 +157,29 @@ def main():
|
||||
"""
|
||||
Receive the email via the stdin and send it to the OpenERP Server
|
||||
"""
|
||||
|
||||
parser = configure_parser()
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
|
||||
method = "message_process"
|
||||
email_parser = EmailParser(options.userid,
|
||||
options.password,
|
||||
options.model,
|
||||
options.default,
|
||||
dbname=options.dbname,
|
||||
host=options.host,
|
||||
port=options.port)
|
||||
|
||||
|
||||
options.dbname,
|
||||
options.host,
|
||||
options.port,
|
||||
model=options.model,
|
||||
email_default= options.default)
|
||||
msg_txt = sys.stdin.read()
|
||||
|
||||
custom_values = {}
|
||||
if not options.model:
|
||||
method = "message_catchall"
|
||||
try:
|
||||
custom_values = dict(eval(options.custom_values or {} ))
|
||||
custom_values = dict(eval(options.custom_values or "{}" ))
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
try:
|
||||
email_parser.parse(msg_txt, custom_values, options.save_original or False)
|
||||
email_parser.parse(method, msg_txt, custom_values, options.save_original or False)
|
||||
except Exception:
|
||||
msg = '\n'.join([
|
||||
'parameters',
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="mail_alias_demo_user" model="mail.alias">
|
||||
<field name="alias_name">demo</field>
|
||||
<field name="alias_model_id" ref="model_res_users"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_force_thread_id" ref="base.user_demo"/>
|
||||
<field name="alias_defaults">{}</field>
|
||||
</record>
|
||||
|
||||
<record model="res.users" id="base.user_demo">
|
||||
<field name="alias_id" ref="mail_alias_demo_user"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -20,5 +20,5 @@
|
||||
##############################################################################
|
||||
|
||||
import mail_compose_message
|
||||
|
||||
import update_mail_alias
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import orm
|
||||
from osv import fields
|
||||
|
||||
class transient_update_maildomain(orm.TransientModel):
|
||||
|
||||
_name = "transient.update.maildomain"
|
||||
_description = "Update Mail Domain"
|
||||
_columns = {
|
||||
'name' : fields.text('Domain', required=True),
|
||||
}
|
||||
def update_domain(self, cr, uid, ids, context=None):
|
||||
config_parameter_pool = self.pool.get("ir.config_parameter")
|
||||
for record in self.browse(cr, uid, ids, context):
|
||||
config_parameter_pool.set_param(cr, uid, "mail.catchall.domain", record.name, context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="transient_update_maildomain_form">
|
||||
<field name="name">transient.update.maildomain.form</field>
|
||||
<field name="model">transient.update.maildomain</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml" >
|
||||
<form string="Configure Mail Domain" version="7.0">
|
||||
<header>
|
||||
<button name="update_domain" string="Update"
|
||||
type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</header>
|
||||
<group colspan="4">
|
||||
<separator string="Email Domain" colspan="4"/>
|
||||
<field name="name" nolabel="1" colspan="4" placeholder="openerp.my.openerp.com"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_transient_update_maildomain_form" model="ir.actions.act_window">
|
||||
<field name="name">Configure Mail Domain</field>
|
||||
<field name="res_model">transient.update.maildomain</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<!-- View for general setting -->>
|
||||
|
||||
<record id="view_general_configuration_mail_domain" model="ir.ui.view">
|
||||
<field name="name">General Settings</field>
|
||||
<field name="model">base.config.settings</field>
|
||||
<field name="inherit_id" ref="base_setup.view_general_configuration"/>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/sheet/group[@string='Others']" position='inside'>
|
||||
<group colspan="4" col="4">
|
||||
<label string="Configure Mail Domain" for="id"/>
|
||||
<button type="action" name="%(action_transient_update_maildomain_form)d" string="Configure" icon="gtk-execute"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -55,7 +55,7 @@ class project_task_type(osv.osv):
|
||||
class project(osv.osv):
|
||||
_name = "project.project"
|
||||
_description = "Project"
|
||||
_inherits = {'account.analytic.account': "analytic_account_id"}
|
||||
_inherits = {'account.analytic.account': "analytic_account_id","mail.alias":"alias_id"}
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
|
||||
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
@@ -164,6 +164,8 @@ class project(osv.osv):
|
||||
for task in self.pool.get('project.task').browse(cr, uid, task_ids, context):
|
||||
res[task.project_id.id] += 1
|
||||
return res
|
||||
def _get_alias_model(self, cr, uid, context=None):
|
||||
return [('model_project_task', "Tasks")]
|
||||
|
||||
def _get_followers(self, cr, uid, ids, name, arg, context=None):
|
||||
'''
|
||||
@@ -215,12 +217,13 @@ class project(osv.osv):
|
||||
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
|
||||
'task_count': fields.function(_task_count, type='integer', string="Open Tasks"),
|
||||
'color': fields.integer('Color Index'),
|
||||
'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True),
|
||||
'alias_model': fields.selection(_get_alias_model, "Alias Model",select="1", required=True),
|
||||
'privacy_visibility': fields.selection([('public','Public'), ('followers','Followers Only')], 'Privacy / Visibility'),
|
||||
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,),
|
||||
'followers': fields.function(_get_followers, method=True, fnct_search=_search_followers,
|
||||
type='many2many', relation='res.users', string='Followers'),
|
||||
}
|
||||
|
||||
def dummy(self, cr, uid, ids, context):
|
||||
return True
|
||||
|
||||
@@ -236,6 +239,7 @@ class project(osv.osv):
|
||||
'priority': 1,
|
||||
'sequence': 10,
|
||||
'type_ids': _get_type_common,
|
||||
'alias_model':'model_project_task',
|
||||
}
|
||||
|
||||
# TODO: Why not using a SQL contraints ?
|
||||
@@ -250,6 +254,26 @@ class project(osv.osv):
|
||||
(_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date'])
|
||||
]
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
res = super(project,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
|
||||
if view_type == 'form' or view_type == 'kanban':
|
||||
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)
|
||||
if view_type == "form":
|
||||
model_node = doc.xpath("//field[@name='alias_model']")[0]
|
||||
parent = model_node.getparent()
|
||||
parent.remove(model_node)
|
||||
else:
|
||||
model_node = doc.xpath("//field[@name='alias_id']")[0]
|
||||
parent = model_node.getparent()
|
||||
parent.remove(model_node)
|
||||
res['arch'] = etree.tostring(doc)
|
||||
return res
|
||||
|
||||
def set_template(self, cr, uid, ids, context=None):
|
||||
res = self.setActive(cr, uid, ids, value=False, context=context)
|
||||
return res
|
||||
@@ -497,9 +521,17 @@ def Project():
|
||||
return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(project, self).create(cr, uid, vals, context=context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
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, "project", vals.get('alias_model','model_project_task'))
|
||||
vals.update({'alias_name':"project",
|
||||
'alias_model_id': res_id})
|
||||
alias_pool.create_unique_alias(cr, uid, vals, context=context)
|
||||
res = super( project, self).create(cr, uid, vals, context)
|
||||
record = self.read(cr, uid, res, context)
|
||||
alias_pool.write(cr, uid, [record['alias_id']], {'alias_defaults':{'project_id': record['id']}}, context)
|
||||
self.create_send_note(cr, uid, [res], context=context)
|
||||
return res
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_append_note(cr, uid, ids, body=_("Project has been <b>created</b>."), context=context)
|
||||
@@ -520,6 +552,16 @@ def Project():
|
||||
message = _("Project has been <b>closed</b>.")
|
||||
return self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
model_pool = self.pool.get('ir.model.data')
|
||||
alias_pool = self.pool.get('mail.alias')
|
||||
# if alias_model have been changed then change alias_model_id of alias also.
|
||||
if vals.get('alias_model'):
|
||||
model, res_id = model_pool.get_object_reference( cr, uid, "project", vals.get('alias_model','model_project_task'))
|
||||
alias_id = self.browse(cr, uid, ids[0], context).alias_id
|
||||
alias_pool.write(cr, uid, [alias_id.id], {'alias_model_id': res_id}, context=context)
|
||||
return super(project, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
class task(base_stage, osv.osv):
|
||||
_name = "project.task"
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
ref('base.user_vad')])]" name="members"/>
|
||||
<field name="user_id" ref="base.user_al"/>
|
||||
<field name="name">Integrate a Sale and Warehouse Management.</field>
|
||||
<field name="alias_model">model_project_task</field>
|
||||
</record>
|
||||
|
||||
<!-- Tasks -->
|
||||
@@ -290,6 +291,7 @@
|
||||
<field name="parent_id" ref="all_projects_account"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge')])]" name="type_ids"/>
|
||||
<field name="alias_model">model_project_task</field>
|
||||
</record>
|
||||
<record id="project_project_21" model="project.project">
|
||||
<field name="priority">10</field>
|
||||
@@ -298,6 +300,7 @@
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development')])]" name="type_ids"/>
|
||||
<field eval="[(6, 0, [ref('base.user_root'),ref('base.user_demo')])]" name="members"/>
|
||||
<field name="alias_model">model_project_task</field>
|
||||
</record>
|
||||
<record id="project_project_22" model="project.project">
|
||||
<field name="priority">20</field>
|
||||
@@ -306,6 +309,7 @@
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="[(6, 0, [ref('project_tt_specification'), ref('project_tt_development')])]" name="type_ids"/>
|
||||
<field eval="[(6, 0, [ref('base.user_root'),ref('base.user_demo')])]" name="members"/>
|
||||
<field name="alias_model">model_project_task</field>
|
||||
</record>
|
||||
<record id="project_project_23" model="project.project">
|
||||
<field name="priority">30</field>
|
||||
@@ -313,6 +317,7 @@
|
||||
<field name="name">Install, data import, configuration</field>
|
||||
<field eval="[(6, 0, [ref('project_tt_development')])]" name="type_ids"/>
|
||||
<field eval="[(6, 0, [ref('base.user_root'),ref('base.user_demo')])]" name="members"/>
|
||||
<field name="alias_model">model_project_task</field>
|
||||
</record>
|
||||
|
||||
<!-- Tasks -->
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
<field name="analytic_account_id" invisible="1" required="0"/>
|
||||
<field name="parent_id" invisible="1" string="Parent" domain="[('id','!=',analytic_account_id)]" context="{'current_model': 'project.project'}"/>
|
||||
<field name="privacy_visibility"/>
|
||||
<field name="alias_id" required="0" domain="[('alias_model_id','in',('project.task','project.issue'))]"/>
|
||||
<field name="alias_model"/>
|
||||
</group>
|
||||
<group>
|
||||
<table>
|
||||
@@ -192,6 +194,7 @@
|
||||
<field name="date"/>
|
||||
<field name="color"/>
|
||||
<field name="task_count"/>
|
||||
<field name="alias_id"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_project oe_kanban_auto_height oe_kanban_global_click">
|
||||
@@ -216,7 +219,9 @@
|
||||
<div>Deadline</div>
|
||||
<div><field name="date"/></div>
|
||||
</div>
|
||||
|
||||
<div t-if="record.alias_id.raw_value">
|
||||
<a t-attf-href="mailto:#{record.alias_id.raw_value}"><field name="alias_id"/></a>
|
||||
</div>
|
||||
<div class="oe_kanban_project_fields oe_kanban_project_progress">
|
||||
<div>Progress</div>
|
||||
<div><t t-esc="Math.round(record.effective_hours.raw_value)"/> / <t t-esc="Math.round(record.planned_hours.raw_value)"/> <field name="company_uom_id"/></div>
|
||||
|
||||
@@ -581,6 +581,9 @@ project_issue()
|
||||
class project(osv.osv):
|
||||
_inherit = "project.project"
|
||||
|
||||
def _get_alias_model(self, cr, uid, context=None):
|
||||
return [('model_project_task', "Tasks"),("model_project_issue", "Issue")]
|
||||
|
||||
def _issue_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)])
|
||||
@@ -592,6 +595,7 @@ class project(osv.osv):
|
||||
'project_escalation_id' : fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
|
||||
'reply_to' : fields.char('Reply-To Email Address', size=256),
|
||||
'issue_count': fields.function(_issue_count, type='integer'),
|
||||
'alias_model': fields.selection(_get_alias_model, "Alias Model"),
|
||||
}
|
||||
|
||||
def _check_escalation(self, cr, uid, ids, context=None):
|
||||
|
||||
Reference in New Issue
Block a user