I already tried everything and searched everywhere for an answer but I wasn't successful.
I want to implement a custom function to retrieve filtered values for a Many2one selection list. Usually you would use a domain for that but the domain-options given are not sufficient to achieve my goal.
What function do I have to override to modify the selection list for a given Many2one field?
Thank you, Lars
UPDATE:
Thank you for your answers. I used name_search
to analyze the generated WHERE clause.
Here what I want to achieve and my findings so far:
programs = fields.Many2many(
comodel_name='hr.program',
relation='hr_process_onboarding_wizard_programs')
program_department = fields.Many2one(
comodel_name='hr.department',
domain="[('programs', 'in', programs)]")
Field programs is represented as a many2many_checkboxes widget.
When I select 2 values, the following domain-filter is being passed to name_search
: ['programs', 'in', [1, 2]]
This will generate the following SQL-Query (excerpt of the interesting part): (SELECT "hr_department_id" FROM "hr_programs_departments" WHERE "hr_program_id" IN (1,2))
The result list is of course the UNION of programs [1,2] but I would expect the INTERSECTION of programs [1,2].
Afaik there is no domain filter to get the intersection.
UPDATE 2:
After thinking about the given filter operators I would expect =
to do exactly what I want but operator =
is generating the same WHERE clause as for in
.
This is my quick-hack solution using name_search
in class HrDepartment
.
I added a attribute context="{'intersect': True}"
to the field in the corresponding view to be failsafe in other contexts.
The domain
is still in place and being used in must_contain_programs
.
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
is_intersect_context = self._context.get('intersect')
must_contain_programs = args[0][2]
if(is_intersect_context and len(must_contain_programs) > 1):
all_departments = self.env['hr.department'].search([])
filtered_departments = []
for department in all_departments:
if all(program_id in department.programs.ids for program_id in must_contain_programs):
filtered_departments.append(department)
if len(filtered_departments) > 0:
intersect_res = []
for filtered_department in filtered_departments:
intersect_res.append((filtered_department.id, filtered_department.name))
intersect_res.sort(key=lambda tuple: tuple[0])
if name != '':
res = list(filter(lambda tuple: name.upper() in tuple[1].upper(), intersect_res))
else:
res = intersect_res
else:
res = super(HrDepartment, self).name_search(name, args, operator, limit)
return res