Skip to content
Snippets Groups Projects
Commit bc5b7293 authored by gawa-odoo's avatar gawa-odoo Committed by Gauthier Wala (gawa)
Browse files

[FIX] analytic: allow filtering based on analytic distribution


Currently, the field `analytic_distribution` does not appear in
the filters, while it should (to be able to filter `account_move_line`
for example).
We added Json to the filterable fields. If not overriden, it will
search on it like a String.

We also have to add a non-stored field to be able to define a search
function for `analytic_distribution`, to be able to search based
on the keys of the json.

closes odoo/odoo#116496

Signed-off-by: default avatarWilliam André (wan) <wan@odoo.com>
parent ef09c121
No related branches found
No related tags found
No related merge requests found
......@@ -131,6 +131,12 @@ msgstr ""
msgid "Analytic Distribution Models"
msgstr ""
#. module: analytic
#: model:ir.model.fields,field_description:analytic.field_account_analytic_distribution_model__analytic_distribution_search
#: model:ir.model.fields,field_description:analytic.field_analytic_mixin__analytic_distribution_search
msgid "Analytic Distribution Search"
msgstr ""
#. module: analytic
#. odoo-javascript
#: code:addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js:0
......@@ -649,6 +655,13 @@ msgstr ""
msgid "Operating Costs"
msgstr ""
#. module: analytic
#. odoo-python
#: code:addons/analytic/models/analytic_mixin.py:0
#, python-format
msgid "Operation not supported"
msgstr ""
#. module: analytic
#. odoo-javascript
#: code:addons/analytic/static/src/components/analytic_distribution/analytic_distribution.js:0
......
......@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, fields, api, _
from odoo.tools.float_utils import float_round, float_compare
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError, ValidationError
class AnalyticMixin(models.AbstractModel):
_name = 'analytic.mixin'
......@@ -13,6 +13,11 @@ class AnalyticMixin(models.AbstractModel):
compute="_compute_analytic_distribution", store=True, copy=True, readonly=False,
precompute=True
)
# Json non stored to be able to search on analytic_distribution.
analytic_distribution_search = fields.Json(
store=False,
search="_search_analytic_distribution"
)
analytic_precision = fields.Integer(
store=False,
default=lambda self: self.env['decimal.precision'].precision_get("Percentage Analytic"),
......@@ -32,9 +37,38 @@ class AnalyticMixin(models.AbstractModel):
self.env.cr.execute(query)
super().init()
@api.model
def fields_get(self, allfields=None, attributes=None):
""" Hide analytic_distribution_search from filterable/searchable fields"""
res = super().fields_get(allfields, attributes)
if res.get('analytic_distribution_search'):
res['analytic_distribution_search']['searchable'] = False
return res
def _compute_analytic_distribution(self):
pass
def _search_analytic_distribution(self, operator, value):
if operator not in ['=', '!=', 'ilike', 'not ilike'] or not isinstance(value, (str, bool)):
raise UserError(_('Operation not supported'))
operator_name_search = '=' if operator in ('=', '!=') else 'ilike'
account_ids = list(self.env['account.analytic.account']._name_search(name=value, operator=operator_name_search))
query = f"""
SELECT id
FROM {self._table}
WHERE analytic_distribution ?| array[%s]
"""
operator_inselect = 'inselect' if operator in ('=', 'ilike') else 'not inselect'
return [('id', operator_inselect, (query, [[str(account_id) for account_id in account_ids]]))]
@api.model
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
for arg in args:
if isinstance(arg, (list, tuple)) and arg[0] == 'analytic_distribution' and isinstance(arg[2], str):
arg[0] = 'analytic_distribution_search'
return super()._search(args, offset, limit, order, count, access_rights_uid)
def write(self, vals):
""" Format the analytic_distribution float value, so equality on analytic_distribution can be done """
decimal_precision = self.env['decimal.precision'].precision_get('Percentage Analytic')
......
......@@ -23,6 +23,7 @@ const FIELD_TYPES = {
float: "number",
id: "id",
integer: "number",
json: "json",
html: "char",
many2many: "char",
many2one: "char",
......@@ -50,6 +51,14 @@ const FIELD_OPERATORS = {
{ symbol: "!=", description: _lt("is set"), value: false },
{ symbol: "=", description: _lt("is not set"), value: false },
],
json: [
{ symbol: "ilike", description: _lt("contains") },
{ symbol: "not ilike", description: _lt("doesn't contain") },
{ symbol: "=", description: _lt("is equal to") },
{ symbol: "!=", description: _lt("is not equal to") },
{ symbol: "!=", description: _lt("is set"), value: false },
{ symbol: "=", description: _lt("is not set"), value: false },
],
date: [
{ symbol: "=", description: _lt("is equal to") },
{ symbol: "!=", description: _lt("is not equal to") },
......
......@@ -88,6 +88,12 @@ QUnit.module("Search", (hooks) => {
type: "binary",
searchable: true,
},
json_field: {
name: "json_field",
string: "Jason",
type: "json",
searchable: true,
},
},
records: {},
},
......@@ -385,6 +391,58 @@ QUnit.module("Search", (hooks) => {
assert.containsOnce(target, ".o_add_custom_filter_menu .dropdown-menu");
});
QUnit.test("json field is available", async function (assert) {
assert.expect(10);
const controlPanel = await makeWithSearch({
serverData,
resModel: "foo",
Component: ControlPanel,
searchViewId: false,
searchMenuTypes: ["filter"],
searchViewFields: {
json_field: {
name: "json_field",
string: "Json",
type: "json",
default: "{'1': 50}",
searchable: true,
},
},
});
await toggleFilterMenu(target);
assert.deepEqual(getFacetTexts(target), []);
assert.deepEqual(getDomain(controlPanel), []);
assert.containsNone(target, ".o_menu_item");
assert.containsOnce(target, ".o_add_custom_filter_menu button.dropdown-toggle");
// the 'Add Custom Filter' menu should be closed;
assert.containsNone(target, ".o_add_custom_filter_menu .dropdown-menu");
await toggleAddCustomFilter(target);
// the 'Add Custom Filter' menu should be open;
assert.containsOnce(target, ".o_add_custom_filter_menu .dropdown-menu");
await editConditionField(target, 0, "json_field");
await applyFilter(target);
assert.deepEqual(getFacetTexts(target), ["Json contains \"\""]);
assert.deepEqual(getDomain(controlPanel), [["json_field", "ilike", ""]]);
await removeFacet(target);
await toggleFilterMenu(target);
await toggleAddCustomFilter(target);
await editConditionField(target, 0, "json_field");
await editConditionOperator(target, 0, "!=");
await applyFilter(target);
assert.deepEqual(getFacetTexts(target), ["Json is not equal to \"\""]);
assert.deepEqual(getDomain(controlPanel), [["json_field", "!=", ""]]);
});
QUnit.test("selection field: default and updated value", async function (assert) {
assert.expect(11);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment