From 35017adaa9ff48089ce347683ac85ab6b6e83eca Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 26 Apr 2024 09:18:21 +0000 Subject: [PATCH] [FIX] hr_expense: allow to create expenses via alias for employees not related to a user Current behavior: When trying to create an expense using alias, if a `hr.employee` not linked to a user want to, he won't be able This bug occurs after this [commit](https://github.com/odoo/odoo/commit/fbeb7aebcadbe77ff7774b538550373650b329fe) Steps to reproduce the error : - Create an employee not related to a user - Configure alias for expenses - Try to send an email to the expense's alias and check at the logs After this commit: Employees without a related user will be able to create an expense from an email alias opw-3892778 opw-3892701 opw-3893319 opw-3893591 closes odoo/odoo#163672 X-original-commit: 1dd67119c27d219eac2b726ef88cc4af3bed2814 Signed-off-by: Brice Bartoletti (bib) --- addons/hr_expense/models/hr_expense.py | 32 ++++++++++++---- .../tests/test_expenses_mail_import.py | 37 +++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 38e1cb5247b..d7e956a2b48 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -920,14 +920,9 @@ class HrExpense(models.Model): @api.model def message_new(self, msg_dict, custom_values=None): email_address = email_split(msg_dict.get('email_from', False))[0] + employee = self._get_employee_from_email(email_address) - employee = self.env['hr.employee'].search([ - '|', - ('work_email', 'ilike', email_address), - ('user_id.email', 'ilike', email_address) - ]).filtered(lambda e: e.company_id == e.user_id.company_id) - - if len(employee) != 1: + if not employee: return super().message_new(msg_dict, custom_values=custom_values) expense_description = msg_dict.get('subject', '') @@ -967,6 +962,29 @@ class HrExpense(models.Model): self._send_expense_success_mail(msg_dict, expense) return expense + @api.model + def _get_employee_from_email(self, email_address): + employee = self.env['hr.employee'].search([ + ('user_id', '!=', False), + '|', + ('work_email', 'ilike', email_address), + ('user_id.email', 'ilike', email_address), + ]) + + if len(employee) > 1: + # Several employees can be linked to the same user. + # In that case, we only keep the employee that matched the user's company. + return employee.filtered(lambda e: e.company_id == e.user_id.company_id) + + if not employee: + # An employee does not always have a user. + return self.env['hr.employee'].search([ + ('user_id', '=', False), + ('work_email', 'ilike', email_address), + ], limit=1) + + return employee + @api.model def _parse_product(self, expense_description): """ diff --git a/addons/hr_expense/tests/test_expenses_mail_import.py b/addons/hr_expense/tests/test_expenses_mail_import.py index 70d8b0d9ec7..f2c81522a09 100644 --- a/addons/hr_expense/tests/test_expenses_mail_import.py +++ b/addons/hr_expense/tests/test_expenses_mail_import.py @@ -67,6 +67,43 @@ class TestExpensesMailImport(TestExpenseCommon): 'employee_id': company_2_employee.id, }]) + def test_import_expense_from_email_employee_without_user(self): + """When an employee is not linked to a user, he has to be able to create expenses from email""" + employee = self.expense_employee + employee.user_id = False + + message_parsed = { + 'message_id': "the-world-is-a-ghetto", + 'subject': 'New expense', + 'email_from': employee.work_email, + 'to': 'catchall@yourcompany.com', + 'body': "Don't you know, that for me, and for you", + 'attachments': [], + } + + expense = self.env['hr.expense'].message_new(message_parsed) + self.assertRecordValues(expense, [{ + 'employee_id': employee.id, + }]) + + def test_import_expense_from_email_no_product(self): + message_parsed = { + 'message_id': "the-world-is-a-ghetto", + 'subject': 'no product code 800', + 'email_from': self.expense_user_employee.email, + 'to': 'catchall@yourcompany.com', + 'body': "Don't you know, that for me, and for you", + 'attachments': [], + } + + expense = self.env['hr.expense'].message_new(message_parsed) + + self.assertRecordValues(expense, [{ + 'product_id': False, + 'total_amount': 800.0, + 'employee_id': self.expense_employee.id, + }]) + def test_import_expense_from_mail_parsing_subjects(self): def assertParsedValues(subject, currencies, exp_description, exp_amount, exp_product, exp_currency): product, amount, currency_id, description = self.env['hr.expense'] \