[IMP] base_name_search_improved: patches
parent
6b66b2f323
commit
a768a1de63
|
@ -1,6 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from odoo import models
|
from odoo import SUPERUSER_ID, api, models
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -8,4 +8,8 @@ _logger = logging.getLogger(__name__)
|
||||||
def uninstall_hook(cr, registry):
|
def uninstall_hook(cr, registry):
|
||||||
_logger.info("Reverting Patches...")
|
_logger.info("Reverting Patches...")
|
||||||
models.BaseModel._revert_method("fields_view_get")
|
models.BaseModel._revert_method("fields_view_get")
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
env["ir.model.fields"].with_context(_force_unlink=True).search(
|
||||||
|
[("name", "=", "smart_search")]
|
||||||
|
).unlink()
|
||||||
_logger.info("Done!")
|
_logger.info("Done!")
|
||||||
|
|
|
@ -55,60 +55,7 @@ def _extend_name_results(self, domain, results, limit):
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
# TODO move all this to register_hook
|
def patch_name_search():
|
||||||
|
|
||||||
|
|
||||||
_add_magic_fields_original = models.BaseModel._add_magic_fields
|
|
||||||
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _add_magic_fields(self):
|
|
||||||
res = _add_magic_fields_original(self)
|
|
||||||
|
|
||||||
if (
|
|
||||||
"base_name_search_improved" in self.env.registry._init_modules
|
|
||||||
and "smart_search" not in self._fields
|
|
||||||
):
|
|
||||||
self._add_field(
|
|
||||||
"smart_search",
|
|
||||||
fields.Char(
|
|
||||||
automatic=True,
|
|
||||||
compute="_compute_smart_search",
|
|
||||||
search="_search_smart_search",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
models.BaseModel._add_magic_fields = _add_magic_fields
|
|
||||||
|
|
||||||
|
|
||||||
class IrModel(models.Model):
|
|
||||||
_inherit = "ir.model"
|
|
||||||
|
|
||||||
add_smart_search = fields.Boolean(help="Add Smart Search on search views",)
|
|
||||||
name_search_ids = fields.Many2many("ir.model.fields", string="Name Search Fields")
|
|
||||||
name_search_domain = fields.Char()
|
|
||||||
|
|
||||||
@api.constrains("name_search_ids", "name_search_domain", "add_smart_search")
|
|
||||||
def update_search_wo_restart(self):
|
|
||||||
self.clear_caches()
|
|
||||||
|
|
||||||
@api.constrains("name_search_domain")
|
|
||||||
def check_name_search_domain(self):
|
|
||||||
for rec in self.filtered("name_search_domain"):
|
|
||||||
name_search_domain = False
|
|
||||||
try:
|
|
||||||
name_search_domain = literal_eval(rec.name_search_domain)
|
|
||||||
except Exception as error:
|
|
||||||
raise ValidationError(
|
|
||||||
_("Couldn't eval Name Search Domain (%s)") % error
|
|
||||||
)
|
|
||||||
if not isinstance(name_search_domain, list):
|
|
||||||
raise ValidationError(_("Name Search Domain must be a list of tuples"))
|
|
||||||
|
|
||||||
def _register_hook(self):
|
|
||||||
def make_name_search():
|
|
||||||
@api.model
|
@api.model
|
||||||
def name_search(self, name="", args=None, operator="ilike", limit=100):
|
def name_search(self, name="", args=None, operator="ilike", limit=100):
|
||||||
limit = limit or 0
|
limit = limit or 0
|
||||||
|
@ -131,15 +78,11 @@ class IrModel(models.Model):
|
||||||
# Try regular search on each additional search field
|
# Try regular search on each additional search field
|
||||||
for rec_name in all_names[1:]:
|
for rec_name in all_names[1:]:
|
||||||
domain = [(rec_name, operator, name)]
|
domain = [(rec_name, operator, name)]
|
||||||
res = _extend_name_results(
|
res = _extend_name_results(self, base_domain + domain, res, limit)
|
||||||
self, base_domain + domain, res, limit
|
|
||||||
)
|
|
||||||
# Try ordered word search on each of the search fields
|
# Try ordered word search on each of the search fields
|
||||||
for rec_name in all_names:
|
for rec_name in all_names:
|
||||||
domain = [(rec_name, operator, name.replace(" ", "%"))]
|
domain = [(rec_name, operator, name.replace(" ", "%"))]
|
||||||
res = _extend_name_results(
|
res = _extend_name_results(self, base_domain + domain, res, limit)
|
||||||
self, base_domain + domain, res, limit
|
|
||||||
)
|
|
||||||
# Try unordered word search on each of the search fields
|
# Try unordered word search on each of the search fields
|
||||||
# we only perform this search if we have at least one
|
# we only perform this search if we have at least one
|
||||||
# separator character
|
# separator character
|
||||||
|
@ -153,14 +96,13 @@ class IrModel(models.Model):
|
||||||
word_domain and ["|"] + word_domain or word_domain
|
word_domain and ["|"] + word_domain or word_domain
|
||||||
) + [(rec_name, operator, word)]
|
) + [(rec_name, operator, word)]
|
||||||
domain = (domain and ["&"] + domain or domain) + word_domain
|
domain = (domain and ["&"] + domain or domain) + word_domain
|
||||||
res = _extend_name_results(
|
res = _extend_name_results(self, base_domain + domain, res, limit)
|
||||||
self, base_domain + domain, res, limit
|
|
||||||
)
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
return name_search
|
return name_search
|
||||||
|
|
||||||
|
|
||||||
def patch_fields_view_get():
|
def patch_fields_view_get():
|
||||||
@api.model
|
@api.model
|
||||||
def fields_view_get(
|
def fields_view_get(
|
||||||
|
@ -180,9 +122,7 @@ class IrModel(models.Model):
|
||||||
placeholder = placeholders[0]
|
placeholder = placeholders[0]
|
||||||
else:
|
else:
|
||||||
placeholder = eview.xpath("//search")[0]
|
placeholder = eview.xpath("//search")[0]
|
||||||
placeholder.addnext(
|
placeholder.addnext(etree.Element("field", {"name": "smart_search"}))
|
||||||
etree.Element("field", {"name": "smart_search"})
|
|
||||||
)
|
|
||||||
eview.remove(placeholder)
|
eview.remove(placeholder)
|
||||||
res["arch"] = etree.tostring(eview)
|
res["arch"] = etree.tostring(eview)
|
||||||
res["fields"].update(self.fields_get(["smart_search"]))
|
res["fields"].update(self.fields_get(["smart_search"]))
|
||||||
|
@ -190,6 +130,16 @@ class IrModel(models.Model):
|
||||||
|
|
||||||
return fields_view_get
|
return fields_view_get
|
||||||
|
|
||||||
|
|
||||||
|
class Base(models.AbstractModel):
|
||||||
|
|
||||||
|
_inherit = "base"
|
||||||
|
|
||||||
|
# TODO perhaps better to create only the field when enabled on the model
|
||||||
|
smart_search = fields.Char(
|
||||||
|
compute="_compute_smart_search", search="_search_smart_search",
|
||||||
|
)
|
||||||
|
|
||||||
def _compute_smart_search(self):
|
def _compute_smart_search(self):
|
||||||
self.smart_search = False
|
self.smart_search = False
|
||||||
|
|
||||||
|
@ -220,11 +170,32 @@ class IrModel(models.Model):
|
||||||
return domain
|
return domain
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# add methods of computed fields
|
|
||||||
if not hasattr(models.BaseModel, "_compute_smart_search"):
|
class IrModel(models.Model):
|
||||||
models.BaseModel._compute_smart_search = _compute_smart_search
|
_inherit = "ir.model"
|
||||||
if not hasattr(models.BaseModel, "_search_smart_search"):
|
|
||||||
models.BaseModel._search_smart_search = _search_smart_search
|
add_smart_search = fields.Boolean(help="Add Smart Search on search views",)
|
||||||
|
name_search_ids = fields.Many2many("ir.model.fields", string="Name Search Fields")
|
||||||
|
name_search_domain = fields.Char()
|
||||||
|
|
||||||
|
@api.constrains("name_search_ids", "name_search_domain", "add_smart_search")
|
||||||
|
def update_search_wo_restart(self):
|
||||||
|
self.clear_caches()
|
||||||
|
|
||||||
|
@api.constrains("name_search_domain")
|
||||||
|
def check_name_search_domain(self):
|
||||||
|
for rec in self.filtered("name_search_domain"):
|
||||||
|
name_search_domain = False
|
||||||
|
try:
|
||||||
|
name_search_domain = literal_eval(rec.name_search_domain)
|
||||||
|
except Exception as error:
|
||||||
|
raise ValidationError(
|
||||||
|
_("Couldn't eval Name Search Domain (%s)") % error
|
||||||
|
)
|
||||||
|
if not isinstance(name_search_domain, list):
|
||||||
|
raise ValidationError(_("Name Search Domain must be a list of tuples"))
|
||||||
|
|
||||||
|
def _register_hook(self):
|
||||||
|
|
||||||
_logger.info("Patching fields_view_get on BaseModel")
|
_logger.info("Patching fields_view_get on BaseModel")
|
||||||
models.BaseModel._patch_method("fields_view_get", patch_fields_view_get())
|
models.BaseModel._patch_method("fields_view_get", patch_fields_view_get())
|
||||||
|
@ -232,7 +203,7 @@ class IrModel(models.Model):
|
||||||
for model in self.sudo().search(self.ids or []):
|
for model in self.sudo().search(self.ids or []):
|
||||||
Model = self.env.get(model.model)
|
Model = self.env.get(model.model)
|
||||||
if Model is not None:
|
if Model is not None:
|
||||||
Model._patch_method("name_search", make_name_search())
|
Model._patch_method("name_search", patch_name_search())
|
||||||
|
|
||||||
return super(IrModel, self)._register_hook()
|
return super(IrModel, self)._register_hook()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue