Browse Source

[IMP] server_action_navigate: black, isort, prettier

14.0
Quentin Tawry 3 years ago
committed by Ashish Hirpara
parent
commit
d1ec51edf6
  1. 5
      server_action_navigate/__manifest__.py
  2. 20
      server_action_navigate/demo/ir_actions_server.xml
  3. 58
      server_action_navigate/models/ir_actions_server.py
  4. 27
      server_action_navigate/models/ir_actions_server_navigate_line.py
  5. 30
      server_action_navigate/tests/test_module.py
  6. 49
      server_action_navigate/views/view_ir_actions_server.xml

5
server_action_navigate/__manifest__.py

@ -12,9 +12,6 @@
"license": "AGPL-3", "license": "AGPL-3",
"depends": ["base"], "depends": ["base"],
"maintainers": ["legalsylvain"], "maintainers": ["legalsylvain"],
"data": [
"security/ir.model.access.csv",
"views/view_ir_actions_server.xml",
],
"data": ["security/ir.model.access.csv", "views/view_ir_actions_server.xml"],
"demo": ["demo/ir_actions_server.xml"], "demo": ["demo/ir_actions_server.xml"],
} }

20
server_action_navigate/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>

58
server_action_navigate/models/ir_actions_server.py

@ -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',
compute='_compute_max_navigate_line',
store=True
string="Max Navigate sequence in lines",
compute="_compute_max_navigate_line",
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)
action.max_navigate_line_model =\
action.navigate_line_ids\
and action.navigate_line_ids[-1].field_model\
max(action.mapped("navigate_line_ids.sequence") or [0]) + 1
)
action.max_navigate_line_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(_(
"The Action Server %s is not correctly set\n"
" : No fields defined"))
raise UserError(
_("The Action Server %s is not correctly set\n" " : 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
domain = "[('id','in',[" + ','.join(map(str, item_ids)) + "])]"
item_ids = eval_context["records"].mapped(mapped_field_value).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)])
view_mode = 'tree,form'
model = IrModel.search([("model", "=", model_name)])
view_mode = "tree,form"
result = { result = {
'name': model.name,
'domain': domain,
'res_model': model_name,
'target': 'current',
'type': 'ir.actions.act_window',
'view_mode': view_mode,
"name": model.name,
"domain": domain,
"res_model": model_name,
"target": "current",
"type": "ir.actions.act_window",
"view_mode": view_mode,
} }
return result return result

27
server_action_navigate/models/ir_actions_server_navigate_line.py

@ -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(
string="Model", related="field_id.relation", store=True)
field_model = fields.Char(string="Model", related="field_id.relation", store=True)
action_id = fields.Many2one( action_id = fields.Many2one(
comodel_name="ir.actions.server", string="Action",
required=True, ondelete="cascade")
comodel_name="ir.actions.server",
string="Action",
required=True,
ondelete="cascade",
)
field_id = fields.Many2one( field_id = fields.Many2one(
comodel_name="ir.model.fields", string="Field",
required=True)
comodel_name="ir.model.fields", string="Field", 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',
self.env.context.get('navigate_line_ids', []),
"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': {
'field_id': [
('ttype', 'in', ['many2one', 'one2many', 'many2many']),
('model', '=', model),
"domain": {
"field_id": [
("ttype", "in", ["many2one", "one2many", "many2many"]),
("model", "=", model),
], ],
} }
} }

30
server_action_navigate/tests/test_module.py

@ -3,50 +3,46 @@
# 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_ids=self.users.ids).run()
active_model="res.users", active_ids=self.users.ids
).run()
self.assertEqual(result.get("id", False), False) self.assertEqual(result.get("id", False), False)
self.assertEqual(
result.get('res_model', False), 'res.partner.category')
self.assertEqual(result.get("res_model", False), "res.partner.category")
self.assertEqual( self.assertEqual(
safe_eval(result.get('domain', [])),
[("id", "in", self.users.mapped("partner_id.category_id").ids)]
safe_eval(result.get("domain", [])),
[("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(
line_qty - 1,
len(self.action_server.navigate_line_ids)
)
self.assertEqual(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_ids=self.users.ids).run()
active_model="res.users", active_ids=self.users.ids
).run()
self.assertEqual( self.assertEqual(
result.get("id", False), result.get("id", False),
self.env.ref("base.action_partner_category_form").id, self.env.ref("base.action_partner_category_form").id,
)
)

49
server_action_navigate/views/view_ir_actions_server.xml

@ -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"
attrs="{'invisible': [('state', '!=', 'navigate')]}">
<page
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_model" invisible="1"/>
<field name="max_navigate_line_sequence" 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"
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"/>
<field name="navigate_line_ids" context="{'navigate_line_ids': navigate_line_ids}" nolabel="1" colspan="4">
<button
name="delete_last_line"
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"
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"/>
<field
name="navigate_action_id"
attrs="{'invisible': [('navigate_line_ids', '=', [])]}"
/>
</group> </group>
</page> </page>
</xpath> </xpath>
</field> </field>
</record> </record>
</odoo> </odoo>
Loading…
Cancel
Save