mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[WIP] Manage Nodes and Groups by Odoo version
This commit is contained in:
42
hotel_node_master/README.rst
Normal file
42
hotel_node_master/README.rst
Normal file
@@ -0,0 +1,42 @@
|
||||
=================
|
||||
Hotel Master Node
|
||||
=================
|
||||
|
||||
This module is for providing centralized hotel management features for hootel.
|
||||
|
||||
You can manage:
|
||||
|
||||
- Node connection data
|
||||
- Remote users and access groups
|
||||
|
||||
**Installation**
|
||||
|
||||
To install this module, you need to:
|
||||
|
||||
**External dependencies**
|
||||
- OdooRPC, a Python package providing an easy way to pilot your Odoo servers through RPC
|
||||
|
||||
**Configuration**
|
||||
|
||||
To configure this module, you need to:
|
||||
|
||||
**Usage**
|
||||
|
||||
To use this module, you need to:
|
||||
|
||||
**Try me on Runbot**
|
||||
|
||||
**Known issues / Roadmap**
|
||||
|
||||
...
|
||||
|
||||
**Bug Tracker**
|
||||
|
||||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback here.
|
||||
|
||||
Credits
|
||||
|
||||
Contributors
|
||||
|
||||
Maintainer
|
||||
|
||||
3
hotel_node_master/__init__.py
Normal file
3
hotel_node_master/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
26
hotel_node_master/__manifest__.py
Normal file
26
hotel_node_master/__manifest__.py
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
'name': 'Hotel Master Node',
|
||||
'summary': """Provides centralized hotel management features""",
|
||||
'version': '0.1.0',
|
||||
'author': 'Pablo Q. Barriuso, \
|
||||
Darío Lodeiros, \
|
||||
Alexandre Díaz, \
|
||||
Odoo Community Association (OCA)',
|
||||
'category': 'Generic Modules/Hotel Management',
|
||||
'depends': [
|
||||
'project'
|
||||
],
|
||||
'external_dependencies':
|
||||
{'python' : ['odoorpc']},
|
||||
'license': "AGPL-3",
|
||||
'data': [
|
||||
'views/hotel_node.xml',
|
||||
'views/hotel_node_user.xml',
|
||||
'views/hotel_node_group.xml',
|
||||
'security/hotel_node_security.xml',
|
||||
'security/ir.model.access.csv'
|
||||
],
|
||||
'demo': [],
|
||||
'auto_install': False,
|
||||
'installable': True
|
||||
}
|
||||
5
hotel_node_master/models/__init__.py
Normal file
5
hotel_node_master/models/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import hotel_node
|
||||
from . import hotel_node_user
|
||||
from . import hotel_node_group
|
||||
110
hotel_node_master/models/hotel_node.py
Normal file
110
hotel_node_master/models/hotel_node.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# Copyright 2018 Pablo Q. Barriuso
|
||||
# Copyright 2018 Alexandre Díaz
|
||||
# Copyright 2018 Dario Lodeiros
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import wdb
|
||||
import logging
|
||||
import urllib.error
|
||||
import odoorpc.odoo
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HotelNode(models.Model):
|
||||
|
||||
_inherit = ['project.project']
|
||||
|
||||
_description = 'Centralized hotel management features'
|
||||
|
||||
active = fields.Boolean('Active', default=True,
|
||||
help='The active field allows you to hide the \
|
||||
node without removing it.')
|
||||
sequence = fields.Integer('Sequence', default=0,
|
||||
help='Gives the sequence order when displaying the list of Nodes.')
|
||||
|
||||
odoo_version = fields.Char()
|
||||
odoo_host = fields.Char('Host', required=True,
|
||||
help='Full URL to the host.')
|
||||
odoo_db = fields.Char('Database Name',
|
||||
help='Odoo database name.')
|
||||
odoo_user = fields.Char('Username',
|
||||
help='Odoo administration user.')
|
||||
odoo_password = fields.Char('Password',
|
||||
help='Odoo password.')
|
||||
odoo_port = fields.Integer(string='TCP Port', default=443,
|
||||
help='Specify the TCP port for the XML-RPC protocol.')
|
||||
odoo_protocol = fields.Selection([('jsonrpc', 'jsonrpc'), ('jsonrpc+ssl', 'jsonrpc+ssl')],
|
||||
'Protocol', required=True, default='jsonrpc+ssl')
|
||||
|
||||
user_ids = fields.One2many('hotel.node.user', 'node_id',
|
||||
'Users with access to this hotel')
|
||||
|
||||
group_ids = fields.Many2many('hotel.node.group', 'hotel_node_group_rel', 'node_id', 'group_id',
|
||||
string='Access Groups')
|
||||
|
||||
@api.constrains('group_ids')
|
||||
def _check_group_version(self):
|
||||
"""
|
||||
:raise: ValidationError
|
||||
"""
|
||||
for node in self:
|
||||
domain = [('id', 'in', node.group_ids.ids), ('odoo_version', '!=', node.odoo_version)]
|
||||
invalid_groups = self.env["hotel.node.group"].search(domain)
|
||||
if len(invalid_groups) > 0:
|
||||
msg = _("At least one group is not within the node version.") + " " + \
|
||||
_("Odoo version of the node: %s") % node.odoo_version
|
||||
_logger.warning(msg)
|
||||
raise ValidationError(msg)
|
||||
|
||||
_sql_constraints = [
|
||||
('db_node_id_uniq', 'unique (odoo_db, id)',
|
||||
'The database name of the hotel must be unique within the Master Node!'),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
"""
|
||||
:param dict vals: the model's fields as a dictionary
|
||||
:return: new hotel node record created.
|
||||
:raise: ValidationError
|
||||
"""
|
||||
try:
|
||||
noderpc = odoorpc.ODOO(vals['odoo_host'], vals['odoo_protocol'], vals['odoo_port'])
|
||||
noderpc.login(vals['odoo_db'], vals['odoo_user'], vals['odoo_password'])
|
||||
|
||||
vals.update({'odoo_version': noderpc.version})
|
||||
|
||||
remote_domain = [('model', '=', 'res.groups')]
|
||||
remote_fields = ['complete_name', 'display_name']
|
||||
remote_groups = noderpc.env['ir.model.data'].search_read(remote_domain, remote_fields)
|
||||
|
||||
noderpc.logout()
|
||||
|
||||
except (odoorpc.error.RPCError, odoorpc.error.InternalError, urllib.error.URLError) as err:
|
||||
raise ValidationError(err)
|
||||
else:
|
||||
master_groups = self.env["hotel.node.group"].search_read(
|
||||
[('odoo_version', '=', vals['odoo_version'])], ['xml_id'])
|
||||
|
||||
gui_ids = [r['id'] for r in master_groups]
|
||||
xml_ids = [r['xml_id'] for r in master_groups]
|
||||
|
||||
group_ids = []
|
||||
for group in remote_groups:
|
||||
if group['complete_name'] in xml_ids:
|
||||
idx = xml_ids.index(group['complete_name'])
|
||||
group_ids.append((4, gui_ids[idx], 0))
|
||||
else:
|
||||
group_ids.append((0, 0, {
|
||||
'name': group['display_name'],
|
||||
'xml_id': group['complete_name'],
|
||||
'odoo_version': vals['odoo_version'],
|
||||
}))
|
||||
vals.update({'group_ids': group_ids})
|
||||
|
||||
node_id = super().create(vals)
|
||||
|
||||
return node_id
|
||||
36
hotel_node_master/models/hotel_node_group.py
Normal file
36
hotel_node_master/models/hotel_node_group.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright 2018 Pablo Q. Barriuso
|
||||
# Copyright 2018 Alexandre Díaz
|
||||
# Copyright 2018 Dario Lodeiros
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HotelNodeGroup(models.Model):
|
||||
_name = "hotel.node.group"
|
||||
_description = "Hotel Access Groups"
|
||||
|
||||
active = fields.Boolean(default=True,
|
||||
help="The active field allows you to hide the \
|
||||
group without removing it.")
|
||||
sequence = fields.Integer(default=0,
|
||||
help="Gives the sequence order when displaying the list of Groups.")
|
||||
|
||||
name = fields.Char(required=True, translate=True)
|
||||
node_ids = fields.Many2many('project.project', 'hotel_node_group_rel', 'group_id', 'node_id',
|
||||
string='Hotels')
|
||||
user_ids = fields.Many2many('hotel.node.user', 'hotel_node_user_group_rel', 'group_id', 'user_id',
|
||||
string='Users')
|
||||
# xml_id represents the complete module.name, xml_id = ("%s.%s" % (data['module'], data['name']))
|
||||
xml_id = fields.Char(string='External Identifier', required=True,
|
||||
help="External Key/Identifier that can be used for "
|
||||
"data integration with third-party systems")
|
||||
odoo_version = fields.Char('Odoo Version')
|
||||
|
||||
_sql_constraints = [
|
||||
('xml_id_uniq', 'unique (odoo_version, xml_id)',
|
||||
'_(The external identifier of the group must be unique within an Odoo version!')
|
||||
]
|
||||
211
hotel_node_master/models/hotel_node_user.py
Normal file
211
hotel_node_master/models/hotel_node_user.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# Copyright 2018 Pablo Q. Barriuso
|
||||
# Copyright 2018 Alexandre Díaz
|
||||
# Copyright 2018 Dario Lodeiros
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import wdb
|
||||
import logging
|
||||
import urllib.error
|
||||
import odoorpc.odoo
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HotelNodeUser(models.Model):
|
||||
_name = "hotel.node.user"
|
||||
_description = "Users with access to a hotel"
|
||||
|
||||
def _default_groups(self):
|
||||
pass
|
||||
|
||||
active = fields.Boolean(default=True,
|
||||
help="The active field allows you to hide the \
|
||||
user without removing it.")
|
||||
sequence = fields.Integer(default=0,
|
||||
help="Gives the sequence order when displaying the list of Users.")
|
||||
|
||||
node_id = fields.Many2one('project.project', 'Hotel', required=True)
|
||||
# remote users are managed as partners into the central node
|
||||
partner_id = fields.Many2one('res.partner', required=True)
|
||||
# Remote login for the hotels
|
||||
login = fields.Char(require=True,
|
||||
help="Used to log into the hotel")
|
||||
# Password for login into the remote hotels
|
||||
password = fields.Char(default='', invisible=True, copy=False,
|
||||
help="Keep empty if you don't want the user to be able to connect on the hotel.")
|
||||
# Remote user id for client-server understanding
|
||||
remote_user_id = fields.Integer(require=True, invisible=True, copy=False,
|
||||
help="ID of the target record in the remote database")
|
||||
|
||||
# The same user can not be assigned to the same hotel
|
||||
# _sql_constraints = [
|
||||
# ('user_id_node_id_key', 'UNIQUE (user_id, node_id)',
|
||||
# 'You can not have two users with the same login in the same hotel!')
|
||||
# ]
|
||||
|
||||
# Users access control ...
|
||||
group_ids = fields.Many2many('hotel.node.group', 'hotel_node_user_group_rel', 'user_id', 'group_id',
|
||||
string='Groups', default=_default_groups, require=True,
|
||||
help="Access rights for this user in this hotel.")
|
||||
|
||||
# @api.constrains('user_id', 'node_id')
|
||||
# def _check_user_node_unicity(self):
|
||||
# if self.search_count([
|
||||
# ('user_id', '=', self.user_id.id),
|
||||
# ('node_id', '=', self.node_id.id),
|
||||
# ]) > 1:
|
||||
# raise ValidationError(_("You can not have two users with the same login in the same hotel!"))
|
||||
|
||||
# Constraints and onchanges
|
||||
@api.constrains('group_ids')
|
||||
def _check_group_ids(self):
|
||||
# TODO ensure all group_ids are within the node version
|
||||
domain = [('id', 'in', self.group_ids.ids), ('odoo_version', '!=', self.node_id.odoo_version)]
|
||||
invalid_groups = self.env["hotel.node.group"].search(domain)
|
||||
if len(invalid_groups) > 0:
|
||||
msg = _("At least one group is not within the node version.") + " " + \
|
||||
_("Odoo version of the node: %s") % self.node_id.odoo_version
|
||||
_logger.warning(msg)
|
||||
raise ValidationError(msg)
|
||||
|
||||
@api.onchange('node_id')
|
||||
def _onchange_node_id(self):
|
||||
if self.node_id:
|
||||
# TODO clean group_ids
|
||||
# self.group_ids = []
|
||||
node = self.env["project.project"].search([('id', '=', self.node_id.id)])
|
||||
return {'domain': {'group_ids': [('odoo_version', '=', node.odoo_version)]}}
|
||||
|
||||
return {'domain': {'group_ids': []}}
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
"""
|
||||
:param dict vals: the model's fields as a dictionary
|
||||
:return: new hotel user record created.
|
||||
:raise: ValidationError
|
||||
"""
|
||||
wdb.set_trace()
|
||||
node = self.env["project.project"].browse(vals['node_id'])
|
||||
|
||||
if 'group_ids' in vals:
|
||||
domain = [('id', 'in', vals['group_ids'][0][2]), ('odoo_version', '!=', node.odoo_version)]
|
||||
invalid_groups = self.env["hotel.node.group"].search(domain)
|
||||
if len(invalid_groups) > 0:
|
||||
msg = _("At least one group is not within the node version.") + " " + \
|
||||
_("Odoo version in node: %s") % node.odoo_version
|
||||
_logger.error(msg)
|
||||
raise ValidationError(msg)
|
||||
|
||||
try:
|
||||
noderpc = odoorpc.ODOO(node.odoo_host, node.odoo_protocol, node.odoo_port)
|
||||
noderpc.login(node.odoo_db, node.odoo_user, node.odoo_password)
|
||||
|
||||
partner = self.env["res.partner"].browse(vals['partner_id'])
|
||||
remote_vals = {
|
||||
'name': partner.name,
|
||||
'login': vals['login'],
|
||||
}
|
||||
|
||||
groups = self.env["hotel.node.group"].browse(vals['group_ids'][0][2])
|
||||
# TODO Improve one rpc call per remote group for better performance
|
||||
remote_groups = [noderpc.env.ref(r.xml_id).id for r in groups]
|
||||
remote_vals.update({'groups_id': [[6, False, remote_groups]]})
|
||||
|
||||
# create user and delegate in remote node the default values for the user
|
||||
remote_user_id = noderpc.env['res.users'].create(remote_vals)
|
||||
_logger.info('User #%s created remote res.users with ID: [%s]',
|
||||
self._context.get('uid'), remote_user_id)
|
||||
vals.update({'remote_user_id': remote_user_id})
|
||||
|
||||
noderpc.logout()
|
||||
|
||||
except (odoorpc.error.RPCError, odoorpc.error.InternalError, urllib.error.URLError) as err:
|
||||
_logger.error(err)
|
||||
raise ValidationError(err)
|
||||
else:
|
||||
return super().create(vals)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
"""
|
||||
:param dict vals: a dictionary of fields to update and the value to set on them.
|
||||
:raise: ValidationError
|
||||
"""
|
||||
for rec in self:
|
||||
if 'node_id' in vals and vals['node_id'] != rec.node_id.id:
|
||||
msg = _("Changing a node user is not allowed. Please create a new user instead.")
|
||||
_logger.error(msg)
|
||||
raise ValidationError(msg)
|
||||
|
||||
node = rec.node_id
|
||||
|
||||
if 'group_ids' in vals:
|
||||
domain = [('id', 'in', vals['group_ids'][0][2]), ('odoo_version', '!=', node.odoo_version)]
|
||||
invalid_groups = self.env["hotel.node.group"].search(domain)
|
||||
if len(invalid_groups) > 0:
|
||||
msg = _("At least one group is not within the node version.") + " " + \
|
||||
_("Odoo version in node: %s") % node.odoo_version
|
||||
_logger.error(msg)
|
||||
raise ValidationError(msg)
|
||||
|
||||
try:
|
||||
noderpc = odoorpc.ODOO(node.odoo_host, node.odoo_protocol, node.odoo_port)
|
||||
noderpc.login(node.odoo_db, node.odoo_user, node.odoo_password)
|
||||
|
||||
remote_vals = {}
|
||||
|
||||
if 'active' in vals:
|
||||
remote_vals.update({'active': vals['active']})
|
||||
|
||||
if 'password' in vals:
|
||||
remote_vals.update({'password': vals['password']})
|
||||
|
||||
if 'partner_id' in vals:
|
||||
partner = self.env["res.partner"].browse(vals['partner_id'])
|
||||
remote_vals.update({'name': partner.name})
|
||||
|
||||
if 'group_ids' in vals:
|
||||
groups = self.env["hotel.node.group"].browse(vals['group_ids'][0][2])
|
||||
# TODO Improve one rpc call per remote group for better performance
|
||||
remote_groups = [noderpc.env.ref(r.xml_id).id for r in groups]
|
||||
remote_vals.update({'groups_id': [[6, False, remote_groups]]})
|
||||
|
||||
noderpc.env['res.users'].write([rec.remote_user_id], remote_vals)
|
||||
_logger.info('User #%s updated remote res.users with ID: [%s]',
|
||||
self._context.get('uid'), rec.remote_user_id)
|
||||
|
||||
noderpc.logout()
|
||||
|
||||
except (odoorpc.error.RPCError, odoorpc.error.InternalError, urllib.error.URLError) as err:
|
||||
_logger.error(err)
|
||||
raise ValidationError(err)
|
||||
|
||||
# TODO update record in central node only if the corresponding remote call was successfully
|
||||
return super().write(vals)
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
"""
|
||||
:raise: ValidationError
|
||||
"""
|
||||
# TODO In production users are archived instead of removed
|
||||
for rec in self:
|
||||
try:
|
||||
node = rec.node_id
|
||||
|
||||
noderpc = odoorpc.ODOO(node.odoo_host, node.odoo_protocol, node.odoo_port)
|
||||
noderpc.login(node.odoo_db, node.odoo_user, node.odoo_password)
|
||||
|
||||
noderpc.env['res.users'].unlink([rec.remote_user_id])
|
||||
_logger.info('User #%s deleted remote res.users with ID: [%s]',
|
||||
self._context.get('uid'), rec.remote_user_id)
|
||||
noderpc.logout()
|
||||
|
||||
except (odoorpc.error.RPCError, odoorpc.error.InternalError, urllib.error.URLError) as err:
|
||||
_logger.error(err)
|
||||
raise ValidationError(err)
|
||||
|
||||
return super().unlink()
|
||||
3
hotel_node_master/security/hotel_node_security.xml
Normal file
3
hotel_node_master/security/hotel_node_security.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="0">
|
||||
</odoo>
|
||||
1
hotel_node_master/security/ir.model.access.csv
Normal file
1
hotel_node_master/security/ir.model.access.csv
Normal file
@@ -0,0 +1 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
|
BIN
hotel_node_master/static/description/icon.png
Normal file
BIN
hotel_node_master/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
151
hotel_node_master/views/hotel_node.xml
Normal file
151
hotel_node_master/views/hotel_node.xml
Normal file
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="hotel_node_view_form" model="ir.ui.view">
|
||||
<field name="name">hotel.node.view.form</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Hotel Node">
|
||||
<sheet string="Hotel Node">
|
||||
<div class="oe_button_box" name="button_box" groups="base.group_user">
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="" icon="fa-tasks">
|
||||
<field string="Tasks" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
|
||||
</button>
|
||||
<button name="toggle_active" type="object"
|
||||
confirm="(Un)archiving a hotel node automatically (un)archives its issues. Do you want to proceed?"
|
||||
class="oe_stat_button" icon="fa-archive">
|
||||
<field name="active" widget="boolean_button"
|
||||
options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="name" placeholder="Hotel Name"/>
|
||||
</h1>
|
||||
<div name="options_active" class="oe_edit_only">
|
||||
<div>
|
||||
<label for="label_tasks" class="oe_inline" string="Name of the tasks :"/>
|
||||
<field name="label_tasks" class="oe_inline oe_input_align"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<notebook>
|
||||
<page name="remote_access" string="Remote Access">
|
||||
<group name="remote_access" string="Hotel Node">
|
||||
<group>
|
||||
<field name="odoo_host" />
|
||||
<field name="odoo_protocol" />
|
||||
<field name="odoo_port" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="odoo_db" />
|
||||
<field name="odoo_user" />
|
||||
<field name="odoo_password" password="True" />
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="groups" string="Groups" attrs="{'invisible':[('id','=',False)]}">
|
||||
<group>
|
||||
<field name="odoo_version" readonly="1"/>
|
||||
<field name="group_ids" domain="[('odoo_version','=',odoo_version)]"/>
|
||||
</group>
|
||||
</page>
|
||||
<page name="users" string="Users" attrs="{'invisible':[('id','=',False)]}">
|
||||
<group>
|
||||
<field name="user_ids" context="{'default_node_id': id}" />
|
||||
</group>
|
||||
</page>
|
||||
<page name="settings" string="Settings">
|
||||
<group>
|
||||
<field name="user_id" string="Node Manager"
|
||||
attrs="{'readonly':[('active','=',False)]}"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"
|
||||
help="Follow this node to automatically track the events associated to tasks and issues of this node."
|
||||
groups="base.group_user"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hotel_node_view_tree" model="ir.ui.view">
|
||||
<field name="name">hotel.node.view.tree</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-bf="message_needaction==True" decoration-muted="active == False" string="Hotels">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="name" string="Hotel Name"/>
|
||||
<field name="odoo_host"/>
|
||||
<field name="odoo_db"/>
|
||||
<field name="odoo_version"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hotel_node_action_open_dashboard" model="ir.actions.act_window">
|
||||
<field name="name">Hotels</field>
|
||||
<field name="res_model">project.project</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="view_mode">kanban,form</field>
|
||||
<field name="target">main</field>
|
||||
</record>
|
||||
|
||||
<!-- Action to open Hotel Nodes List -->
|
||||
<act_window id="hotel_node_action"
|
||||
name="List of Hotels"
|
||||
res_model="project.project"
|
||||
view_mode="tree,form"
|
||||
/>
|
||||
<!-- Action to open Hotel Users List -->
|
||||
<act_window id="hotel_node_user_action"
|
||||
name="List of Users in Hotels"
|
||||
res_model="hotel.node.user"
|
||||
view_mode="tree,form"
|
||||
/>
|
||||
<!-- Action to open Hotel Groups List -->
|
||||
<act_window id="hotel_node_group_action"
|
||||
name="List of Access Groups in Hotels"
|
||||
res_model="hotel.node.group"
|
||||
view_mode="tree,form"
|
||||
/>
|
||||
|
||||
<!-- Menu default to open Hotel Nodes Dashboard -->
|
||||
<menuitem id="hotel_node_dashboard_menu"
|
||||
name="Hotel Central Dashboard"
|
||||
action="hotel_node_action_open_dashboard"
|
||||
/>
|
||||
<!-- Menu Management Section -->
|
||||
<menuitem id="dashboard_menu"
|
||||
name="Management"
|
||||
parent="hotel_node_dashboard_menu"
|
||||
/>
|
||||
<!-- Menu item to open Hotel Nodes List -->
|
||||
<menuitem id="hotel_node_menu"
|
||||
name="Hotels"
|
||||
action="hotel_node_action"
|
||||
parent="dashboard_menu"
|
||||
sequence="1"
|
||||
/>
|
||||
<!-- Menu item to open Hotel Users List -->
|
||||
<menuitem id="hotel_node_user_menu"
|
||||
name="Users"
|
||||
action="hotel_node_user_action"
|
||||
parent="dashboard_menu"
|
||||
sequence="2"
|
||||
/>
|
||||
<!-- Menu item to open Hotel Users List -->
|
||||
<menuitem id="hotel_node_group_menu"
|
||||
name="Access Groups"
|
||||
action="hotel_node_group_action"
|
||||
parent="dashboard_menu"
|
||||
sequence="3"
|
||||
/>
|
||||
</odoo>
|
||||
14
hotel_node_master/views/hotel_node_group.xml
Normal file
14
hotel_node_master/views/hotel_node_group.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="hotel_node_group_view_tree" model="ir.ui.view">
|
||||
<field name="name">hotel.node.group.tree</field>
|
||||
<field name="model">hotel.node.group</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="odoo_version"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
53
hotel_node_master/views/hotel_node_user.xml
Normal file
53
hotel_node_master/views/hotel_node_user.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="hotel_node_user_view_form" model="ir.ui.view">
|
||||
<field name="name">hotel.node.user.view.form</field>
|
||||
<field name="model">hotel.node.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Users">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="toggle_active" type="object"
|
||||
class="oe_stat_button" icon="fa-archive">
|
||||
<field name="active" widget="boolean_button"
|
||||
options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="partner_id" string="Central user" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="partner_id" required="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group attrs="{'invisible': [('partner_id', '=', False)]}">
|
||||
<group name="login">
|
||||
<field name="login"/>
|
||||
<field name="password" password="True"/>
|
||||
</group>
|
||||
<group name="nodes">
|
||||
<field name="node_id"/>
|
||||
<field name="remote_user_id" readonly="1" attrs="{'invisible': [('id', '=', False)]}" />
|
||||
</group>
|
||||
</group>
|
||||
<group name="groups" attrs="{'invisible': [('node_id', '=', False)]}">
|
||||
<field name="group_ids"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hotel_node_user_view_tree" model="ir.ui.view">
|
||||
<field name="name">hotel.node.user.tree</field>
|
||||
<field name="model">hotel.node.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="login"/>
|
||||
<field name="node_id"/>
|
||||
<field name="remote_user_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user