Initial commit: Mail packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:51 +02:00
commit 4e53507711
1948 changed files with 751201 additions and 0 deletions

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mailing_trace_report

View file

@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, tools
class MailingTraceReport(models.Model):
_name = 'mailing.trace.report'
_auto = False
_description = 'Mass Mailing Statistics'
# mailing
name = fields.Char(string='Mass Mail', readonly=True)
mailing_type = fields.Selection([('mail', 'Mail')], string='Type', default='mail', required=True)
campaign = fields.Char(string='Mailing Campaign', readonly=True)
scheduled_date = fields.Datetime(string='Scheduled Date', readonly=True)
state = fields.Selection(
[('draft', 'Draft'), ('test', 'Tested'), ('done', 'Sent')],
string='Status', readonly=True)
email_from = fields.Char('From', readonly=True)
# traces
scheduled = fields.Integer(readonly=True)
sent = fields.Integer(readonly=True)
delivered = fields.Integer(readonly=True)
error = fields.Integer(readonly=True)
opened = fields.Integer(readonly=True)
replied = fields.Integer(readonly=True)
bounced = fields.Integer(readonly=True)
canceled = fields.Integer(readonly=True)
clicked = fields.Integer(readonly=True)
def init(self):
"""Mass Mail Statistical Report: based on mailing.trace that models the various
statistics collected for each mailing, and mailing.mailing model that models the
various mailing performed. """
tools.drop_view_if_exists(self.env.cr, 'mailing_trace_report')
self.env.cr.execute(self._report_get_request())
def _report_get_request(self):
sql_select = 'SELECT %s' % ', '.join(self._report_get_request_select_items())
sql_from = 'FROM %s' % ' '.join(self._report_get_request_from_items())
sql_where_items = self._report_get_request_where_items()
if sql_where_items and len(sql_where_items) == 1:
sql_where = 'WHERE %s' % sql_where_items[0]
elif sql_where_items:
sql_where = 'WHERE %s' % ' AND '.join(sql_where_items)
else:
sql_where = ''
sql_group_by = 'GROUP BY %s' % ', '.join(self._report_get_request_group_by_items())
return f"CREATE OR REPLACE VIEW mailing_trace_report AS ({sql_select} {sql_from} {sql_where} {sql_group_by} )"
def _report_get_request_select_items(self):
return [
'min(trace.id) as id',
'utm_source.name as name',
'mailing.mailing_type',
'utm_campaign.name as campaign',
'trace.create_date as scheduled_date',
'mailing.state',
'mailing.email_from',
"COUNT(trace.id) as scheduled",
'COUNT(trace.sent_datetime) as sent',
"(COUNT(trace.id) - COUNT(trace.trace_status) FILTER (WHERE trace.trace_status IN ('error', 'bounce', 'cancel'))) as delivered",
"COUNT(trace.trace_status) FILTER (WHERE trace.trace_status = 'error') as error",
"COUNT(trace.trace_status) FILTER (WHERE trace.trace_status = 'bounce') as bounced",
"COUNT(trace.trace_status) FILTER (WHERE trace.trace_status = 'cancel') as canceled",
"COUNT(trace.trace_status) FILTER (WHERE trace.trace_status = 'open') as opened",
"COUNT(trace.trace_status) FILTER (WHERE trace.trace_status = 'reply') as replied",
"COUNT(trace.links_click_datetime) as clicked",
]
def _report_get_request_from_items(self):
return [
'mailing_trace as trace',
'LEFT JOIN mailing_mailing as mailing ON (trace.mass_mailing_id=mailing.id)',
'LEFT JOIN utm_campaign as utm_campaign ON (mailing.campaign_id = utm_campaign.id)',
'LEFT JOIN utm_source as utm_source ON (mailing.source_id = utm_source.id)'
]
def _report_get_request_where_items(self):
return []
def _report_get_request_group_by_items(self):
return [
'trace.create_date',
'utm_source.name',
'utm_campaign.name',
'mailing.mailing_type',
'mailing.state',
'mailing.email_from'
]

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mailing_trace_report_view_tree" model="ir.ui.view">
<field name="name">mailing.trace.report.view.tree</field>
<field name="model">mailing.trace.report</field>
<field name="arch" type="xml">
<tree string="Mass Mailing Statistics" sample="1">
<field name="name"/>
<field name="campaign" groups="mass_mailing.group_mass_mailing_campaign"/>
<field name="mailing_type" invisible="1"/>
<field name="scheduled_date" string="Scheduled On"/>
<field name="state"/>
<field name="scheduled"/>
<field name="sent"/>
<field name="delivered"/>
<field name="opened"/>
<field name="replied"/>
<field name="clicked"/>
<field name="canceled" optional="hide"/>
<field name="error" optional="hide"/>
<field name="bounced" optional="hide"/>
</tree>
</field>
</record>
<record id="mailing_trace_report_view_pivot" model="ir.ui.view">
<field name="name">mailing.trace.report.view.pivot</field>
<field name="model">mailing.trace.report</field>
<field name="arch" type="xml">
<pivot string="Mass Mailing Statistics" disable_linking="1" sample="1">
<field name="name" type="row"/>
<field name="sent" type="measure"/>
<field name="scheduled" type="measure"/>
<field name="delivered" type="measure"/>
<field name="opened" type="measure"/>
<field name="replied" type="measure"/>
<field name="clicked" type="measure"/>
<field name="canceled"/>
<field name="error"/>
<field name="bounced"/>
</pivot>
</field>
</record>
<record id="mailing_trace_report_view_graph" model="ir.ui.view">
<field name="name">mailing.trace.report.view.graph</field>
<field name="model">mailing.trace.report</field>
<field name="arch" type="xml">
<graph string="Mass Mailing Statistics" disable_linking="1" sample="1">
<field name="name"/>
<field name="sent" type="measure"/>
<field name="replied"/>
<field name="clicked"/>
</graph>
</field>
</record>
<record id="mailing_trace_report_view_search" model="ir.ui.view">
<field name="name">mailing.trace.report.view.search</field>
<field name="model">mailing.trace.report</field>
<field name="arch" type="xml">
<search string="Mass Mailing Statistics">
<field name="name" string="Mailing"/>
<field name="campaign" string="Campaign" groups="mass_mailing.group_mass_mailing_campaign"/>
<filter name="filter_scheduled_date" date="scheduled_date"/>
<group expand="0" string="Extended Filters...">
<field name="scheduled_date"/>
</group>
<group expand="1" string="Group By...">
<filter string="Mass Mailing Campaign" domain="[]" name="mass_mailing_campaign"
context="{'group_by':'campaign'}" groups="mass_mailing.group_mass_mailing_campaign"/>
<filter string="State" domain="[]" name="state"
context="{'group_by':'state'}"/>
<filter string="Sent By" domain="[]" name="sent_by"
context="{'group_by':'email_from'}"/>
<separator/>
<filter string="Scheduled Period" name="scheduled_date"
domain="[]" context="{'group_by':'scheduled_date'}"/>
</group>
</search>
</field>
</record>
<!-- Actions and Menuitems -->
<record id="mailing_trace_report_action_mail" model="ir.actions.act_window">
<field name="name">Mass Mailing Analysis</field>
<field name="res_model">mailing.trace.report</field>
<field name="domain">[('mailing_type', '=', 'mail')]</field>
<field name="view_mode">graph,pivot,tree</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Mass Mailing Statistics allows you to check different mailing related information
like number of bounced mails, opened mails, replied mails. You can sort out
your analysis by different groups to get accurate grained analysis.
</p>
</field>
</record>
</odoo>