mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 09:32:07 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,136 @@
|
|||
# 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
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
from ..identifier_adapter import IdentifierAdapter
|
||||
|
||||
|
||||
class CleanupPurgeLineColumn(models.TransientModel):
|
||||
_inherit = "cleanup.purge.line"
|
||||
_name = "cleanup.purge.line.column"
|
||||
_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
|
||||
)
|
||||
|
||||
def purge(self):
|
||||
"""
|
||||
Unlink columns upon manual confirmation.
|
||||
"""
|
||||
if self:
|
||||
objs = self
|
||||
else:
|
||||
objs = self.env["cleanup.purge.line.column"].browse(
|
||||
self._context.get("active_ids")
|
||||
)
|
||||
for line in objs:
|
||||
if line.purged:
|
||||
continue
|
||||
model_pool = self.env[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
|
||||
self.env.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 self.env.cr.fetchone()[0]:
|
||||
continue
|
||||
|
||||
self.logger.info(
|
||||
"Dropping column %s from table %s", line.name, model_pool._table
|
||||
)
|
||||
self.env.cr.execute(
|
||||
"ALTER TABLE %s DROP COLUMN %s",
|
||||
(IdentifierAdapter(model_pool._table), IdentifierAdapter(line.name)),
|
||||
)
|
||||
line.write({"purged": True})
|
||||
# we need this commit because the ORM will deadlock if
|
||||
# we still have a pending transaction
|
||||
self.env.cr.commit() # pylint: disable=invalid-commit
|
||||
return True
|
||||
|
||||
|
||||
class CleanupPurgeWizardColumn(models.TransientModel):
|
||||
_inherit = "cleanup.purge.wizard"
|
||||
_name = "cleanup.purge.wizard.column"
|
||||
_description = "Purge columns"
|
||||
|
||||
# List of known columns in use without corresponding fields
|
||||
# Format: {table: [fields]}
|
||||
blacklist = {
|
||||
"wkf_instance": ["uid"], # lp:1277899
|
||||
"res_users": ["password", "password_crypt", "totp_secret"],
|
||||
"res_partner": ["signup_token"],
|
||||
}
|
||||
|
||||
@api.model
|
||||
def get_orphaned_columns(self, model_pools):
|
||||
"""
|
||||
From openobject-server/openerp/osv/orm.py
|
||||
Iterate on the database columns to identify columns
|
||||
of fields which have been removed
|
||||
"""
|
||||
columns = list(
|
||||
{
|
||||
column.name
|
||||
for model_pool in model_pools
|
||||
for column in model_pool._fields.values()
|
||||
if not (column.compute is not None and not column.store)
|
||||
}
|
||||
)
|
||||
columns += models.MAGIC_COLUMNS
|
||||
columns += self.blacklist.get(model_pools[0]._table, [])
|
||||
|
||||
self.env.cr.execute(
|
||||
"SELECT a.attname FROM pg_class c, pg_attribute a "
|
||||
"WHERE c.relname=%s AND c.oid=a.attrelid AND a.attisdropped=False "
|
||||
"AND pg_catalog.format_type(a.atttypid, a.atttypmod) "
|
||||
"NOT IN ('cid', 'tid', 'oid', 'xid') "
|
||||
"AND a.attname NOT IN %s",
|
||||
(model_pools[0]._table, tuple(columns)),
|
||||
)
|
||||
return [column for column, in self.env.cr.fetchall()]
|
||||
|
||||
@api.model
|
||||
def find(self):
|
||||
"""
|
||||
Search for columns that are not in the corresponding model.
|
||||
|
||||
Group models by table to prevent false positives for columns
|
||||
that are only in some of the models sharing the same table.
|
||||
Example of this is 'sale_id' not being a field of stock.picking.in
|
||||
"""
|
||||
res = []
|
||||
|
||||
# mapping of tables to tuples (model id, [pool1, pool2, ...])
|
||||
table2model = {}
|
||||
|
||||
for model in self.env["ir.model"].search([]):
|
||||
if model.model not in self.env:
|
||||
continue
|
||||
model_pool = self.env[model.model]
|
||||
if not model_pool._auto:
|
||||
continue
|
||||
table2model.setdefault(model_pool._table, (model.id, []))[1].append(
|
||||
model_pool
|
||||
)
|
||||
|
||||
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:
|
||||
raise UserError(_("No orphaned columns found"))
|
||||
return res
|
||||
|
||||
purge_line_ids = fields.One2many(
|
||||
"cleanup.purge.line.column", "wizard_id", "Columns to purge"
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue