diff --git a/addons/crm/tests/test_crm_lead_lost.py b/addons/crm/tests/test_crm_lead_lost.py index a4fe7216240..735d3ec2ed3 100644 --- a/addons/crm/tests/test_crm_lead_lost.py +++ b/addons/crm/tests/test_crm_lead_lost.py @@ -4,6 +4,7 @@ from odoo.addons.crm.tests import common as crm_common from odoo.exceptions import AccessError from odoo.tests.common import tagged, users +from odoo.tools import mute_logger @tagged('lead_manage', 'lead_lost') @@ -18,34 +19,96 @@ class TestLeadConvert(crm_common.TestCrmCommon): @users('user_sales_salesman') def test_lead_lost(self): + """ Test setting a lead as lost using the wizard. Also check that an + 'html editor' void content used as feedback is not logged on the lead. """ + # Initial data + self.assertEqual(len(self.lead_1.message_ids), 1, 'Should contain creation message') + creation_message = self.lead_1.message_ids[0] + self.assertEqual(creation_message.subtype_id, self.env.ref('crm.mt_lead_create')) + + # Update responsible as ACLs is "own only" for user_sales_salesman self.lead_1.with_user(self.user_sales_manager).write({ 'user_id': self.user_sales_salesman.id, 'probability': 32, }) self.flush_tracking() - lead = self.lead_1.with_user(self.env.user) + lead = self.env['crm.lead'].browse(self.lead_1.ids) + self.assertFalse(lead.lost_reason) self.assertEqual(lead.probability, 32) self.assertEqual(len(lead.message_ids), 2, 'Should have tracked new responsible') + update_message = lead.message_ids[0] + self.assertEqual(update_message.subtype_id, self.env.ref('mail.mt_note')) + # mark as lost using the wizard lost_wizard = self.env['crm.lead.lost'].with_context({ 'active_ids': lead.ids, }).create({ - 'lost_reason_id': self.lost_reason.id + 'lost_reason_id': self.lost_reason.id, + 'lost_feedback': '
', # void content }) lost_wizard.action_lost_reason_apply() self.flush_tracking() - self.assertEqual(lead.probability, 0) - self.assertEqual(lead.automated_probability, 0) + # check lead update self.assertFalse(lead.active) + self.assertEqual(lead.automated_probability, 0) self.assertEqual(lead.lost_reason, self.lost_reason) # TDE FIXME: should be called lost_reason_id non didjou + self.assertEqual(lead.probability, 0) # check messages self.assertEqual(len(lead.message_ids), 3, 'Should have logged a tracking message for lost lead with reason') + update_message = lead.message_ids[0] + self.assertEqual(update_message.subtype_id, self.env.ref('crm.mt_lead_lost')) + self.assertEqual(len(update_message.tracking_value_ids), 2, 'Tracking: active, lost reason') + self.assertTracking( + update_message, + [('active', 'boolean', True, False), + ('lost_reason', 'many2one', False, self.lost_reason) + ] + ) + + @users('user_sales_leads') + def test_lead_lost_batch_wfeedback(self): + """ Test setting leads as lost in batch using the wizard, including a log + message. """ + leads = self._create_leads_batch(lead_type='lead', count=10, probabilities=[10, 20, 30]) + self.assertEqual(len(leads), 10) + self.flush_tracking() + + lost_wizard = self.env['crm.lead.lost'].with_context({ + 'active_ids': leads.ids, + }).create({ + 'lost_reason_id': self.lost_reason.id, + 'lost_feedback': 'I cannot find it. It was in my closet and pouf, disappeared.
', + }) + lost_wizard.action_lost_reason_apply() + self.flush_tracking() + + for lead in leads: + # check content + self.assertFalse(lead.active) + self.assertEqual(lead.automated_probability, 0) + self.assertEqual(lead.probability, 0) + self.assertEqual(lead.lost_reason, self.lost_reason) + # check messages + self.assertEqual(len(lead.message_ids), 3, 'Should have 3 messages: creation, lost, and log') + lost_message = lead.message_ids.filtered(lambda msg: msg.subtype_id == self.env.ref('crm.mt_lead_lost')) + self.assertTrue(lost_message) + self.assertTracking( + lost_message, + [('active', 'boolean', True, False), + ('lost_reason', 'many2one', False, self.lost_reason) + ] + ) + note_message = lead.message_ids.filtered(lambda msg: msg.subtype_id == self.env.ref('mail.mt_note')) + self.assertTrue(note_message) + self.assertEqual(note_message.body, 'I cannot find it. It was in my closet and pouf, disappeared.
') @users('user_sales_salesman') + @mute_logger('odoo.addons.base.models') def test_lead_lost_crm_rights(self): + """ Test ACLs of lost reasons management and usage """ lead = self.lead_1.with_user(self.env.user) # nice try little salesman but only managers can create lost reason to avoid bloating the DB diff --git a/addons/crm/wizard/crm_lead_lost.py b/addons/crm/wizard/crm_lead_lost.py index 8f64a40579b..f2ca5958544 100644 --- a/addons/crm/wizard/crm_lead_lost.py +++ b/addons/crm/wizard/crm_lead_lost.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models +from odoo import fields, models, _ +from odoo.tools.mail import is_html_empty class CrmLeadLost(models.TransientModel): @@ -8,7 +10,20 @@ class CrmLeadLost(models.TransientModel): _description = 'Get Lost Reason' lost_reason_id = fields.Many2one('crm.lost.reason', 'Lost Reason') + lost_feedback = fields.Html( + 'Closing Note', sanitize=True, + help="Closing note logged in leads discussion history." + ) def action_lost_reason_apply(self): + self.ensure_one() leads = self.env['crm.lead'].browse(self.env.context.get('active_ids')) - return leads.action_set_lost(lost_reason=self.lost_reason_id.id) + res = leads.action_set_lost(lost_reason=self.lost_reason_id.id) + if not is_html_empty(self.lost_feedback): + leads._message_log_batch( + bodies=dict( + (lead.id, self.lost_feedback) + for lead in leads), + subject=False, + ) + return res diff --git a/addons/crm/wizard/crm_lead_lost_views.xml b/addons/crm/wizard/crm_lead_lost_views.xml index 79611a98e7c..c6ca6b23aca 100644 --- a/addons/crm/wizard/crm_lead_lost_views.xml +++ b/addons/crm/wizard/crm_lead_lost_views.xml @@ -8,6 +8,7 @@