463 lines
30 KiB
Python
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
|