Odoo 17中如何显示hr.applicant的归档重复记录?
问题描述
开发的重复记录检测功能可在弹窗下拉列表展示活跃重复项,但无法显示归档状态的重复记录。日志显示已检测到归档重复项(ID:8,active为False),但下拉列表中无法看到该记录。
hr_applicant模型代码
selected_duplicate_id = fields.Many2one('hr.applicant', string="选中的重复项", domain="[('id', 'in', duplicate_ids)]") duplicate_ids = fields.Many2many( 'hr.applicant', string="重复项", compute='_compute_duplicates', store=False ) show_duplicates_warning = fields.Boolean( string="显示警告", compute='_compute_duplicates' ) @api.model def name_search(self, name='', args=None, operator='ilike', limit=100): args = list(args or []) _logger.info("name_search called with name=%s, args=%s, context=%s", name, args, self._context) if self._context.get('active_test') is False: args = [arg for arg in args if arg[0] != 'active'] args = expression.AND([args, [('active', 'in', [True, False])]]) duplicate_ids = self._context.get('duplicate_ids', []) if duplicate_ids: args = expression.AND([args, [('id', 'in', duplicate_ids)]]) else: for arg in args: if arg[0] == 'id' and arg[1] == 'in' and not arg[2]: _logger.warning("Empty id list in name_search args: %s", args) return [] result = super(Applicant, self).name_search(name=name, args=args, operator=operator, limit=limit) _logger.info("name_search result: %s", result) return result @api.depends('email_from', 'partner_mobile_sanitized') def _compute_duplicates(self): for applicant in self: duplicates = self.env['hr.applicant'] if applicant.email_normalized or applicant.partner_mobile_sanitized: domain = applicant._get_similar_applicants_domain() _logger.info("Domain for applicant %s: %s", applicant.id, domain) if domain: duplicates = self.env['hr.applicant'].with_context(active_test=False).search(domain) _logger.info("Duplicates for applicant %s: %s (Active: %s)", applicant.id, duplicates.ids, [d.active for d in duplicates]) applicant.duplicate_ids = duplicates applicant.show_duplicates_warning = bool(duplicates) if applicant.selected_duplicate_id and applicant.selected_duplicate_id.id not in duplicates.ids: applicant.selected_duplicate_id = False @api.depends('email_from', 'partner_mobile_sanitized') def _compute_application_count(self): if not any(self._ids): for applicant in self: duplicates = self.env['hr.applicant'].with_context( active_test=False ) if applicant.email_normalized or applicant.partner_mobile_sanitized: domain = applicant._get_similar_applicants_domain() if domain: duplicates = self.env['hr.applicant'].with_context( active_test=False ).search(domain) applicant.application_count = len(duplicates) _logger.info("Found duplicates (active/inactive): %s", [(d.id, d.partner_name, d.active) for d in applicant.duplicate_ids]) return self.flush_recordset(['email_normalized', 'partner_mobile_sanitized']) self.env.cr.execute(""" SELECT a.id, ( SELECT COUNT(*) FROM hr_applicant AS sub WHERE a.id != sub.id AND sub.create_date < a.create_date AND ((a.email_normalized <> '' AND a.email_normalized = sub.email_normalized) OR (a.partner_mobile_sanitized <> '' AND a.partner_mobile_sanitized = sub.partner_mobile_sanitized)) AND (sub.active = TRUE OR sub.active = FALSE) ) AS similar_applicants FROM hr_applicant AS a WHERE id IN %(ids)s """, {'ids': tuple(self._origin.ids)}) query_results = self.env.cr.dictfetchall() mapped_data = {result['id']: result['similar_applicants'] for result in query_results} for applicant in self: applicant.application_count = mapped_data.get(applicant.id, 0) def action_show_duplicates_dialog(self): self.ensure_one() self._compute_duplicates() _logger.info("Opening duplicates dialog for applicant %s with duplicates: %s", self.id, self.duplicate_ids.ids) return { 'name': '检测到重复项', 'type': 'ir.actions.act_window', 'res_model': 'hr.applicant', 'view_mode': 'form', 'views': [(self.env.ref('hr_recruitment.hr_applicant_view_form').id, 'form')], 'target': 'new', 'res_id': self.id, 'context': { 'dialog_size': 'large', 'create': False, 'edit': False, 'active_test': False, 'default_duplicate_ids': self.duplicate_ids.ids, 'duplicate_ids': self.duplicate_ids.ids, } }
XML表单代码
<h4><i class="fa fa-warning me-2"/>检测到重复项!</h4> <field name="duplicate_ids" widget="many2many_tags" options="{'no_create': True}"/> <div class="row mt-2"> <div class="col-md-12"> <div class="o_form_label">选择要合并的主记录:</div> <field name="selected_duplicate_id" widget="many2one" options="{'no_create': True, 'no_open': True}" context="{'active_test': False, 'hr_force_show_archived': True, 'search_default_duplicates': True}" domain="[('id', 'in', duplicate_ids)]" class="oe_inline w-100"/> </div> </div>
日志信息
odoo-1 | 2025-07-18 15:13:31,399 1 INFO Test odoo.tools.translate: Domain for applicant 9: ['&', '&', '|', ('email_normalized', '=ilike', 'test@gmail.com'), ('partner_mobile_sanitized', '=', '958604986'), ('id', '!=', 9), ('active', 'in', [True, False])] odoo-1 | 2025-07-18 15:13:31,401 1 INFO Test odoo.tools.translate: Duplicates for applicant 9: [8] (Active: [False])
排查与解决步骤
从日志可知,_compute_duplicates已正确获取到归档重复记录,但下拉列表不显示,问题出在name_search逻辑或上下文传递:
修正
name_search的active过滤逻辑
当前代码用expression.AND合并条件可能存在优先级问题,直接追加active条件更可靠:@api.model def name_search(self, name='', args=None, operator='ilike', limit=100): args = list(args or []) _logger.info("name_search called with name=%s, args=%s, context=%s", name, args, self._context) if self._context.get('active_test') is False: # 移除所有active相关条件,明确包含所有状态记录 args = [arg for arg in args if arg[0] != 'active'] args.append(('active', 'in', [True, False])) duplicate_ids = self._context.get('duplicate_ids', []) if duplicate_ids: args = expression.AND([args, [('id', 'in', duplicate_ids)]]) else: for arg in args: if arg[0] == 'id' and arg[1] == 'in' and not arg[2]: _logger.warning("Empty id list in name_search args: %s", args) return [] result = super(Applicant, self).name_search(name=name, args=args, operator=operator, limit=limit) _logger.info("name_search result: %s", result) return result确认上下文传递有效性
检查name_search日志中的self._context是否包含active_test=False和duplicate_ids=[8]。如果上下文未正确传递,需确保弹窗的context与字段的context叠加生效(当前XML和弹窗逻辑已设置,大概率没问题)。验证返回结果
修改后查看name_search result日志,确认返回结果包含ID8的记录。若后端返回但前端不显示,需检查前端是否有额外过滤逻辑(Odoo默认不会做此处理)。
内容的提问来源于stack exchange,提问作者tonbari
相关产品推荐
相关产品推荐

