mirror of
https://github.com/OCA/server-backend.git
synced 2025-02-18 09:52:42 +02:00
[IMP] server_action_navigate: black, isort, prettier
This commit is contained in:
committed by
Sylvain LE GAL
parent
b099a40ace
commit
f73945cba1
@@ -12,9 +12,6 @@
|
|||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"depends": ["base"],
|
"depends": ["base"],
|
||||||
"maintainers": ["legalsylvain"],
|
"maintainers": ["legalsylvain"],
|
||||||
"data": [
|
"data": ["security/ir.model.access.csv", "views/view_ir_actions_server.xml"],
|
||||||
"security/ir.model.access.csv",
|
|
||||||
"views/view_ir_actions_server.xml",
|
|
||||||
],
|
|
||||||
"demo": ["demo/ir_actions_server.xml"],
|
"demo": ["demo/ir_actions_server.xml"],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,26 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
|
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
|
||||||
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="navigate_partner_2_tags" model="ir.actions.server">
|
<record id="navigate_partner_2_tags" model="ir.actions.server">
|
||||||
<field name="name">See tags of Partners</field>
|
<field name="name">See tags of Partners</field>
|
||||||
<field name="state">navigate</field>
|
<field name="state">navigate</field>
|
||||||
<field name="model_id" ref="base.model_res_users"/>
|
<field name="model_id" ref="base.model_res_users" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="navigate_line_1" model="ir.actions.server.navigate.line">
|
<record id="navigate_line_1" model="ir.actions.server.navigate.line">
|
||||||
<field name="action_id" ref="navigate_partner_2_tags"/>
|
<field name="action_id" ref="navigate_partner_2_tags" />
|
||||||
<field name="sequence">1</field>
|
<field name="sequence">1</field>
|
||||||
<field name="field_id" ref="base.field_res_users__partner_id"/>
|
<field name="field_id" ref="base.field_res_users__partner_id" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="navigate_line_2" model="ir.actions.server.navigate.line">
|
<record id="navigate_line_2" model="ir.actions.server.navigate.line">
|
||||||
<field name="action_id" ref="navigate_partner_2_tags"/>
|
<field name="action_id" ref="navigate_partner_2_tags" />
|
||||||
<field name="sequence">2</field>
|
<field name="sequence">2</field>
|
||||||
<field name="field_id" ref="base.field_res_partner__category_id"/>
|
<field name="field_id" ref="base.field_res_partner__category_id" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<function model="ir.actions.server" name="create_action">
|
<function model="ir.actions.server" name="create_action">
|
||||||
<value eval="[ref('navigate_partner_2_tags')]"/>
|
<value eval="[ref('navigate_partner_2_tags')]" />
|
||||||
</function>
|
</function>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -13,25 +13,29 @@ class IrActionsServer(models.Model):
|
|||||||
|
|
||||||
navigate_action_id = fields.Many2one(
|
navigate_action_id = fields.Many2one(
|
||||||
string="Navigation Action",
|
string="Navigation Action",
|
||||||
comodel_name='ir.actions.act_window',
|
comodel_name="ir.actions.act_window",
|
||||||
domain="[('res_model', '=', max_navigate_line_model)]",
|
domain="[('res_model', '=', max_navigate_line_model)]",
|
||||||
help="Define here the action used when the navigation will be executed"
|
help="Define here the action used when the navigation will be executed"
|
||||||
" if empty, a generic action will be used.")
|
" if empty, a generic action will be used.",
|
||||||
|
)
|
||||||
|
|
||||||
navigate_line_ids = fields.One2many(
|
navigate_line_ids = fields.One2many(
|
||||||
comodel_name="ir.actions.server.navigate.line",
|
comodel_name="ir.actions.server.navigate.line",
|
||||||
string="Navigate Lines", inverse_name="action_id")
|
string="Navigate Lines",
|
||||||
|
inverse_name="action_id",
|
||||||
|
)
|
||||||
|
|
||||||
max_navigate_line_sequence = fields.Integer(
|
max_navigate_line_sequence = fields.Integer(
|
||||||
string='Max Navigate sequence in lines',
|
string="Max Navigate sequence in lines",
|
||||||
compute='_compute_max_navigate_line',
|
compute="_compute_max_navigate_line",
|
||||||
store=True
|
store=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
max_navigate_line_model = fields.Char(
|
max_navigate_line_model = fields.Char(
|
||||||
string="Max Navigate Model in lines",
|
string="Max Navigate Model in lines",
|
||||||
compute="_compute_max_navigate_line",
|
compute="_compute_max_navigate_line",
|
||||||
store=True)
|
store=True,
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends("navigate_line_ids", "model_id")
|
@api.depends("navigate_line_ids", "model_id")
|
||||||
def _compute_max_navigate_line(self):
|
def _compute_max_navigate_line(self):
|
||||||
@@ -43,11 +47,13 @@ class IrActionsServer(models.Model):
|
|||||||
"""
|
"""
|
||||||
for action in self:
|
for action in self:
|
||||||
action.max_navigate_line_sequence = (
|
action.max_navigate_line_sequence = (
|
||||||
max(action.mapped('navigate_line_ids.sequence') or [0]) + 1)
|
max(action.mapped("navigate_line_ids.sequence") or [0]) + 1
|
||||||
action.max_navigate_line_model =\
|
)
|
||||||
action.navigate_line_ids\
|
action.max_navigate_line_model = (
|
||||||
and action.navigate_line_ids[-1].field_model\
|
action.navigate_line_ids
|
||||||
|
and action.navigate_line_ids[-1].field_model
|
||||||
or action.model_id.model
|
or action.model_id.model
|
||||||
|
)
|
||||||
|
|
||||||
def delete_last_line(self):
|
def delete_last_line(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -56,34 +62,34 @@ class IrActionsServer(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def run_action_navigate_multi(self, action, eval_context=None):
|
def run_action_navigate_multi(self, action, eval_context=None):
|
||||||
IrModel = self.env['ir.model']
|
IrModel = self.env["ir.model"]
|
||||||
lines = action.navigate_line_ids
|
lines = action.navigate_line_ids
|
||||||
if not lines:
|
if not lines:
|
||||||
raise UserError(_(
|
raise UserError(
|
||||||
"The Action Server %s is not correctly set\n"
|
_("The Action Server %s is not correctly set\n" " : No fields defined")
|
||||||
" : No fields defined"))
|
)
|
||||||
mapped_field_value = ".".join(lines.mapped("field_id.name"))
|
mapped_field_value = ".".join(lines.mapped("field_id.name"))
|
||||||
|
|
||||||
item_ids = eval_context['records'].mapped(mapped_field_value).ids
|
item_ids = eval_context["records"].mapped(mapped_field_value).ids
|
||||||
domain = "[('id','in',[" + ','.join(map(str, item_ids)) + "])]"
|
domain = "[('id','in',[" + ",".join(map(str, item_ids)) + "])]"
|
||||||
|
|
||||||
# Use Defined action if defined
|
# Use Defined action if defined
|
||||||
if action.navigate_action_id:
|
if action.navigate_action_id:
|
||||||
return_action = action.navigate_action_id
|
return_action = action.navigate_action_id
|
||||||
result = return_action.read()[0]
|
result = return_action.read()[0]
|
||||||
result['domain'] = domain
|
result["domain"] = domain
|
||||||
else:
|
else:
|
||||||
# Otherwise, return a default action
|
# Otherwise, return a default action
|
||||||
model_name = action.max_navigate_line_model
|
model_name = action.max_navigate_line_model
|
||||||
model = IrModel.search([('model', '=', model_name)])
|
model = IrModel.search([("model", "=", model_name)])
|
||||||
view_mode = 'tree,form'
|
view_mode = "tree,form"
|
||||||
result = {
|
result = {
|
||||||
'name': model.name,
|
"name": model.name,
|
||||||
'domain': domain,
|
"domain": domain,
|
||||||
'res_model': model_name,
|
"res_model": model_name,
|
||||||
'target': 'current',
|
"target": "current",
|
||||||
'type': 'ir.actions.act_window',
|
"type": "ir.actions.act_window",
|
||||||
'view_mode': view_mode,
|
"view_mode": view_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -12,33 +12,34 @@ class IrActionsServerNavigateLine(models.Model):
|
|||||||
|
|
||||||
sequence = fields.Integer(string="Sequence", default=1)
|
sequence = fields.Integer(string="Sequence", default=1)
|
||||||
|
|
||||||
field_model = fields.Char(
|
field_model = fields.Char(string="Model", related="field_id.relation", store=True)
|
||||||
string="Model", related="field_id.relation", store=True)
|
|
||||||
|
|
||||||
action_id = fields.Many2one(
|
action_id = fields.Many2one(
|
||||||
comodel_name="ir.actions.server", string="Action",
|
comodel_name="ir.actions.server",
|
||||||
required=True, ondelete="cascade")
|
string="Action",
|
||||||
|
required=True,
|
||||||
|
ondelete="cascade",
|
||||||
|
)
|
||||||
|
|
||||||
field_id = fields.Many2one(
|
field_id = fields.Many2one(
|
||||||
comodel_name="ir.model.fields", string="Field",
|
comodel_name="ir.model.fields", string="Field", required=True
|
||||||
required=True)
|
)
|
||||||
|
|
||||||
# when adding a record, onchange is called for every field on the
|
# when adding a record, onchange is called for every field on the
|
||||||
# form, also in editable list views
|
# form, also in editable list views
|
||||||
@api.onchange('field_id')
|
@api.onchange("field_id")
|
||||||
def _onchange_field_id(self):
|
def _onchange_field_id(self):
|
||||||
# check out the docstring of this in odoo/models.py
|
# check out the docstring of this in odoo/models.py
|
||||||
lines = self.action_id.resolve_2many_commands(
|
lines = self.action_id.resolve_2many_commands(
|
||||||
'navigate_line_ids',
|
"navigate_line_ids", self.env.context.get("navigate_line_ids", []),
|
||||||
self.env.context.get('navigate_line_ids', []),
|
|
||||||
)
|
)
|
||||||
lines = sum(map(self.new, lines), self.browse([]))
|
lines = sum(map(self.new, lines), self.browse([]))
|
||||||
model = lines[-1:].field_id.relation or self.action_id.model_id.model
|
model = lines[-1:].field_id.relation or self.action_id.model_id.model
|
||||||
return {
|
return {
|
||||||
'domain': {
|
"domain": {
|
||||||
'field_id': [
|
"field_id": [
|
||||||
('ttype', 'in', ['many2one', 'one2many', 'many2many']),
|
("ttype", "in", ["many2one", "one2many", "many2many"]),
|
||||||
('model', '=', model),
|
("model", "=", model),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,48 +3,44 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from odoo.tests.common import TransactionCase
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
from odoo.tools.safe_eval import safe_eval
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
|
|
||||||
class TestModule(TransactionCase):
|
class TestModule(TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.action_server = self.env.ref(
|
self.action_server = self.env.ref(
|
||||||
"server_action_navigate.navigate_partner_2_tags")
|
"server_action_navigate.navigate_partner_2_tags"
|
||||||
|
)
|
||||||
self.users = self.env["res.users"].search([])
|
self.users = self.env["res.users"].search([])
|
||||||
|
|
||||||
def test_action_result(self):
|
def test_action_result(self):
|
||||||
result = self.action_server.with_context(
|
result = self.action_server.with_context(
|
||||||
active_model="res.users",
|
active_model="res.users", active_ids=self.users.ids
|
||||||
active_ids=self.users.ids).run()
|
).run()
|
||||||
|
|
||||||
self.assertEqual(result.get("id", False), False)
|
self.assertEqual(result.get("id", False), False)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(result.get("res_model", False), "res.partner.category")
|
||||||
result.get('res_model', False), 'res.partner.category')
|
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
safe_eval(result.get('domain', [])),
|
safe_eval(result.get("domain", [])),
|
||||||
[("id", "in", self.users.mapped("partner_id.category_id").ids)]
|
[("id", "in", self.users.mapped("partner_id.category_id").ids)],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_delete_last_line(self):
|
def test_delete_last_line(self):
|
||||||
line_qty = len(self.action_server.navigate_line_ids)
|
line_qty = len(self.action_server.navigate_line_ids)
|
||||||
self.action_server.delete_last_line()
|
self.action_server.delete_last_line()
|
||||||
self.assertEqual(
|
self.assertEqual(line_qty - 1, len(self.action_server.navigate_line_ids))
|
||||||
line_qty - 1,
|
|
||||||
len(self.action_server.navigate_line_ids)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_action_navigate_with_action(self):
|
def test_action_navigate_with_action(self):
|
||||||
self.action_server.navigate_action_id = self.env.ref(
|
self.action_server.navigate_action_id = self.env.ref(
|
||||||
"base.action_partner_category_form")
|
"base.action_partner_category_form"
|
||||||
|
)
|
||||||
|
|
||||||
result = self.action_server.with_context(
|
result = self.action_server.with_context(
|
||||||
active_model="res.users",
|
active_model="res.users", active_ids=self.users.ids
|
||||||
active_ids=self.users.ids).run()
|
).run()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result.get("id", False),
|
result.get("id", False),
|
||||||
|
|||||||
@@ -1,40 +1,55 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
|
Copyright (C) 2020 - Today: GRAP (http://www.grap.coop)
|
||||||
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_ir_actions_server_form" model="ir.ui.view">
|
<record id="view_ir_actions_server_form" model="ir.ui.view">
|
||||||
<field name="model">ir.actions.server</field>
|
<field name="model">ir.actions.server</field>
|
||||||
<field name="inherit_id" ref="base.view_server_action_form"/>
|
<field name="inherit_id" ref="base.view_server_action_form" />
|
||||||
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//page[@name='code']" position="after">
|
<xpath expr="//page[@name='code']" position="after">
|
||||||
<page string="Navigation Options" name='page_navigate' autofocus="autofocus"
|
<page
|
||||||
attrs="{'invisible': [('state', '!=', 'navigate')]}">
|
string="Navigation Options"
|
||||||
|
name='page_navigate'
|
||||||
|
autofocus="autofocus"
|
||||||
|
attrs="{'invisible': [('state', '!=', 'navigate')]}"
|
||||||
|
>
|
||||||
<group>
|
<group>
|
||||||
<field name="max_navigate_line_sequence" invisible="1"/>
|
<field name="max_navigate_line_sequence" invisible="1" />
|
||||||
<field name="max_navigate_line_model" invisible="1"/>
|
<field name="max_navigate_line_model" invisible="1" />
|
||||||
<!-- we can check emptyness of a 2many like this since v10 i think /-->
|
<!-- we can check emptyness of a 2many like this since v10 i think /-->
|
||||||
<button name="delete_last_line" string="Delete Last Line" type="object"
|
<button
|
||||||
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"/>
|
name="delete_last_line"
|
||||||
<field name="navigate_line_ids" context="{'navigate_line_ids': navigate_line_ids}" nolabel="1" colspan="4">
|
string="Delete Last Line"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="navigate_line_ids"
|
||||||
|
context="{'navigate_line_ids': navigate_line_ids}"
|
||||||
|
nolabel="1"
|
||||||
|
colspan="4"
|
||||||
|
>
|
||||||
<tree editable="bottom" delete="false">
|
<tree editable="bottom" delete="false">
|
||||||
<!-- the handle widget takes care of the sequence /-->
|
<!-- the handle widget takes care of the sequence /-->
|
||||||
<field name="sequence" widget="handle" invisible="True" />
|
<field
|
||||||
|
name="sequence"
|
||||||
|
widget="handle"
|
||||||
|
invisible="True"
|
||||||
|
/>
|
||||||
<field name="field_id" />
|
<field name="field_id" />
|
||||||
<field name="field_model"/>
|
<field name="field_model" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<field name="navigate_action_id"
|
<field
|
||||||
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"/>
|
name="navigate_action_id"
|
||||||
|
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user