From 414312b519c08002d75d51cc7d96c62e2b49ee6e Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Thu, 19 Sep 2019 16:35:03 +0200 Subject: [PATCH] Add possibility to delete attachments --- autovacuum_message_attachment/README.rst | 66 -------------- autovacuum_message_attachment/__manifest__.py | 6 +- autovacuum_message_attachment/data/data.xml | 15 +++- .../models/__init__.py | 4 +- .../models/autovacuum_mixin.py | 45 ++++++++++ .../models/ir_attachment.py | 9 ++ .../models/mail_message.py | 42 +-------- ...{message_vacuum_rule.py => vacuum_rule.py} | 79 +++++++++++------ .../readme/CONFIGURE.rst | 6 +- .../readme/DESCRIPTION.rst | 1 + .../readme/ROADMAP.rst | 2 + .../security/ir.model.access.csv | 4 +- .../tests/__init__.py | 3 +- ...age_vacuum_rule.py => test_vacuum_rule.py} | 85 +++++++++++++++---- ...essage_rule_vacuum.xml => rule_vacuum.xml} | 37 ++++---- 15 files changed, 231 insertions(+), 173 deletions(-) delete mode 100644 autovacuum_message_attachment/README.rst create mode 100644 autovacuum_message_attachment/models/autovacuum_mixin.py create mode 100644 autovacuum_message_attachment/models/ir_attachment.py rename autovacuum_message_attachment/models/{message_vacuum_rule.py => vacuum_rule.py} (59%) create mode 100644 autovacuum_message_attachment/readme/ROADMAP.rst rename autovacuum_message_attachment/tests/{test_message_vacuum_rule.py => test_vacuum_rule.py} (55%) rename autovacuum_message_attachment/views/{message_rule_vacuum.xml => rule_vacuum.xml} (53%) diff --git a/autovacuum_message_attachment/README.rst b/autovacuum_message_attachment/README.rst deleted file mode 100644 index 6bd41a699..000000000 --- a/autovacuum_message_attachment/README.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png - :alt: License: LGPL-3 - -======================= -AutoVacuum Mail Message -======================= - -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. - - -Configuration -============= - -* Go to the menu configuration => Technical => Email => Message vacuum Rule -* 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). -* Activate the cron AutoVacuum Mails and Messages - -It is recommanded to run it frequently and when the system is not very loaded. -(For instance : once a day, during the night.) - - -Usage -===== - -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/149/9.0 - -Bug Tracker -=========== - -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. - -Credits -======= - -Images ------- - -* Odoo Community Association: `Icon `_. - -Contributors ------------- - -* Florian da Costa - -Do not contact contributors directly about support or help with technical issues. - -Maintainer ----------- - -.. image:: https://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: https://odoo-community.org - -This module is maintained by the OCA. - -OCA, or the Odoo Community Association, is a nonprofit organization whose -mission is to support the collaborative development of Odoo features and -promote its widespread use. - -To contribute to this module, please visit https://odoo-community.org. diff --git a/autovacuum_message_attachment/__manifest__.py b/autovacuum_message_attachment/__manifest__.py index dd39b8fda..e09663fa8 100644 --- a/autovacuum_message_attachment/__manifest__.py +++ b/autovacuum_message_attachment/__manifest__.py @@ -2,20 +2,20 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). { - "name": "AutoVacuum Mail Message", + "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 to clean database", + "summary": "Automatically delete old mail messages and attachments", "depends": [ "mail", ], "data": [ "data/data.xml", - "views/message_rule_vacuum.xml", + "views/rule_vacuum.xml", "security/ir.model.access.csv", ], } diff --git a/autovacuum_message_attachment/data/data.xml b/autovacuum_message_attachment/data/data.xml index 3b0eae78b..e036e64f2 100644 --- a/autovacuum_message_attachment/data/data.xml +++ b/autovacuum_message_attachment/data/data.xml @@ -10,9 +10,22 @@ days -1 code - model.autovacuum_mail_message() + model.autovacuum('message') + + AutoVacuum Attachments + + + 1 + days + -1 + code + model.autovacuum('attachment') + + + + diff --git a/autovacuum_message_attachment/models/__init__.py b/autovacuum_message_attachment/models/__init__.py index 4aa3f9f69..32b44bd3c 100644 --- a/autovacuum_message_attachment/models/__init__.py +++ b/autovacuum_message_attachment/models/__init__.py @@ -1,2 +1,4 @@ +from . import autovacuum_mixin +from . import ir_attachment from . import mail_message -from . import message_vacuum_rule +from . import vacuum_rule diff --git a/autovacuum_message_attachment/models/autovacuum_mixin.py b/autovacuum_message_attachment/models/autovacuum_mixin.py new file mode 100644 index 000000000..6fe0f756e --- /dev/null +++ b/autovacuum_message_attachment/models/autovacuum_mixin.py @@ -0,0 +1,45 @@ +# 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 + +_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: + domain = rule.get_domain() + records = self.search(domain) + records.batch_unlink() diff --git a/autovacuum_message_attachment/models/ir_attachment.py b/autovacuum_message_attachment/models/ir_attachment.py new file mode 100644 index 000000000..c12cac548 --- /dev/null +++ b/autovacuum_message_attachment/models/ir_attachment.py @@ -0,0 +1,9 @@ +# Copyright (C) 2018 Akretion +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class IrAttachment(models.Model): + _name = "ir.attachment" + _inherit = ["ir.attachment", "autovacuum.mixin"] diff --git a/autovacuum_message_attachment/models/mail_message.py b/autovacuum_message_attachment/models/mail_message.py index 6501b81f8..33825d90e 100644 --- a/autovacuum_message_attachment/models/mail_message.py +++ b/autovacuum_message_attachment/models/mail_message.py @@ -1,44 +1,10 @@ +# -*- coding: utf-8 -*- # Copyright (C) 2018 Akretion # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -import logging - -import odoo -from odoo import api, models - -_logger = logging.getLogger(__name__) +from odoo import models class MailMessage(models.Model): - _inherit = "mail.message" - - @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_messages = self[0:1000] - self -= batch_delete_messages - # 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_messages.with_env(new_env).unlink() - new_env.cr.commit() - except Exception as e: - _logger.exception( - "Failed to delete messages : %s", str(e)) - - # Call by cron - @api.model - def autovacuum_mail_message(self): - rules = self.env['message.vacuum.rule'].search([]) - for rule in rules: - domain = rule.get_message_domain() - messages = self.search(domain) - messages.batch_unlink() + _name = "mail.message" + _inherit = ["mail.message", "autovacuum.mixin"] diff --git a/autovacuum_message_attachment/models/message_vacuum_rule.py b/autovacuum_message_attachment/models/vacuum_rule.py similarity index 59% rename from autovacuum_message_attachment/models/message_vacuum_rule.py rename to autovacuum_message_attachment/models/vacuum_rule.py index 0b798d05f..b662f4288 100644 --- a/autovacuum_message_attachment/models/message_vacuum_rule.py +++ b/autovacuum_message_attachment/models/vacuum_rule.py @@ -9,13 +9,13 @@ from odoo.tools.safe_eval import safe_eval import datetime -class MessageVacuumRule(models.Model): - _name = "message.vacuum.rule" +class VacuumRule(models.Model): + _name = "vacuum.rule" _description = "Rules Used to delete message historic" @api.depends('model_ids') @api.multi - def _compute_model_id(self): + 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 @@ -23,10 +23,18 @@ class MessageVacuumRule(models.Model): rule.model_id = 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( - 'message.vacuum.rule')) + 'vacuum.rule')) message_subtype_ids = fields.Many2many( 'mail.message.subtype', string="Subtypes", help="Message subtypes concerned by the rule. If left empty, the " @@ -40,7 +48,7 @@ class MessageVacuumRule(models.Model): "models into account") model_id = fields.Many2one( 'ir.model', readonly=True, - compute='_compute_model_id', + 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( @@ -49,7 +57,7 @@ class MessageVacuumRule(models.Model): ('email', 'Email'), ('comment', 'Comment'), ('notification', 'System notification'), - ('all', 'All')], required=True) + ('all', 'All')]) retention_time = fields.Integer( required=True, default=365, help="Number of days the messages concerned by this rule will be " @@ -67,11 +75,10 @@ class MessageVacuumRule(models.Model): _("The Retention Time can't be 0 days")) @api.multi - def get_message_domain(self): - self.ensure_one() + def _get_message_domain(self): today = date.today() - limit_date = today - timedelta(days=self.retention_time) - limit_date = limit_date.strftime(DEFAULT_SERVER_DATE_FORMAT) + limit_date = (today - timedelta(days=self.retention_time)).strftime( + DEFAULT_SERVER_DATE_FORMAT) message_domain = [('date', '<', limit_date)] if self.message_type != 'all': message_domain += [('message_type', '=', self.message_type)] @@ -80,24 +87,48 @@ class MessageVacuumRule(models.Model): message_domain += [('model', 'in', models)] subtype_ids = self.message_subtype_ids.ids - subtype_domain = [] if subtype_ids and self.empty_subtype: - subtype_domain = ['|', ('subtype_id', 'in', subtype_ids), + message_domain = ['|', ('subtype_id', 'in', subtype_ids), ('subtype_id', '=', False)] elif subtype_ids and not self.empty_subtype: - subtype_domain += [('subtype_id', 'in', subtype_ids)] + message_domain += [('subtype_id', 'in', subtype_ids)] elif not subtype_ids and not self.empty_subtype: - subtype_domain += [('subtype_id', '!=', False)] - message_domain += subtype_domain + message_domain += [('subtype_id', '!=', False)] + return message_domain + + @api.multi + def _get_attachment_domain(self): + today = date.today() + limit_date = (today - timedelta(days=self.retention_time)).strftime( + DEFAULT_SERVER_DATE_FORMAT) + attachment_domain = [('create_date', '<', limit_date)] + if self.filename_pattern: + attachment_domain += [('name', 'ilike', self.filename_pattern)] + if self.model_ids: + models = self.model_ids.mapped('model') + attachment_domain += [('res_model', 'in', models)] + else: + # Avoid deleting attachment without model, if there are, it is + # probably some attachments created by Odoo + attachment_domain += [('res_model', '!=', False)] + return attachment_domain + + @api.multi + def get_domain(self): + self.ensure_one() + domain = [] + if self.ttype == 'message': + domain += self._get_message_domain() + elif self.ttype == 'attachment': + domain += self._get_attachment_domain() + # Case we want a condition on linked model records if self.model_id and self.model_filter_domain: - domain = safe_eval(self.model_filter_domain, - locals_dict={'datetime': datetime}) + record_domain = safe_eval(self.model_filter_domain, + locals_dict={'datetime': datetime}) - res_model = self.model_id.model - res_records = self.env[res_model].with_context( - active_test=False).search(domain) - res_ids = res_records.ids - message_domain += ['|', ('res_id', 'in', res_ids), - ('res_id', '=', False)] - return message_domain + res_ids = self.env[self.model_id.model].with_context( + active_test=False).search(record_domain).ids + domain += ['|', ('res_id', 'in', res_ids), + ('res_id', '=', False)] + return domain diff --git a/autovacuum_message_attachment/readme/CONFIGURE.rst b/autovacuum_message_attachment/readme/CONFIGURE.rst index a5af99737..a422d44b8 100644 --- a/autovacuum_message_attachment/readme/CONFIGURE.rst +++ b/autovacuum_message_attachment/readme/CONFIGURE.rst @@ -1,6 +1,6 @@ -* Go to the menu configuration => Technical => Email => Message 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). -* Activate the cron AutoVacuum Mails and Messages +* 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.) diff --git a/autovacuum_message_attachment/readme/DESCRIPTION.rst b/autovacuum_message_attachment/readme/DESCRIPTION.rst index 04463783e..b7e6fcec4 100644 --- a/autovacuum_message_attachment/readme/DESCRIPTION.rst +++ b/autovacuum_message_attachment/readme/DESCRIPTION.rst @@ -1,3 +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. diff --git a/autovacuum_message_attachment/readme/ROADMAP.rst b/autovacuum_message_attachment/readme/ROADMAP.rst new file mode 100644 index 000000000..8c221582b --- /dev/null +++ b/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. diff --git a/autovacuum_message_attachment/security/ir.model.access.csv b/autovacuum_message_attachment/security/ir.model.access.csv index 9f3a70325..e6ba8428c 100644 --- a/autovacuum_message_attachment/security/ir.model.access.csv +++ b/autovacuum_message_attachment/security/ir.model.access.csv @@ -1,2 +1,2 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_full_message_vaccum_rule,access.full.message.vaccum.rule,model_message_vacuum_rule,base.group_system,1,1,1,1 +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 diff --git a/autovacuum_message_attachment/tests/__init__.py b/autovacuum_message_attachment/tests/__init__.py index 6d036f0b6..008d37fbf 100644 --- a/autovacuum_message_attachment/tests/__init__.py +++ b/autovacuum_message_attachment/tests/__init__.py @@ -1,4 +1,3 @@ -# © 2018 Akretion (Florian da Costa) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from . import test_message_vacuum_rule +from . import test_vacuum_rule diff --git a/autovacuum_message_attachment/tests/test_message_vacuum_rule.py b/autovacuum_message_attachment/tests/test_vacuum_rule.py similarity index 55% rename from autovacuum_message_attachment/tests/test_message_vacuum_rule.py rename to autovacuum_message_attachment/tests/test_vacuum_rule.py index 8a1fece8d..dd55cd290 100644 --- a/autovacuum_message_attachment/tests/test_message_vacuum_rule.py +++ b/autovacuum_message_attachment/tests/test_vacuum_rule.py @@ -5,17 +5,19 @@ 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 TestMessageVacuumRule(common.TransactionCase): +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': 'mail.channel', - 'res_id': self.env.ref('mail.channel_all_employees').id, + 'model': 'res.partner', + 'res_id': self.env.ref('base.partner_root').id, 'subject': 'Test', 'body': 'Body Test', } @@ -23,49 +25,51 @@ class TestMessageVacuumRule(common.TransactionCase): def tearDown(self): self.registry.leave_test_mode() - super(TestMessageVacuumRule, self).tearDown() + super(TestVacuumRule, self).tearDown() def setUp(self): - super(TestMessageVacuumRule, self).setUp() + 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.channel_model = self.env.ref('mail.model_mail_channel') + 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.channel_model.id])], + 'model_ids': [(6, 0, [self.env.ref('base.model_res_partner').id])], 'message_subtype_ids': [(6, 0, [self.subtype.id])], } - rule = self.env['message.vacuum.rule'].create(rule_vals) + 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_mail_message() + 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 wront or subtype is empty + # is wrong or subtype is empty self.assertEqual(len(message), 3) rule.write({'message_type': 'notification', 'retention_time': 405}) - self.message_obj.autovacuum_mail_message() + 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_mail_message() + self.message_obj.autovacuum(ttype='message') message = self.message_obj.search( [('id', 'in', message_ids)]) @@ -75,20 +79,66 @@ class TestMessageVacuumRule(common.TransactionCase): rule.write({'message_type': 'email', 'message_subtype_ids': [(6, 0, [])], 'empty_subtype': True}) - self.message_obj.autovacuum_mail_message() + 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['message.vacuum.rule'].create(rule_vals) + self.env['vacuum.rule'].create(rule_vals) def test_res_model_domain(self): partner = self.env['res.partner'].create({'name': 'Test Partner'}) @@ -100,19 +150,20 @@ class TestMessageVacuumRule(common.TransactionCase): 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['message.vacuum.rule'].create(rule_vals) - self.message_obj.autovacuum_mail_message() + 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_mail_message() + self.message_obj.autovacuum(ttype='message') self.assertEqual(len(partner.message_ids), 0) diff --git a/autovacuum_message_attachment/views/message_rule_vacuum.xml b/autovacuum_message_attachment/views/rule_vacuum.xml similarity index 53% rename from autovacuum_message_attachment/views/message_rule_vacuum.xml rename to autovacuum_message_attachment/views/rule_vacuum.xml index 35e8d4739..68194e7b1 100644 --- a/autovacuum_message_attachment/views/message_rule_vacuum.xml +++ b/autovacuum_message_attachment/views/rule_vacuum.xml @@ -2,27 +2,34 @@ - - message.vacuum.rule.form.view - message.vacuum.rule + + vacuum.rule.form.view + vacuum.rule
+ - - + + + + + + + + + - - + @@ -31,27 +38,25 @@ - - message.vacuum.rule.form.view - message.vacuum.rule + + vacuum.rule.form.view + vacuum.rule - - - - Message Vacuum Rules - message.vacuum.rule + + Message and Attachment Vacuum Rule + vacuum.rule form tree,form - +