[FIX] {test_}mail: fix invalid kanban status when using activity done

How to reproduce:
- Install CRM with demo data
- Configure one activity type to keep done activities
- Go to CRM and chose a kanban column with a green status (only planned
activities for that state)
- On a lead of that column, add an activity of the type chosen above with a
deadline in the past
- When going back to the kanban view, that column has the overdue status (red)
- Mark that activity as done
- Reload the kanban view

The kanban column has still the status overdue (red) while there are no more
overdue activity in that state.

With this fix, after reloading the kanban view, the header displays the correct
status summary. In the example above, the kanban column header is green.

While adding test, we have noticed that the 2 methods _read_group_groupby and
_search_activity_state were computing the activity state differently leading to
inconsistency. Actually, the newly added test was failing because the
read_group was returning 2 overdue records while only one was. We correct this
here as well by using the same computation in the 2 methods.

Technical note: archived activities were returned when grouping by
activity_state because that part was done in SQL and not taking into account
the recently added active field. While adding it in the "_read_group_groupby"
method, we also add it in "_search_activity_state" to avoid the same problem
when searching on activity_state.

Task-3732333

closes odoo/odoo#153274

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Pierre-Yves Dufays
2024-02-29 16:00:28 +00:00
parent 0dfee1606b
commit b09ccfc2d7
2 changed files with 27 additions and 7 deletions
+7 -5
View File
@@ -163,6 +163,7 @@ class MailActivityMixin(models.AbstractModel):
search_states_int = {integer_state_value.get(s or False) for s in search_states}
self.env['mail.activity'].flush_model(['active', 'date_deadline', 'res_model', 'user_id'])
query = """
SELECT res_id
FROM (
@@ -182,7 +183,7 @@ class MailActivityMixin(models.AbstractModel):
ON res_users.id = mail_activity.user_id
LEFT JOIN res_partner
ON res_partner.id = res_users.partner_id
WHERE mail_activity.res_model = %(res_model_table)s
WHERE mail_activity.res_model = %(res_model_table)s AND mail_activity.active = true
GROUP BY res_id
) AS res_record
WHERE %(search_states_int)s @> ARRAY[activity_state]
@@ -271,18 +272,19 @@ class MailActivityMixin(models.AbstractModel):
"""
(SELECT res_id,
CASE
WHEN min(date_deadline - (now() AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))::date) > 0 THEN 'planned'
WHEN min(date_deadline - (now() AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))::date) < 0 THEN 'overdue'
WHEN min(date_deadline - (now() AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))::date) = 0 THEN 'today'
WHEN min(EXTRACT(day from (mail_activity.date_deadline - DATE_TRUNC('day', %(today_utc)s AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))))) > 0 THEN 'planned'
WHEN min(EXTRACT(day from (mail_activity.date_deadline - DATE_TRUNC('day', %(today_utc)s AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))))) < 0 THEN 'overdue'
WHEN min(EXTRACT(day from (mail_activity.date_deadline - DATE_TRUNC('day', %(today_utc)s AT TIME ZONE COALESCE(res_partner.tz, %(tz)s))))) = 0 THEN 'today'
ELSE null
END AS activity_state
FROM mail_activity
JOIN res_users ON (res_users.id = mail_activity.user_id)
JOIN res_partner ON (res_partner.id = res_users.partner_id)
WHERE res_model = %(res_model)s
WHERE res_model = %(res_model)s AND mail_activity.active = true
GROUP BY res_id)
""",
res_model=self._name,
today_utc=pytz.utc.localize(datetime.utcnow()),
tz=tz,
)
alias = query.join(self._table, "id", sql_join, "res_id", "last_activity_state")
+20 -2
View File
@@ -600,12 +600,14 @@ class TestActivityMixin(TestActivityCommon):
])
origin_1, origin_2 = self.env['mail.test.activity'].search([], limit=2)
activity_type = self.env.ref('test_mail.mail_act_test_todo')
activity_type.sudo().keep_done = True
with patch('odoo.addons.mail.models.mail_activity.datetime', MockedDatetime), \
patch('odoo.addons.mail.models.mail_activity_mixin.datetime', MockedDatetime):
origin_1_activity_1 = self.env['mail.activity'].create({
'summary': 'Test',
'activity_type_id': 1,
'activity_type_id': activity_type.id,
'res_model_id': self.env.ref('test_mail.model_mail_test_activity').id,
'res_id': origin_1.id,
'date_deadline': today_utc,
@@ -623,7 +625,7 @@ class TestActivityMixin(TestActivityCommon):
origin_2_activity_1 = self.env['mail.activity'].create({
'summary': 'Test',
'activity_type_id': 1,
'activity_type_id': activity_type.id,
'res_model_id': self.env.ref('test_mail.model_mail_test_activity').id,
'res_id': origin_2.id,
'date_deadline': today_utc + relativedelta(hours=8),
@@ -674,6 +676,22 @@ class TestActivityMixin(TestActivityCommon):
self.assertTrue(len(result) > 0)
self.assertEqual(result, all_activity_mixin_record.filtered(lambda p: p.activity_state in ('today', False)))
# Check that activity done are not taken into account by group and search by activity_state.
Model = self.env['mail.test.activity']
search_params = {
'domain': [('id', 'in', (origin_1 | origin_2).ids), ('activity_state', '=', 'overdue')]}
read_group_params = {'domain': [('id', 'in', (origin_1 | origin_2).ids)], 'fields': ['id:array_agg'],
'groupby': ['activity_state']}
self.assertEqual(Model.search(**search_params), origin_1)
self.assertEqual(
{(e['activity_state'], e['activity_state_count']) for e in Model.read_group(**read_group_params)},
{('today', 1), ('overdue', 1)})
origin_1_activity_2.action_feedback(feedback='Done')
self.assertFalse(Model.search(**search_params))
self.assertEqual(
{(e['activity_state'], e['activity_state_count']) for e in Model.read_group(**read_group_params)},
{('today', 2)})
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.tests')
def test_mail_activity_mixin_search_state_different_day_but_close_time(self):
"""Test the case where there's less than 24 hours between the deadline and now_tz,