机企猫 隐藏项目模块修改接入(可隐藏导出、新建等项目)
14
jikimo_hide_options/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import models
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def uninstall_hook(cr, registry):
|
||||
# 使用cr来执行数据库操作
|
||||
with api.Environment.manage():
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
# 执行数据清理操作
|
||||
access_rights = env['access.right'].search([])
|
||||
access_rights.unlink()
|
||||
followers = env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
followers.unlink()
|
||||
32
jikimo_hide_options/__manifest__.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': '机企猫 隐藏项目',
|
||||
'version': '16.0.1.0.0',
|
||||
'category': 'Extra Tools, Productivity',
|
||||
'summary': """ Can hide options from user """,
|
||||
'description': """ By using this module we can hide the options like create,
|
||||
delete,export,and archive/un archive in the model which we want. Here we
|
||||
are also able to select the user groups except Administrator which we want
|
||||
to apply the above hiding functionality """,
|
||||
'author': '机企猫-MGW',
|
||||
'company': '机企猫',
|
||||
'depends': ['base_setup', 'mail'],
|
||||
'data': [
|
||||
'security/security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/model_access_rights_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'jikimo_hide_options/static/src/js/form_controller.js',
|
||||
'jikimo_hide_options/static/src/js/list_controller.js',
|
||||
'jikimo_hide_options/static/src/js/kanban_controller.js'
|
||||
]
|
||||
},
|
||||
'images': ['static/description/banner.jpg'],
|
||||
'license': 'LGPL-3',
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': False,
|
||||
'uninstall_hook': 'uninstall_hook',
|
||||
}
|
||||
4
jikimo_hide_options/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import model_access_rights
|
||||
from . import models
|
||||
|
||||
107
jikimo_hide_options/models/model_access_rights.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class ModelAccessRights(models.Model):
|
||||
"""This class is used to detect, which all options want to hide from the
|
||||
specified group and model"""
|
||||
_name = 'access.right'
|
||||
_inherit = 'mail.thread'
|
||||
_description = 'Manage Modules Access Control'
|
||||
_rec_name = 'model_id'
|
||||
|
||||
model_id = fields.Many2one('ir.model', ondelete='cascade', required=True,
|
||||
help="select the model")
|
||||
groups_id = fields.Many2one('res.groups', required=True,
|
||||
help="select the group")
|
||||
is_delete = fields.Boolean(string="Delete", help="hide the delete option")
|
||||
is_export = fields.Boolean(string="Export",
|
||||
help="hide the 'Export All'"
|
||||
" option from list view")
|
||||
is_create_or_update = fields.Boolean(string="Create/Update",
|
||||
help="hide the create option from list"
|
||||
" as well as form view")
|
||||
is_archive = fields.Boolean(string="Archive/UnArchive",
|
||||
help="hide the archive option")
|
||||
|
||||
@api.model
|
||||
def hide_buttons(self):
|
||||
"""This function contains a query that detects which all options want
|
||||
to hide, in which model,and to which user groups"""
|
||||
access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
'is_export',
|
||||
'is_create_or_update',
|
||||
'is_archive',
|
||||
'groups_id'])
|
||||
for dic in access_right_rec:
|
||||
model = self.env['ir.model'].sudo().browse(dic['model_id'][0]).model
|
||||
group_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).name
|
||||
|
||||
module_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).module
|
||||
dic.update({
|
||||
'model': model,
|
||||
'group_name': group_name,
|
||||
'module': module_name
|
||||
})
|
||||
return access_right_rec
|
||||
# @api.model
|
||||
# def hide_buttons(self):
|
||||
# """This function contains a query that detects which all options want
|
||||
# to hide, in which model,and to which user groups"""
|
||||
# access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
# 'is_export',
|
||||
# 'is_create_or_update',
|
||||
# 'is_archive',
|
||||
# 'groups_id'])
|
||||
# for dic in access_right_rec:
|
||||
# model = self.env['ir.model'].sudo().browse(dic['model_id']).model
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).module
|
||||
# dic.update({
|
||||
# 'model': model,
|
||||
# 'group_name': group_name,
|
||||
# 'module': module_name
|
||||
# })
|
||||
# return access_right_rec
|
||||
|
||||
|
||||
# class AccessRightCleanup(models.Model):
|
||||
# _name = 'access.right.cleanup' # 定义一个新的模型名
|
||||
# _description = 'Access Right Cleanup'
|
||||
|
||||
|
||||
|
||||
# @api.model
|
||||
# def _module_uninstall(self):
|
||||
# """在模块卸载时执行清理操作"""
|
||||
# super(AccessRightCleanup, self)._module_uninstall()
|
||||
# # 这里执行你的清理逻辑
|
||||
#
|
||||
# # 获取access.right模型的所有记录
|
||||
# access_rights = self.env['access.right'].search([])
|
||||
# for access_right in access_rights:
|
||||
# # 删除access.right模型的所有记录
|
||||
# access_right.unlink()
|
||||
#
|
||||
# # 查找所有关联到access.right模型的关注者记录
|
||||
# followers = self.env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
# for follower in followers:
|
||||
# # 删除关注者记录
|
||||
# follower.unlink()
|
||||
#
|
||||
# # # 示例:删除自定义数据表(确保先检查外键约束等)
|
||||
# # self.env.cr.execute('DROP TABLE IF EXISTS access_right CASCADE;')
|
||||
#
|
||||
# # 其他清理工作...
|
||||
353
jikimo_hide_options/models/models.py
Normal file
@@ -0,0 +1,353 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
from operator import attrgetter
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.models import BaseModel, _unlink, LOG_ACCESS_COLUMNS, \
|
||||
INSERT_BATCH_SIZE, SQL_DEFAULT
|
||||
# from odoo.tools import OrderedSet, split_every, attrgetter, clean_context
|
||||
from odoo.tools import OrderedSet, split_every, clean_context
|
||||
|
||||
|
||||
@api.model
|
||||
def _create(self, data_list):
|
||||
""" Create records from the stored field values in ``data_list``. """
|
||||
assert data_list
|
||||
cr = self.env.cr
|
||||
|
||||
# insert rows in batches of maximum INSERT_BATCH_SIZE
|
||||
ids = [] # ids of created records
|
||||
other_fields = OrderedSet() # non-column fields
|
||||
|
||||
for data_sublist in split_every(INSERT_BATCH_SIZE, data_list):
|
||||
stored_list = [data['stored'] for data in data_sublist]
|
||||
fnames = sorted({name for stored in stored_list for name in stored})
|
||||
|
||||
columns = []
|
||||
rows = [[] for _ in stored_list]
|
||||
for fname in fnames:
|
||||
field = self._fields[fname]
|
||||
if field.column_type:
|
||||
columns.append(fname)
|
||||
for stored, row in zip(stored_list, rows):
|
||||
if fname in stored:
|
||||
colval = field.convert_to_column(stored[fname], self,
|
||||
stored)
|
||||
if field.translate is True and colval:
|
||||
if 'en_US' not in colval.adapted:
|
||||
colval.adapted['en_US'] = next(
|
||||
iter(colval.adapted.values()))
|
||||
row.append(colval)
|
||||
else:
|
||||
row.append(SQL_DEFAULT)
|
||||
else:
|
||||
other_fields.add(field)
|
||||
|
||||
if field.type == 'properties':
|
||||
# force calling fields.create for properties field because
|
||||
# we might want to update the parent definition
|
||||
other_fields.add(field)
|
||||
|
||||
if not columns:
|
||||
# manage the case where we create empty records
|
||||
columns = ['id']
|
||||
for row in rows:
|
||||
row.append(SQL_DEFAULT)
|
||||
|
||||
header = ", ".join(f'"{column}"' for column in columns)
|
||||
template = ", ".join("%s" for _ in rows)
|
||||
cr.execute(
|
||||
f'INSERT INTO "{self._table}" ({header}) VALUES {template} RETURNING "id"',
|
||||
[tuple(row) for row in rows],
|
||||
)
|
||||
ids.extend(id_ for id_, in cr.fetchall())
|
||||
|
||||
# put the new records in cache, and update inverse fields, for many2one
|
||||
#
|
||||
# cachetoclear is an optimization to avoid modified()'s cost until other_fields are processed
|
||||
cachetoclear = []
|
||||
records = self.browse(ids)
|
||||
inverses_update = defaultdict(list) # {(field, value): ids}
|
||||
common_set_vals = set(
|
||||
LOG_ACCESS_COLUMNS + [self.CONCURRENCY_CHECK_FIELD, 'id',
|
||||
'parent_path'])
|
||||
for data, record in zip(data_list, records):
|
||||
data['record'] = record
|
||||
# DLE P104: test_inherit.py, test_50_search_one2many
|
||||
vals = dict(
|
||||
{k: v for d in data['inherited'].values() for k, v in d.items()},
|
||||
**data['stored'])
|
||||
set_vals = common_set_vals.union(vals)
|
||||
for field in self._fields.values():
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
self.env.cache.set(record, field, ())
|
||||
elif field.related and not field.column_type:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
# DLE P123: `test_adv_activity`, `test_message_assignation_inbox`, `test_message_log`, `test_create_mail_simple`, ...
|
||||
# Set `mail.message.parent_id` to False in cache so it doesn't do the useless SELECT when computing the modified of `child_ids`
|
||||
# in other words, if `parent_id` is not set, no other message `child_ids` are impacted.
|
||||
# + avoid the fetch of fields which are False. e.g. if a boolean field is not passed in vals and as no default set in the field attributes,
|
||||
# then we know it can be set to False in the cache in the case of a create.
|
||||
elif field.name not in set_vals and not field.compute:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
for fname, value in vals.items():
|
||||
field = self._fields[fname]
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
cachetoclear.append((record, field))
|
||||
else:
|
||||
cache_value = field.convert_to_cache(value, record)
|
||||
self.env.cache.set(record, field, cache_value)
|
||||
if field.type in ('many2one', 'many2one_reference') and \
|
||||
self.pool.field_inverses[field]:
|
||||
inverses_update[(field, cache_value)].append(record.id)
|
||||
|
||||
for (field, value), record_ids in inverses_update.items():
|
||||
field._update_inverses(self.browse(record_ids), value)
|
||||
|
||||
# update parent_path
|
||||
records._parent_store_create()
|
||||
|
||||
# protect fields being written against recomputation
|
||||
protected = [(data['protected'], data['record']) for data in data_list]
|
||||
with self.env.protecting(protected):
|
||||
# mark computed fields as todo
|
||||
records.modified(self._fields, create=True)
|
||||
|
||||
if other_fields:
|
||||
# discard default values from context for other fields
|
||||
others = records.with_context(clean_context(self._context))
|
||||
for field in sorted(other_fields, key=attrgetter('_sequence')):
|
||||
field.create([
|
||||
(other, data['stored'][field.name])
|
||||
for other, data in zip(others, data_list)
|
||||
if field.name in data['stored']
|
||||
])
|
||||
|
||||
# mark fields to recompute
|
||||
records.modified([field.name for field in other_fields],
|
||||
create=True)
|
||||
|
||||
# if value in cache has not been updated by other_fields, remove it
|
||||
for record, field in cachetoclear:
|
||||
if self.env.cache.contains(record,
|
||||
field) and not self.env.cache.get(
|
||||
record, field):
|
||||
self.env.cache.remove(record, field)
|
||||
|
||||
# check Python constraints for stored fields
|
||||
records._validate_fields(
|
||||
name for data in data_list for name in data['stored'])
|
||||
records.check_access_rule('create')
|
||||
# This is used to restrict the access right to create a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)],
|
||||
# ['model_id', 'is_create_or_update',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_create_or_update']:
|
||||
# raise UserError('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.')
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)],
|
||||
['model_id', 'is_create_or_update', 'groups_id']
|
||||
)
|
||||
|
||||
# 如果找到相关记录,并且当前用户不是管理员
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
# 获取与权限相关的用户组信息
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
# 如果找到了用户组数据
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
# 检查当前用户是否属于该组
|
||||
if self.env.user.has_group(group_xml_id):
|
||||
# 如果该用户组被限制创建或更新操作
|
||||
if rec['is_create_or_update']:
|
||||
raise UserError(
|
||||
_("You are restricted from performing this operation. Please contact the administrator."))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||
pass
|
||||
|
||||
return records
|
||||
|
||||
|
||||
@api.model
|
||||
def unlink(self):
|
||||
""" unlink()
|
||||
|
||||
Deletes the records in ``self``.
|
||||
|
||||
:raise AccessError: if the user is not allowed to delete all the given records
|
||||
:raise UserError: if the record is default property for other records
|
||||
"""
|
||||
if not self:
|
||||
return True
|
||||
|
||||
self.check_access_rights('unlink')
|
||||
self.check_access_rule('unlink')
|
||||
|
||||
from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG
|
||||
for func in self._ondelete_methods:
|
||||
# func._ondelete is True if it should be called during uninstallation
|
||||
if func._ondelete or not self._context.get(MODULE_UNINSTALL_FLAG):
|
||||
func(self)
|
||||
|
||||
# TOFIX: this avoids an infinite loop when trying to recompute a
|
||||
# field, which triggers the recomputation of another field using the
|
||||
# same compute function, which then triggers again the computation
|
||||
# of those two fields
|
||||
for field in self._fields.values():
|
||||
self.env.remove_to_compute(field, self)
|
||||
|
||||
self.env.flush_all()
|
||||
|
||||
cr = self._cr
|
||||
Data = self.env['ir.model.data'].sudo().with_context({})
|
||||
Defaults = self.env['ir.default'].sudo()
|
||||
Property = self.env['ir.property'].sudo()
|
||||
Attachment = self.env['ir.attachment'].sudo()
|
||||
ir_property_unlink = Property
|
||||
ir_model_data_unlink = Data
|
||||
ir_attachment_unlink = Attachment
|
||||
|
||||
# mark fields that depend on 'self' to recompute them after 'self' has
|
||||
# been deleted (like updating a sum of lines after deleting one line)
|
||||
with self.env.protecting(self._fields.values(), self):
|
||||
self.modified(self._fields, before=True)
|
||||
for sub_ids in cr.split_for_in_conditions(self.ids):
|
||||
records = self.browse(sub_ids)
|
||||
|
||||
# Check if the records are used as default properties.
|
||||
refs = [f'{self._name},{id_}' for id_ in sub_ids]
|
||||
if Property.search(
|
||||
[('res_id', '=', False), ('value_reference', 'in', refs)],
|
||||
limit=1):
|
||||
raise UserError(
|
||||
_('Unable to delete this document because it is used as a default property'))
|
||||
|
||||
# Delete the records' properties.
|
||||
ir_property_unlink |= Property.search([('res_id', 'in', refs)])
|
||||
|
||||
query = f'DELETE FROM "{self._table}" WHERE id IN %s'
|
||||
cr.execute(query, (sub_ids,))
|
||||
|
||||
# Removing the ir_model_data reference if the record being deleted
|
||||
# is a record created by xml/csv file, as these are not connected
|
||||
# with real database foreign keys, and would be dangling references.
|
||||
#
|
||||
# Note: the following steps are performed as superuser to avoid
|
||||
# access rights restrictions, and with no context to avoid possible
|
||||
# side-effects during admin calls.
|
||||
data = Data.search(
|
||||
[('model', '=', self._name), ('res_id', 'in', sub_ids)])
|
||||
ir_model_data_unlink |= data
|
||||
|
||||
# For the same reason, remove the defaults having some of the
|
||||
# records as value
|
||||
Defaults.discard_records(records)
|
||||
|
||||
# For the same reason, remove the relevant records in ir_attachment
|
||||
# (the search is performed with sql as the search method of
|
||||
# ir_attachment is overridden to hide attachments of deleted
|
||||
# records)
|
||||
query = 'SELECT id FROM ir_attachment WHERE res_model=%s AND res_id IN %s'
|
||||
cr.execute(query, (self._name, sub_ids))
|
||||
ir_attachment_unlink |= Attachment.browse(
|
||||
row[0] for row in cr.fetchall())
|
||||
|
||||
# invalidate the *whole* cache, since the orm does not handle all
|
||||
# changes made in the database, like cascading delete!
|
||||
self.env.invalidate_all(flush=False)
|
||||
if ir_property_unlink:
|
||||
ir_property_unlink.unlink()
|
||||
if ir_model_data_unlink:
|
||||
ir_model_data_unlink.unlink()
|
||||
if ir_attachment_unlink:
|
||||
ir_attachment_unlink.unlink()
|
||||
# DLE P93: flush after the unlink, for recompute fields depending on
|
||||
# the modified of the unlink
|
||||
self.env.flush_all()
|
||||
# auditing: deletions are infrequent and leave no trace in the database
|
||||
_unlink.info('User #%s deleted %s records with IDs: %r', self._uid,
|
||||
self._name, self.ids)
|
||||
# This is used to restrict the access right to unlink a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)], ['model_id', 'is_delete',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_delete']:
|
||||
# raise UserError(_('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.'))
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
# current_model_id = self.env['ir.model'].sudo().search([('model', '=', self._name)]).id
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)], ['model_id', 'is_delete', 'groups_id']
|
||||
)
|
||||
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
if self.env.user.has_group(group_xml_id) and rec['is_delete']:
|
||||
raise UserError(
|
||||
_('You are restricted from performing this operation. Please contact the administrator.'))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
BaseModel._create = _create
|
||||
BaseModel.unlink = unlink
|
||||
2
jikimo_hide_options/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_access_right,access.access.right,model_access_right,jikimo_hide_options.model_access_rights_groups_configure_model_access,1,1,1,1
|
||||
|
9
jikimo_hide_options/security/security.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Add a group named Configure Model Access in res.groups-->
|
||||
<odoo>
|
||||
<record id="model_access_rights_groups_configure_model_access" model="res.groups">
|
||||
<field name="name">配置隐藏项目</field>
|
||||
<field name="category_id" ref="base.module_category_usability"/>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
BIN
jikimo_hide_options/static/description/assets/icons/check.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/chevron.png
Normal file
|
After Width: | Height: | Size: 310 B |
BIN
jikimo_hide_options/static/description/assets/icons/cogs.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 733 B |
|
After Width: | Height: | Size: 911 B |
BIN
jikimo_hide_options/static/description/assets/icons/license.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/lifebuoy.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 673 B |
|
After Width: | Height: | Size: 878 B |
BIN
jikimo_hide_options/static/description/assets/icons/puzzle.png
Normal file
|
After Width: | Height: | Size: 653 B |
|
After Width: | Height: | Size: 905 B |
|
After Width: | Height: | Size: 839 B |
|
After Width: | Height: | Size: 427 B |
BIN
jikimo_hide_options/static/description/assets/icons/training.png
Normal file
|
After Width: | Height: | Size: 627 B |
BIN
jikimo_hide_options/static/description/assets/icons/update.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/user.png
Normal file
|
After Width: | Height: | Size: 988 B |
BIN
jikimo_hide_options/static/description/assets/icons/wrench.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/check-box.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/compass.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/corporate.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/features.png
Normal file
|
After Width: | Height: | Size: 589 B |
BIN
jikimo_hide_options/static/description/assets/misc/logo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/pictures.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/pie-chart.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 967 B |
BIN
jikimo_hide_options/static/description/assets/misc/star.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/support.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/whatsapp.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/1.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l2.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l3.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l4.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l5.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l6.png
Normal file
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 94 KiB |
BIN
jikimo_hide_options/static/description/banner.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
jikimo_hide_options/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
596
jikimo_hide_options/static/description/index.html
Normal file
@@ -0,0 +1,596 @@
|
||||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
|
||||
<!-- TITLE BAR -->
|
||||
<div class="d-flex align-items-center justify-content-between"
|
||||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
|
||||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" style="width: 42px; height: 42px;" />
|
||||
<div>
|
||||
<div
|
||||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Community
|
||||
</div>
|
||||
<div
|
||||
style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Enterprise
|
||||
</div>
|
||||
<div
|
||||
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Odoo.sh
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF TITLE BAR -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12">
|
||||
<!-- APP HERO -->
|
||||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
|
||||
Hide Create|Delete|Archive|Export Options - Model Wise</h1>
|
||||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">Hide Create, Delete, Archive, Export Options in Models</p>
|
||||
<!-- END OF APP HERO -->
|
||||
<img src="assets/screenshots/hero.gif" class="img-responsive"
|
||||
style="width: 100%; margin-left: auto; margin-right: auto;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- NAVIGATION SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/compass.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Explore This
|
||||
Module</h2>
|
||||
</div>
|
||||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#overview">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
|
||||
more about this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#features">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
features of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#screenshots">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
screenshots of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF NAVIGATION SECTION -->
|
||||
|
||||
<!-- OVERVIEW SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pie-chart.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Overview
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 py-4">
|
||||
By using this module we can hide the options like create,delete,export,and archive/un archive in the model
|
||||
which we want. Here we are also able to select the user groups except Administrator which we want to apply the
|
||||
above hiding functionality </div>
|
||||
</div>
|
||||
<!-- END OF OVERVIEW SECTION -->
|
||||
|
||||
<!-- FEATURES SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/features.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Features
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div class="d-flex align-items-center" style="margin-top: 40px; margin-bottom: 40px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Easily hide the options like Create,Delete,Export and Archive/UnArchive</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific model</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific user group</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">No additional configuration needed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF FEATURES SECTION -->
|
||||
|
||||
<!-- SCREENSHOTS SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="screenshots">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pictures.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Screenshots
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Go to Settings > Users and there you can see the Configure Model Access, by enabling that
|
||||
option and refresh the page, you can see a new menu named 'Restrict Access Rights'</h3>
|
||||
<img src="assets/screenshots/model_access_right_01.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> User in the Purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_02.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Select the Model, Groups and the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_03.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> We can see Create option is hidden in purchase.order to those who are User
|
||||
in purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_04.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">User in Project module</h3>
|
||||
<img src="assets/screenshots/model_access_right_05.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> By default, we can see Export and Archive/UnArchive options</h3>
|
||||
<img src="assets/screenshots/model_access_right_06.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Select the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_07.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Export and Archive/UnArchive functionality are hidden</h3>
|
||||
<img src="assets/screenshots/model_access_right_08.png" class="img-thumbnail">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SCREENSHOTS SECTION -->
|
||||
<!-- RELATED PRODUCTS -->
|
||||
<div class="d-flex align-items-center"
|
||||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/categories.png"/>
|
||||
</div>
|
||||
<h2 class="mt-2"
|
||||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
|
||||
Related
|
||||
Products
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="demo1" class="row carousel slide" data-ride="carousel">
|
||||
<!-- The slideshow -->
|
||||
<div class="carousel-inner" style="padding: 30px;">
|
||||
<div class="carousel-item" style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_odoo_base/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/1.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/woo_commerce/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l2.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/shopify_odoo_connector/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l3.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item active"
|
||||
style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/hr_zk_attendance/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l4.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/whatsapp_redirect/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l5.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_website_product_media/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l6.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
|
||||
style="width:35px; color:#000"> <span
|
||||
class="carousel-control-prev-icon"><i
|
||||
class="fa fa-chevron-left"
|
||||
style="font-size:24px"></i></span>
|
||||
</a> <a class="carousel-control-next" href="#demo1"
|
||||
data-slide="next" style="width:35px; color:#000">
|
||||
<span class="carousel-control-next-icon"><i
|
||||
class="fa fa-chevron-right"
|
||||
style="font-size:24px"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF RELATED PRODUCTS -->
|
||||
|
||||
<!-- OUR SERVICES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/star.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our Services
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Customization</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Support</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Hire
|
||||
Odoo
|
||||
Developer</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Integration</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Migration</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Consultancy</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Licensing Consultancy</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR SERVICES -->
|
||||
|
||||
<!-- OUR INDUSTRIES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/corporate.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our
|
||||
Industries
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Trading
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easily procure
|
||||
and
|
||||
sell your products</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
POS
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easy
|
||||
configuration
|
||||
and convivial experience</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/education-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Education
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
A platform for
|
||||
educational management</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Manufacturing
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Plan, track and
|
||||
schedule your operations</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
E-commerce & Website
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Mobile
|
||||
friendly,
|
||||
awe-inspiring product pages</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Service Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Keep track of
|
||||
services and invoice</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Restaurant
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Run your bar or
|
||||
restaurant methodically</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Hotel Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
An
|
||||
all-inclusive
|
||||
hotel management application</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR INDUSTRIES -->
|
||||
|
||||
<!-- SUPPORT -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/customer-support.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Support
|
||||
</h2>
|
||||
</div>
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/support.png" height="48" width="48" style="width: 42px; height: 42px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>Need Help?</h4>
|
||||
<p style="line-height: 100%;">Got questions or need help? Get in touch.</p>
|
||||
<a href="mailto:odoo@cybrosys.com">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
|
||||
odoo@cybrosys.com</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/whatsapp.png" height="52" width="52" style="width: 52px; height: 52px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>WhatsApp</h4>
|
||||
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
|
||||
<a href="https://api.whatsapp.com/send?phone=918606827707">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">+91 86068
|
||||
27707</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
|
||||
<img src="assets/misc/logo.png" width="144" height="31"
|
||||
style="width:144px; height: 31px; margin-top: 40px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SUPPORT -->
|
||||
46
jikimo_hide_options/static/src/js/form_controller.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the form view
|
||||
*/
|
||||
import { FormController} from "@web/views/form/form_controller";
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const { onWillStart} = owl;
|
||||
patch(FormController.prototype, 'jikimo_hide_options/static/src/js/form_controller.js.FormController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the form view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.user.hasGroup(group)) {
|
||||
if (!this.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.canCreate = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
this.archInfo.activeActions.delete = false
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
42
jikimo_hide_options/static/src/js/kanban_controller.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { KanbanController } from '@web/views/kanban/kanban_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(KanbanController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.KanbanController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the Kanban view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.model.user.hasGroup(group)) {
|
||||
if (!self.model.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.props.archInfo.activeActions.create=false
|
||||
self.props.archInfo.activeActions.edit=false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.props.archInfo.activeActions.delete=false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
50
jikimo_hide_options/static/src/js/list_controller.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { ListController} from '@web/views/list/list_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(ListController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.ListController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the list view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.userService.hasGroup(group)) {
|
||||
if (!this.userService.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.activeActions.create = false;
|
||||
}
|
||||
if (result[i].is_export) {
|
||||
self.isExportEnable = false
|
||||
self.isExportEnable = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.activeActions.delete = false;
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false;
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
58
jikimo_hide_options/views/model_access_rights_views.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Action for the menu Restrict Model Access-->
|
||||
<record id="access_right_action" model="ir.actions.act_window">
|
||||
<field name="name">隐藏项目</field>
|
||||
<field name="res_model">access.right</field>
|
||||
<field name='view_mode'>tree,form</field>
|
||||
</record>
|
||||
<!-- Tree view for the model access.right-->
|
||||
<record id="access_right_view_tree" model="ir.ui.view">
|
||||
<field name="name">access.right.view.tree</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Form view for the model access.right-->
|
||||
<record id="access_right_view_form" model="ir.ui.view">
|
||||
<field name="name">access.right.view.form</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Creating a menu named Restrict Model Access-->
|
||||
<menuitem id="access_right_menu"
|
||||
name="隐藏项目"
|
||||
parent="base.menu_administration"
|
||||
action="access_right_action"
|
||||
sequence="6"
|
||||
groups="jikimo_hide_options.model_access_rights_groups_configure_model_access"/>
|
||||
</odoo>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||