[13.0][MIG] - report_substitute migration

pull/700/head
sbejaoui 2020-11-06 11:25:04 +01:00 committed by matiasperalta1
parent 8b9266dffe
commit 0f17d279e2
11 changed files with 136 additions and 144 deletions

View File

@ -2,20 +2,19 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Report Substitute', "name": "Report Substitute",
'summary': """ "summary": """
This module allows to create substitution rules for report actions. This module allows to create substitution rules for report actions.
""", """,
'version': '12.0.1.0.0', "version": "13.0.1.0.0",
'license': 'AGPL-3', "license": "AGPL-3",
'author': 'ACSONE SA/NV,' "author": "ACSONE SA/NV," "Odoo Community Association (OCA)",
'Odoo Community Association (OCA)', "website": "https://github.com/OCA/reporting-engine",
'website': 'https://github.com/OCA/reporting-engine', "depends": ["base", "mail"],
'depends': ['base', 'mail'], "data": [
'data': [ "security/ir_actions_report_substitution_rule.xml",
'security/ir_actions_report_substitution_rule.xml', "views/assets_backend.xml",
'views/assets_backend.xml', "views/ir_actions_report.xml",
'views/ir_actions_report.xml',
], ],
'demo': ['demo/action_report.xml'], "demo": ["demo/action_report.xml"],
} }

View File

@ -3,27 +3,30 @@
<template id="substitution_report"> <template id="substitution_report">
<div class="page">Substitution Report</div> <div class="page">Substitution Report</div>
</template> </template>
<report
<report id="substitution_report_print" id="substitution_report_print"
string="Substitution For Technical guide" string="Substitution For Technical guide"
model="ir.module.module" model="ir.module.module"
report_type="qweb-pdf" report_type="qweb-pdf"
file="report_substitute.substitution_report" file="report_substitute.substitution_report"
name="report_substitute.substitution_report"/> name="report_substitute.substitution_report"
/>
<record id="substitution_rule_demo_1" model="ir.actions.report.substitution.rule"> <record id="substitution_rule_demo_1" model="ir.actions.report.substitution.rule">
<field name="action_report_id" ref="base.ir_module_reference_print" /> <field name="action_report_id" ref="base.ir_module_reference_print" />
<field name="substitution_action_report_id" ref="report_substitute.substitution_report_print"/> <field
name="substitution_action_report_id"
ref="report_substitute.substitution_report_print"
/>
</record> </record>
<template id="substitution_report_2"> <template id="substitution_report_2">
<div class="page">Substitution Report 2</div> <div class="page">Substitution Report 2</div>
</template> </template>
<report
<report id="substitution_report_print_2" id="substitution_report_print_2"
string="Substitution 2 For Technical guide" string="Substitution 2 For Technical guide"
model="ir.module.module" model="ir.module.module"
report_type="qweb-pdf" report_type="qweb-pdf"
file="report_substitute.substitution_report_2" file="report_substitute.substitution_report_2"
name="report_substitute.substitution_report_2"/> name="report_substitute.substitution_report_2"
/>
</odoo> </odoo>

View File

@ -7,7 +7,7 @@ from odoo.tools.safe_eval import safe_eval
class IrActionReport(models.Model): class IrActionReport(models.Model):
_inherit = 'ir.actions.report' _inherit = "ir.actions.report"
action_report_substitution_rule_ids = fields.One2many( action_report_substitution_rule_ids = fields.One2many(
comodel_name="ir.actions.report.substitution.rule", comodel_name="ir.actions.report.substitution.rule",
@ -15,20 +15,16 @@ class IrActionReport(models.Model):
string="Substitution Rules", string="Substitution Rules",
) )
@api.multi
def _get_substitution_report(self, model, active_ids): def _get_substitution_report(self, model, active_ids):
self.ensure_one() self.ensure_one()
model = self.env[model] model = self.env[model]
for ( for substitution_report_rule in self.action_report_substitution_rule_ids:
substitution_report_rule
) in self.action_report_substitution_rule_ids:
domain = safe_eval(substitution_report_rule.domain) domain = safe_eval(substitution_report_rule.domain)
domain.append(('id', 'in', active_ids)) domain.append(("id", "in", active_ids))
if set(model.search(domain).ids) == set(active_ids): if set(model.search(domain).ids) == set(active_ids):
return substitution_report_rule.substitution_action_report_id return substitution_report_rule.substitution_action_report_id
return False return False
@api.multi
def get_substitution_report(self, active_ids): def get_substitution_report(self, active_ids):
self.ensure_one() self.ensure_one()
action_report = self action_report = self
@ -42,8 +38,8 @@ class IrActionReport(models.Model):
@api.model @api.model
def get_substitution_report_action(self, action, active_ids): def get_substitution_report_action(self, action, active_ids):
if action.get('id'): if action.get("id"):
action_report = self.browse(action['id']) action_report = self.browse(action["id"])
substitution_report = action_report substitution_report = action_report
while substitution_report: while substitution_report:
action_report = substitution_report action_report = substitution_report
@ -53,12 +49,10 @@ class IrActionReport(models.Model):
action.update(action_report.read()[0]) action.update(action_report.read()[0])
return action return action
@api.multi
def render(self, res_ids, data=None): def render(self, res_ids, data=None):
substitution_report = self.get_substitution_report(res_ids) substitution_report = self.get_substitution_report(res_ids)
return super(IrActionReport, substitution_report).render(res_ids, data) return super(IrActionReport, substitution_report).render(res_ids, data)
@api.noguess
def report_action(self, docids, data=None, config=True): def report_action(self, docids, data=None, config=True):
if docids: if docids:
if isinstance(docids, models.Model): if isinstance(docids, models.Model):

View File

@ -1,15 +1,15 @@
# Copyright 2019 ACSONE SA/NV # Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, _ from odoo import _, api, fields, models
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
class ActionsReportSubstitutionRule(models.Model): class ActionsReportSubstitutionRule(models.Model):
_name = 'ir.actions.report.substitution.rule' _name = "ir.actions.report.substitution.rule"
_description = 'Action Report Substitution Rule' _description = "Action Report Substitution Rule"
_order = 'sequence ASC' _order = "sequence ASC"
sequence = fields.Integer(default=10) sequence = fields.Integer(default=10)
action_report_id = fields.Many2one( action_report_id = fields.Many2one(
@ -28,7 +28,7 @@ class ActionsReportSubstitutionRule(models.Model):
domain="[('model', '=', model)]", domain="[('model', '=', model)]",
) )
@api.constrains('substitution_action_report_id', 'action_report_id') @api.constrains("substitution_action_report_id", "action_report_id")
def _check_substitution_infinite_loop(self): def _check_substitution_infinite_loop(self):
def _check_infinite_loop(original_report, substitution_report): def _check_infinite_loop(original_report, substitution_report):
if original_report == substitution_report: if original_report == substitution_report:
@ -37,8 +37,7 @@ class ActionsReportSubstitutionRule(models.Model):
substitution_rule substitution_rule
) in substitution_report.action_report_substitution_rule_ids: ) in substitution_report.action_report_substitution_rule_ids:
_check_infinite_loop( _check_infinite_loop(
original_report, original_report, substitution_rule.substitution_action_report_id,
substitution_rule.substitution_action_report_id,
) )
for rec in self: for rec in self:

View File

@ -1,23 +1,20 @@
# Copyright 2019 ACSONE SA/NV # Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models from odoo import models
class MailThread(models.AbstractModel): class MailThread(models.AbstractModel):
_inherit = 'mail.thread' _inherit = "mail.thread"
@api.multi
def message_post_with_template(self, template_id, **kwargs): def message_post_with_template(self, template_id, **kwargs):
template = self.env['mail.template'].browse(template_id) template = self.env["mail.template"].browse(template_id)
old_report = False old_report = False
if template and template.report_template and self.ids: if template and template.report_template and self.ids:
active_ids = self.ids active_ids = self.ids
old_report = template.report_template old_report = template.report_template
template.report_template = old_report.get_substitution_report( template.report_template = old_report.get_substitution_report(active_ids)
active_ids
)
res = super().message_post_with_template(template_id, **kwargs) res = super().message_post_with_template(template_id, **kwargs)
if old_report: if old_report:
template.report_template = old_report template.report_template = old_report

View File

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ACSONE SA/NV <!-- Copyright 2019 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo> <odoo>
<record model="ir.model.access" id="action_report_substitution_rule_user_access"> <record model="ir.model.access" id="action_report_substitution_rule_user_access">
<field name="name">action.report.substitution.rule user access</field> <field name="name">action.report.substitution.rule user access</field>
<field name="model_id" ref="model_ir_actions_report_substitution_rule" /> <field name="model_id" ref="model_ir_actions_report_substitution_rule" />
@ -12,7 +10,6 @@
<field name="perm_write" eval="0" /> <field name="perm_write" eval="0" />
<field name="perm_unlink" eval="0" /> <field name="perm_unlink" eval="0" />
</record> </record>
<record model="ir.model.access" id="action_report_substitution_rule_manager_access"> <record model="ir.model.access" id="action_report_substitution_rule_manager_access">
<field name="name">action.report.substitution.rule manager access</field> <field name="name">action.report.substitution.rule manager access</field>
<field name="model_id" ref="model_ir_actions_report_substitution_rule" /> <field name="model_id" ref="model_ir_actions_report_substitution_rule" />

View File

@ -6,34 +6,30 @@ odoo.define("report_substitute.action_report_substitute", function (require) {
var ActionManager = require("web.ActionManager"); var ActionManager = require("web.ActionManager");
ActionManager.include({ ActionManager.include({
/** /**
* Intercept action handling substitute the report action * Intercept action handling substitute the report action
* @override * @override
*/ */
_handleAction: function(action, options) { _handleAction: function(action, options) {
if (action.type === "ir.actions.report" && if (
action.type === "ir.actions.report" &&
action.context.active_ids && action.context.active_ids &&
action.action_report_substitution_rule_ids && action.action_report_substitution_rule_ids &&
action.action_report_substitution_rule_ids != 0) { action.action_report_substitution_rule_ids !== 0
) {
var active_ids = action.context.active_ids; var active_ids = action.context.active_ids;
var self = this; var self = this;
var _super = this._super; var _super = this._super;
var callersArguments = arguments;
return this._rpc({ return this._rpc({
model: "ir.actions.report", model: "ir.actions.report",
method: "get_substitution_report_action", method: "get_substitution_report_action",
args: [action, active_ids] args: [action, active_ids],
}).then(function(substitution_action) { }).then(function(substitution_action) {
callersArguments[0] = substitution_action return _super.apply(self, [substitution_action, options]);
return _super.apply(self, callersArguments);
}); });
} }
return this._super.apply(this, arguments); return this._super.apply(this, arguments);
}, },
}); });
}); });

View File

@ -1,8 +1,8 @@
# Copyright 2019 ACSONE SA/NV # Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
class TestReportSubstitute(TransactionCase): class TestReportSubstitute(TransactionCase):
@ -10,11 +10,14 @@ class TestReportSubstitute(TransactionCase):
# In the demo file we create a new report for ir.module.module model # In the demo file we create a new report for ir.module.module model
# with a substation rule from the original report action # with a substation rule from the original report action
super(TestReportSubstitute, self).setUp() super(TestReportSubstitute, self).setUp()
self.action_report = self.env.ref('base.ir_module_reference_print') self.action_report = self.env.ref("base.ir_module_reference_print")
self.res_ids = self.env.ref('base.module_base').ids self.res_ids = self.env.ref("base.module_base").ids
self.substitution_rule = self.env.ref( self.substitution_rule = self.env.ref(
'report_substitute.substitution_rule_demo_1' "report_substitute.substitution_rule_demo_1"
) )
self.env.company.external_report_layout_id = self.env.ref(
"web.external_layout_standard"
).id
def test_substitution(self): def test_substitution(self):
res = str(self.action_report.render(res_ids=self.res_ids)[0]) res = str(self.action_report.render(res_ids=self.res_ids)[0])
@ -27,13 +30,13 @@ class TestReportSubstitute(TransactionCase):
def test_recursive_substitution(self): def test_recursive_substitution(self):
res = str(self.action_report.render(res_ids=self.res_ids)[0]) res = str(self.action_report.render(res_ids=self.res_ids)[0])
self.assertNotIn('<div class="page">Substitution Report 2</div>', res) self.assertNotIn('<div class="page">Substitution Report 2</div>', res)
self.env['ir.actions.report.substitution.rule'].create( self.env["ir.actions.report.substitution.rule"].create(
{ {
'substitution_action_report_id': self.env.ref( "substitution_action_report_id": self.env.ref(
'report_substitute.substitution_report_print_2' "report_substitute.substitution_report_print_2"
).id, ).id,
'action_report_id': self.env.ref( "action_report_id": self.env.ref(
'report_substitute.substitution_report_print' "report_substitute.substitution_report_print"
).id, ).id,
} }
) )
@ -41,40 +44,38 @@ class TestReportSubstitute(TransactionCase):
self.assertIn('<div class="page">Substitution Report 2</div>', res) self.assertIn('<div class="page">Substitution Report 2</div>', res)
def test_substitution_with_domain(self): def test_substitution_with_domain(self):
self.substitution_rule.write({'domain': "[('name', '=', 'base')]"}) self.substitution_rule.write({"domain": "[('name', '=', 'base')]"})
res = str(self.action_report.render(res_ids=self.res_ids)[0]) res = str(self.action_report.render(res_ids=self.res_ids)[0])
self.assertIn('<div class="page">Substitution Report</div>', res) self.assertIn('<div class="page">Substitution Report</div>', res)
self.substitution_rule.write({'domain': "[('name', '!=', 'base')]"}) self.substitution_rule.write({"domain": "[('name', '!=', 'base')]"})
res = str(self.action_report.render(res_ids=self.res_ids)[0]) res = str(self.action_report.render(res_ids=self.res_ids)[0])
self.assertNotIn('<div class="page">Substitution Report</div>', res) self.assertNotIn('<div class="page">Substitution Report</div>', res)
def test_substitution_with_action_dict(self): def test_substitution_with_action_dict(self):
substitution_report_action = self.env[ substitution_report_action = self.env[
'ir.actions.report' "ir.actions.report"
].get_substitution_report_action( ].get_substitution_report_action(self.action_report.read()[0], self.res_ids)
self.action_report.read()[0], self.res_ids
)
self.assertEqual( self.assertEqual(
substitution_report_action['id'], substitution_report_action["id"],
self.substitution_rule.substitution_action_report_id.id, self.substitution_rule.substitution_action_report_id.id,
) )
def test_substitution_with_report_action(self): def test_substitution_with_report_action(self):
res = self.action_report.report_action(self.res_ids) res = self.action_report.report_action(self.res_ids)
self.assertEqual( self.assertEqual(
res['report_name'], res["report_name"],
self.substitution_rule.substitution_action_report_id.report_name, self.substitution_rule.substitution_action_report_id.report_name,
) )
def test_substitution_infinite_loop(self): def test_substitution_infinite_loop(self):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
self.env['ir.actions.report.substitution.rule'].create( self.env["ir.actions.report.substitution.rule"].create(
{ {
'action_report_id': self.env.ref( "action_report_id": self.env.ref(
'report_substitute.substitution_report_print' "report_substitute.substitution_report_print"
).id, ).id,
'substitution_action_report_id': self.env.ref( "substitution_action_report_id": self.env.ref(
'base.ir_module_reference_print' "base.ir_module_reference_print"
).id, ).id,
} }
) )

View File

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<openerp> <odoo>
<template id="assets_backend" name="report assets" inherit_id="web.assets_backend"> <template id="assets_backend" name="report assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <xpath expr="." position="inside">
<script type="text/javascript" src="/report_substitute/static/src/js/action_manager.js"></script> <script
type="text/javascript"
src="/report_substitute/static/src/js/action_manager.js"
/>
</xpath> </xpath>
</template> </template>
</openerp> </odoo>

View File

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ACSONE SA/NV <!-- Copyright 2019 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo> <odoo>
<record model="ir.ui.view" id="ir_actions_report_form_view"> <record model="ir.ui.view" id="ir_actions_report_form_view">
<field name="name">ir.actions.report.form (in report_substitute)</field> <field name="name">ir.actions.report.form (in report_substitute)</field>
<field name="model">ir.actions.report</field> <field name="model">ir.actions.report</field>
@ -20,16 +18,24 @@
<form> <form>
<sheet> <sheet>
<group> <group>
<field name="action_report_id" <field
invisible="1" readonly="1" name="action_report_id"
required="0"/> invisible="1"
readonly="1"
required="0"
/>
<field name="model" invisible="1" /> <field name="model" invisible="1" />
<field name="substitution_action_report_id" <field
domain="[('model', '=', model), ('id', '!=', parent.id)]"/> name="substitution_action_report_id"
domain="[('model', '=', model), ('id', '!=', parent.id)]"
/>
</group> </group>
<group> <group>
<field name="domain" widget="domain" <field
options="{'model': 'model'}"/> name="domain"
widget="domain"
options="{'model': 'model'}"
/>
</group> </group>
</sheet> </sheet>
</form> </form>
@ -38,6 +44,4 @@
</xpath> </xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -6,30 +6,29 @@ from odoo import api, models
class MailComposeMessage(models.TransientModel): class MailComposeMessage(models.TransientModel):
_inherit = 'mail.compose.message' _inherit = "mail.compose.message"
@api.multi @api.onchange("template_id")
@api.onchange('template_id')
def onchange_template_id_wrapper(self): def onchange_template_id_wrapper(self):
if self.template_id: if self.template_id:
report_template = self.template_id.report_template report_template = self.template_id.report_template
active_ids = [] active_ids = []
if self.env.context.get('active_ids'): if self.env.context.get("active_ids"):
active_ids = self.env.context.get('active_ids') active_ids = self.env.context.get("active_ids")
elif self.env.context.get('default_res_id'): elif self.env.context.get("default_res_id"):
active_ids = [self.env.context.get('default_res_id')] active_ids = [self.env.context.get("default_res_id")]
if ( if (
report_template report_template
and report_template.action_report_substitution_rule_ids and report_template.action_report_substitution_rule_ids
and active_ids and active_ids
): ):
old_report_template = report_template old_tmpl = report_template
self.template_id.report_template = ( self.template_id.report_template = old_tmpl.get_substitution_report(
old_report_template.get_substitution_report(active_ids) active_ids
) )
onchange_result_with_substituted_report = ( onchange_result_with_substituted_report = (
super().onchange_template_id_wrapper() super().onchange_template_id_wrapper()
) )
self.template_id.report_template = old_report_template self.template_id.report_template = old_tmpl
return onchange_result_with_substituted_report return onchange_result_with_substituted_report
return super().onchange_template_id_wrapper() return super().onchange_template_id_wrapper()