diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py index 0b2c0379a4a..ef421dbe916 100644 --- a/addons/hr_recruitment/models/hr_recruitment.py +++ b/addons/hr_recruitment/models/hr_recruitment.py @@ -180,7 +180,7 @@ class Applicant(models.Model): legend_blocked = fields.Char(related='stage_id.legend_blocked', string='Kanban Blocked') legend_done = fields.Char(related='stage_id.legend_done', string='Kanban Valid') legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing') - application_count = fields.Integer(compute='_compute_application_count', help='Applications with the same email') + application_count = fields.Integer(compute='_compute_application_count', help='Applications with the same email or phone or mobile') refuse_reason_id = fields.Many2one('hr.applicant.refuse.reason', string='Refuse Reason', tracking=True) meeting_ids = fields.One2many('calendar.event', 'applicant_id', 'Meetings') meeting_display_text = fields.Char(compute='_compute_meeting_display') @@ -215,40 +215,42 @@ class Applicant(models.Model): applicant.day_close = False applicant.delay_close = False - @api.depends('email_from') + @api.depends('email_from', 'partner_phone', 'partner_mobile') def _compute_application_count(self): self.flush(fnames=['email_from']) - # Filter and gather emails at the same time applicants = self.env['hr.applicant'] - mails = set() for applicant in self: - if applicant.email_from: + if applicant.email_from or applicant.partner_phone or applicant.partner_mobile: applicants |= applicant - mails.add(applicant.email_from.lower()) # Done via SQL since read_group does not support grouping by lowercase field - if mails: + if applicants.ids: query = Query(self.env.cr, self._table, self._table_query) - query.add_where('LOWER("hr_applicant".email_from) in %s', [tuple(mails)]) + query.add_where('hr_applicant.id in %s', [tuple(applicants.ids)]) + # Count into the companies that are selected from the multi-company widget + company_ids = self.env.context.get('allowed_company_ids') + if company_ids: + query.add_where('other.company_id in %s', [tuple(company_ids)]) self._apply_ir_rules(query) from_clause, where_clause, where_clause_params = query.get_sql() + # In case the applicant phone or mobile is configured in wrong field query_str = """ - SELECT LOWER("%(table)s".email_from) as l_email_from, - COUNT("%(table)s".id) as count - FROM %(from)s + SELECT hr_applicant.id as appl_id, + COUNT(other.id) as count + FROM hr_applicant + JOIN hr_applicant other ON LOWER(other.email_from) = LOWER(hr_applicant.email_from) + OR other.partner_phone = hr_applicant.partner_phone OR other.partner_phone = hr_applicant.partner_mobile + OR other.partner_mobile = hr_applicant.partner_mobile OR other.partner_mobile = hr_applicant.partner_phone %(where)s - GROUP BY l_email_from + GROUP BY hr_applicant.id """ % { - 'table': self._table, - 'from': from_clause, 'where': ('WHERE %s' % where_clause) if where_clause else '', } self.env.cr.execute(query_str, where_clause_params) - - application_data_mapped = dict((data['l_email_from'], data['count']) for data in self.env.cr.dictfetchall()) + application_data_mapped = dict((data['appl_id'], data['count']) for data in self.env.cr.dictfetchall()) else: application_data_mapped = dict() for applicant in applicants: - applicant.application_count = application_data_mapped.get(applicant.email_from.lower(), 1) - 1 + applicant.application_count = application_data_mapped.get(applicant.id, 1) - 1 (self - applicants).application_count = False @api.depends_context('lang') @@ -487,16 +489,15 @@ class Applicant(models.Model): } def action_applications_email(self): - # Security rules will apply when loading the view, here we just fetch the ids - mails = set() - for applicant in self: - if applicant.email_from: - mails.add(applicant.email_from.lower()) + self.ensure_one() self.env.cr.execute(""" - SELECT id + SELECT other.id FROM hr_applicant - WHERE LOWER(email_from) in %s - """, (tuple(mails),) + JOIN hr_applicant other ON LOWER(other.email_from) = LOWER(hr_applicant.email_from) + OR other.partner_phone = hr_applicant.partner_phone OR other.partner_phone = hr_applicant.partner_mobile + OR other.partner_mobile = hr_applicant.partner_mobile OR other.partner_mobile = hr_applicant.partner_phone + WHERE hr_applicant.id in %s + """, (tuple(self.ids),) ) ids = [res['id'] for res in self.env.cr.dictfetchall()] return { diff --git a/addons/hr_recruitment/tests/test_recruitment.py b/addons/hr_recruitment/tests/test_recruitment.py index c25efc978b6..81230248e16 100644 --- a/addons/hr_recruitment/tests/test_recruitment.py +++ b/addons/hr_recruitment/tests/test_recruitment.py @@ -26,3 +26,46 @@ class TestRecruitment(TransactionCase): self.assertEqual(dup1.application_count, 1) self.assertEqual(dup2.application_count, 1) self.assertEqual(no_dup.application_count, 0) + + def test_application_count(self): + """ Test that we find same applicants based on simmilar mail, + phone or mobile phone. + """ + A, B, C, D, E, F = self.env['hr.applicant'].create([ + { + 'name': 'Application A', + 'email_from': 'abc@odoo.com', + 'partner_phone': '123', + 'partner_mobile': '14-15-16', + }, + { + 'name': 'Application B', + 'partner_phone': '456', + 'partner_mobile': '11-12-13', + }, + { + 'name': 'Application C', + 'email_from': 'def@odoo.com', + 'partner_phone': '123', + 'partner_mobile': '14-15-16', + }, + { + 'name': 'Application D', + 'email_from': 'def@odoo.com', + 'partner_phone': '456', + 'partner_mobile': '14-15-16', + }, + { + 'name': 'Application E', + }, + { + 'name': 'Application F', + 'partner_phone': '11-12-13', # In case phone is configured in a wrong field + } + ]) + self.assertEqual(A.application_count, 2) # C, D + self.assertEqual(B.application_count, 2) # D, F + self.assertEqual(C.application_count, 2) # A, D + self.assertEqual(D.application_count, 3) # A, B, C + self.assertEqual(E.application_count, 0) + self.assertEqual(F.application_count, 1) # B