diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index eb6f8dd2d9f..7f2e9577569 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -2093,8 +2093,8 @@ class AccountMove(models.Model): def message_new(self, msg_dict, custom_values=None): # OVERRIDE # Add custom behavior when receiving a new invoice through the mail's gateway. - if custom_values.get('move_type', 'entry') not in ('out_invoice', 'in_invoice'): - return False + if (custom_values or {}).get('move_type', 'entry') not in ('out_invoice', 'in_invoice'): + return super().message_new(msg_dict, custom_values=custom_values) def is_internal_partner(partner): # Helper to know if the partner is an internal one. @@ -2125,7 +2125,6 @@ class AccountMove(models.Model): # Create the invoice. values = { - 'name': self.default_get(['name'])['name'], 'invoice_source_email': from_mail_addresses[0], 'partner_id': partners and partners[0].id or False, } @@ -2133,7 +2132,7 @@ class AccountMove(models.Model): move = super(AccountMove, move_ctx).message_new(msg_dict, custom_values=values) # Assign followers. - all_followers_ids = set(partner.id for partner in followers + senders + partners) + all_followers_ids = set(partner.id for partner in followers + senders + partners if is_internal_partner(partner)) move.message_subscribe(list(all_followers_ids)) return move diff --git a/addons/account/tests/__init__.py b/addons/account/tests/__init__.py index 32dacddbd5f..49ed8d23f7e 100644 --- a/addons/account/tests/__init__.py +++ b/addons/account/tests/__init__.py @@ -33,3 +33,4 @@ from . import test_portal_attachment from . import test_tax_report from . import test_reconciliation_heavy_load from . import test_transfer_wizard +from . import test_account_incoming_supplier_invoice diff --git a/addons/account/tests/test_account_incoming_supplier_invoice.py b/addons/account/tests/test_account_incoming_supplier_invoice.py new file mode 100644 index 00000000000..0809cc2c855 --- /dev/null +++ b/addons/account/tests/test_account_incoming_supplier_invoice.py @@ -0,0 +1,126 @@ +import json + +from odoo.addons.account.tests.common import AccountTestCommon +from odoo.tests import tagged + + +@tagged('post_install', '-at_install') +class TestAccountIncomingSupplierInvoice(AccountTestCommon): + + def setUp(self): + super(TestAccountIncomingSupplierInvoice, self).setUp() + + self.env['ir.config_parameter'].sudo().set_param('mail.catchall.domain', 'test-company.odoo.com') + + self.internal_user = self.env['res.users'].create({ + 'name': 'Internal User', + 'login': 'internal.user@test.odoo.com', + 'email': 'internal.user@test.odoo.com', + }) + + self.supplier_partner = self.env['res.partner'].create({ + 'name': 'Your Supplier', + 'email': 'supplier@other.company.com', + 'supplier_rank': 10, + }) + + self.journal = self.env['account.journal'].create({ + 'name': 'Test Journal', + 'code': 'TST', + 'type': 'purchase', + }) + + journal_alias = self.env['mail.alias'].create({ + 'alias_name': 'test-bill', + 'alias_model_id': self.env.ref('account.model_account_move').id, + 'alias_defaults': json.dumps({ + 'move_type': 'in_invoice', + 'company_id': self.env.user.company_id.id, + 'journal_id': self.journal.id, + }), + }) + self.journal.write({'alias_id': journal_alias.id}) + + self.employee_user = self.env.ref('base.user_demo') + + def test_supplier_invoice_mailed_from_supplier(self): + message_parsed = { + 'message_id': 'message-id-dead-beef', + 'subject': 'Incoming bill', + 'from': '%s <%s>' % (self.supplier_partner.name, self.supplier_partner.email), + 'to': '%s@%s' % (self.journal.alias_id.alias_name, self.journal.alias_id.alias_domain), + 'body': "You know, that thing that you bought.", + 'attachments': [b'Hello, invoice'], + } + + invoice = self.env['account.move'].message_new(message_parsed, {'move_type': 'in_invoice', 'journal_id': self.journal.id}) + + message_ids = invoice.message_ids + self.assertEqual(len(message_ids), 1, 'Only one message should be posted in the chatter') + self.assertEqual(message_ids.body, '
Vendor Bill Created
', 'Only the invoice creation should be posted') + + following_partners = invoice.message_follower_ids.mapped('partner_id') + self.assertEqual(following_partners, self.env.ref('base.partner_root')) + + def test_supplier_invoice_forwarded_by_internal_user_without_supplier(self): + """ In this test, the bill was forwarded by an employee, + but no partner email address is found in the body.""" + message_parsed = { + 'message_id': 'message-id-dead-beef', + 'subject': 'Incoming bill', + 'from': '%s <%s>' % (self.internal_user.name, self.internal_user.email), + 'to': '%s@%s' % (self.journal.alias_id.alias_name, self.journal.alias_id.alias_domain), + 'body': "You know, that thing that you bought.", + 'attachments': [b'Hello, invoice'], + } + + invoice = self.env['account.move'].message_new(message_parsed, {'move_type': 'in_invoice', 'journal_id': self.journal.id}) + + message_ids = invoice.message_ids + self.assertEqual(len(message_ids), 1, 'Only one message should be posted in the chatter') + self.assertEqual(message_ids.body, 'Vendor Bill Created
', 'Only the invoice creation should be posted') + + following_partners = invoice.message_follower_ids.mapped('partner_id') + self.assertEqual(following_partners, self.env.ref('base.partner_root') | self.internal_user.partner_id) + + def test_supplier_invoice_forwarded_by_internal_with_supplier_in_body(self): + """ In this test, the bill was forwarded by an employee, + and the partner email address is found in the body.""" + message_parsed = { + 'message_id': 'message-id-dead-beef', + 'subject': 'Incoming bill', + 'from': '%s <%s>' % (self.internal_user.name, self.internal_user.email), + 'to': '%s@%s' % (self.journal.alias_id.alias_name, self.journal.alias_id.alias_domain), + 'body': "Mail sent by %s <%s>:\nYou know, that thing that you bought." % (self.supplier_partner.name, self.supplier_partner.email), + 'attachments': [b'Hello, invoice'], + } + + invoice = self.env['account.move'].message_new(message_parsed, {'move_type': 'in_invoice', 'journal_id': self.journal.id}) + + message_ids = invoice.message_ids + self.assertEqual(len(message_ids), 1, 'Only one message should be posted in the chatter') + self.assertEqual(message_ids.body, 'Vendor Bill Created
', 'Only the invoice creation should be posted') + + following_partners = invoice.message_follower_ids.mapped('partner_id') + self.assertEqual(following_partners, self.env.ref('base.partner_root') | self.internal_user.partner_id) + + def test_supplier_invoice_forwarded_by_internal_with_internal_in_body(self): + """ In this test, the bill was forwarded by an employee, + and the internal user email address is found in the body.""" + message_parsed = { + 'message_id': 'message-id-dead-beef', + 'subject': 'Incoming bill', + 'from': '%s <%s>' % (self.internal_user.name, self.internal_user.email), + 'to': '%s@%s' % (self.journal.alias_id.alias_name, self.journal.alias_id.alias_domain), + 'body': "Mail sent by %s <%s>:\nYou know, that thing that you bought." % (self.internal_user.name, self.internal_user.email), + 'attachments': [b'Hello, invoice'], + } + + invoice = self.env['account.move'].message_new(message_parsed, {'move_type': 'in_invoice', 'journal_id': self.journal.id}) + + message_ids = invoice.message_ids + self.assertEqual(len(message_ids), 1, 'Only one message should be posted in the chatter') + self.assertEqual(message_ids.body, 'Vendor Bill Created
', 'Only the invoice creation should be posted') + + following_partners = invoice.message_follower_ids.mapped('partner_id') + self.assertEqual(following_partners, self.env.ref('base.partner_root') | self.internal_user.partner_id)