Issue
- Open any opportunity
- Go to "Extra Information" and click on "Campaign" field
- try to create new campaign
Traceback is raised
Cause
"self.ids" is empty and the "tuple(self.ids)" on the SQL query return "()"
Solution
Initialize campaign field with default values
opw-2376082
closes odoo/odoo#61476
X-original-commit: 5797be02e32e68e0a188bfdc8b85068fb8fa5435
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Signed-off-by: Achraf <abz-odoo@users.noreply.github.com>
99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models
|
|
|
|
|
|
class UtmCampaign(models.Model):
|
|
_inherit = 'utm.campaign'
|
|
|
|
mailing_mail_ids = fields.One2many(
|
|
'mailing.mailing', 'campaign_id',
|
|
domain=[('mailing_type', '=', 'mail')],
|
|
string='Mass Mailings')
|
|
mailing_mail_count = fields.Integer('Number of Mass Mailing', compute="_compute_mailing_mail_count")
|
|
# stat fields
|
|
received_ratio = fields.Integer(compute="_compute_statistics", string='Received Ratio')
|
|
opened_ratio = fields.Integer(compute="_compute_statistics", string='Opened Ratio')
|
|
replied_ratio = fields.Integer(compute="_compute_statistics", string='Replied Ratio')
|
|
bounced_ratio = fields.Integer(compute="_compute_statistics", string='Bounced Ratio')
|
|
|
|
@api.depends('mailing_mail_ids')
|
|
def _compute_mailing_mail_count(self):
|
|
if self.ids:
|
|
mailing_data = self.env['mailing.mailing'].read_group(
|
|
[('campaign_id', 'in', self.ids)],
|
|
['campaign_id'],
|
|
['campaign_id']
|
|
)
|
|
mapped_data = {m['campaign_id'][0]: m['campaign_id_count'] for m in mailing_data}
|
|
else:
|
|
mapped_data = dict()
|
|
for campaign in self:
|
|
campaign.mailing_mail_count = mapped_data.get(campaign.id, 0)
|
|
|
|
def _compute_statistics(self):
|
|
""" Compute statistics of the mass mailing campaign """
|
|
default_vals = {
|
|
'received_ratio': 0,
|
|
'opened_ratio': 0,
|
|
'replied_ratio': 0,
|
|
'bounced_ratio': 0
|
|
}
|
|
if not self.ids:
|
|
self.update(default_vals)
|
|
return
|
|
self.env.cr.execute("""
|
|
SELECT
|
|
c.id as campaign_id,
|
|
COUNT(s.id) AS expected,
|
|
COUNT(CASE WHEN s.sent is not null THEN 1 ELSE null END) AS sent,
|
|
COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null AND s.ignored is not null THEN 1 ELSE null END) AS ignored,
|
|
COUNT(CASE WHEN s.id is not null AND s.bounced is null THEN 1 ELSE null END) AS delivered,
|
|
COUNT(CASE WHEN s.opened is not null THEN 1 ELSE null END) AS opened,
|
|
COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied,
|
|
COUNT(CASE WHEN s.bounced is not null THEN 1 ELSE null END) AS bounced
|
|
FROM
|
|
mailing_trace s
|
|
RIGHT JOIN
|
|
utm_campaign c
|
|
ON (c.id = s.campaign_id)
|
|
WHERE
|
|
c.id IN %s
|
|
GROUP BY
|
|
c.id
|
|
""", (tuple(self.ids), ))
|
|
|
|
all_stats = self.env.cr.dictfetchall()
|
|
stats_per_campaign = {
|
|
stats['campaign_id']: stats
|
|
for stats in all_stats
|
|
}
|
|
|
|
for campaign in self:
|
|
stats = stats_per_campaign.get(campaign.id)
|
|
if not stats:
|
|
vals = default_vals
|
|
else:
|
|
total = (stats['expected'] - stats['ignored']) or 1
|
|
delivered = stats['sent'] - stats['bounced']
|
|
vals = {
|
|
'received_ratio': 100.0 * delivered / total,
|
|
'opened_ratio': 100.0 * stats['opened'] / total,
|
|
'replied_ratio': 100.0 * stats['replied'] / total,
|
|
'bounced_ratio': 100.0 * stats['bounced'] / total
|
|
}
|
|
|
|
campaign.update(vals)
|
|
|
|
def _get_mailing_recipients(self, model=None):
|
|
"""Return the recipients of a mailing campaign. This is based on the statistics
|
|
build for each mailing. """
|
|
res = dict.fromkeys(self.ids, {})
|
|
for campaign in self:
|
|
domain = [('campaign_id', '=', campaign.id)]
|
|
if model:
|
|
domain += [('model', '=', model)]
|
|
res[campaign.id] = set(self.env['mailing.trace'].search(domain).mapped('res_id'))
|
|
return res
|