317 lines
15 KiB
Python
317 lines
15 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import datetime
|
|
|
|
from odoo import fields
|
|
from odoo.tests import common
|
|
|
|
TYPE_SIZE = 8
|
|
TYPE = ['Type %s' % i for i in range(1,TYPE_SIZE + 1)]
|
|
|
|
NB_START_DAY = 15
|
|
NB_END_DAY = 30
|
|
START_DATE = datetime.datetime(2018,12,1,0,0,0)
|
|
|
|
class TestCohortCommon(common.TransactionCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.CohortType = cls.env['web.cohort.type']
|
|
cls.WebCohortSimpleModel = cls.env['web.cohort.simple.model']
|
|
cls.type_ids = []
|
|
for t in TYPE:
|
|
cls.type_ids.append(cls.CohortType.create({'name': t}).id)
|
|
|
|
class TestCohortForward(TestCohortCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
start_date = START_DATE
|
|
end_date = start_date
|
|
data_list = []
|
|
for i in range(0,NB_START_DAY): #Start date on 20 days
|
|
for j in range(0,NB_END_DAY):
|
|
data = {
|
|
'name': "[%s:%s]" % (i, j),
|
|
'type_id': cls.type_ids[int(TYPE_SIZE * j / NB_END_DAY)],
|
|
'datetime_start': start_date,
|
|
'datetime_stop': end_date,
|
|
'date_start': fields.Date.to_date(start_date),
|
|
'date_stop': fields.Date.to_date(end_date),
|
|
'revenue': j * 10,
|
|
}
|
|
data_list.append(data)
|
|
end_date = end_date + datetime.timedelta(days=3)
|
|
|
|
start_date = start_date + datetime.timedelta(days=5)
|
|
end_date = start_date
|
|
cls.WebCohortSimpleModel.create(data_list)
|
|
|
|
def test_forward_datetime(self):
|
|
#Test interval
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'year', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 2)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 81)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 0)
|
|
#Test when start date of column is > Today
|
|
self.assertEqual(result[0]['columns'][14]['percentage'], '')
|
|
#Since percentage is 0 at second year, churn value should be equal to total value
|
|
self.assertEqual(result[0]['columns'][1]['churn_value'], result[0]['value'])
|
|
#Total of value of each row should be equal to the number of data generated
|
|
self.assertEqual(result[0]['value'] + result[1]['value'], NB_START_DAY * NB_END_DAY)
|
|
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'month', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 3)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 81)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 46.7)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'week', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 11)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 96.7)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 90.0)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'day', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), NB_START_DAY)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 96.7)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 96.7)
|
|
|
|
#Test measure
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'revenue', 'week', [], 'retention', 'forward')['rows']
|
|
#Sum of value should be 0 + 10 + 20 + ... + 390 * 20, (gaussian sum 0 to 39) * 10 * 20
|
|
self.assertEqual(sum(v['value'] for v in result), (29 * 30 / 2) * 10 * NB_START_DAY)
|
|
#Percentage should be different from count measure and value as well
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100.0)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 99.3)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'type_id', 'week', [], 'retention', 'forward')['rows']
|
|
#There is 8 type so value should be 8
|
|
self.assertEqual(result[0]['value'], TYPE_SIZE)
|
|
#Test Churn mode
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'year', [], 'churn', 'forward')['rows']
|
|
#Percentage is 100 - rentention %
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], round(100 - 81, 2))
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 100 - 0)
|
|
|
|
def test_forward_date(self):
|
|
#Test interval
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'__count', 'year', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 2)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 81)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 0)
|
|
#Test when start date of column is > Today
|
|
self.assertEqual(result[0]['columns'][14]['percentage'], '')
|
|
#Since percentage is 0 at second year, churn value should be equal to total value
|
|
self.assertEqual(result[0]['columns'][1]['churn_value'], result[0]['value'])
|
|
#Total of value of each row should be equal to the number of data generated
|
|
self.assertEqual(result[0]['value'] + result[1]['value'], NB_START_DAY * NB_END_DAY)
|
|
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'__count', 'month', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 3)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 81)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 46.7)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'__count', 'week', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), 11)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 96.7)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 90.0)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'__count', 'day', [], 'retention', 'forward')['rows']
|
|
self.assertEqual(len(result), NB_START_DAY)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 96.7)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 96.7)
|
|
|
|
#Test measure
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'revenue', 'week', [], 'retention', 'forward')['rows']
|
|
#Sum of value should be 0 + 10 + 20 + ... + 390 * 20, (gaussian sum 0 to 39) * 10 * 20
|
|
self.assertEqual(sum(v['value'] for v in result), (29 * 30 / 2) * 10 * NB_START_DAY)
|
|
#Percentage should be different from count measure and value as well
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100.0)
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 99.3)
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'type_id', 'week', [], 'retention', 'forward')['rows']
|
|
#There is 8 type so value should be 8
|
|
self.assertEqual(result[0]['value'], TYPE_SIZE)
|
|
#Test Churn mode
|
|
result = self.WebCohortSimpleModel.get_cohort_data("date_start", "date_stop",
|
|
'__count', 'year', [], 'churn', 'forward')['rows']
|
|
#Percentage is 100 - rentention %
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], round(100 - 81, 2))
|
|
self.assertEqual(result[0]['columns'][1]['percentage'], 100 - 0)
|
|
|
|
def test_empty_data(self):
|
|
""" In some reports, some columns can be empty.
|
|
Say a model "event", with a field "rating_ids" (relation) and a field "avg_rating" (float related).
|
|
If an event has no rating, it would make sense that its "avg_rating" is False rather than 0.
|
|
In this case, the event shouldn't be displayed in the cohort.
|
|
"""
|
|
start_date = START_DATE - datetime.timedelta(weeks=1)
|
|
self.WebCohortSimpleModel.create([{
|
|
'name': "no revenue",
|
|
'date_start': start_date,
|
|
'date_stop': start_date + datetime.timedelta(days=i),
|
|
} for i in range(7)])
|
|
|
|
result = self.WebCohortSimpleModel.with_context(test_empty_data=True).get_cohort_data(
|
|
'date_start', 'date_stop', 'revenue', 'week', [], 'retention', 'forward'
|
|
)
|
|
self.assertNotIn(
|
|
'W47 2018', (row['date'] for row in result['rows']),
|
|
'Empty data should not be displayed',
|
|
)
|
|
|
|
def test_aggregator_avg(self):
|
|
""" In some reports, some columns can be empty.
|
|
Say a model "event", with a field "rating_ids" (relation) and a field "avg_rating" (float related).
|
|
If an event has no rating, it would make sense that its "avg_rating" is False rather than 0.
|
|
In this case, the event shouldn't be taken into account in the cohort average.
|
|
"""
|
|
self.patch(self.WebCohortSimpleModel._fields['revenue'], 'aggregator', 'avg')
|
|
result = self.WebCohortSimpleModel.get_cohort_data(
|
|
'date_start', 'date_stop', 'revenue', 'week', [], 'retention', 'forward'
|
|
)
|
|
self.assertFalse(
|
|
any(
|
|
column['percentage'] < 0
|
|
for row in result['rows']
|
|
for column in row['columns']
|
|
),
|
|
'All percentages should be positive',
|
|
)
|
|
|
|
|
|
class TestCohortBackward(TestCohortCommon):
|
|
def setUp(self):
|
|
super().setUp()
|
|
# activate an extra lang that uses ISO weeks
|
|
self.env['res.lang']._activate_lang('en_GB')
|
|
start_date = START_DATE
|
|
end_date = start_date + datetime.timedelta(days=7) #Start in the future
|
|
data_list = []
|
|
for i in range(0,NB_START_DAY): #Start date on 20 days
|
|
for j in range(0,NB_END_DAY):
|
|
data = {
|
|
'name': "[%s:%s]" % (i, j),
|
|
'type_id': self.type_ids[int(TYPE_SIZE * j / NB_END_DAY)],
|
|
'datetime_start': start_date,
|
|
'datetime_stop': end_date,
|
|
'revenue': j * 10,
|
|
}
|
|
data_list.append(data)
|
|
|
|
#Create record with datetime_stop empty
|
|
data = {
|
|
'name': "[%s:%s] No Stop" % (i, j),
|
|
'type_id': self.type_ids[int(TYPE_SIZE * j / NB_END_DAY)],
|
|
'datetime_start': start_date,
|
|
'datetime_stop': False,
|
|
'revenue': j * 10,
|
|
}
|
|
data_list.append(data)
|
|
end_date = end_date - datetime.timedelta(days=3)
|
|
|
|
start_date = start_date + datetime.timedelta(days=5)
|
|
end_date = start_date + datetime.timedelta(days=7)
|
|
self.WebCohortSimpleModel.create(data_list)
|
|
|
|
def test_backward(self):
|
|
#Test interval
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'year', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(len(result), 2)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100.0)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 51)
|
|
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'month', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(len(result), 3)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100)
|
|
self.assertEqual(result[0]['columns'][-2]['percentage'], 63.3)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 51)
|
|
|
|
# with ISO week
|
|
result = self.WebCohortSimpleModel.with_context(lang='en_GB').get_cohort_data(
|
|
"datetime_start", "datetime_stop", '__count', 'week', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(len(result), 11)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100)
|
|
self.assertEqual(result[0]['columns'][5]['percentage'], 93.3)
|
|
self.assertEqual(result[0]['columns'][-2]['percentage'], 58.3)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 53.3)
|
|
|
|
# with en_US week
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'week', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(len(result), 11)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100)
|
|
self.assertEqual(result[0]['columns'][5]['percentage'], 93.3)
|
|
self.assertEqual(result[0]['columns'][-2]['percentage'], 58.3)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 55)
|
|
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'day', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(len(result), NB_START_DAY)
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 63.3)
|
|
self.assertEqual(result[0]['columns'][-2]['percentage'], 55)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 55)
|
|
|
|
#Test measure
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'revenue', 'week', [], 'retention', 'backward')['rows']
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'type_id', 'week', [], 'retention', 'backward')['rows']
|
|
#There is 8 type so value should be 8
|
|
self.assertEqual(result[0]['value'], TYPE_SIZE)
|
|
#Test Churn mode
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'__count', 'month', [], 'churn', 'backward')['rows']
|
|
self.assertEqual(result[0]['columns'][0]['percentage'], 100 - 100)
|
|
self.assertEqual(result[0]['columns'][-2]['percentage'], 100 - 63.3)
|
|
self.assertEqual(result[0]['columns'][-1]['percentage'], 100 - 51)
|
|
|
|
|
|
class TestCohortEmptyFuturBackward(TestCohortCommon):
|
|
def setUp(self):
|
|
super().setUp()
|
|
start_date = START_DATE
|
|
end_date = start_date - datetime.timedelta(days=10)
|
|
data_list = []
|
|
for j in range(0, 5):
|
|
data = {
|
|
'name': "[%s] backward" % (j),
|
|
'type_id': self.type_ids[int(TYPE_SIZE * j / NB_END_DAY)],
|
|
'datetime_start': start_date,
|
|
'datetime_stop': end_date,
|
|
'revenue': j * 10,
|
|
}
|
|
data_list.append(data)
|
|
end_date = end_date + datetime.timedelta(days=1)
|
|
|
|
self.WebCohortSimpleModel.create(data_list)
|
|
|
|
def test_empty_backward(self):
|
|
"""
|
|
Test when there is no data in the row 0 and in the future
|
|
"""
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'revenue', 'day', [], 'retention', 'backward')['rows']
|
|
|
|
self.assertEqual(result[0]['columns'][0]['value'], 100)
|
|
self.assertEqual(result[0]['columns'][-1]['value'], 0)
|
|
|
|
class TestCohortEmpty(TestCohortCommon):
|
|
def test_empty_backward(self):
|
|
"""
|
|
Test that view doesn't crash when there is no data
|
|
"""
|
|
result = self.WebCohortSimpleModel.get_cohort_data("datetime_start", "datetime_stop",
|
|
'revenue', 'day', [], 'retention', 'backward')['rows']
|
|
self.assertEqual(result, [])
|