|
|
@ -1,77 +1,70 @@ |
|
|
|
# Copyright 2018 Eficent Business and IT Consulting Services S.L. |
|
|
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
|
|
|
from odoo import api, fields, models, _ |
|
|
|
from odoo.exceptions import UserError |
|
|
|
import ast |
|
|
|
|
|
|
|
from odoo import _, api, fields, models |
|
|
|
from odoo.exceptions import UserError |
|
|
|
|
|
|
|
|
|
|
|
class PrivacyPartnerReport(models.TransientModel): |
|
|
|
_name = "privacy.partner.report" |
|
|
|
_description = "Privacy Partner Report" |
|
|
|
|
|
|
|
company_id = fields.Many2one( |
|
|
|
comodel_name='res.company', |
|
|
|
string='Company', |
|
|
|
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, |
|
|
|
comodel_name="res.partner", string="Partner", required=True, |
|
|
|
) |
|
|
|
table_ids = fields.Many2many( |
|
|
|
comodel_name='privacy.partner.data', |
|
|
|
string='Models with related partner data', |
|
|
|
comodel_name="privacy.partner.data", string="Models with related partner data", |
|
|
|
) |
|
|
|
|
|
|
|
@api.onchange('partner_id') |
|
|
|
@api.onchange("partner_id") |
|
|
|
def _onchange_partner_id(self): |
|
|
|
if self.partner_id: |
|
|
|
data = self._get_tables_from_partner(self.partner_id) |
|
|
|
names = self._get_table_names(data) |
|
|
|
tables = self.env['privacy.partner.data'] |
|
|
|
tables = self.env["privacy.partner.data"] |
|
|
|
for name in sorted(names): |
|
|
|
vals = self._get_default_table( |
|
|
|
name=name, |
|
|
|
data=[t for t in data if t[0] == name and not t[5]], |
|
|
|
name=name, data=[t for t in data if t[0] == name and not t[5]], |
|
|
|
) |
|
|
|
if vals: |
|
|
|
tables |= self.env['privacy.partner.data'].create(vals) |
|
|
|
tables |= self.env["privacy.partner.data"].create(vals) |
|
|
|
self.table_ids = tables |
|
|
|
else: |
|
|
|
self.table_ids = self.env['privacy.partner.data'] |
|
|
|
self.table_ids = self.env["privacy.partner.data"] |
|
|
|
return { |
|
|
|
'domain': { |
|
|
|
'table_ids': [ |
|
|
|
('id', 'in', self.table_ids.ids)], |
|
|
|
}, |
|
|
|
"domain": {"table_ids": [("id", "in", self.table_ids.ids)]}, |
|
|
|
} |
|
|
|
|
|
|
|
@api.onchange('company_id') |
|
|
|
@api.onchange("company_id") |
|
|
|
def _onchange_company_id(self): |
|
|
|
if not self.company_id: |
|
|
|
self.company_id = self.env.user.company_id |
|
|
|
return { |
|
|
|
'domain': { |
|
|
|
'partner_id': [ |
|
|
|
('company_id', 'in', [self.company_id.id, False])], |
|
|
|
"domain": { |
|
|
|
"partner_id": [("company_id", "in", [self.company_id.id, False])], |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
def button_export_xlsx(self): |
|
|
|
self.ensure_one() |
|
|
|
if not self.table_ids: |
|
|
|
raise UserError(_('No data for this partner.')) |
|
|
|
raise UserError(_("No data for this partner.")) |
|
|
|
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 |
|
|
|
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 |
|
|
|
|
|
|
|
@staticmethod |
|
|
@ -86,54 +79,55 @@ class PrivacyPartnerReport(models.TransientModel): |
|
|
|
for key, value in row.items(): |
|
|
|
label = self.env[model]._fields[key].string or key |
|
|
|
if self.env[model]._fields[key].store: |
|
|
|
if 'many2one' == self.env[model]._fields[key].type: |
|
|
|
if "many2one" == self.env[model]._fields[key].type: |
|
|
|
comodel = self.env[model]._fields[key].comodel_name |
|
|
|
if value: |
|
|
|
record = self.env[comodel].sudo().browse(value) |
|
|
|
cleaned_rows[i][label] = record.display_name |
|
|
|
else: |
|
|
|
cleaned_rows[i][label] = rows[i][key] |
|
|
|
elif 'binary' == self.env[model]._fields[key].type: |
|
|
|
elif "binary" == self.env[model]._fields[key].type: |
|
|
|
binary = self._transform_binary(rows[i][key]) |
|
|
|
if binary: |
|
|
|
cleaned_rows[i][label] = binary |
|
|
|
elif '2many' not in self.env[model]._fields[key].type: |
|
|
|
elif "2many" not in self.env[model]._fields[key].type: |
|
|
|
cleaned_rows[i][label] = rows[i][key] |
|
|
|
return cleaned_rows |
|
|
|
|
|
|
|
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] |
|
|
|
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']['id'] = str(data['form']['id']) |
|
|
|
data['form']['used_context'] = dict( |
|
|
|
used_context, lang=self.env.context.get('lang', 'en_US')) |
|
|
|
data["form"]["id"] = str(data["form"]["id"]) |
|
|
|
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) |
|
|
|
|
|
|
|
def compute_data_for_report(self, data): |
|
|
|
if not data.get('form'): |
|
|
|
if not data.get("form"): |
|
|
|
raise UserError( |
|
|
|
_("Form content is missing, this report cannot be printed.")) |
|
|
|
partner = data['form'].get('partner_id', False) |
|
|
|
_("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'].sudo().browse(partner[0]) |
|
|
|
tables = data['form'].get('table_ids', False) |
|
|
|
raise UserError(_("No provided partner.")) |
|
|
|
partner = self.env["res.partner"].sudo().browse(partner[0]) |
|
|
|
tables = data["form"].get("table_ids", False) |
|
|
|
if tables: |
|
|
|
tables = self.env['privacy.partner.data'].browse(tables) |
|
|
|
tables = self.env["privacy.partner.data"].browse(tables) |
|
|
|
tables = self._get_rows_from_tables(tables, partner) |
|
|
|
data.update({'tables': tables, }) |
|
|
|
data.update({"tables": tables}) |
|
|
|
return data |
|
|
|
|
|
|
|
def _exclude_column(self, model, column): |
|
|
|
|
|
|
|
# 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'): |
|
|
|
if model in ("mail.compose.message", "survey.mail.compose.message"): |
|
|
|
if column in ("needaction_partner_ids", "starred_partner_ids"): |
|
|
|
return True |
|
|
|
# feel free to add more specific cases meanwhile the issue is not fixed |
|
|
|
|
|
|
@ -147,12 +141,14 @@ class PrivacyPartnerReport(models.TransientModel): |
|
|
|
res |= self.env[t[1]].sudo().browse(t[3]) |
|
|
|
if res: |
|
|
|
values = { |
|
|
|
'name': name, |
|
|
|
'model_id': self.env['ir.model'].sudo().search( |
|
|
|
[('model', '=', res._name)]).id, |
|
|
|
'count_rows': len(res.ids), |
|
|
|
'field_type': field_type, |
|
|
|
'res_ids': res.ids, |
|
|
|
"name": name, |
|
|
|
"model_id": self.env["ir.model"] |
|
|
|
.sudo() |
|
|
|
.search([("model", "=", res._name)]) |
|
|
|
.id, |
|
|
|
"count_rows": len(res.ids), |
|
|
|
"field_type": field_type, |
|
|
|
"res_ids": res.ids, |
|
|
|
} |
|
|
|
return values |
|
|
|
return {} |
|
|
@ -166,12 +162,15 @@ class PrivacyPartnerReport(models.TransientModel): |
|
|
|
|
|
|
|
def _get_rows_from_model(self, model, partner): |
|
|
|
lines = self.env[model.model] |
|
|
|
columns = [k for k, v in self.env[model.model]._fields.items() |
|
|
|
if v.comodel_name == 'res.partner' and |
|
|
|
v.store and not self._exclude_column(model.model, k)] |
|
|
|
columns = [ |
|
|
|
k |
|
|
|
for k, v in self.env[model.model]._fields.items() |
|
|
|
if v.comodel_name == "res.partner" |
|
|
|
and v.store |
|
|
|
and not self._exclude_column(model.model, k) |
|
|
|
] |
|
|
|
for column in columns: |
|
|
|
lines |= self.env[model.model].sudo().search( |
|
|
|
[(column, '=', partner.id)]) |
|
|
|
lines |= self.env[model.model].sudo().search([(column, "=", partner.id)]) |
|
|
|
rows = lines.sudo().read(load=False) |
|
|
|
rows = self._clean_data(model.model, rows) |
|
|
|
return rows |
|
|
@ -191,15 +190,30 @@ class PrivacyPartnerReport(models.TransientModel): |
|
|
|
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] |
|
|
|
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 |
|
|
|
v.store and not self._exclude_column(m, k)] |
|
|
|
for m in [x for x in self.env.registry.keys()]] if t] |
|
|
|
if v.comodel_name == "res.partner" |
|
|
|
and self.env[m]._auto |
|
|
|
and v.store |
|
|
|
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[4] == "many2many": |
|
|
|
if t[3]: |
|
|
|
relation = self.env[t[1]]._fields[t[2]].relation |
|
|
|
if relation: |
|
|
@ -207,44 +221,38 @@ class PrivacyPartnerReport(models.TransientModel): |
|
|
|
return tables |
|
|
|
|
|
|
|
def _print_report(self, data, xlsx_report=False): |
|
|
|
records = self.env[data['model']].sudo().browse(data.get('ids', [])) |
|
|
|
records = self.env[data["model"]].sudo().browse(data.get("ids", [])) |
|
|
|
if xlsx_report: |
|
|
|
return self.env.ref('privacy_partner_report.report_partner_xlsx').\ |
|
|
|
with_context(landscape=True).report_action( |
|
|
|
records, data=data) |
|
|
|
return ( |
|
|
|
self.env.ref("privacy_partner_report.report_partner_xlsx") |
|
|
|
.with_context(landscape=True) |
|
|
|
.report_action(records, data=data) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
class PrivacyPartnerData(models.TransientModel): |
|
|
|
_name = "privacy.partner.data" |
|
|
|
_description = "Privacy Partner Data" |
|
|
|
|
|
|
|
name = fields.Char( |
|
|
|
string='Database Table', |
|
|
|
) |
|
|
|
name = fields.Char(string="Database Table",) |
|
|
|
model_id = fields.Many2one( |
|
|
|
comodel_name='ir.model', |
|
|
|
ondelete='cascade', |
|
|
|
string='Models', |
|
|
|
) |
|
|
|
field_type = fields.Char( |
|
|
|
string="Type", oldname='type', |
|
|
|
comodel_name="ir.model", ondelete="cascade", string="Models", |
|
|
|
) |
|
|
|
count_rows = fields.Integer( |
|
|
|
default=0, |
|
|
|
string='Number of lines', |
|
|
|
field_type = fields.Char(string="Type", oldname="type",) |
|
|
|
count_rows = fields.Integer(default=0, string="Number of lines",) |
|
|
|
res_ids = fields.Char( |
|
|
|
"Related Document IDs", index=True, help="List of Related Document IDs" |
|
|
|
) |
|
|
|
res_ids = fields.Char('Related Document IDs', index=True, |
|
|
|
help='List of Related Document IDs') |
|
|
|
|
|
|
|
def action_view_records(self): |
|
|
|
self.ensure_one() |
|
|
|
response = { |
|
|
|
'name': self.model_id.display_name, |
|
|
|
'type': 'ir.actions.act_window', |
|
|
|
'res_model': self.model_id.model, |
|
|
|
'view_mode': 'tree,form', |
|
|
|
'domain': [('id', 'in', ast.literal_eval(self.res_ids))], |
|
|
|
'target': 'current', |
|
|
|
'context': {'delete': True}, |
|
|
|
"name": self.model_id.display_name, |
|
|
|
"type": "ir.actions.act_window", |
|
|
|
"res_model": self.model_id.model, |
|
|
|
"view_mode": "tree,form", |
|
|
|
"domain": [("id", "in", ast.literal_eval(self.res_ids))], |
|
|
|
"target": "current", |
|
|
|
"context": {"delete": True}, |
|
|
|
} |
|
|
|
return response |