diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index 2d6648fb54b..9930b981f80 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -461,13 +461,7 @@ class MassMailing(models.Model): at = fields.Datetime.from_string(values['ab_testing_schedule_datetime']) ab_testing_cron._trigger(at=at) mailings = super().create(vals_list) - campaign_vals = [ - mailing._get_default_ab_testing_campaign_values() - for mailing in mailings - if mailing.ab_testing_enabled and not mailing.campaign_id - ] - self.env['utm.campaign'].create(campaign_vals) - + mailings._create_ab_testing_utm_campaigns() mailings._fix_attachment_ownership() return mailings @@ -475,15 +469,13 @@ class MassMailing(models.Model): def write(self, values): if values.get('body_html'): values['body_html'] = self._convert_inline_images_to_urls(values['body_html']) - # When ab_testing_enabled is checked we create a campaign if there is none set. - if values.get('ab_testing_enabled') and not values.get('campaign_id'): - # Compute the values of the A/B test campaign based on the first mailing - values['campaign_id'] = self.env['utm.campaign'].create(self[0]._get_default_ab_testing_campaign_values(values)).id # If ab_testing is already enabled on a mailing and the campaign is removed, we raise a ValidationError if values.get('campaign_id') is False and any(mailing.ab_testing_enabled for mailing in self) and 'ab_testing_enabled' not in values: raise ValidationError(_("A campaign should be set when A/B test is enabled")) result = super(MassMailing, self).write(values) + if values.get('ab_testing_enabled'): + self._create_ab_testing_utm_campaigns() self._fix_attachment_ownership() if any(self.mapped('ab_testing_schedule_datetime')): @@ -493,6 +485,14 @@ class MassMailing(models.Model): return result + def _create_ab_testing_utm_campaigns(self): + """ Creates the A/B test campaigns for the mailings that do not have campaign set already """ + campaign_vals = [ + mailing._get_default_ab_testing_campaign_values() + for mailing in self.filtered(lambda mailing: mailing.ab_testing_enabled and not mailing.campaign_id) + ] + return self.env['utm.campaign'].create(campaign_vals) + def _fix_attachment_ownership(self): for record in self: record.attachment_ids.write({'res_model': record._name, 'res_id': record.id}) diff --git a/addons/mass_mailing/models/utm_campaign.py b/addons/mass_mailing/models/utm_campaign.py index 7913cc44bdc..90505e4b389 100644 --- a/addons/mass_mailing/models/utm_campaign.py +++ b/addons/mass_mailing/models/utm_campaign.py @@ -22,7 +22,7 @@ class UtmCampaign(models.Model): # A/B Testing ab_testing_mailings_count = fields.Integer("A/B Test Mailings #", compute="_compute_mailing_mail_count") - ab_testing_completed = fields.Boolean("A/B Testing Campaign Finished") + ab_testing_completed = fields.Boolean("A/B Testing Campaign Finished", copy=False) ab_testing_schedule_datetime = fields.Datetime('Send Final On', default=lambda self: fields.Datetime.now() + relativedelta(days=1), help="Date that will be used to know when to determine and send the winner mailing") @@ -66,8 +66,8 @@ class UtmCampaign(models.Model): mapped_data = dict() ab_testing_mapped_data = dict() for campaign in self: - campaign.mailing_mail_count = sum(mapped_data.get(campaign.id, [])) - campaign.ab_testing_mailings_count = sum(ab_testing_mapped_data.get(campaign.id, [])) + campaign.mailing_mail_count = sum(mapped_data.get(campaign._origin.id or campaign.id, [])) + campaign.ab_testing_mailings_count = sum(ab_testing_mapped_data.get(campaign._origin.id or campaign.id, [])) @api.constrains('ab_testing_total_pc', 'ab_testing_completed') def _check_ab_testing_total_pc(self): diff --git a/addons/mass_mailing/static/src/scss/mass_mailing.scss b/addons/mass_mailing/static/src/scss/mass_mailing.scss index 1b0de618a99..e80cb417b1d 100644 --- a/addons/mass_mailing/static/src/scss/mass_mailing.scss +++ b/addons/mass_mailing/static/src/scss/mass_mailing.scss @@ -215,23 +215,6 @@ font-size: 90%; } -@media only screen and (min-width: 1200px) { - .o_utm_campaign_mass_mailing_substats { - padding-right: 210px; - div { - margin-left: 50px; - } - } -} - -@media only screen and (min-width: 768px) and (max-width: 1200px) { - .o_utm_campaign_mass_mailing_substats { - padding-right: 180px; - div { - margin-left: 30px; - } - } -} .o_mailing_contact_import_list { min-height: 150px; diff --git a/addons/mass_mailing/static/src/scss/mass_mailing_mobile.scss b/addons/mass_mailing/static/src/scss/mass_mailing_mobile.scss index 4c04e47f4a0..7ea9713d05e 100644 --- a/addons/mass_mailing/static/src/scss/mass_mailing_mobile.scss +++ b/addons/mass_mailing/static/src/scss/mass_mailing_mobile.scss @@ -1,9 +1,4 @@ @include media-breakpoint-down(md) { - .o_utm_campaign_mass_mailing_substats { - width: 80%; - margin: 0 auto; - justify-content: space-between !important; - } // For field to occupy full width in small devices. We need '!important' // here because of the 'w-auto' class used in the view. .o_form_editable div[name="mailing_filter_id"] { diff --git a/addons/mass_mailing/tests/test_mailing_ab_testing.py b/addons/mass_mailing/tests/test_mailing_ab_testing.py index 5d3880c9a13..da89ee73e47 100644 --- a/addons/mass_mailing/tests/test_mailing_ab_testing.py +++ b/addons/mass_mailing/tests/test_mailing_ab_testing.py @@ -103,11 +103,35 @@ class TestMailingABTesting(MassMailCommon): }) ab_mailing.invalidate_recordset() - # Check if the campaign is correclty created and the values set on the mailing are still the same + # Check if the campaign is correctly created and the values set on the mailing are still the same self.assertTrue(ab_mailing.campaign_id, "A campaign id is present for the A/B test mailing") self.assertEqual(ab_mailing.ab_testing_winner_selection, 'manual', "The selection winner has been propagated correctly") self.assertEqual(ab_mailing.ab_testing_schedule_datetime, schedule_datetime, "The schedule date has been propagated correctly") + # Check that while enabling the A/B testing, if campaign is already set, new one should not be created + created_mailing_campaign = ab_mailing.campaign_id + ab_mailing.ab_testing_enabled = False + ab_mailing.ab_testing_enabled = True + self.assertEqual(ab_mailing.campaign_id, created_mailing_campaign, "No new campaign should have been created") + + # Check that while enabling the A/B testing, if user manually selects a campaign, it should be saved + # rather than being replaced with the automatically created one + ab_mailing.write({'ab_testing_enabled': False, 'campaign_id': False}) + ab_mailing.write({'ab_testing_enabled': True, 'campaign_id': created_mailing_campaign}) + self.assertEqual(ab_mailing.campaign_id, created_mailing_campaign, "No new campaign should have been created") + + ab_mailing_2 = self.env['mailing.mailing'].create({ + 'subject': 'A/B Testing V2', + 'contact_list_ids': self.mailing_list.ids, + }) + ab_mailing_2.invalidate_recordset() + + ab_mailing_2.ab_testing_enabled = True + # Check if the campaign is correctly created with default values + self.assertTrue(ab_mailing.campaign_id, "A campaign id is present for the A/B test mailing") + self.assertTrue(ab_mailing.ab_testing_winner_selection, "The selection winner has been set to default value") + self.assertTrue(ab_mailing.ab_testing_schedule_datetime, "The schedule date has been set to default value") + @mute_logger('odoo.addons.mail.models.mail_mail') @users('user_marketing') def test_mailing_ab_testing_manual_flow(self): diff --git a/addons/mass_mailing/views/utm_campaign_views.xml b/addons/mass_mailing/views/utm_campaign_views.xml index 48afe6c1b12..8e4281cdeae 100644 --- a/addons/mass_mailing/views/utm_campaign_views.xml +++ b/addons/mass_mailing/views/utm_campaign_views.xml @@ -9,7 +9,7 @@ - + - - - - - - - + + + + + + + + + + + + @@ -24,19 +25,30 @@ attrs="{'invisible': ['|', ('mailing_sms_count', '=', 0), ('is_mailing_campaign_activated', '=', False)]}" groups="mass_mailing.group_mass_mailing_user"> - + - - - - - + + + + + + + + + + +