Skip to content
Permalink
Browse files

[IMP] mail, test_mail, *: add new email.cc.mixin on main models

*: crm, project, maintenance, hr_recruitment

When a record is created from an email, cc can be lost. This commit
proposes a new mixin to keep cc on the record and allows to create
partner for each of them when sending a message from the chatter.

The mixin is added on the mail recors that can be created from mail.alias:

document
helpdesk.ticket
mrp.eco
quality.alert
hr.applicant
crm.lead
project.task
mail.channel
maintenance.equipment

Task: 1925001
  • Loading branch information...
Xavier-Do committed Feb 19, 2019
1 parent 2249c2a commit 3a6e90e2db8540ab42b19892059ee0102bbf40ca
@@ -50,7 +50,7 @@ class Lead(models.Model):
_name = "crm.lead"
_description = "Lead/Opportunity"
_order = "priority desc,activity_date_deadline,id desc"
_inherit = ['mail.thread', 'mail.activity.mixin', 'utm.mixin', 'format.address.mixin', 'mail.blacklist.mixin']
_inherit = ['mail.cc.mixin', 'mail.thread', 'mail.activity.mixin', 'utm.mixin', 'format.address.mixin', 'mail.blacklist.mixin']
_primary_email = 'email_from'

def _default_probability(self):
@@ -74,7 +74,6 @@ def _default_stage_id(self):
index=True, tracking=True, help='When sending mails, the default email address is taken from the Sales Team.')
kanban_state = fields.Selection([('grey', 'No next activity planned'), ('red', 'Next activity late'), ('green', 'Next activity is planned')],
string='Kanban State', compute='_compute_kanban_state')
email_cc = fields.Text('Global CC', help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma")
description = fields.Text('Notes')
tag_ids = fields.Many2many('crm.lead.tag', 'crm_lead_tag_rel', 'lead_id', 'tag_id', string='Tags', help="Classify and analyze your lead/opportunity categories like: Training, Service")
contact_name = fields.Char('Contact Name', tracking=30)
@@ -1197,7 +1196,6 @@ def message_new(self, msg_dict, custom_values=None):
defaults = {
'name': msg_dict.get('subject') or _("No Subject"),
'email_from': msg_dict.get('from'),
'email_cc': msg_dict.get('cc'),
'partner_id': msg_dict.get('author_id', False),
}
if msg_dict.get('author_id'):
@@ -107,6 +107,7 @@
aria-label="Blacklisted" attrs="{'invisible': [('is_blacklisted', '=', False)]}" groups="base.group_user"></i>
<field name="email_from" widget="email"/>
</div>
<field name="email_cc" groups="base.group_no_one"/>
<field name="function"/>
<field name="phone" widget="phone"/>
<field name="mobile"/>
@@ -92,7 +92,7 @@ class Applicant(models.Model):
_name = "hr.applicant"
_description = "Applicant"
_order = "priority desc, id desc"
_inherit = ['mail.thread', 'mail.activity.mixin', 'utm.mixin']
_inherit = ['mail.cc.mixin', 'mail.thread', 'mail.activity.mixin', 'utm.mixin']

def _default_stage_id(self):
if self._context.get('default_job_id'):
@@ -117,8 +117,6 @@ def _default_company_id(self):
active = fields.Boolean("Active", default=True, help="If the active field is set to false, it will allow you to hide the case without removing it.")
description = fields.Text("Description")
email_from = fields.Char("Email", size=128, help="Applicant email")
email_cc = fields.Text("Watchers Emails", size=252,
help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma")
probability = fields.Float("Probability")
partner_id = fields.Many2one('res.partner', "Contact")
create_date = fields.Datetime("Creation Date", readonly=True, index=True)
@@ -407,7 +405,6 @@ def message_new(self, msg, custom_values=None):
'name': msg.get('subject') or _("No Subject"),
'partner_name': val,
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'partner_id': msg.get('author_id', False),
}
if msg.get('priority'):
@@ -131,6 +131,7 @@
<group>
<field name="partner_id"/>
<field name="email_from" widget="email"/>
<field name="email_cc" groups="base.group_no_one"/>
<field name="partner_phone"/>
<field name="partner_mobile"/>
<field name="type_id" placeholder="Degree"/>
@@ -10,6 +10,7 @@
from . import mail_activity
from . import mail_mail
from . import mail_thread
from . import mail_cc_mixin
from . import mail_address_mixin
from . import mail_blacklist
from . import mail_channel
@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import _, api, fields, models, tools


class MailCCMixin(models.AbstractModel):
_name = 'mail.cc.mixin'
_inherit = 'mail.thread'
_description = 'Email CC management'

email_cc = fields.Char('Email cc', help='List of cc from incoming emails.')

def _email_dict(self, cc_string):
'''return a dict of sanitize_email:raw_email from a string of cc'''
if not cc_string:
return {}
return {tools.email_split(cc)[0]: cc for cc in [cc.strip() for cc in cc_string.split(',')] if tools.email_split(cc)}

@api.model
def message_new(self, msg_dict, custom_values=None):
if custom_values is None:
custom_values = {}
cc_values = {
'email_cc': ", ".join(self._email_dict(msg_dict.get('cc')).values()),
}
cc_values.update(custom_values)
return super(MailCCMixin, self).message_new(msg_dict, cc_values)

@api.multi
def message_update(self, msg_dict, update_vals=None):
'''Adds cc email to self.email_cc while trying to keep email as raw as possible but unique'''
if update_vals is None:
update_vals = {}
cc_values = {}
new_cc = self._email_dict(msg_dict.get('cc'))
if new_cc:
old_cc = self._email_dict(self.email_cc)
new_cc.update(old_cc)
cc_values['email_cc'] = ", ".join(new_cc.values())
cc_values.update(update_vals)
return super(MailCCMixin, self).message_update(msg_dict, cc_values)

@api.multi
def message_get_suggested_recipients(self):
recipients = super(MailCCMixin, self).message_get_suggested_recipients()
for record in self:
if record.email_cc:
for email in tools.email_split_and_format(record.email_cc):
record._message_add_suggested_recipient(recipients, email=email, reason=_('CC Email'))
return recipients
@@ -81,7 +81,7 @@ def unlink(self):
return res

def get_alias_model_name(self, vals):
return vals.get('alias_model', 'maintenance.equipment')
return vals.get('alias_model', 'maintenance.request')

def get_alias_values(self):
values = super(MaintenanceEquipmentCategory, self).get_alias_values()
@@ -253,9 +253,10 @@ def _cron_generate_requests(self):
if not next_requests:
equipment._create_new_request(equipment.next_action_date)


class MaintenanceRequest(models.Model):
_name = 'maintenance.request'
_inherit = ['mail.thread', 'mail.activity.mixin']
_inherit = ['mail.cc.mixin', 'mail.thread', 'mail.activity.mixin']
_description = 'Maintenance Request'
_order = "id desc"

@@ -94,6 +94,7 @@
class="oe_inline"/> <span class="ml8">hours</span>
</div>
<field name="priority" widget="priority"/>
<field name="email_cc" string="Email cc" groups="base.group_no_one"/>
</group>
</group>
<field name='description' placeholder="Internal Note ......."/>
@@ -399,7 +399,7 @@ class Task(models.Model):
_name = "project.task"
_description = "Task"
_date_name = "date_assign"
_inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin', 'rating.mixin']
_inherit = ['mail.cc.mixin', 'portal.mixin', 'mail.thread', 'mail.activity.mixin', 'rating.mixin']
_mail_post_access = 'read'
_order = "priority desc, sequence, id desc"

@@ -496,8 +496,6 @@ def _read_group_stage_ids(self, stages, domain, order):
subtask_project_id = fields.Many2one('project.project', related="project_id.subtask_project_id", string='Sub-task Project', readonly=True)
subtask_count = fields.Integer("Sub-task count", compute='_compute_subtask_count')
email_from = fields.Char(string='Email', help="These people will receive email.", index=True)
email_cc = fields.Char(string='Watchers Emails', help="""These email addresses will be added to the CC field of all inbound
and outbound emails for this record before being sent. Separate multiple email addresses with a comma""")
# Computed field about working time elapsed between record creation and assignation/closing.
working_hours_open = fields.Float(compute='_compute_elapsed', string='Working hours to assign', store=True, group_operator="avg")
working_hours_close = fields.Float(compute='_compute_elapsed', string='Working hours to close', store=True, group_operator="avg")
@@ -835,7 +833,6 @@ def message_new(self, msg, custom_values=None):
defaults = {
'name': msg.get('subject') or _("No Subject"),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'planned_hours': 0.0,
'partner_id': msg.get('author_id')
}
@@ -124,3 +124,10 @@ class MailModel(models.Model):
def _value_pc(self):
for record in self:
record.value_pc = float(record.value) / 100


class MailCC(models.Model):
_name = 'mail.test.cc'
_inherit = ['mail.cc.mixin', 'mail.thread']

name = fields.Char()
@@ -10,3 +10,6 @@ access_mail_test_full_portal,mail.test.full.portal,model_mail_test_full,base.gro
access_mail_test_full_user,mail.test.full.user,model_mail_test_full,base.group_user,1,1,1,1
access_mail_test_portal,mail.test.portal,model_mail_test,base.group_portal,1,1,0,0
access_mail_test_user,mail.test.user,model_mail_test,base.group_user,1,1,1,1
access_mail_test_cc_portal,mail.test.cc.portal,model_mail_test_cc,base.group_portal,1,0,0,0
access_mail_test_cc_user,mail.test.cc.user,model_mail_test_cc,base.group_user,1,1,1,1

@@ -6,6 +6,7 @@
from . import test_mail_mail
from . import test_mail_race
from . import test_mail_resend
from . import test_mail_cc
from . import test_mail_channel
from . import test_mail_gateway
from . import test_mail_template
@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.addons.test_mail.tests import common
from odoo.tests import tagged
from odoo.tools import mute_logger, email_split_and_format
from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE


@tagged('cc_test')
class TestMailResend(common.BaseFunctionalTest, common.MockEmails):

@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_cc_new(self):
alias = self.env['mail.alias'].create({
'alias_name': 'cc_record',
'alias_user_id': False,
'alias_model_id': self.env['ir.model']._get('mail.test.cc').id,
'alias_contact': 'everyone'})
record = self.format_and_process(MAIL_TEMPLATE, target_model='mail.test.cc', to='cc_record@example.com',
cc='cc1@example.com, cc2@example.com')
cc = email_split_and_format(record.email_cc)
self.assertEqual(sorted(cc), ['cc1@example.com', 'cc2@example.com'], 'cc should contains exactly 2 cc')

@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_cc_update_with_old(self):
record = self.env['mail.test.cc'].create({'email_cc': 'cc1 <cc1@example.com>, cc2@example.com'})
alias = self.env['mail.alias'].create({
'alias_name': 'cc_record',
'alias_user_id': False,
'alias_model_id': self.env['ir.model']._get('mail.test.cc').id,
'alias_contact': 'everyone',
'alias_force_thread_id': record.id})

self.format_and_process(MAIL_TEMPLATE, subject='Re: Frogs', target_model='mail.test.cc',
msg_id='1198923581.41972151344608186799.JavaMail.diff1@agrolait.com',
to='cc_record@example.com',
cc='cc2 <cc2@example.com>, cc3@example.com')
cc = email_split_and_format(record.email_cc)
self.assertEqual(sorted(cc), ['cc1 <cc1@example.com>', 'cc2@example.com', 'cc3@example.com'], 'new cc should have been added on record (unique)')

@mute_logger('odoo.addons.mail.models.mail_thread')
def test_message_cc_update_no_old(self):
record = self.env['mail.test.cc'].create({})
alias = self.env['mail.alias'].create({
'alias_name': 'cc_record',
'alias_user_id': False,
'alias_model_id': self.env['ir.model']._get('mail.test.cc').id,
'alias_contact': 'everyone',
'alias_force_thread_id': record.id})
self.format_and_process(MAIL_TEMPLATE, subject='Re: Frogs', target_model='mail.test.cc',
msg_id='1198923581.41972151344608186799.JavaMail.diff1@agrolait.com',
to='cc_record@example.com',
cc='cc2 <cc2@example.com>, cc3@example.com')
cc = email_split_and_format(record.email_cc)
self.assertEqual(sorted(cc), ['cc2 <cc2@example.com>', 'cc3@example.com'], 'new cc should have been added on record (unique)')

@mute_logger('odoo.addons.mail.models.mail_mail')
def test_mail_cc_recipient_suggestion(self):
record = self.env['mail.test.cc'].create({'email_cc': 'cc1@example.com, cc2@example.com, cc3 <cc3@example.com>'})
suggestions = record.message_get_suggested_recipients()[record.id]
self.assertEqual(sorted(suggestions), [
(False, 'cc1@example.com', 'CC Email'),
(False, 'cc2@example.com', 'CC Email'),
(False, 'cc3 <cc3@example.com>', 'CC Email')
], 'cc should be in suggestions')

0 comments on commit 3a6e90e

Please sign in to comment.
You can’t perform that action at this time.