You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

256 lines
9.3 KiB

# -*- coding: utf-8 -*-
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from openerp import api, fields, models, _
from openerp.osv import fields as old_fields
from openerp.exceptions import UserError
class GDPRPartnerReport(models.TransientModel):
_name = "gdpr.partner.report"
_description = "GDPR Partner Report"
company_id = fields.Many2one(
comodel_name='res.company',
string='Company',
required=True,
default=lambda self: self.env.user.company_id,
)
partner_id = fields.Many2one(
comodel_name='res.partner',
string='Partner',
required=True,
)
table_ids = fields.Many2many(
comodel_name='gdpr.partner.data',
string='Models with related partner data',
)
@api.multi
@api.onchange('partner_id')
def _onchange_table_ids(self):
self.ensure_one()
for report in self:
if report.partner_id:
data = self._get_tables_from_partner(self.partner_id)
names = self._get_table_names(data)
tables = self.env['gdpr.partner.data']
for name in sorted(names):
vals = report._get_default_table(
name=name,
data=[t for t in data if t[0] == name and not t[5]],
)
if vals:
tables |= self.env['gdpr.partner.data'].create(vals)
report.table_ids = tables
else:
report.table_ids = self.env['gdpr.partner.data']
return {
'domain': {
'table_ids': [
('id', 'in', report.table_ids.ids)],
},
}
@api.onchange('company_id')
def _onchange_company_id(self):
if self.company_id:
return {
'domain': {
'partner_id': [
('company_id', 'in', [self.company_id.id, False])],
},
}
else:
return {
'domain': {
'partner_id': [('company_id', '=', False)],
},
}
@api.multi
def button_export_pdf(self):
self.ensure_one()
return self.check_report()
@api.multi
def button_export_xlsx(self):
self.ensure_one()
return self.check_report(xlsx_report=True)
def _build_contexts(self, data):
result = {}
result['partner_id'] = data['form']['partner_id'][0] or False
result['company_id'] = data['form']['company_id'][0] or False
result['table_ids'] = 'table_ids' in data['form'] and \
data['form']['table_ids'] or False
return result
def _clean_data(self, model, rows):
cleaned_rows = []
for i, row in enumerate(rows):
cleaned_rows.append({})
for key, value in row.items():
label = self.env[model]._fields[key].string or key
if 'many2' in self.env[model]._fields[key].type:
comodel = self.env[model]._fields[key].comodel_name
if value:
record = self.env[comodel].browse(value)
cleaned_rows[i][label] = str(record.display_name)
else:
cleaned_rows[i][label] = rows[i][key]
else:
cleaned_rows[i][label] = rows[i][key]
return cleaned_rows
@api.multi
def check_report(self, xlsx_report=False):
self.ensure_one()
data = {}
data['ids'] = self.env.context.get('active_ids', [])
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
data['form'] = self.read(['partner_id', 'company_id', 'table_ids'])[0]
used_context = self._build_contexts(data)
data['form']['used_context'] = dict(
used_context, lang=self.env.context.get('lang', 'en_US'))
return self._print_report(data=data, xlsx_report=xlsx_report)
@api.multi
def compute_data_for_report(self, data):
if not data.get('form'):
raise UserError(
_("Form content is missing, this report cannot be printed."))
partner = data['form'].get('partner_id', False)
if not partner:
raise UserError(
_("No provided partner."))
partner = self.env['res.partner'].browse(partner[0])
tables = data['form'].get('table_ids', False)
if tables:
tables = self.env['gdpr.partner.data'].browse(tables)
tables = self._get_rows_from_tables(tables, partner)
data.update({'tables': tables, })
return data
def _exclude_column(self, model, column):
# To remove in v10:
# (non-stored function fields should have _fnct_search)
column_info = self.env[model]._columns.get(column)
next_model = self.env[model]
while not column_info and column in next_model._inherit_fields:
next_model = self.env[next_model._inherit_fields[column][0]]
column_info = next_model._columns.get(column)
if isinstance(column_info, old_fields.function) \
and not column_info.store and not column_info._fnct_search:
return True
# https://github.com/odoo/odoo/issues/24927
if model in ('mail.compose.message', 'survey.mail.compose.message'):
if column in ('needaction_partner_ids', 'starred_partner_ids'):
return True
return False
def _get_default_table(self, name, data):
if data:
data_type = data[0][4]
res = self.env[data[0][1]]
for t in data:
res |= self.env[t[1]].browse(t[3])
if res:
values = {
'name': name,
'model_id': self.env['ir.model'].search(
[('model', '=', res._name)]).id,
'count_rows': len(res.ids),
'type': data_type,
}
return values
return {}
def _get_model_from_table(self, table, partner):
new_tables = {}
for model in table.model_id:
rows = self._get_rows_from_model(model, partner)
new_tables[str(model.display_name)] = rows
return new_tables
def _get_rows_from_model(self, model, partner):
cr = self.env.cr
lines = self.env[model.model]
columns = [k for k, v in self.env[model.model]._fields.items()
if v.comodel_name == 'res.partner' and
not self._exclude_column(model.model, k)]
for column in columns:
lines |= self.env[model.model].search([(column, '=', partner.id)])
line_ids = ', '.join([str(i) for i in lines.ids])
query = "SELECT * FROM %s WHERE id IN (%s)" % (
model.model.replace('.', '_'), line_ids)
cr.execute(query)
rows = cr.dictfetchall()
rows = self._clean_data(model.model, rows)
return rows
def _get_rows_from_tables(self, tables, partner):
new_tables = {}
for table in tables:
data_table = self._get_model_from_table(table, partner)
new_tables[str(table.name)] = data_table
return new_tables
def _get_table_names(self, data):
names = []
for t in data:
if t[3] and not t[5] and t[0] not in names:
names.append(t[0])
return names
def _get_tables_from_partner(self, partner):
tables = [t[0] for t in [
[[self.env[m]._table, m, k, self.env[m].sudo().search(
[(k, '=', partner.id)]).ids, v.type, self.env[m]._transient]
for k, v in self.env[m]._fields.items()
if v.comodel_name == 'res.partner' and self.env[m]._auto and
not self._exclude_column(m, k)]
for m in [x for x in self.env.registry.keys()]] if t]
for i, t in enumerate(tables):
if t[4] == 'many2many':
if t[3]:
relation = self.env[t[1]]._fields[t[2]].relation
if relation:
tables[i][0] = relation
return tables
def _print_report(self, data, xlsx_report=False):
records = self.env[data['model']].browse(data.get('ids', []))
processed_data = self.compute_data_for_report(data)
if xlsx_report:
kkk = self.env['report'].with_context(landscape=True).get_action(
records=records, report_name='gdpr.report_partner_xlsx',
data=processed_data)
return kkk
else:
return self.env['report'].with_context(landscape=True).get_action(
records=records, report_name='gdpr.report_partner',
data=processed_data)
class GDPRPartnerData(models.TransientModel):
_name = "gdpr.partner.data"
_description = "GDPR Partner Data"
name = fields.Char(
string='Database Table',
)
model_id = fields.Many2one(
comodel_name='ir.model',
ondelete='cascade',
string='Models',
)
type = fields.Char(
string="Type",
)
count_rows = fields.Integer(
default=0,
string='Number of lines',
)