[MIG] database_cleanup: Migration to 14.0
parent
d1acfa4b4a
commit
7d8967fe32
|
@ -1,10 +1,29 @@
|
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
===================
|
||||
Base Technical User
|
||||
===================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/server-tools/tree/14.0/database_cleanup
|
||||
:alt: OCA/server-tools
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/server-tools-14-0/server-tools-14-0-database_cleanup
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/149/14.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
================
|
||||
Database cleanup
|
||||
================
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
Clean your Odoo database from remnants of modules, models, columns and
|
||||
tables left by uninstalled modules (prior to 7.0) or a homebrew database
|
||||
|
@ -16,6 +35,11 @@ with the technical details of the Odoo data model of *all* the modules
|
|||
that have ever been installed on your database, and do not purge any module,
|
||||
model, column or table if you do not know exactly what you are doing.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
|
@ -28,42 +52,46 @@ in one big step (if you are *really* confident).
|
|||
|
||||
.. 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/11.0
|
||||
:target: https://runbot.odoo-community.org/runbot/149/14.0
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/database_cleanup/issues>`_.
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/server-tools/issues/new?body=module:%20database_cleanup%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Images
|
||||
------
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
* Therp BV
|
||||
|
||||
Contributors
|
||||
------------
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Stefan Rijnhart <stefan@opener.amsterdam>
|
||||
* Holger Brunn <hbrunn@therp.nl>
|
||||
* Stéphane Mangin <stephane.mangin@camptocamp.com>
|
||||
|
||||
Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:community@mail.odoo.com>`_ or the `appropriate specialized mailinglist <https://odoo-community.org/groups>`_ for help, and the bug tracker linked in `Bug Tracker`_ above for technical issues.
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. 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.
|
||||
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/14.0/base_technical_user>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp SA <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
{
|
||||
"name": "Database cleanup",
|
||||
"version": "12.0.1.0.1",
|
||||
"version": "14.0.1.0.0",
|
||||
"author": "Therp BV,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/server-tools",
|
||||
"depends": ["base"],
|
||||
"license": "AGPL-3",
|
||||
"category": "Tools",
|
||||
|
@ -18,6 +20,7 @@
|
|||
"views/create_indexes.xml",
|
||||
"views/purge_properties.xml",
|
||||
"views/menu.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
"installable": True,
|
||||
}
|
|
@ -457,7 +457,7 @@ msgstr "Purge obsolete modules"
|
|||
#, fuzzy
|
||||
#| msgid "Purge obsolete models"
|
||||
msgid "Purge obsolete properties"
|
||||
msgstr "Purge obsolete models"
|
||||
msgstr "Purge obsolete properties"
|
||||
|
||||
#. module: database_cleanup
|
||||
#: model:ir.ui.menu,name:database_cleanup.menu_purge_tables
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# Copyright 2017 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import api, fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
from ..identifier_adapter import IdentifierAdapter
|
||||
|
||||
|
@ -9,14 +10,13 @@ from ..identifier_adapter import IdentifierAdapter
|
|||
class CreateIndexesLine(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.create_indexes.line"
|
||||
_description = "Cleanup Create Indexes line"
|
||||
|
||||
purged = fields.Boolean("Created")
|
||||
wizard_id = fields.Many2one("cleanup.create_indexes.wizard")
|
||||
field_id = fields.Many2one("ir.model.fields", required=True)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
tables = set()
|
||||
for field in self.mapped("field_id"):
|
||||
model = self.env[field.model]
|
||||
name = "{}_{}_index".format(model._table, field.name)
|
||||
|
@ -28,8 +28,6 @@ class CreateIndexesLine(models.TransientModel):
|
|||
IdentifierAdapter(field.name),
|
||||
),
|
||||
)
|
||||
tables.add(model._table)
|
||||
for table in tables:
|
||||
self.env.cr.execute("analyze %s", (IdentifierAdapter(model._table),))
|
||||
self.write(
|
||||
{
|
||||
|
@ -48,7 +46,6 @@ class CreateIndexesWizard(models.TransientModel):
|
|||
"wizard_id",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def find(self):
|
||||
res = list()
|
||||
for field in self.env["ir.model.fields"].search(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import _, api, fields, models
|
||||
|
@ -10,14 +11,13 @@ from ..identifier_adapter import IdentifierAdapter
|
|||
class CleanupPurgeLineColumn(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.column"
|
||||
_description = "Purge Column Wizard Lines"
|
||||
_description = "Cleanup Purge Line Column"
|
||||
|
||||
model_id = fields.Many2one("ir.model", "Model", required=True, ondelete="CASCADE")
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.column", "Purge Wizard", readonly=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""
|
||||
Unlink columns upon manual confirmation.
|
||||
|
@ -123,7 +123,7 @@ class CleanupPurgeWizardColumn(models.TransientModel):
|
|||
model_pool
|
||||
)
|
||||
|
||||
for table, model_spec in table2model.items():
|
||||
for _table, model_spec in table2model.items():
|
||||
for column in self.get_orphaned_columns(model_spec[1]):
|
||||
res.append((0, 0, {"name": column, "model_id": model_spec[0]}))
|
||||
if not res:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
@ -9,13 +10,13 @@ from ..identifier_adapter import IdentifierAdapter
|
|||
class CleanupPurgeLineData(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.data"
|
||||
_description = "Cleanup Purge Line Data"
|
||||
|
||||
data_id = fields.Many2one("ir.model.data", "Data entry")
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.data", "Purge Wizard", readonly=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""Unlink data entries upon manual confirmation."""
|
||||
if self:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import _, api, fields, models
|
||||
|
@ -8,13 +9,13 @@ from odoo.exceptions import UserError
|
|||
class CleanupPurgeLineMenu(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.menu"
|
||||
_description = "Cleanup Purge Line Menu"
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.menu", "Purge Wizard", readonly=True
|
||||
)
|
||||
menu_id = fields.Many2one("ir.ui.menu", "Menu entry")
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""Unlink menu entries upon manual confirmation."""
|
||||
if self:
|
||||
|
@ -47,9 +48,7 @@ class CleanupPurgeWizardMenu(models.TransientModel):
|
|||
):
|
||||
if menu.action.type != "ir.actions.act_window":
|
||||
continue
|
||||
if (menu.action.res_model and menu.action.res_model not in self.env) or (
|
||||
menu.action.src_model and menu.action.src_model not in self.env
|
||||
):
|
||||
if menu.action.res_model and menu.action.res_model not in self.env:
|
||||
res.append(
|
||||
(
|
||||
0,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import _, api, fields, models
|
||||
|
@ -25,7 +26,6 @@ class IrModel(models.Model):
|
|||
class IrModelFields(models.Model):
|
||||
_inherit = "ir.model.fields"
|
||||
|
||||
@api.multi
|
||||
def _prepare_update(self):
|
||||
"""this function crashes for undefined models"""
|
||||
existing = self.filtered(lambda x: x.model in self.env)
|
||||
|
@ -35,13 +35,12 @@ class IrModelFields(models.Model):
|
|||
class CleanupPurgeLineModel(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.model"
|
||||
_description = "Purge models"
|
||||
_description = "Cleanup Purge Line Model"
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.model", "Purge Wizard", readonly=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""
|
||||
Unlink models upon manual confirmation.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import _, api, fields, models
|
||||
|
@ -33,12 +34,12 @@ class IrModelData(models.Model):
|
|||
class CleanupPurgeLineModule(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.module"
|
||||
_description = "Cleanup Purge Line Module"
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.module", "Purge Wizard", readonly=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""
|
||||
Uninstall modules upon manual confirmation, then reload
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
# Copyright 2017 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import api, fields, models
|
||||
|
||||
REASON_DUPLICATE = 1
|
||||
REASON_DEFAULT = 2
|
||||
REASON_DEFAULT_FALSE = 3
|
||||
REASON_UNKNOWN_MODEL = 4
|
||||
REASON_DUPLICATE = "REASON_DUPLICATE"
|
||||
REASON_DEFAULT = "REASON_DEFAULT"
|
||||
REASON_DEFAULT_FALSE = "REASON_DEFAULT_FALSE"
|
||||
REASON_UNKNOWN_MODEL = "REASON_UNKNOWN_MODEL"
|
||||
|
||||
|
||||
class CleanupPurgeLineProperty(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.property"
|
||||
_description = "Purge properties"
|
||||
_description = "Cleanup Purge Line Property"
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.property", "Purge Wizard", readonly=True
|
||||
|
@ -27,7 +28,6 @@ class CleanupPurgeLineProperty(models.TransientModel):
|
|||
]
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""Delete properties"""
|
||||
self.write({"purged": True})
|
||||
|
@ -58,12 +58,7 @@ class CleanupPurgeWizardProperty(models.TransientModel):
|
|||
except KeyError:
|
||||
result.append(
|
||||
{
|
||||
"name": "%s@%s: %s"
|
||||
% (
|
||||
prop.name,
|
||||
prop.res_id,
|
||||
value,
|
||||
),
|
||||
"name": "{}@{}: {}".format(prop.name, prop.res_id, value),
|
||||
"property_id": prop.id,
|
||||
"reason": REASON_UNKNOWN_MODEL,
|
||||
}
|
||||
|
@ -72,12 +67,7 @@ class CleanupPurgeWizardProperty(models.TransientModel):
|
|||
if not value:
|
||||
result.append(
|
||||
{
|
||||
"name": "%s@%s: %s"
|
||||
% (
|
||||
prop.name,
|
||||
prop.res_id,
|
||||
value,
|
||||
),
|
||||
"name": "{}@{}: {}".format(prop.name, prop.res_id, value),
|
||||
"property_id": prop.id,
|
||||
"reason": REASON_DEFAULT_FALSE,
|
||||
}
|
||||
|
@ -127,8 +117,9 @@ class CleanupPurgeWizardProperty(models.TransientModel):
|
|||
for redundant_property in self.env["ir.property"].search(domain):
|
||||
result.append(
|
||||
{
|
||||
"name": "%s@%s: %s"
|
||||
% (prop.name, redundant_property.res_id, prop.get_by_record()),
|
||||
"name": "{}@{}: {}".format(
|
||||
prop.name, redundant_property.res_id, prop.get_by_record()
|
||||
),
|
||||
"property_id": redundant_property.id,
|
||||
"reason": REASON_DEFAULT,
|
||||
}
|
||||
|
@ -148,8 +139,9 @@ class CleanupPurgeWizardProperty(models.TransientModel):
|
|||
for prop in self.env["ir.property"].search([("id", "in", ids)])[1:]:
|
||||
result.append(
|
||||
{
|
||||
"name": "%s@%s: %s"
|
||||
% (prop.name, prop.res_id, prop.get_by_record()),
|
||||
"name": "{}@{}: {}".format(
|
||||
prop.name, prop.res_id, prop.get_by_record()
|
||||
),
|
||||
"property_id": prop.id,
|
||||
"reason": REASON_DUPLICATE,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
from odoo import _, api, fields, models
|
||||
|
@ -10,13 +11,12 @@ from ..identifier_adapter import IdentifierAdapter
|
|||
class CleanupPurgeLineTable(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.table"
|
||||
_description = "Purge tables wizard lines"
|
||||
_description = "Cleanup Purge Line Table"
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
"cleanup.purge.wizard.table", "Purge Wizard", readonly=True
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
"""
|
||||
Unlink tables upon manual confirmation.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright 2014-2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp <https://camptocamp.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
# pylint: disable=consider-merging-classes-inherited
|
||||
|
||||
|
@ -21,7 +22,6 @@ class CleanupPurgeLine(models.AbstractModel):
|
|||
|
||||
logger = logging.getLogger("odoo.addons.database_cleanup")
|
||||
|
||||
@api.multi
|
||||
def purge(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -46,11 +46,9 @@ class PurgeWizard(models.AbstractModel):
|
|||
res["purge_line_ids"] = self.find()
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def find(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@api.multi
|
||||
def purge_all(self):
|
||||
self.mapped("purge_line_ids").purge()
|
||||
return True
|
||||
|
@ -70,7 +68,6 @@ class PurgeWizard(models.AbstractModel):
|
|||
},
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def select_lines(self):
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
|
@ -80,7 +77,6 @@ class PurgeWizard(models.AbstractModel):
|
|||
"domain": [("wizard_id", "in", self.ids)],
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
return [(this.id, self._description) for this in self]
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
* Stefan Rijnhart <stefan@opener.amsterdam>
|
||||
* Holger Brunn <hbrunn@therp.nl>
|
||||
* Stéphane Mangin <stephane.mangin@camptocamp.com>
|
|
@ -0,0 +1,9 @@
|
|||
Clean your Odoo database from remnants of modules, models, columns and
|
||||
tables left by uninstalled modules (prior to 7.0) or a homebrew database
|
||||
upgrade to a new major version of Odoo.
|
||||
|
||||
Caution! This module is potentially harmful and can *easily* destroy the
|
||||
integrity of your data. Do not use if you are not entirely comfortable
|
||||
with the technical details of the Odoo data model of *all* the modules
|
||||
that have ever been installed on your database, and do not purge any module,
|
||||
model, column or table if you do not know exactly what you are doing.
|
|
@ -0,0 +1,10 @@
|
|||
After installation of this module, go to the Settings menu -> Technical ->
|
||||
Database cleanup. This menu is only available to members of the *Access Rights*
|
||||
group. Go through the modules, models, columns and tables
|
||||
entries under this menu (in that order) and find out if there is orphaned data
|
||||
in your database. You can either delete entries by line, or sweep all entries
|
||||
in one big step (if you are *really* confident).
|
||||
|
||||
.. 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/11.0
|
|
@ -0,0 +1,17 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_cleanup_create_indexes_line,access_cleanup_create_indexes_line,model_cleanup_create_indexes_line,base.group_user,1,1,1,1
|
||||
access_cleanup_create_indexes_wizard,access_cleanup_create_indexes_wizard,model_cleanup_create_indexes_wizard,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_module,access_cleanup_purge_line_module,model_cleanup_purge_line_module,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_module,access_cleanup_purge_wizard_module,model_cleanup_purge_wizard_module,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_model,access_cleanup_purge_line_model,model_cleanup_purge_line_model,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_model,access_cleanup_purge_wizard_model,model_cleanup_purge_wizard_model,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_column,access_cleanup_purge_line_column,model_cleanup_purge_line_column,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_column,access_cleanup_purge_wizard_column,model_cleanup_purge_wizard_column,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_table,access_cleanup_purge_line_table,model_cleanup_purge_line_table,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_table,access_cleanup_purge_wizard_table,model_cleanup_purge_wizard_table,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_data,access_cleanup_purge_line_data,model_cleanup_purge_line_data,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_data,access_cleanup_purge_wizard_data,model_cleanup_purge_wizard_data,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_menu,access_cleanup_purge_line_menu,model_cleanup_purge_line_menu,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_menu,access_cleanup_purge_wizard_menu,model_cleanup_purge_wizard_menu,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_line_property,access_cleanup_purge_line_property,model_cleanup_purge_line_property,base.group_user,1,1,1,1
|
||||
access_cleanup_purge_wizard_property,access_cleanup_purge_wizard_property,model_cleanup_purge_wizard_property,base.group_user,1,1,1,1
|
|
|
@ -1,3 +1,12 @@
|
|||
# Copyright 2016 Therp BV <http://therp.nl>
|
||||
# Copyright 2021 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from . import test_database_cleanup
|
||||
from . import common
|
||||
from . import test_create_indexes
|
||||
from . import test_purge_columns
|
||||
from . import test_purge_data
|
||||
from . import test_purge_menus
|
||||
from . import test_purge_models
|
||||
from . import test_purge_modules
|
||||
from . import test_purge_properties
|
||||
from . import test_purge_tables
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo.modules.registry import Registry
|
||||
from odoo.tests import TransactionCase
|
||||
from odoo.tests.common import tagged
|
||||
|
||||
|
||||
# Use post_install to get all models loaded more info: odoo/odoo#13458
|
||||
@tagged("post_install", "-at_install")
|
||||
class Common(TransactionCase):
|
||||
def setUp(self):
|
||||
super(Common, self).setUp()
|
||||
# this reloads our registry, and we don't want to run tests twice
|
||||
# we also need the original registry for further tests, so save a
|
||||
# reference to it
|
||||
self.original_registry = Registry.registries[self.env.cr.dbname]
|
||||
|
||||
def tearDown(self):
|
||||
super(Common, self).tearDown()
|
||||
# Force rollback to avoid unstable test database
|
||||
self.env.cr.rollback()
|
||||
# reset afterwards
|
||||
Registry.registries[self.env.cr.dbname] = self.original_registry
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCreateIndexesLine(Common):
|
||||
def setUp(self):
|
||||
super(TestCreateIndexesLine, self).setUp()
|
||||
# delete some index and check if our module recreated it
|
||||
self.env.cr.execute("drop index res_partner_name_index")
|
||||
|
||||
def test_deleted_index(self):
|
||||
wizard = self.env["cleanup.create_indexes.wizard"].create({})
|
||||
wizard.purge_all()
|
||||
self.env.cr.execute(
|
||||
"select indexname from pg_indexes where "
|
||||
"indexname='res_partner_name_index' and tablename='res_partner' "
|
||||
)
|
||||
self.assertEqual(self.env.cr.rowcount, 1)
|
|
@ -1,154 +0,0 @@
|
|||
# Copyright 2016 Therp BV <http://therp.nl>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from psycopg2 import ProgrammingError
|
||||
|
||||
from odoo.modules.registry import Registry
|
||||
from odoo.tests.common import TransactionCase, at_install, post_install
|
||||
from odoo.tools import config, mute_logger
|
||||
|
||||
|
||||
# Use post_install to get all models loaded more info: odoo/odoo#13458
|
||||
@at_install(False)
|
||||
@post_install(True)
|
||||
class TestDatabaseCleanup(TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestDatabaseCleanup, self).setUp()
|
||||
self.module = None
|
||||
self.model = None
|
||||
# Create one property for tests
|
||||
self.env["ir.property"].create(
|
||||
{
|
||||
"fields_id": self.env.ref("base.field_res_partner__name").id,
|
||||
"type": "char",
|
||||
"value_text": "My default partner name",
|
||||
}
|
||||
)
|
||||
|
||||
def test_database_cleanup(self):
|
||||
# delete some index and check if our module recreated it
|
||||
self.env.cr.execute("drop index res_partner_name_index")
|
||||
create_indexes = self.env["cleanup.create_indexes.wizard"].create({})
|
||||
create_indexes.purge_all()
|
||||
self.env.cr.execute(
|
||||
"select indexname from pg_indexes "
|
||||
"where indexname='res_partner_name_index' and "
|
||||
"tablename='res_partner'"
|
||||
)
|
||||
self.assertEqual(self.env.cr.rowcount, 1)
|
||||
# duplicate a property
|
||||
duplicate_property = self.env["ir.property"].search([], limit=1).copy()
|
||||
purge_property = self.env["cleanup.purge.wizard.property"].create({})
|
||||
purge_property.purge_all()
|
||||
self.assertFalse(duplicate_property.exists())
|
||||
# create an orphaned column
|
||||
self.env.cr.execute(
|
||||
"alter table res_partner add column database_cleanup_test int"
|
||||
)
|
||||
# We need use a model that is not blocked (Avoid use res.users)
|
||||
partner_model = self.env["ir.model"].search(
|
||||
[("model", "=", "res.partner")], limit=1
|
||||
)
|
||||
purge_columns = self.env["cleanup.purge.wizard.column"].create(
|
||||
{
|
||||
"purge_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{"model_id": partner_model.id, "name": "database_cleanup_test"},
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
purge_columns.purge_all()
|
||||
# must be removed by the wizard
|
||||
with self.assertRaises(ProgrammingError):
|
||||
with self.env.registry.cursor() as cr:
|
||||
with mute_logger("odoo.sql_db"):
|
||||
cr.execute("select database_cleanup_test from res_partner")
|
||||
|
||||
# create a data entry pointing nowhere
|
||||
self.env.cr.execute("select max(id) + 1 from res_users")
|
||||
self.env["ir.model.data"].create(
|
||||
{
|
||||
"module": "database_cleanup",
|
||||
"name": "test_no_data_entry",
|
||||
"model": "res.users",
|
||||
"res_id": self.env.cr.fetchone()[0],
|
||||
}
|
||||
)
|
||||
purge_data = self.env["cleanup.purge.wizard.data"].create({})
|
||||
purge_data.purge_all()
|
||||
# must be removed by the wizard
|
||||
with self.assertRaises(ValueError):
|
||||
self.env.ref("database_cleanup.test_no_data_entry")
|
||||
|
||||
# create a nonexistent model
|
||||
self.model = self.env["ir.model"].create(
|
||||
{
|
||||
"name": "Database cleanup test model",
|
||||
"model": "x_database.cleanup.test.model",
|
||||
}
|
||||
)
|
||||
self.env.cr.execute(
|
||||
"insert into ir_attachment (name, res_model, res_id, type) values "
|
||||
"('test attachment', 'database.cleanup.test.model', 42, 'binary')"
|
||||
)
|
||||
self.env.registry.models.pop("x_database.cleanup.test.model")
|
||||
purge_models = self.env["cleanup.purge.wizard.model"].create({})
|
||||
purge_models.purge_all()
|
||||
# must be removed by the wizard
|
||||
self.assertFalse(
|
||||
self.env["ir.model"].search(
|
||||
[
|
||||
("model", "=", "x_database.cleanup.test.model"),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# create a nonexistent module
|
||||
self.module = self.env["ir.module.module"].create(
|
||||
{
|
||||
"name": "database_cleanup_test",
|
||||
"state": "to upgrade",
|
||||
}
|
||||
)
|
||||
purge_modules = self.env["cleanup.purge.wizard.module"].create({})
|
||||
# this reloads our registry, and we don't want to run tests twice
|
||||
# we also need the original registry for further tests, so save a
|
||||
# reference to it
|
||||
original_registry = Registry.registries[self.env.cr.dbname]
|
||||
config.options["test_enable"] = False
|
||||
purge_modules.purge_all()
|
||||
config.options["test_enable"] = True
|
||||
# must be removed by the wizard
|
||||
self.assertFalse(
|
||||
self.env["ir.module.module"].search(
|
||||
[
|
||||
("name", "=", "database_cleanup_test"),
|
||||
]
|
||||
)
|
||||
)
|
||||
# reset afterwards
|
||||
Registry.registries[self.env.cr.dbname] = original_registry
|
||||
|
||||
# create an orphaned table
|
||||
self.env.cr.execute("create table database_cleanup_test (test int)")
|
||||
purge_tables = self.env["cleanup.purge.wizard.table"].create({})
|
||||
purge_tables.purge_all()
|
||||
with self.assertRaises(ProgrammingError):
|
||||
with self.env.registry.cursor() as cr:
|
||||
with mute_logger("odoo.sql_db"):
|
||||
cr.execute("select * from database_cleanup_test")
|
||||
|
||||
def tearDown(self):
|
||||
super(TestDatabaseCleanup, self).tearDown()
|
||||
with self.registry.cursor() as cr2:
|
||||
# Release blocked tables with pending deletes
|
||||
self.env.cr.rollback()
|
||||
if self.module:
|
||||
cr2.execute(
|
||||
"DELETE FROM ir_module_module WHERE id=%s", (self.module.id,)
|
||||
)
|
||||
if self.model:
|
||||
cr2.execute("DELETE FROM ir_model WHERE id=%s", (self.model.id,))
|
||||
cr2.commit()
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from psycopg2 import ProgrammingError
|
||||
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineColumn(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineColumn, self).setUp()
|
||||
# create an orphaned column
|
||||
self.env.cr.execute(
|
||||
"alter table res_partner add column database_cleanup_test int"
|
||||
)
|
||||
|
||||
def test_empty_column(self):
|
||||
# We need use a model that is not blocked (Avoid use res.users)
|
||||
partner_model = self.env["ir.model"].search(
|
||||
[("model", "=", "res.partner")], limit=1
|
||||
)
|
||||
wizard = self.env["cleanup.purge.wizard.column"].create(
|
||||
{
|
||||
"purge_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{"model_id": partner_model.id, "name": "database_cleanup_test"},
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
wizard.purge_all()
|
||||
# must be removed by the wizard
|
||||
with self.assertRaises(ProgrammingError):
|
||||
with self.env.registry.cursor() as cr:
|
||||
with mute_logger("odoo.sql_db"):
|
||||
cr.execute("select database_cleanup_test from res_partner")
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineData(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineData, self).setUp()
|
||||
# create a data entry pointing nowhere
|
||||
self.env.cr.execute("select max(id) + 1 from res_users")
|
||||
self.env["ir.model.data"].create(
|
||||
{
|
||||
"module": "database_cleanup",
|
||||
"name": "test_no_data_entry",
|
||||
"model": "res.users",
|
||||
"res_id": self.env.cr.fetchone()[0],
|
||||
}
|
||||
)
|
||||
|
||||
def test_pointing_nowhere(self):
|
||||
wizard = self.env["cleanup.purge.wizard.data"].create({})
|
||||
wizard.purge_all()
|
||||
# must be removed by the wizard
|
||||
with self.assertRaises(ValueError):
|
||||
self.env.ref("database_cleanup.test_no_data_entry")
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineMenu(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineMenu, self).setUp()
|
||||
# create a new empty menu
|
||||
self.menu = self.env["ir.ui.menu"].create({"name": "database_cleanup_test"})
|
||||
|
||||
def test_empty_menu(self):
|
||||
wizard = self.env["cleanup.purge.wizard.menu"].create(
|
||||
{
|
||||
"purge_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"menu_id": self.menu.id,
|
||||
},
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
wizard.purge_all()
|
||||
self.assertFalse(
|
||||
self.env["ir.ui.menu"].search(
|
||||
[
|
||||
("name", "=", "database_cleanup_test"),
|
||||
]
|
||||
)
|
||||
)
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineColumn(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineColumn, self).setUp()
|
||||
# create a nonexistent model
|
||||
self.model_name = "x_database.cleanup.test.model"
|
||||
self.model_values = {
|
||||
"name": "Database cleanup test model",
|
||||
"model": self.model_name,
|
||||
}
|
||||
self.model = self.env["ir.model"].create(self.model_values)
|
||||
self.env.cr.execute(
|
||||
"insert into ir_attachment (name, res_model, res_id, type) values "
|
||||
"('test attachment', %s, 42, 'binary')",
|
||||
[self.model_name],
|
||||
)
|
||||
self.env.registry.models.pop(self.model_name)
|
||||
|
||||
def tearDown(self):
|
||||
""" We recreate the model to avoid registry Exception at loading """
|
||||
super(TestCleanupPurgeLineColumn, self).tearDown()
|
||||
# FIXME: issue origin is not clear but it must be addressed.
|
||||
self.model = self.env["ir.model"].create(self.model_values)
|
||||
|
||||
def test_empty_model(self):
|
||||
wizard = self.env["cleanup.purge.wizard.model"].create({})
|
||||
wizard.purge_all()
|
||||
# must be removed by the wizard
|
||||
self.assertFalse(
|
||||
self.env["ir.model"].search(
|
||||
[
|
||||
("model", "=", self.model_name),
|
||||
]
|
||||
)
|
||||
)
|
|
@ -0,0 +1,35 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
import threading
|
||||
|
||||
from odoo.tools import config
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineModule(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineModule, self).setUp()
|
||||
# create a nonexistent module
|
||||
self.module = self.env["ir.module.module"].create(
|
||||
{
|
||||
"name": "database_cleanup_test",
|
||||
"state": "to upgrade",
|
||||
}
|
||||
)
|
||||
|
||||
def test_remove_to_upgrade_module(self):
|
||||
wizard = self.env["cleanup.purge.wizard.module"].create({})
|
||||
config.options["test_enable"] = False # Maybe useless now ?!
|
||||
self.patch(threading.currentThread(), "testing", False)
|
||||
wizard.purge_all()
|
||||
config.options["test_enable"] = True # Maybe useless now ?!
|
||||
self.patch(threading.currentThread(), "testing", True)
|
||||
# must be removed by the wizard
|
||||
self.assertFalse(
|
||||
self.env["ir.module.module"].search(
|
||||
[
|
||||
("name", "=", "database_cleanup_test"),
|
||||
]
|
||||
)
|
||||
)
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineProperty(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineProperty, self).setUp()
|
||||
# Create one property for tests
|
||||
self.partner_name_field_id = self.env["ir.model.fields"].search(
|
||||
[("name", "=", "name"), ("model_id.model", "=", "res.partner")], limit=1
|
||||
)
|
||||
|
||||
def test_property_to_not_removed(self):
|
||||
self.property = self.env["ir.property"].create(
|
||||
{
|
||||
"fields_id": self.partner_name_field_id.id,
|
||||
"type": "char",
|
||||
"value_text": "My default partner name",
|
||||
"res_id": False,
|
||||
}
|
||||
)
|
||||
wizard = self.env["cleanup.purge.wizard.property"].create({})
|
||||
wizard.purge_all()
|
||||
self.assertTrue(self.property.exists())
|
||||
|
||||
def test_property_no_value(self):
|
||||
self.property = self.env["ir.property"].create(
|
||||
{
|
||||
"fields_id": self.partner_name_field_id.id,
|
||||
"type": "char",
|
||||
"value_text": False,
|
||||
"res_id": False,
|
||||
}
|
||||
)
|
||||
wizard = self.env["cleanup.purge.wizard.property"].create({})
|
||||
wizard.purge_all()
|
||||
self.assertFalse(self.property.exists())
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright 2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from psycopg2 import ProgrammingError
|
||||
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
from .common import Common
|
||||
|
||||
|
||||
class TestCleanupPurgeLineTable(Common):
|
||||
def setUp(self):
|
||||
super(TestCleanupPurgeLineTable, self).setUp()
|
||||
# create an orphaned table
|
||||
self.env.cr.execute("create table database_cleanup_test (test int)")
|
||||
|
||||
def test_empty_table(self):
|
||||
wizard = self.env["cleanup.purge.wizard.table"].create({})
|
||||
wizard.purge_all()
|
||||
with self.assertRaises(ProgrammingError):
|
||||
with self.env.registry.cursor() as cr:
|
||||
with mute_logger("odoo.sql_db"):
|
||||
cr.execute("select * from database_cleanup_test")
|
|
@ -15,7 +15,7 @@
|
|||
<field name="state">code</field>
|
||||
<field name="model_id" ref="database_cleanup.model_cleanup_purge_wizard_menu" />
|
||||
<field name="code">
|
||||
action = env.get('cleanup.purge.wizard.menu').get_wizard_action()
|
||||
action = env.get('cleanup.purge.wizard').get_wizard_action()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
Loading…
Reference in New Issue