credativ team mailing list archive
-
credativ team
-
Mailing list archive
-
Message #05742
[Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
Stefan Rijnhart (Therp) has proposed merging lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools.
Requested reviews:
OpenUpgrade Committers (openupgrade-committers)
For more details, see:
https://code.launchpad.net/~therp-nl/openupgrade-tools/7.0-add-database_cleanup/+merge/203633
Partial implementation of https://blueprints.launchpad.net/openupgrade-server/+spec/service-module-feature.
This proposal adds a module to clean up after a homebrew migration process such as OpenUpgrade.
--
https://code.launchpad.net/~therp-nl/openupgrade-tools/7.0-add-database_cleanup/+merge/203633
Your team OpenUpgrade Committers is requested to review the proposed merge of lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools.
=== added directory 'database_cleanup'
=== added file 'database_cleanup/__init__.py'
--- database_cleanup/__init__.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/__init__.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,1 @@
+from . import model
=== added file 'database_cleanup/__openerp__.py'
--- database_cleanup/__openerp__.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/__openerp__.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Database cleanup',
+ 'version': '0.1',
+ 'author': 'Therp BV',
+ 'depends': ['base'],
+ 'license': 'AGPL-3',
+ 'category': 'Tools',
+ 'data': [
+ 'view/purge_modules.xml',
+ 'view/purge_models.xml',
+ 'view/purge_columns.xml',
+ 'view/purge_tables.xml',
+ 'view/menu.xml',
+ ],
+ 'description': """\
+Clean your OpenERP 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 OpenERP.
+
+After installation of this module, go to the Settings menu -> Technical ->
+Database cleanup. 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).
+
+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 OpenERP 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.
+""",
+
+}
=== added directory 'database_cleanup/model'
=== added file 'database_cleanup/model/__init__.py'
--- database_cleanup/model/__init__.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/__init__.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,5 @@
+from . import purge_wizard
+from . import purge_modules
+from . import purge_models
+from . import purge_columns
+from . import purge_tables
=== added file 'database_cleanup/model/purge_columns.py'
--- database_cleanup/model/purge_columns.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/purge_columns.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+
+class CleanupPurgeLineColumn(orm.TransientModel):
+ _inherit = 'cleanup.purge.line'
+ _name = 'cleanup.purge.line.column'
+
+ _columns = {
+ 'model_id': fields.many2one(
+ 'ir.model', 'Model',
+ required=True, ondelete='CASCADE'),
+ 'wizard_id': fields.many2one(
+ 'cleanup.purge.wizard.column', 'Purge Wizard', readonly=True),
+ }
+
+ def purge(self, cr, uid, ids, context=None):
+ """
+ Unlink columns upon manual confirmation.
+ """
+ for line in self.browse(cr, uid, ids, context=context):
+ if line.purged:
+ continue
+
+ model_pool = self.pool[line.model_id.model]
+
+ # Check whether the column actually still exists.
+ # Inheritance such as stock.picking.in from stock.picking
+ # can lead to double attempts at removal
+ cr.execute(
+ 'SELECT count(attname) FROM pg_attribute '
+ 'WHERE attrelid = '
+ '( SELECT oid FROM pg_class WHERE relname = %s ) '
+ 'AND attname = %s',
+ (model_pool._table, line.name));
+ if not cr.fetchone()[0]:
+ continue
+
+ self.logger.info(
+ 'Dropping column %s from table %s',
+ line.name, model_pool._table)
+ cr.execute(
+ """
+ ALTER TABLE "%s" DROP COLUMN "%s"
+ """ % (model_pool._table, line.name))
+ line.write({'purged': True})
+ cr.commit()
+ return True
+
+class CleanupPurgeWizardColumn(orm.TransientModel):
+ _inherit = 'cleanup.purge.wizard'
+ _name = 'cleanup.purge.wizard.column'
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(CleanupPurgeWizardColumn, self).default_get(
+ cr, uid, fields, context=context)
+ if 'name' in fields:
+ res['name'] = _('Purge columns')
+ return res
+
+ def get_orphaned_columns(self, cr, uid, model_pool, context=None):
+ """
+ From openobject-server/openerp/osv/orm.py
+ Iterate on the database columns to identify columns
+ of fields which have been removed
+ """
+ columns = [
+ c for c in model_pool._columns
+ if not (isinstance(model_pool._columns[c], fields.function)
+ and not model_pool._columns[c].store)]
+ columns += orm.MAGIC_COLUMNS
+ cr.execute("SELECT a.attname"
+ " FROM pg_class c, pg_attribute a"
+ " WHERE c.relname=%s"
+ " AND c.oid=a.attrelid"
+ " AND a.attisdropped=%s"
+ " AND pg_catalog.format_type(a.atttypid, a.atttypmod)"
+ " NOT IN ('cid', 'tid', 'oid', 'xid')"
+ " AND a.attname NOT IN %s",
+ (model_pool._table, False, tuple(columns))),
+ return [column[0] for column in cr.fetchall()]
+
+ def find(self, cr, uid, context=None):
+ """
+ Search for columns that cannot be instanciated.
+ """
+ res = []
+ model_pool = self.pool['ir.model']
+ model_ids = model_pool.search(cr, uid, [], context=context)
+ line_pool = self.pool['cleanup.purge.line.column']
+ for model in model_pool.browse(cr, uid, model_ids, context=context):
+ model_pool = self.pool.get(model.model)
+ if not model_pool or not model_pool._auto:
+ continue
+ for column in self.get_orphaned_columns(
+ cr, uid, model_pool, context=context):
+ res.append((0, 0, {
+ 'name': column,
+ 'model_id': model.id}))
+ if not res:
+ raise orm.except_orm(
+ _('Nothing to do'),
+ _('No orphaned columns found'))
+ return res
+
+ _columns = {
+ 'purge_line_ids': fields.one2many(
+ 'cleanup.purge.line.column',
+ 'wizard_id', 'Columns to purge'),
+ }
=== added file 'database_cleanup/model/purge_models.py'
--- database_cleanup/model/purge_models.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/purge_models.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+import logging
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+from openerp.addons.base.ir.ir_model import MODULE_UNINSTALL_FLAG
+
+
+class IrModel(orm.Model):
+ _inherit = 'ir.model'
+
+ def _drop_table(self, cr, uid, ids, context=None):
+ # Allow to skip this step during model unlink
+ # The super method crashes if the model cannot be instantiated
+ if context and context.get('no_drop_table'):
+ return True
+ return super(IrModel, self)._drop_table(cr, uid, ids, context=context)
+
+
+class CleanupPurgeLineModel(orm.TransientModel):
+ _inherit = 'cleanup.purge.line'
+ _name = 'cleanup.purge.line.model'
+
+ _columns = {
+ 'wizard_id': fields.many2one(
+ 'cleanup.purge.wizard.model', 'Purge Wizard', readonly=True),
+ }
+
+ def purge(self, cr, uid, ids, context=None):
+ """
+ Unlink models upon manual confirmation.
+ """
+ model_pool = self.pool['ir.model']
+ attachment_pool = self.pool['ir.attachment']
+ constraint_pool = self.pool['ir.model.constraint']
+
+ local_context=(context or {}).copy()
+ local_context.update({
+ MODULE_UNINSTALL_FLAG: True,
+ 'no_drop_table': True,
+ })
+
+ for line in self.browse(cr, uid, ids, context=context):
+ cr.execute(
+ "SELECT id, model from ir_model WHERE model = %s",
+ (line.name,))
+ row = cr.fetchone()
+ if row:
+ self.logger.info('Purging model %s', row[1])
+ attachment_ids = attachment_pool.search(
+ cr, uid, [('res_model', '=', line.name)], context=context)
+ if attachment_ids:
+ attachment_pool.write(
+ cr, uid, attachment_ids, {'res_model': False},
+ context=context)
+ constraint_ids = constraint_pool.search(
+ cr, uid, [('model', '=', line.name)], context=context)
+ if constraint_ids:
+ constraint_pool.unlink(
+ cr, uid, constraint_ids, context=context)
+ model_pool.unlink(cr, uid, [row[0]], context=local_context)
+ line.write({'purged': True})
+ cr.commit()
+ return True
+
+
+class CleanupPurgeWizardModel(orm.TransientModel):
+ _inherit = 'cleanup.purge.wizard'
+ _name = 'cleanup.purge.wizard.model'
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(CleanupPurgeWizardModel, self).default_get(
+ cr, uid, fields, context=context)
+ if 'name' in fields:
+ res['name'] = _('Purge models')
+ return res
+
+ def find(self, cr, uid, context=None):
+ """
+ Search for models that cannot be instanciated.
+ """
+ res = []
+ cr.execute("SELECT model from ir_model")
+ for (model,) in cr.fetchall():
+ if not self.pool.get(model):
+ res.append((0, 0, {'name': model}))
+ if not res:
+ raise orm.except_orm(
+ _('Nothing to do'),
+ _('No orphaned models found'))
+ return res
+
+ _columns = {
+ 'purge_line_ids': fields.one2many(
+ 'cleanup.purge.line.model',
+ 'wizard_id', 'Models to purge'),
+ }
=== added file 'database_cleanup/model/purge_modules.py'
--- database_cleanup/model/purge_modules.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/purge_modules.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp import pooler
+from openerp.osv import orm, fields
+from openerp.modules.module import get_module_path
+from openerp.tools.translate import _
+
+
+class CleanupPurgeLineModule(orm.TransientModel):
+ _inherit = 'cleanup.purge.line'
+ _name = 'cleanup.purge.line.module'
+
+ _columns = {
+ 'wizard_id': fields.many2one(
+ 'cleanup.purge.wizard.module', 'Purge Wizard', readonly=True),
+ }
+
+ def purge(self, cr, uid, ids, context=None):
+ """
+ Uninstall modules upon manual confirmation, then reload
+ the database.
+ """
+ module_pool = self.pool['ir.module.module']
+ lines = self.browse(cr, uid, ids, context=context)
+ module_names = [line.name for line in lines if not line.purged]
+ module_ids = module_pool.search(
+ cr, uid, [('name', 'in', module_names)], context=context)
+ if not module_ids:
+ return True
+ self.logger.info('Purging modules %s', ', '.join(module_names))
+ module_pool.write(
+ cr, uid, module_ids, {'state': 'to remove'}, context=context)
+ cr.commit()
+ _db, _pool = pooler.restart_pool(cr.dbname, update_module=True)
+ module_pool.unlink(cr, uid, module_ids, context=context)
+ return self.write(cr, uid, ids, {'purged': True}, context=context)
+
+
+class CleanupPurgeWizardModule(orm.TransientModel):
+ _inherit = 'cleanup.purge.wizard'
+ _name = 'cleanup.purge.wizard.module'
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(CleanupPurgeWizardModule, self).default_get(
+ cr, uid, fields, context=context)
+ if 'name' in fields:
+ res['name'] = _('Purge modules')
+ return res
+
+ def find(self, cr, uid, context=None):
+ module_pool = self.pool['ir.module.module']
+ module_ids = module_pool.search(cr, uid, [], context=context)
+ res = []
+ for module in module_pool.browse(cr, uid, module_ids, context=context):
+ if get_module_path(module.name):
+ continue
+ if module.state == 'uninstalled':
+ module_pool.unlink(cr, uid, module.id, context=context)
+ continue
+ res.append((0, 0, {'name': module.name}))
+
+ if not res:
+ raise orm.except_orm(
+ _('Nothing to do'),
+ _('No modules found to purge'))
+ return res
+
+ _columns = {
+ 'purge_line_ids': fields.one2many(
+ 'cleanup.purge.line.module',
+ 'wizard_id', 'Modules to purge'),
+ }
=== added file 'database_cleanup/model/purge_tables.py'
--- database_cleanup/model/purge_tables.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/purge_tables.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+
+class CleanupPurgeLineTable(orm.TransientModel):
+ _inherit = 'cleanup.purge.line'
+ _name = 'cleanup.purge.line.table'
+
+ _columns = {
+ 'wizard_id': fields.many2one(
+ 'cleanup.purge.wizard.table', 'Purge Wizard', readonly=True),
+ }
+
+ def purge(self, cr, uid, ids, context=None):
+ """
+ Unlink tables upon manual confirmation.
+ """
+ lines = self.browse(cr, uid, ids, context=context)
+ tables = [line.name for line in lines]
+ for line in lines:
+ if line.purged:
+ continue
+
+ # Retrieve constraints on the tables to be dropped
+ # This query is referenced in numerous places
+ # on the Internet but credits probably go to Tom Lane
+ # in this post http://www.postgresql.org/\
+ # message-id/22895.1226088573@xxxxxxxxxxxxx
+ # Only using the constraint name and the source table,
+ # but I'm leaving the rest in for easier debugging
+ cr.execute(
+ """
+ SELECT conname, confrelid::regclass, af.attname AS fcol,
+ conrelid::regclass, a.attname AS col
+ FROM pg_attribute af, pg_attribute a,
+ (SELECT conname, conrelid, confrelid,conkey[i] AS conkey,
+ confkey[i] AS confkey
+ FROM (select conname, conrelid, confrelid, conkey, confkey,
+ generate_series(1,array_upper(conkey,1)) AS i
+ FROM pg_constraint WHERE contype = 'f') ss) ss2
+ WHERE af.attnum = confkey AND af.attrelid = confrelid AND
+ a.attnum = conkey AND a.attrelid = conrelid
+ AND confrelid::regclass = '%s'::regclass;
+ """ % line.name)
+
+ for constraint in cr.fetchall():
+ if constraint[3] in tables:
+ self.logger.info(
+ 'Dropping constraint %s on table %s (to be dropped)',
+ constraint[0], constraint[3])
+ cr.execute(
+ "ALTER TABLE %s DROP CONSTRAINT %s" % (
+ constraint[3], constraint[0]))
+
+ self.logger.info(
+ 'Dropping table %s', line.name)
+ cr.execute("DROP TABLE \"%s\"" % (line.name,))
+ line.write({'purged': True})
+ cr.commit()
+ return True
+
+class CleanupPurgeWizardTable(orm.TransientModel):
+ _inherit = 'cleanup.purge.wizard'
+ _name = 'cleanup.purge.wizard.table'
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(CleanupPurgeWizardTable, self).default_get(
+ cr, uid, fields, context=context)
+ if 'name' in fields:
+ res['name'] = _('Purge modules')
+ return res
+
+ def find(self, cr, uid, context=None):
+ """
+ Search for tables that cannot be instantiated.
+ Ignore views for now.
+ """
+ model_ids = self.pool['ir.model'].search(cr, uid, [], context=context)
+ line_pool = self.pool['cleanup.purge.line.table']
+ known_tables = []
+ for model in self.pool['ir.model'].browse(
+ cr, uid, model_ids, context=context):
+
+ model_pool = self.pool.get(model.model)
+ if not model_pool:
+ continue
+ known_tables.append(model_pool._table)
+ known_tables += [
+ column._sql_names(model_pool)[0]
+ for column in model_pool._columns.values()
+ if column._type == 'many2many'
+ # unstored function fields of type m2m don't have _rel
+ and hasattr(column, '_rel')
+ ]
+
+ # Cannot pass table names as a psycopg argument
+ known_tables_repr = ",".join(
+ [("'%s'" % table) for table in known_tables])
+ cr.execute(
+ """
+ SELECT table_name FROM information_schema.tables
+ WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
+ AND table_name NOT IN (%s)""" % known_tables_repr)
+
+ res = [(0, 0, {'name': row[0]}) for row in cr.fetchall()]
+ if not res:
+ raise orm.except_orm(
+ _('Nothing to do'),
+ _('No orphaned tables found'))
+ return res
+
+ _columns = {
+ 'purge_line_ids': fields.one2many(
+ 'cleanup.purge.line.table',
+ 'wizard_id', 'Tables to purge'),
+ }
=== added file 'database_cleanup/model/purge_wizard.py'
--- database_cleanup/model/purge_wizard.py 1970-01-01 00:00:00 +0000
+++ database_cleanup/model/purge_wizard.py 2014-01-28 21:13:47 +0000
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2014 Therp BV (<http://therp.nl>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import logging
+from openerp.osv import orm, fields
+
+
+class CleanupPurgeLine(orm.AbstractModel):
+ """ Abstract base class for the purge wizard lines """
+ _name = 'cleanup.purge.line'
+ _columns = {
+ 'name': fields.char('Name', size=256, readonly=True),
+ 'purged': fields.boolean('Purged', readonly=True),
+ }
+
+ logger = logging.getLogger('openerp.addons.database_cleanup')
+
+ def purge(self, cr, uid, ids, context=None):
+ raise NotImplementedError
+
+class PurgeWizard(orm.AbstractModel):
+ """ Abstract base class for the purge wizards """
+ _name = 'cleanup.purge.wizard'
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(PurgeWizard, self).default_get(
+ cr, uid, fields, context=context)
+ if 'purge_line_ids' in fields:
+ res['purge_line_ids'] = self.find(cr, uid, context=None)
+ return res
+
+ def find(self, cr, uid, ids, context=None):
+ raise NotImplementedError
+
+ def purge_all(self, cr, uid, ids, context=None):
+ line_pool = self.pool[self._columns['purge_line_ids']._obj]
+ for wizard in self.browse(cr, uid, ids, context=context):
+ line_pool.purge(
+ cr, uid, [line.id for line in wizard.purge_line_ids],
+ context=context)
+ return True
+
+ _columns = {
+ 'name': fields.char('Name', size=64, readonly=True),
+ }
=== added directory 'database_cleanup/static'
=== added directory 'database_cleanup/static/src'
=== added directory 'database_cleanup/static/src/img'
=== added file 'database_cleanup/static/src/img/icon.png'
Binary files database_cleanup/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and database_cleanup/static/src/img/icon.png 2014-01-28 21:13:47 +0000 differ
=== added directory 'database_cleanup/view'
=== added file 'database_cleanup/view/menu.xml'
--- database_cleanup/view/menu.xml 1970-01-01 00:00:00 +0000
+++ database_cleanup/view/menu.xml 2014-01-28 21:13:47 +0000
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record model="ir.ui.menu" id="menu_database_cleanup">
+ <field name="name">Database cleanup</field>
+ <field name="sequence" eval="10" />
+ <!-- attach to Settings -> Technical -->
+ <field name="parent_id" ref="base.menu_custom"/>
+ </record>
+
+ <record model="ir.ui.menu" id="menu_purge_modules">
+ <field name="name">Purge obsolete modules</field>
+ <field name="sequence" eval="10" />
+ <field name="action" ref="action_purge_modules" />
+ <field name="parent_id" ref="menu_database_cleanup"/>
+ </record>
+
+ <record model="ir.ui.menu" id="menu_purge_models">
+ <field name="name">Purge obsolete models</field>
+ <field name="sequence" eval="20" />
+ <field name="action" ref="action_purge_models" />
+ <field name="parent_id" ref="menu_database_cleanup"/>
+ </record>
+
+ <record model="ir.ui.menu" id="menu_purge_columns">
+ <field name="name">Purge obsolete columns</field>
+ <field name="sequence" eval="30" />
+ <field name="action" ref="action_purge_columns" />
+ <field name="parent_id" ref="menu_database_cleanup"/>
+ </record>
+
+ <record model="ir.ui.menu" id="menu_purge_tables">
+ <field name="name">Purge obsolete tables</field>
+ <field name="sequence" eval="30" />
+ <field name="action" ref="action_purge_tables" />
+ <field name="parent_id" ref="menu_database_cleanup"/>
+ </record>
+
+ </data>
+</openerp>
=== added file 'database_cleanup/view/purge_columns.xml'
--- database_cleanup/view/purge_columns.xml 1970-01-01 00:00:00 +0000
+++ database_cleanup/view/purge_columns.xml 2014-01-28 21:13:47 +0000
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="purge_columns_view" model="ir.ui.view">
+ <field name="name">Form view for purge columns wizard</field>
+ <field name="model">cleanup.purge.wizard.column</field>
+ <field name="arch" type="xml">
+ <form string="Purge columns" version="7.0">
+ <h1>
+ <field name="name"/>
+ </h1>
+ <button type="object" name="purge_all" string="Purge all columns" />
+ <field name="purge_line_ids" colspan="4" nolabel="1">
+ <tree string="Purge columns">
+ <field name="name" />
+ <field name="model_id" />
+ <field name="purged" invisible="0" />
+ <button type="object" name="purge"
+ icon="gtk-cancel" string="Purge this column"
+ attrs="{'invisible': [('purged', '=', True)]}"/>
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_purge_columns" model="ir.actions.act_window">
+ <field name="name">Purge columns</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">cleanup.purge.wizard.column</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'database_cleanup/view/purge_models.xml'
--- database_cleanup/view/purge_models.xml 1970-01-01 00:00:00 +0000
+++ database_cleanup/view/purge_models.xml 2014-01-28 21:13:47 +0000
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="purge_models_view" model="ir.ui.view">
+ <field name="name">Form view for purge models wizard</field>
+ <field name="model">cleanup.purge.wizard.model</field>
+ <field name="arch" type="xml">
+ <form string="Purge models" version="7.0">
+ <h1>
+ <field name="name"/>
+ </h1>
+ <button type="object" name="purge_all" string="Purge all models" />
+ <field name="purge_line_ids" colspan="4" nolabel="1">
+ <tree string="Purge models">
+ <field name="name" />
+ <field name="purged" invisible="0" />
+ <button type="object" name="purge"
+ icon="gtk-cancel" string="Purge this model"
+ attrs="{'invisible': [('purged', '=', True)]}"/>
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_purge_models" model="ir.actions.act_window">
+ <field name="name">Purge models</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">cleanup.purge.wizard.model</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'database_cleanup/view/purge_modules.xml'
--- database_cleanup/view/purge_modules.xml 1970-01-01 00:00:00 +0000
+++ database_cleanup/view/purge_modules.xml 2014-01-28 21:13:47 +0000
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="purge_modules_view" model="ir.ui.view">
+ <field name="name">Form view for purge modules wizard</field>
+ <field name="model">cleanup.purge.wizard.module</field>
+ <field name="arch" type="xml">
+ <form string="Purge modules" version="7.0">
+ <h1>
+ <field name="name"/>
+ </h1>
+ <button type="object" name="purge_all" string="Purge all modules" />
+ <field name="purge_line_ids" colspan="4" nolabel="1">
+ <tree string="Purge modules">
+ <field name="name" />
+ <field name="purged" invisible="0" />
+ <button type="object" name="purge"
+ icon="gtk-cancel" string="Purge this module"
+ attrs="{'invisible': [('purged', '=', True)]}"/>
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_purge_modules" model="ir.actions.act_window">
+ <field name="name">Purge modules</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">cleanup.purge.wizard.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'database_cleanup/view/purge_tables.xml'
--- database_cleanup/view/purge_tables.xml 1970-01-01 00:00:00 +0000
+++ database_cleanup/view/purge_tables.xml 2014-01-28 21:13:47 +0000
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="purge_tables_view" model="ir.ui.view">
+ <field name="name">Form view for purge tables wizard</field>
+ <field name="model">cleanup.purge.wizard.table</field>
+ <field name="arch" type="xml">
+ <form string="Purge tables" version="7.0">
+ <h1>
+ <field name="name"/>
+ </h1>
+ <button type="object" name="purge_all" string="Purge all tables" />
+ <field name="purge_line_ids" colspan="4" nolabel="1">
+ <tree string="Purge tables">
+ <field name="name" />
+ <field name="purged" invisible="0" />
+ <button type="object" name="purge"
+ icon="gtk-cancel" string="Purge this table"
+ attrs="{'invisible': [('purged', '=', True)]}"/>
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_purge_tables" model="ir.actions.act_window">
+ <field name="name">Purge tables</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">cleanup.purge.wizard.table</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ </record>
+
+ </data>
+</openerp>
Follow ups
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-12-18
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Acsone, 2014-12-12
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Acsone, 2014-12-10
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Pedro Manuel Baeza, 2014-12-08
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-12-08
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Acsone, 2014-12-06
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Pedro Manuel Baeza, 2014-03-30
-
[Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-03-28
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-03-28
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Pedro Manuel Baeza, 2014-03-28
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-02-20
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-02-12
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-02-10
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-02-08
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Guewen Baconnier @ Camptocamp, 2014-02-06
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Stefan Rijnhart (Therp), 2014-02-05
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Guewen Baconnier @ Camptocamp, 2014-02-03
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Guewen Baconnier @ Camptocamp, 2014-01-30
-
Re: [Merge] lp:~therp-nl/openupgrade-tools/7.0-add-database_cleanup into lp:openupgrade-tools
From: Guewen Baconnier @ Camptocamp, 2014-01-30