Skip to content

Commit

Permalink
TA#63122 [MIG] Module mail_activity_not_deleted (#19)
Browse files Browse the repository at this point in the history
* Port mail_activity_not_deleted to 12.0 (#8)

* Port mail_activity_not_deleted to 12.0

* Fix feedback message on activities (#31)

* TA#34363 port auditlog to v14

Remove super_calendar (will not be supported anymore by Numigi.

* TA#34363 port modules to odoo version 14.0

* Ta#47907 [MIG][14.0] (#107)

* [MIG] base_extended_security: Migration to 14.0

* TA#47907 [MIG][14.0] : auditlog,base_extended_security, test_http_request

* TA#47907 [MIG][14.0] : All modules + 2 others

* TA#47907 [MIG][14.0] : change ir_attachment_name_autocomplete name

* TA#47907 [MIG][14.0] : add ir_attachment_name_autocomplete name in the mainifest

* TA#47907 [MIG][14.0] : fix test setupclass

* TA#47907 [MIG][14.0] : update dockerfile

* TA#47907 [MIG][14.0] : update test setup

* TA#47907 [MIG][14.0] : update test setup

* TA#47907 [MIG][14.0] : update test setup

* TA#48105 [ADD] module auth_oauth_microsoft (#113)

* TA#48502 [IMP] Add pre-commit-config, flake8 and workflow to repo (#132)

* TA#48502 [IMP] Add pre-commit-config, flake8 and workflow to repo

* TA#63122 [FIX] migration mail_activity_not_deleted (#138)

* TA#63122 [MIG] Module mail_activity_not_deleted

---------

Co-authored-by: David Dufresne <27902736+ddufresne@users.noreply.github.com>
Co-authored-by: Abdellatif BENZBIRIA <a.benzbiria@magnetomedia.net>
  • Loading branch information
3 people authored Mar 6, 2024
1 parent 9610a25 commit 92245f9
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 11 deletions.
23 changes: 12 additions & 11 deletions .docker_files/main/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
'name': 'Main Module',
'version': '1.0.0',
'author': 'Numigi',
'maintainer': 'Numigi',
'website': 'https://www.numigi.com',
'license': 'LGPL-3',
'category': 'Other',
'summary': 'Install all addons required for testing.',
'depends': [
'fetchmail_outlook_by_company',
"name": "Main Module",
"version": "1.0.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://www.numigi.com",
"license": "LGPL-3",
"category": "Other",
"summary": "Install all addons required for testing.",
"depends": [
"fetchmail_outlook_by_company",
"mail_activity_not_deleted",
],
'installable': True,
"installable": True,
}
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ RUN mkdir -p "${THIRD_PARTY_ADDONS}" && chown -R odoo "${THIRD_PARTY_ADDONS}"
USER odoo

COPY fetchmail_outlook_by_company /mnt/extra-addons/fetchmail_outlook_by_company
COPY mail_activity_not_deleted /mnt/extra-addons/mail_activity_not_deleted

COPY .docker_files/main /mnt/extra-addons/main
COPY .docker_files/odoo.conf /etc/odoo
18 changes: 18 additions & 0 deletions mail_activity_not_deleted/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Mail Activity Not Deleted
=========================
Since version 11.0, Odoo adds the concept of activities.
One issue with this feature is that when an activity is completed, the activity record is deleted from the database.

This module deactivates terminated activities instead of deleting them from the mail_activity table.

New State
---------
The state Done is added to activities. Any completed activity is automatically set to Done.

New Field
---------
The field Date Done is added to activities. When completing the activity, this field is filled with the current time.

Contributors
------------
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
4 changes: 4 additions & 0 deletions mail_activity_not_deleted/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import models
14 changes: 14 additions & 0 deletions mail_activity_not_deleted/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
'name': 'Mail Activity Not Deleted',
'version': '14.0.1.0.1',
'author': 'Numigi',
'maintainer': 'Numigi',
'license': 'LGPL-3',
'category': 'Other',
'summary': 'Deactivate terminated activities instead of deleting.',
'depends': ['mail'],
'installable': True,
}
33 changes: 33 additions & 0 deletions mail_activity_not_deleted/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mail_activity_not_deleted
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-05-29 15:13-0400\n"
"PO-Revision-Date: 2018-05-29 19:13+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 1.8.7.1\n"

#. module: mail_activity_not_deleted
#: model:ir.model.fields,field_description:mail_activity_not_deleted.field_mail_activity_active
msgid "Active"
msgstr "Actif"

#. module: mail_activity_not_deleted
#: model:ir.model,name:mail_activity_not_deleted.model_mail_activity
msgid "Activity"
msgstr "Activité"

#. module: mail_activity_not_deleted
#: model:ir.model.fields,field_description:mail_activity_not_deleted.field_mail_activity_date_done
msgid "Date Done"
msgstr "Terminé le"
4 changes: 4 additions & 0 deletions mail_activity_not_deleted/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import mail_activity, user, mail_activity_mixin
39 changes: 39 additions & 0 deletions mail_activity_not_deleted/models/mail_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# © 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from datetime import datetime

from odoo import api, fields, models


class MailActivityInactivatedInsteadOfDeleted(models.Model):

_inherit = "mail.activity"

active = fields.Boolean(default=True)
date_done = fields.Datetime()

state = fields.Selection(selection_add=[("done", "Done")])

@api.depends("date_deadline")
def _compute_state(self):
super()._compute_state()

done_activities = self.filtered(lambda a: a.date_done)
for activity in done_activities:
activity.state = "done"

def unlink(self):
self.write(
{"active": False, "date_done": datetime.now()}
)
for activity in self:
activity._update_record_date_deadline()

return True

def _update_record_date_deadline(self):
"""Update the stored fields that depend on activity_ids on the related record."""
record = self.env[self.res_model].browse(self.res_id)
record.modified(["activity_ids"])
record.recompute()
12 changes: 12 additions & 0 deletions mail_activity_not_deleted/models/mail_activity_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# © 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from odoo import fields, models


class MailActivityMixin(models.AbstractModel):

_inherit = 'mail.activity.mixin'

# auto_join prevents the active filter from being automatically applied.
activity_ids = fields.One2many(auto_join=False)
83 changes: 83 additions & 0 deletions mail_activity_not_deleted/models/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from collections import defaultdict

from odoo import api, fields, models, modules


class User(models.Model):

_inherit = 'res.users'

@api.model
def systray_get_activities(self):
"""Prevent inactive activities from appearing in the main Odoo navbar.
This method is a copy from the method defined at:
odoo/addons/mail/models/res_users.py
Only the active filter was added in the sql query.
"""
query = """SELECT array_agg(res_id) as res_ids, m.id, count(*),
CASE
WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today'
WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue'
WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned'
END AS states
FROM mail_activity AS act
JOIN ir_model AS m ON act.res_model_id = m.id
WHERE user_id = %(user_id)s
AND act.active
GROUP BY m.id, states;
"""
self.env.cr.execute(
query,
{
"today": fields.Date.context_today(self),
"user_id": self.env.uid,
},
)
activity_data = self.env.cr.dictfetchall()
records_by_state_by_model = defaultdict(
lambda: {"today": set(), "overdue": set(), "planned": set(), "all": set()}
)
for data in activity_data:
records_by_state_by_model[data["id"]][data["states"]] = set(data["res_ids"])
records_by_state_by_model[data["id"]]["all"] = records_by_state_by_model[
data["id"]
]["all"] | set(data["res_ids"])
user_activities = {}
for model_id in records_by_state_by_model:
model_dic = records_by_state_by_model[model_id]
model = (
self.env["ir.model"]
.browse(model_id)
.with_prefetch(tuple(records_by_state_by_model.keys()))
)
allowed_records = self.env[model.model].search(
[("id", "in", tuple(model_dic["all"]))]
)
if not allowed_records:
continue
module = self.env[model.model]._original_module
icon = module and modules.module.get_module_icon(module)
today = len(model_dic["today"] & set(allowed_records.ids))
overdue = len(model_dic["overdue"] & set(allowed_records.ids))
user_activities[model.model] = {
"name": model.name,
"model": model.model,
"type": "activity",
"icon": icon,
"total_count": today + overdue,
"today_count": today,
"overdue_count": overdue,
"planned_count": len(model_dic["planned"] & set(allowed_records.ids)),
"actions": [
{
"icon": "fa-clock-o",
"name": "Summary",
}
],
}
return list(user_activities.values())
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions mail_activity_not_deleted/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

from . import test_mail_activity
70 changes: 70 additions & 0 deletions mail_activity_not_deleted/tests/test_mail_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from datetime import datetime
from odoo.tests import common


class TestMailActivity(common.SavepointCase):

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner = cls.env['res.partner'].create({'name': 'Test'})
cls.partner.write({
'activity_ids': [(0, 0, {
'res_id': cls.partner.id,
'res_model_id': cls.env.ref('base.model_res_partner').id,
'date_deadline': datetime.now().date(),
'user_id': cls.env.user.id,
})]
})
cls.activity = cls.partner.activity_ids

def test_when_activity_is_completed_then_it_is_inactive_instead_of_deleted(self):
self.assertTrue(self.activity.active)

self.activity.action_done()
self.assertTrue(self.activity.exists())
self.assertFalse(self.activity.active)

def test_when_activity_is_rescheduled_then_it_is_inactive_instead_of_deleted(self):
self.assertTrue(self.activity.active)

self.activity.action_done_schedule_next()
self.assertTrue(self.activity.exists())
self.assertFalse(self.activity.active)

def test_when_record_is_deactivated_then_the_activity_is_inactive_instead_of_deleted(self):
self.assertTrue(self.activity.active)

self.partner.active = False
self.activity.refresh()
self.assertTrue(self.activity.exists())
self.assertFalse(self.activity.active)

def test_the_date_done_is_computed_when_the_activity_is_completed(self):
self.assertFalse(self.activity.date_done)

time_before = datetime.now()
self.activity.action_done()
time_after = datetime.now()

self.assertLessEqual(time_before, self.activity.date_done)
self.assertLessEqual(self.activity.date_done, time_after)

def test_the_state_is_done_after_the_activity_is_completed(self):
self.assertNotEqual(self.activity.state, 'done')
self.activity.action_done()
self.activity.refresh()
self.assertEqual(self.activity.state, 'done')

def test_when_the_activity_is_archived_then_it_is_not_due_today(self):
self.assertEqual(self.partner.activity_state, 'today')
self.activity.action_done()
self.assertFalse(self.partner.activity_state)

def test_when_the_activity_is_archived_then_partner_has_no_activity_deadline(self):
self.assertTrue(self.partner.activity_date_deadline)
self.activity.action_done()
self.assertFalse(self.partner.activity_date_deadline)

0 comments on commit 92245f9

Please sign in to comment.