Browse Source

Merge PR #1674 into 12.0

Signed-off-by LoisRForgeFlow
12.0-mig-module_prototyper_last
OCA-git-bot 4 years ago
parent
commit
27a56ee330
  1. 1
      autovacuum_message_attachment/__init__.py
  2. 21
      autovacuum_message_attachment/__manifest__.py
  3. 31
      autovacuum_message_attachment/data/data.xml
  4. 158
      autovacuum_message_attachment/i18n/autovacuum_mail_message.pot
  5. 180
      autovacuum_message_attachment/i18n/fr.po
  6. 5
      autovacuum_message_attachment/models/__init__.py
  7. 71
      autovacuum_message_attachment/models/autovacuum_mixin.py
  8. 13
      autovacuum_message_attachment/models/base.py
  9. 27
      autovacuum_message_attachment/models/ir_attachment.py
  10. 32
      autovacuum_message_attachment/models/mail_message.py
  11. 86
      autovacuum_message_attachment/models/vacuum_rule.py
  12. 6
      autovacuum_message_attachment/readme/CONFIGURE.rst
  13. 2
      autovacuum_message_attachment/readme/CONTRIBUTORS.rst
  14. 4
      autovacuum_message_attachment/readme/DESCRIPTION.rst
  15. 2
      autovacuum_message_attachment/readme/ROADMAP.rst
  16. 2
      autovacuum_message_attachment/security/ir.model.access.csv
  17. BIN
      autovacuum_message_attachment/static/description/icon.png
  18. 3
      autovacuum_message_attachment/tests/__init__.py
  19. 169
      autovacuum_message_attachment/tests/test_vacuum_rule.py
  20. 67
      autovacuum_message_attachment/views/rule_vacuum.xml

1
autovacuum_message_attachment/__init__.py

@ -0,0 +1 @@
from . import models

21
autovacuum_message_attachment/__manifest__.py

@ -0,0 +1,21 @@
# Copyright (C) 2018 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": "AutoVacuum Mail Message and Attachment",
"version": "12.0.1.0.0",
"category": "Tools",
"website": "https://github.com/OCA/server-tools",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "LGPL-3",
"installable": True,
"summary": "Automatically delete old mail messages and attachments",
"depends": [
"mail",
],
"data": [
"data/data.xml",
"views/rule_vacuum.xml",
"security/ir.model.access.csv",
],
}

31
autovacuum_message_attachment/data/data.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="ir_cron_vacuum_message" model="ir.cron">
<field name="name">AutoVacuum Mails and Messages</field>
<field eval="False" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="state">code</field>
<field name="code">model.autovacuum('message')</field>
<field eval="False" name="doall"/>
<field name="model_id" ref="mail.model_mail_message"/>
</record>
<record id="ir_cron_vacuum_attachment" model="ir.cron">
<field name="name">AutoVacuum Attachments</field>
<field eval="False" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="state">code</field>
<field name="code">model.autovacuum('attachment')</field>
<field eval="False" name="doall"/>
<field name="model_id" ref="base.model_ir_attachment"/>
</record>
</odoo>

158
autovacuum_message_attachment/i18n/autovacuum_mail_message.pot

@ -0,0 +1,158 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * autovacuum_mail_message
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "All"
msgstr ""
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "Comment"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_company_id
msgid "Company"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_create_uid
msgid "Created by"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_create_date
msgid "Created on"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_display_name
msgid "Display Name"
msgstr ""
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "Email"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_empty_subtype
msgid "Empty subtype"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_id
msgid "ID"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule___last_update
msgid "Last Modified on"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_write_uid
msgid "Last Updated by"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_write_date
msgid "Last Updated on"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model,name:autovacuum_mail_message.model_mail_message
msgid "Message"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Models"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Subtypes"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.actions.act_window,name:autovacuum_mail_message.action_message_vacuum_rule
#: model:ir.ui.menu,name:autovacuum_mail_message.menu_action_message_vacuum_rule
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Vacuum Rule"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_message_subtype_ids
msgid "Message subtypes concerned by the rule. If left empty, the system won't take the subtype into account to find the messages to delete"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_message_type
msgid "Message type"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_model_ids
msgid "Models"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_model_ids
msgid "Models concerned by the rule. If left empty, it will take all models into account"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_name
msgid "Name"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_retention_time
msgid "Number of days the messages concerned by this rule will be keeped in the database after creation. Once the delay is passed, they will be automatically deleted."
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_retention_time
msgid "Retention time"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model,name:autovacuum_mail_message.model_message_vacuum_rule
msgid "Rules Used to delete message historic"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_message_subtype_ids
msgid "Subtypes"
msgstr ""
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "System notification"
msgstr ""
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_empty_subtype
msgid "Take also into account messages with no subtypes"
msgstr ""
#. module: autovacuum_mail_message
#: code:addons/autovacuum_mail_message/models/message_vacuum_rule.py:48
#, python-format
msgid "The Retention Time can't be 0 days"
msgstr ""

180
autovacuum_message_attachment/i18n/fr.po

@ -0,0 +1,180 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * autovacuum_mail_message
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-29 11:30+0000\n"
"PO-Revision-Date: 2018-03-29 11:30+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "All"
msgstr "Tous"
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "Comment"
msgstr "Commentaires"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_company_id
msgid "Company"
msgstr "Société"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_create_uid
msgid "Created by"
msgstr "Créé par"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_create_date
msgid "Created on"
msgstr "Créé le"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_display_name
msgid "Display Name"
msgstr "Nom à afficher"
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "Email"
msgstr "Email"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_empty_subtype
msgid "Empty subtype"
msgstr "Sous-type Vide"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_id
msgid "ID"
msgstr "ID"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule___last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_write_uid
msgid "Last Updated by"
msgstr "Dernière modification par"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: autovacuum_mail_message
#: model:ir.model,name:autovacuum_mail_message.model_mail_message
msgid "Message"
msgstr "Message"
#. module: autovacuum_mail_message
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Models"
msgstr "Documents des messages"
#. module: autovacuum_mail_message
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Subtypes"
msgstr "Sous-types des messages"
#. module: autovacuum_mail_message
#: model:ir.actions.act_window,name:autovacuum_mail_message.action_message_vacuum_rule
#: model:ir.ui.menu,name:autovacuum_mail_message.menu_action_message_vacuum_rule
#: model:ir.ui.view,arch_db:autovacuum_mail_message.message_vacuum_rule_form_view
msgid "Message Vacuum Rule"
msgstr "Règle de supression des messages"
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_message_subtype_ids
msgid ""
"Message subtypes concerned by the rule. If left empty, the system won't take "
"the subtype into account to find the messages to delete"
msgstr ""
"Sous-types de message concernés par cette règle. Si c'est laissé vide, le "
"système ne prendra pas en compte les sous type pour trouver les messages à "
"supprimer"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_message_type
msgid "Message type"
msgstr "Type de message"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_model_ids
msgid "Models"
msgstr "Documents"
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_model_ids
msgid ""
"Models concerned by the rule. If left empty, it will take all models into "
"account"
msgstr ""
"Documents concernés par la règle. Si c'est laissé vide, les messages de tous "
"les modèles seront pris en compte"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_name
msgid "Name"
msgstr "Nom"
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_retention_time
msgid ""
"Number of days the messages concerned by this rule will be keeped in the "
"database after creation. Once the delay is passed, they will be "
"automatically deleted."
msgstr ""
"Nombre de jour de rétention des messages concerné par la règle. Une fois ce "
"délai passé, les messages sont automatiquement supprimés"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_retention_time
msgid "Retention time"
msgstr "Temps de rétention"
#. module: autovacuum_mail_message
#: model:ir.model,name:autovacuum_mail_message.model_message_vacuum_rule
msgid "Rules Used to delete message historic"
msgstr "Règle de supression automatique de message"
#. module: autovacuum_mail_message
#: model:ir.model.fields,field_description:autovacuum_mail_message.field_message_vacuum_rule_message_subtype_ids
msgid "Subtypes"
msgstr "Sous-types"
#. module: autovacuum_mail_message
#: selection:message.vacuum.rule,message_type:0
msgid "System notification"
msgstr "Notification Système"
#. module: autovacuum_mail_message
#: model:ir.model.fields,help:autovacuum_mail_message.field_message_vacuum_rule_empty_subtype
msgid "Take also into account messages with no subtypes"
msgstr "Prend également en compte les messages sans aucun sous-type"
#. module: autovacuum_mail_message
#: code:addons/autovacuum_mail_message/models/message_vacuum_rule.py:48
#, python-format
msgid "The Retention Time can't be 0 days"
msgstr "Le temps de retention ne peut pas être de 0 jours."
#~ msgid "Companies"
#~ msgstr "Sociétés"
#~ msgid "mail_message_subtype"
#~ msgstr "mail_message_subtype"

5
autovacuum_message_attachment/models/__init__.py

@ -0,0 +1,5 @@
from . import autovacuum_mixin
from . import ir_attachment
from . import mail_message
from . import vacuum_rule
from . import base

71
autovacuum_message_attachment/models/autovacuum_mixin.py

@ -0,0 +1,71 @@
# Copyright (C) 2019 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
import logging
import odoo
from odoo import api, models
from odoo.tools.safe_eval import safe_eval
import datetime
_logger = logging.getLogger(__name__)
class AutovacuumMixin(models.AbstractModel):
_name = "autovacuum.mixin"
_description = "Mixin used to delete messages or attachments"
@api.multi
def batch_unlink(self):
with api.Environment.manage():
with odoo.registry(
self.env.cr.dbname).cursor() as new_cr:
new_env = api.Environment(new_cr, self.env.uid,
self.env.context)
try:
while self:
batch_delete = self[0:1000]
self -= batch_delete
# do not attach new env to self because it may be
# huge, and the cache is cleaned after each unlink
# so we do not want to much record is the env in
# which we call unlink because odoo would prefetch
# fields, cleared right after.
batch_delete.with_env(new_env).unlink()
new_env.cr.commit()
except Exception as e:
_logger.exception(
"Failed to delete Ms : %s" % (self._name, str(e)))
# Call by cron
@api.model
def autovacuum(self, ttype='message'):
rules = self.env['vacuum.rule'].search([('ttype', '=', ttype)])
for rule in rules:
records = rule._search_autovacuum_records()
records.batch_unlink()
def _get_autovacuum_domain(self, rule):
return []
def _get_autovacuum_records(self, rule):
if rule.model_id and rule.model_filter_domain:
return self._get_autovacuum_records_model(rule)
return self.search(self._get_autovacuum_domain(rule))
def _get_autovacuum_records_model(self, rule):
domain = self._get_autovacuum_domain(rule)
record_domain = safe_eval(rule.model_filter_domain,
locals_dict={'datetime': datetime})
autovacuum_relation = self._autovacuum_relation
for leaf in domain:
if not isinstance(leaf, (tuple, list)):
record_domain.append(leaf)
continue
field, operator, value = leaf
record_domain.append(
('%s.%s' % (autovacuum_relation, field), operator, value))
records = self.env[rule.model_id.model].search(record_domain)
return self.search(
domain + [('res_id', 'in', records.ids)]
)

13
autovacuum_message_attachment/models/base.py

@ -0,0 +1,13 @@
# Copyright (C) 2019 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models
class Base(models.AbstractModel):
_inherit = "base"
attachment_ids = fields.One2many(
'ir.attachment', 'res_id', string='Attachments',
domain=lambda self: [('res_model', '=', self._name)], auto_join=True
)

27
autovacuum_message_attachment/models/ir_attachment.py

@ -0,0 +1,27 @@
# Copyright (C) 2018 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models
from datetime import timedelta
class IrAttachment(models.Model):
_name = "ir.attachment"
_inherit = ["ir.attachment", "autovacuum.mixin"]
_autovacuum_relation = 'attachment_ids'
def _get_autovacuum_domain(self, rule):
domain = super()._get_autovacuum_domain(rule)
today = fields.Datetime.now()
limit_date = today - timedelta(days=rule.retention_time)
domain += [('create_date', '<', limit_date)]
if rule.filename_pattern:
domain += [('name', 'ilike', rule.filename_pattern)]
if rule.model_ids:
models = rule.model_ids.mapped('model')
domain += [('res_model', 'in', models)]
else:
# Avoid deleting attachment without model, if there are, it is
# probably some attachments created by Odoo
domain += [('res_model', '!=', False)]
return domain

32
autovacuum_message_attachment/models/mail_message.py

@ -0,0 +1,32 @@
# Copyright (C) 2018 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models
from datetime import timedelta
class MailMessage(models.Model):
_name = "mail.message"
_inherit = ["mail.message", "autovacuum.mixin"]
_autovacuum_relation = 'message_ids'
def _get_autovacuum_domain(self, rule):
domain = super()._get_autovacuum_domain(rule)
today = fields.Datetime.now()
limit_date = today - timedelta(days=rule.retention_time)
domain += [('date', '<', limit_date)]
if rule.message_type != 'all':
domain += [('message_type', '=', rule.message_type)]
if rule.model_ids:
models = rule.model_ids.mapped('model')
domain += [('model', 'in', models)]
subtype_ids = rule.message_subtype_ids.ids
if subtype_ids and rule.empty_subtype:
domain = [
'|', ('subtype_id', 'in', subtype_ids),
('subtype_id', '=', False)]
elif subtype_ids and not rule.empty_subtype:
domain += [('subtype_id', 'in', subtype_ids)]
elif not subtype_ids and not rule.empty_subtype:
domain += [('subtype_id', '!=', False)]
return domain

86
autovacuum_message_attachment/models/vacuum_rule.py

@ -0,0 +1,86 @@
# Copyright (C) 2018 Akretion
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import _, api, exceptions, fields, models
class VacuumRule(models.Model):
_name = "vacuum.rule"
_description = "Rules Used to delete message historic"
@api.depends('model_ids')
@api.multi
def _get_model_id(self):
for rule in self:
if rule.model_ids and len(rule.model_ids) == 1:
rule.model_id = rule.model_ids.id
rule.model = rule.model_id.model
else:
rule.model_id = False
rule.model = False
name = fields.Char(required=True)
ttype = fields.Selection(
selection=[('attachment', 'Attachment'),
('message', 'Message')],
string="Type",
required=True)
filename_pattern = fields.Char(
help=("If set, only attachments containing this pattern will be"
" deleted."))
company_id = fields.Many2one(
'res.company', string="Company",
default=lambda self: self.env['res.company']._company_default_get(
'vacuum.rule'))
message_subtype_ids = fields.Many2many(
'mail.message.subtype', string="Subtypes",
help="Message subtypes concerned by the rule. If left empty, the "
"system won't take the subtype into account to find the "
"messages to delete")
empty_subtype = fields.Boolean(
help="Take also into account messages with no subtypes")
model_ids = fields.Many2many(
'ir.model', string="Models",
help="Models concerned by the rule. If left empty, it will take all "
"models into account")
model_id = fields.Many2one(
'ir.model', readonly=True,
compute='_get_model_id',
help="Technical field used to set attributes (invisible/required, "
"domain, etc...for other fields, like the domain filter")
model_filter_domain = fields.Text(
string='Model Filter Domain')
model = fields.Char(
readonly=True,
compute='_get_model_id',
string='Model code'
)
message_type = fields.Selection([
('email', 'Email'),
('comment', 'Comment'),
('notification', 'System notification'),
('all', 'All')])
retention_time = fields.Integer(
required=True, default=365,
help="Number of days the messages concerned by this rule will be "
"keeped in the database after creation. Once the delay is "
"passed, they will be automatically deleted.")
active = fields.Boolean(default=True)
description = fields.Text()
@api.multi
@api.constrains('retention_time')
def retention_time_not_null(self):
for rule in self:
if not rule.retention_time:
raise exceptions.ValidationError(
_("The Retention Time can't be 0 days"))
def _search_autovacuum_records(self):
self.ensure_one()
model = self.ttype
if model == 'message':
model = 'mail.message'
elif model == 'attachment':
model = 'ir.attachment'
return self.env[model]._get_autovacuum_records(self)

6
autovacuum_message_attachment/readme/CONFIGURE.rst

@ -0,0 +1,6 @@
* Go to the menu configuration => Technical => Email => Message And Attachment Vacuum Rules
* Add the adequates rules for your company. On each rule, you can indicate the models, type and subtypes for which you want to delete the messages, along with a retention time (in days). Or for attachment, you can specify a substring of the name.
* Activate the cron AutoVacuum Mails and Messages and/or AutoVacuum Attachments
It is recommanded to run it frequently and when the system is not very loaded.
(For instance : once a day, during the night.)

2
autovacuum_message_attachment/readme/CONTRIBUTORS.rst

@ -0,0 +1,2 @@
* Florian da Costa <florian.dacosta@akretion.com>
* Enric Tobella <etobella@creublanca.es>

4
autovacuum_message_attachment/readme/DESCRIPTION.rst

@ -0,0 +1,4 @@
Odoo create a lot of message and/or mails. With time it can slow the system or take a lot of disk space.
The goal of this module is to clean these message once they are obsolete.
The same may happen with attachment that we store.
You can choose various criterias manage which messages you want to delete automatically.

2
autovacuum_message_attachment/readme/ROADMAP.rst

@ -0,0 +1,2 @@
You have to be careful with rules regarding attachment deletion because Odoo find the attachment to delete with their name.
Odoo will find all attachments containing the substring configured on the rule, so you have to be specific enough on the other criterias (concerned models...) to avoid unwanted attachment deletion.

2
autovacuum_message_attachment/security/ir.model.access.csv

@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_full_vaccum_rule,access.full.vaccum.rule,model_vacuum_rule,base.group_system,1,1,1,1

BIN
autovacuum_message_attachment/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

3
autovacuum_message_attachment/tests/__init__.py

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_vacuum_rule

169
autovacuum_message_attachment/tests/test_vacuum_rule.py

@ -0,0 +1,169 @@
# © 2018 Akretion (Florian da Costa)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import date, timedelta
from odoo import api, exceptions
from odoo.tests import common
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
import base64
class TestVacuumRule(common.TransactionCase):
def create_mail_message(self, message_type, subtype):
vals = {
'message_type': message_type,
'subtype_id': subtype and subtype.id or False,
'date': self.before_400_days,
'model': 'res.partner',
'res_id': self.env.ref('base.partner_root').id,
'subject': 'Test',
'body': 'Body Test',
}
return self.message_obj.create(vals)
def tearDown(self):
self.registry.leave_test_mode()
super(TestVacuumRule, self).tearDown()
def setUp(self):
super(TestVacuumRule, self).setUp()
self.registry.enter_test_mode(self.env.cr)
self.env = api.Environment(self.registry.test_cr, self.env.uid,
self.env.context)
self.subtype = self.env.ref('mail.mt_comment')
self.message_obj = self.env['mail.message']
self.attachment_obj = self.env['ir.attachment']
self.partner_model = self.env.ref('base.model_res_partner')
today = date.today()
self.before_400_days = today - timedelta(days=400)
def test_mail_vacuum_rules(self):
rule_vals = {
'name': 'Subtype Model',
'ttype': 'message',
'retention_time': 399,
'message_type': 'email',
'model_ids': [(6, 0, [self.env.ref('base.model_res_partner').id])],
'message_subtype_ids': [(6, 0, [self.subtype.id])],
}
rule = self.env['vacuum.rule'].create(rule_vals)
m1 = self.create_mail_message('notification', self.subtype)
m2 = self.create_mail_message('email', self.env.ref('mail.mt_note'))
m3 = self.create_mail_message('email', False)
message_ids = [m1.id, m2.id, m3.id]
self.message_obj.autovacuum(ttype='message')
message = self.message_obj.search(
[('id', 'in', message_ids)])
# no message deleted because either message_type is wrong or subtype
# is wrong or subtype is empty
self.assertEqual(len(message),
3)
rule.write({'message_type': 'notification', 'retention_time': 405})
self.message_obj.autovacuum(ttype='message')
message = self.message_obj.search(
[('id', 'in', message_ids)])
# no message deleted because of retention time
self.assertEqual(len(message),
3)
rule.write({'retention_time': 399})
self.message_obj.autovacuum(ttype='message')
message = self.message_obj.search(
[('id', 'in', message_ids)])
self.assertEqual(len(message),
2)
rule.write({'message_type': 'email',
'message_subtype_ids': [(6, 0, [])],
'empty_subtype': True})
self.message_obj.autovacuum(ttype='message')
message = self.message_obj.search(
[('id', 'in', message_ids)])
self.assertEqual(len(message),
0)
def create_attachment(self, name):
vals = {
'name': name,
'datas': base64.b64encode(b'Content'),
'datas_fname': name,
'res_id': self.env.ref('base.partner_root').id,
'res_model': 'res.partner',
}
return self.env['ir.attachment'].create(vals)
def test_attachment_vacuum_rule(self):
rule_vals = {
'name': 'Partner Attachments',
'ttype': 'attachment',
'retention_time': 100,
'model_ids': [(6, 0, [self.partner_model.id])],
'filename_pattern': 'test',
}
self.env['vacuum.rule'].create(rule_vals)
a1 = self.create_attachment('Test-dummy')
a2 = self.create_attachment('test24')
# Force create date to old date to test deletion with 100 days
# retention time
before_102_days = date.today() - timedelta(days=102)
before_102_days_str = before_102_days.strftime(
DEFAULT_SERVER_DATE_FORMAT)
self.env.cr.execute("""
UPDATE ir_attachment SET create_date = '%s'
WHERE id = %s
""" % (before_102_days_str, a2.id))
a2.write({'create_date': date.today() - timedelta(days=102)})
a3 = self.create_attachment('other')
self.env.cr.execute("""
UPDATE ir_attachment SET create_date = '%s'
WHERE id = %s
""" % (before_102_days_str, a3.id))
attachment_ids = [a1.id, a2.id, a3.id]
self.attachment_obj.autovacuum(ttype='attachment')
attachments = self.attachment_obj.search(
[('id', 'in', attachment_ids)])
# Only one message deleted because other 2 are with bad name or to
# recent.
self.assertEqual(len(attachments),
2)
def test_retention_time_constraint(self):
rule_vals = {
'name': 'Subtype Model',
'ttype': 'message',
'retention_time': 0,
'message_type': 'email',
}
with self.assertRaises(exceptions.ValidationError):
self.env['vacuum.rule'].create(rule_vals)
def test_res_model_domain(self):
partner = self.env['res.partner'].create({'name': 'Test Partner'})
# automatic creation message
self.assertEqual(len(partner.message_ids), 1)
# change date message to simulate it is an old one
partner.message_ids.write({'date': '2017-01-01'})
partner_model = self.env.ref('base.model_res_partner')
rule_vals = {
'name': 'Partners',
'ttype': 'message',
'retention_time': 399,
'message_type': 'all',
'model_ids': [(6, 0, [partner_model.id])],
'model_filter_domain': "[['name', '=', 'Dummy']]",
'empty_subtype': True,
}
rule = self.env['vacuum.rule'].create(rule_vals)
self.message_obj.autovacuum(ttype='message')
# no message deleted as the filter does not match
self.assertEqual(len(partner.message_ids), 1)
rule.write({
'model_filter_domain': "[['name', '=', 'Test Partner']]"
})
self.message_obj.autovacuum(ttype='message')
self.assertEqual(len(partner.message_ids), 0)

67
autovacuum_message_attachment/views/rule_vacuum.xml

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="vacuum_rule_form_view">
<field name="name">vacuum.rule.form.view</field>
<field name="model">vacuum.rule</field>
<field name="arch" type="xml">
<form string="Message Vacuum Rule">
<sheet>
<group col="1">
<group col="4">
<field name="name"/>
<field name="ttype"/>
<field name="company_id"/>
<field name="retention_time"/>
<field name="active"/>
</group>
<group col="4" attrs="{'invisible': [('ttype', '!=', 'message')]}">
<field name="message_type" attrs="{'required': [('ttype', '=', 'message')]}"/>
<field name="empty_subtype"/>
</group>
<group string="Message Subtypes">
<field name="message_subtype_ids" nolabel="1"/>
</group>
<group attrs="{'invisible': [('ttype', '!=', 'attachment')]}">
<field name="filename_pattern"/>
</group>
<group string="Message Models">
<field name="model_ids" nolabel="1"/>
</group>
<group>
<field name="model_id"/>
<field name="model" invisible="1"/>
<field name="model_filter_domain" attrs="{'invisible': [('model_id', '=', False)]}" widget="domain" options="{'model': 'model'}"/>
</group>
<group string="Description">
<field name="description"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="vacuum_rule_tree_view">
<field name="name">vacuum.rule.form.view</field>
<field name="model">vacuum.rule</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="company_id"/>
<field name="retention_time"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_vacuum_rule">
<field name="name">Message and Attachment Vacuum Rule</field>
<field name="res_model">vacuum.rule</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_action_vacuum_rule" parent="base.menu_email" action="action_vacuum_rule"/>
</odoo>
Loading…
Cancel
Save