Files
test/sf_global_search/models/global_search.py
2023-04-24 16:00:08 +08:00

463 lines
30 KiB
Python

# Copyright (C) Softhealer Technologies.
from odoo import fields, models, api, _
from odoo.exceptions import UserError
FIELD_TYPES = [(key, key) for key in sorted(fields.Field.by_type)]
from odoo import api, fields, models, _
from odoo.osv import expression
class ResCompany(models.Model):
_inherit = 'res.company'
enable_menu_search = fields.Boolean(
"Enable Menu Global Search", default=True)
start_search_after_letter = fields.Integer(
"Search Start After Letter", default=0)
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
enable_menu_search = fields.Boolean(
related="company_id.enable_menu_search", string="Enable Menu Global Search", readonly=False)
start_search_after_letter = fields.Integer(
related="company_id.start_search_after_letter", string="Search Start After Letter", readonly=False)
class GlobalSearch(models.Model):
_name = 'global.search'
_description = 'Global search'
_rec_name = 'model_id'
model_id = fields.Many2one('ir.model', string='Applies To', required=True, index=True, ondelete='cascade',
help="The model this field belongs to")
field_ids = fields.Many2many(
'ir.model.fields', string='Fields', domain="[('model_id','=',model_id)]")
main_field_id = fields.Many2one('ir.model.fields', string="Name Field",
required=True, domain="[('model_id','=',model_id)]", ondelete='cascade')
global_field_ids = fields.One2many(
'global.search.fields', 'global_search_id', string='Fields ')
@api.model
def get_search_result(self, query):
search_result = {}
if self.env.user.company_id.enable_menu_search:
menu_roots = self.env['ir.ui.menu'].search(
[('parent_id', '=', False)])
menu_data = self.env['ir.ui.menu'].search(
[('id', 'child_of', menu_roots.ids), ('action', '!=', False)])
if menu_data:
menu_data = menu_data._filter_visible_menus()
for menu in menu_data:
if query[0].lower() in menu.complete_name.lower():
search_result['menu| '+menu.complete_name] = {
'id': menu.id, 'action': menu.action.id, 'name': menu.complete_name}
# if company id field is not in model
for search_rec in self.env['global.search'].sudo().search([]):
# All Field List including name field
normal_fields_list = []
m2o_fields_list = []
o2m_fields_list = []
for fields in search_rec.global_field_ids:
field = fields.field_id
if field.ttype in ['char', 'boolean', 'text', 'date', 'datetime', 'float', 'integer', 'selection', 'monetary', 'html']:
normal_fields_list.append(field)
elif field.ttype in ['many2one']:
if search_rec.main_field_id not in m2o_fields_list:
m2o_fields_list.append(search_rec.main_field_id)
m2o_fields_list.append(field)
elif field.ttype in ['one2many']:
o2m_fields_list.append(field)
# Fetch all record of this current model with defined field list
try:
# check company_id field in model
company_id_field = self.env['ir.model.fields'].sudo().search(
[('name', '=', 'company_id'), ('model_id', '=', search_rec.model_id.id)])
if not company_id_field:
if normal_fields_list:
normal_fields = []
domain = []
count = 0
for field_row in normal_fields_list:
field = field_row.name
normal_fields.append(field)
if field != 'display_name':
domain.append((field, 'ilike', query[0]))
else:
count += 1
if normal_fields:
model_obj = self.env[search_rec.model_id.model].search_read(domain, normal_fields, order='id')
for model_rec in model_obj:
for field_row in normal_fields_list:
field = field_row
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
model_rec['model'] = field.model_id.model
model_rec['model_name'] = field.model_id.name
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
search_result[self.env.user.company_id.name+'|'+search_result_record+' > '+field.field_description+' : '+str(
object_data)] = model_rec
if count != 0:
field_list = ['display_name']
model_obj = self.env[search_rec.model_id.model].search_read(
[], field_list, order='id')
for model_rec in model_obj:
if model_rec.get('display_name'):
object_data = model_rec.get('display_name')
if object_data and query[0].lower() in str(object_data).casefold():
model_rec['model'] = search_rec.model_id.model
model_rec['model_name'] = search_rec.model_id.name
search_result[self.env.user.company_id.name+'|'+"Display Name"+' : '+str(
object_data)] = model_rec
if m2o_fields_list:
m2o_fields = []
domain = []
for field_row in m2o_fields_list:
field = field_row.name
m2o_fields.append(field)
domain.append(('%s.name' %(field), 'ilike', query[0]))
model_obj = self.env[search_rec.model_id.model].search_read(domain, m2o_fields, order='id')
for model_rec in model_obj:
for field_row in m2o_fields_list:
field = field_row
if field.name != 'display_name':
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
model_rec['model'] = field.model_id.model
model_rec['model_name'] = field.model_id.name
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
str_object_data = str(
object_data[1])
search_result[self.env.user.company_id.name+'|'+search_result_record+' > ' +
field.field_description+' : '+str_object_data] = model_rec
if o2m_fields_list:
for super_field_row in o2m_fields_list:
field = super_field_row.field_id.name
inside_normal_fields = []
inside_m2o_field_list = []
for o2m_field in super_field_row.field_ids:
field = o2m_field.field_id
if field.ttype in ['char', 'boolean', 'text', 'date', 'datetime', 'float', 'integer', 'selection', 'monetary', 'html']:
inside_normal_fields.append(field)
elif field.ttype in ['many2one']:
inside_m2o_field_list.append(field)
if search_rec.main_field_id not in inside_m2o_field_list:
inside_m2o_field_list.append(search_rec.main_field_id)
if search_rec.main_field_id not in inside_normal_fields:
inside_normal_fields.append(search_rec.main_field_id)
if inside_normal_fields:
normal_fields = []
domain = []
for field_row in inside_normal_fields:
field = field_row.name
normal_fields.append(field)
domain.append((field, 'ilike', query[0]))
model_obj = self.env[search_rec.model_id.model].search_read(domain, normal_fields, order='id')
for model_rec in model_obj:
for field_row in inside_normal_fields:
field = field_row
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
some_id = model_rec['id']
some_record = self.env[super_field_row.model_id.model].browse(some_id)
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
parent_obj = getattr(some_record, super_field_row.field_id.relation_field)
model_rec['model'] = parent_obj._name
model_rec['model_name'] = parent_obj._name.upper()
model_rec['id'] = parent_obj.id
str_object_data = str(
object_data)
search_result[self.env.user.company_id.name+'|'+parent_obj.name+' > ' +
field.field_description+' : '+str_object_data] = model_rec
if inside_m2o_field_list:
m2o_fields = []
domain = []
for field_row in inside_m2o_field_list:
field = field_row.name
m2o_fields.append(field)
domain.append(('%s.name' %(field), 'ilike', query[0]))
model_obj = self.env[search_rec.model_id.model].search_read(domain, m2o_fields, order='id')
for model_rec in model_obj:
for field_row in inside_m2o_field_list:
field = field_row
if field.name != 'display_name':
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
some_id = model_rec['id']
some_record = self.env[super_field_row.model_id.model].browse(some_id)
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
parent_obj = getattr(some_record, super_field_row.field_id.relation_field)
model_rec['model'] = parent_obj._name
model_rec['model_name'] = parent_obj._name.upper()
model_rec['id'] = parent_obj.id
str_object_data = str(
object_data[1])
search_result[self.env.user.company_id.name+'|'+parent_obj.name+' > ' +
field.field_description+' : '+str_object_data] = model_rec
except Exception as e:
print(e)
# if company id field is in model
# All Global Search Records
count = 1
for company in self.env['res.company'].search([]):
print("\n\n\n self.env.context.get('allowed_company_ids')",self.env.context)
# in self.env.context.get('allowed_company_ids')
if company.id:
for search_rec in self.env['global.search'].sudo().search([]):
# All Field List including name field
field_list = []
for field in search_rec.global_field_ids:
field_list.append(field.field_id.name)
if search_rec.main_field_id.name not in field_list:
field_list.append(search_rec.main_field_id.name)
normal_fields_list = []
m2o_fields_list = []
o2m_fields_list = []
external_addition = 0
for fields in search_rec.global_field_ids:
field = fields.field_id
if field.ttype in ['char', 'boolean', 'text', 'date', 'datetime', 'float', 'integer', 'selection', 'monetary', 'html']:
normal_fields_list.append(field)
elif field.ttype in ['many2one']:
m2o_fields_list.append(field)
elif field.ttype in ['one2many']:
o2m_fields_list.append(fields)
if search_rec.main_field_id not in m2o_fields_list:
m2o_fields_list.append(search_rec.main_field_id)
if search_rec.main_field_id not in normal_fields_list:
external_addition += 1
normal_fields_list.append(search_rec.main_field_id)
try:
# check company_id field in model
company_id_field = self.env['ir.model.fields'].sudo().search(
[('name', '=', 'company_id'), ('model_id', '=', search_rec.model_id.id)])
if company_id_field:
if normal_fields_list:
normal_fields = [field_row.name for field_row in normal_fields_list]
domain = []
domain_multi_company = [('company_id', 'in', [company.id,False])]
field_domain = expression.OR([[(field_row.name, 'ilike', query[0])] for field_row in normal_fields_list if field_row.name != 'display_name'])
domain = expression.AND([domain_multi_company, field_domain])
if normal_fields:
model_obj = self.env[search_rec.model_id.model].search_read(domain, normal_fields, order='id')
for model_rec in model_obj:
for field_row in normal_fields_list:
field = field_row
if field.name != 'display_name':
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
model_rec['model'] = field.model_id.model
model_rec['model_name'] = field.model_id.name
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
search_result[company.name+'|'+search_result_record+' > '+field.field_description+' : '+str(
object_data)] = model_rec
if external_addition == 0:
field_list = ['display_name']
model_obj = self.env[search_rec.model_id.model].search_read(
['|', ('company_id', '=', company.id), ('company_id', '=', False)], field_list, order='id')
for model_rec in model_obj:
if model_rec.get('display_name'):
object_data = model_rec.get('display_name')
if object_data and query[0].lower() in str(object_data).casefold():
model_rec['model'] = search_rec.model_id.model
model_rec['model_name'] = search_rec.model_id.name
search_result[company.name+'|'+"Display Name"+' : '+str(
object_data)] = model_rec
if m2o_fields_list:
m2o_fields = [field_row.name for field_row in m2o_fields_list]
domain = []
domain_multi_company = [('company_id', 'in', [company.id,False])]
field_domain = expression.OR([[('%s.name' %(field_row.name), 'ilike', query[0])] for field_row in m2o_fields_list if field_row.name != 'display_name'])
domain = expression.AND([domain_multi_company, field_domain])
model_obj = self.env[search_rec.model_id.model].search_read(domain, m2o_fields, order='id')
for model_rec in model_obj:
for field_row in m2o_fields_list:
field = field_row
if field.name != 'display_name':
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data[1]).casefold():
model_rec['model'] = field.model_id.model
model_rec['model_name'] = field.model_id.name
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
str_object_data = str(
object_data[1])
search_result[company.name+'|'+search_result_record+' > ' +
field.field_description+' : '+str_object_data] = model_rec
if o2m_fields_list:
for super_field_row in o2m_fields_list:
field = super_field_row.field_id.name
inside_normal_fields = []
inside_m2o_field_list = []
for o2m_field in super_field_row.field_ids:
field = o2m_field.field_id
if field.ttype in ['char', 'boolean', 'text', 'date', 'datetime', 'float', 'integer', 'selection', 'monetary', 'html']:
inside_normal_fields.append(field)
elif field.ttype in ['many2one']:
if search_rec.main_field_id not in inside_m2o_field_list:
inside_m2o_field_list.append(search_rec.main_field_id)
inside_m2o_field_list.append(field)
if search_rec.main_field_id not in inside_normal_fields:
inside_normal_fields.append(search_rec.main_field_id)
if inside_normal_fields:
normal_fields = [field_row.name for field_row in inside_normal_fields]
domain = []
domain_multi_company = [('company_id', 'in', [company.id,False])]
field_domain = expression.OR([[(field_row.name, 'ilike', query[0])] for field_row in inside_normal_fields if field_row.name != 'display_name'])
domain = expression.AND([domain_multi_company, field_domain])
model_obj = self.env[super_field_row.related_model_id].search_read(domain, normal_fields, order='id')
for model_rec in model_obj:
for field_row in inside_normal_fields:
field = field_row
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data).casefold():
some_id = model_rec['id']
some_record = self.env[super_field_row.model_id.model].browse(some_id)
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
parent_obj = getattr(some_record, super_field_row.field_id.relation_field)
model_rec['model'] = parent_obj._name
model_rec['model_name'] = parent_obj._name.upper()
model_rec['id'] = parent_obj.id
str_object_data = str(
object_data)
search_result[company.name+'|'+parent_obj.name+' > ' +
field.field_description+' : '+str_object_data] = model_rec
if inside_m2o_field_list:
m2o_fields = [field_row.name for field_row in inside_m2o_field_list]
domain = []
domain_multi_company = [('company_id', 'in', [company.id,False])]
if len(m2o_fields) > 1:
field_domain = expression.OR([[('%s.name' %(field_row.name), 'ilike', query[0])] for field_row in inside_m2o_field_list if field_row.name != 'display_name'])
else:
field_domain = ([('%s.name' %(field_row.name), 'ilike', query[0])] for field_row in m2o_fields)
domain = expression.AND([domain_multi_company, field_domain])
model_obj = self.env[super_field_row.related_model_id].search_read(domain, m2o_fields, order='id')
for model_rec in model_obj:
for field_row in inside_m2o_field_list:
field = field_row
if field.name != 'display_name':
if model_rec.get(field.name):
object_data = model_rec.get(field.name)
if object_data and query[0].lower() in str(object_data[1]).casefold():
some_id = model_rec['id']
some_record = self.env[super_field_row.model_id.model].browse(some_id)
search_result_record = model_rec.get(
search_rec.main_field_id.name) or ''
parent_obj = getattr(some_record, super_field_row.field_id.relation_field)
model_rec['model'] = parent_obj._name
model_rec['model_name'] = parent_obj._name.upper()
model_rec['id'] = parent_obj.id
str_object_data = str(
object_data[1])
search_result[company.name+'|'+parent_obj.name+' > ' +
field.field_description+' : '+str_object_data] = model_rec
except Exception as e:
print(e)
return search_result
class GlobalSearchFields(models.Model):
_name = 'global.search.fields'
_description = 'Global search fields'
global_search_id = fields.Many2one('global.search', string='Related Model')
sequence = fields.Integer(string='Sequence', default=10)
field_id = fields.Many2one(
'ir.model.fields', string='Position Field', ondelete='cascade')
name = fields.Char("Label", related="field_id.field_description")
model_id = fields.Many2one('ir.model', string='Model', ondelete='cascade')
related_model_id = fields.Char(
string='Relation With', related="field_id.relation")
ttype = fields.Selection(
string='Field Type', required=True, related="field_id.ttype")
field_ids = fields.One2many(
'o2m.global.search.fields', 'global_o2m_search_id', string='Fields')
@api.onchange('field_id')
def _onchange_field_id(self):
if self.field_id:
if self.field_id.relation:
model = self.env['ir.model'].sudo().search(
[('model', '=', self.field_id.relation)], limit=1)
if model:
self.model_id = model.id
def sh_o2m_dynamic_action_action(self):
if self.ttype == 'one2many':
view = self.env.ref('sf_global_search.sh_o2m_global_search_form')
return {
'name': _('O2M Object Fields'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'global.search.fields',
'views': [(view.id, 'form')],
'view_id': view.id,
'target': 'new',
'res_id': self.id,
}
else:
view = self.env.ref('sf_global_search.sh_m2o_global_search_form')
return {
'name': _('M2O Object Fields'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'global.search.fields',
'views': [(view.id, 'form')],
'view_id': view.id,
'target': 'new',
'res_id': self.id,
}
class O2MGlobalSearch(models.Model):
_name = 'o2m.global.search.fields'
_description = 'O2m Global search fields'
sequence = fields.Integer(string='Sequence', default=10)
name = fields.Char("Label")
field_id = fields.Many2one(
'ir.model.fields', string='Position Field', ondelete='cascade')
global_o2m_search_id = fields.Many2one(
'global.search.fields', string='Global O2M Search', ondelete='cascade')
model_id = fields.Many2one(
'ir.model', string='Relation With ', ondelete='cascade')
related_model_id = fields.Char(
string='Relation With', related="field_id.relation")
ttype = fields.Selection(
string='Field Type', required=True, related="field_id.ttype")
@api.onchange('field_id')
def _onchange_field_id(self):
if self.field_id:
if self.field_id.ttype in ['one2many', 'many2many']:
raise UserError(
"Field type One2many and Many2many not supported inside O2M wizard !")
self.name = self.field_id.field_description
if self.field_id.relation:
model = self.env['ir.model'].sudo().search(
[('model', '=', self.field_id.relation)], limit=1)
if model:
self.model_id = model.id