Add trend spark lines to marketing automation scenario and activity

This commit is contained in:
Cédric Krier
2023-11-07 00:21:00 +01:00
parent a543d94a28
commit b919e5c828
6 changed files with 102 additions and 4 deletions
+1
View File
@@ -1,3 +1,4 @@
* Add trend spark lines
* Add reporting on scenario and activity per period
* Display block rate instead of absolute value
* Display email rates instead of absolute value
@@ -13,6 +13,8 @@ from functools import partial
from urllib.parse import (
parse_qsl, quote, urlencode, urljoin, urlsplit, urlunsplit)
from dateutil.relativedelta import relativedelta
try:
import html2text
except ImportError:
@@ -23,6 +25,11 @@ from genshi.template import MarkupTemplate, TextTemplate
from sql import Literal
from sql.aggregate import Count
try:
import pygal
except ImportError:
pygal = None
from trytond.config import config
from trytond.i18n import gettext
from trytond.model import (
@@ -32,7 +39,7 @@ from trytond.pool import Pool
from trytond.pyson import Eval, If, PYSONDecoder, TimeDelta
from trytond.report import Report
from trytond.sendmail import SMTPDataManager, sendmail_transactional
from trytond.tools import grouped_slice, reduce_ids
from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
from trytond.tools.email_ import convert_ascii_email, set_from_header
from trytond.transaction import Transaction
from trytond.url import http_host
@@ -59,7 +66,56 @@ def _formataddr(name, email):
return formataddr((name, convert_ascii_email(email)))
class Scenario(Workflow, ModelSQL, ModelView):
def trend_mixin(model_name, field_name):
class TrendMixin:
__slots__ = ()
def get_trend(self, name):
name = name[:-len('_trend')]
if pygal:
chart = pygal.Line()
chart.add('', [
getattr(ts, name, 0) or 0
for ts in self.trends])
return chart.render_sparktext()
@property
def trends(self):
pool = Pool()
Model = pool.get(model_name)
Date = pool.get('ir.date')
delta = self._trend_period_delta()
date = Date.today()
date -= 10 * delta
records = Model.search([
('date', '>=', date),
(field_name, '=', self.id),
],
order=[('date', 'ASC')])
for record, next_record in pairwise_longest(records):
yield record
if delta and next_record:
date = record.date + delta
while date < next_record.date:
yield None
date += delta
@classmethod
def _trend_period_delta(cls):
context = Transaction().context
return {
'year': relativedelta(years=1),
'month': relativedelta(months=1),
'day': relativedelta(days=1),
}.get(context.get('period', 'month'))
return TrendMixin
class Scenario(
trend_mixin('marketing.automation.reporting.scenario', 'scenario'),
Workflow, ModelSQL, ModelView):
"Marketing Scenario"
__name__ = 'marketing.automation.scenario'
@@ -77,6 +133,9 @@ class Scenario(Workflow, ModelSQL, ModelView):
block_rate = fields.Function(
fields.Float("Block Rate"),
'get_rate')
block_rate_trend = fields.Function(
fields.Char("Block Rate Trend"),
'get_trend')
unsubscribable = fields.Boolean(
"Unsubscribable",
help="If checked parties are also unsubscribed from the scenario.")
@@ -273,7 +332,9 @@ class Scenario(Workflow, ModelSQL, ModelView):
RecordActivity.save(record_activities)
class Activity(ModelSQL, ModelView):
class Activity(
trend_mixin('marketing.automation.reporting.activity', 'activity'),
ModelSQL, ModelView):
"Marketing Activity"
__name__ = 'marketing.automation.activity'
@@ -380,6 +441,13 @@ class Activity(ModelSQL, ModelView):
'invisible': Eval('action') != 'send_email',
}),
'get_rate')
email_open_rate_trend = fields.Function(
fields.Char(
"E-mail Open Rate Trend",
states={
'invisible': Eval('action') != 'send_email',
}),
'get_trend')
email_click_rate = fields.Function(
fields.Float(
"E-mail Click Rate",
@@ -387,6 +455,13 @@ class Activity(ModelSQL, ModelView):
'invisible': Eval('action') != 'send_email',
}),
'get_rate')
email_click_rate_trend = fields.Function(
fields.Char(
"E-mail Click Rate Trend",
states={
'invisible': Eval('action') != 'send_email',
}),
'get_trend')
email_click_through_rate = fields.Function(
fields.Float(
"E-mail Click-Through Rate",
@@ -394,6 +469,13 @@ class Activity(ModelSQL, ModelView):
'invisible': Eval('action') != 'send_email',
}),
'get_rate')
email_click_through_rate_trend = fields.Function(
fields.Char(
"E-mail Click-Through Rate Trend",
states={
'invisible': Eval('action') != 'send_email',
}),
'get_trend')
@classmethod
def __setup__(cls):
+4 -1
View File
@@ -49,7 +49,9 @@ requires.append(get_require_version('trytond'))
tests_require = [
get_require_version('proteus'),
get_require_version('trytond_sale')]
get_require_version('trytond_sale'),
'pygal',
]
setup(name=name,
version=version,
@@ -123,6 +125,7 @@ setup(name=name,
python_requires='>=3.8',
install_requires=requires,
extras_require={
'sparklines': ['pygal'],
'test': tests_require,
},
zip_safe=False,
@@ -115,6 +115,8 @@ Trigger scenario::
0
>>> scenario.block_rate
0.0
>>> bool(scenario.block_rate_trend)
True
>>> reporting, = ReportingScenario.find([])
>>> reporting.record_count
@@ -201,10 +203,16 @@ Trigger open email and reminder after delay::
0
>>> root_activity.email_open_rate
1.0
>>> bool(root_activity.email_open_rate_trend)
True
>>> root_activity.email_click_rate
0.0
>>> bool(root_activity.email_click_rate_trend)
True
>>> root_activity.email_click_through_rate
0.0
>>> bool(root_activity.email_click_through_rate_trend)
True
>>> reporting, = ReportingActivity.find([
... ('activity', '=', root_activity.id),
@@ -9,10 +9,13 @@ this repository contains the full copyright notices and license terms. -->
<field name="email_open_rate" factor="100">
<suffix string="%" name="email_open_rate"/>
</field>
<field name="email_open_rate_trend" expand="1"/>
<field name="email_click_rate" factor="100">
<suffix string="%" name="email_click_rate"/>
</field>
<field name="email_open_rate_trend" expand="1"/>
<field name="email_click_through_rate" factor="100">
<suffix string="%" name="email_click_through_rate"/>
</field>
<field name="email_click_through_rate_trend" expand="1"/>
</tree>
@@ -8,5 +8,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="block_rate" factor="100">
<suffix string="%" name="block_rate"/>
</field>
<field name="block_rate_trend" expand="1"/>
<field name="state"/>
</tree>