[FIX] account: do not sent user as vendor when sending bill by email

On purchase journals, there is the possibility to set up an alias to
automatically create vendor bills from incoming email.
Three types of emails can send the bill:
- the vendor, with email matching a partner in database
- an internal user, possibly forwarding the bill he received from the vendor
- an unknown address
In the third case, the address will be ignored.
In the first, we found the vendor, so he can be set as partner_id of the bill.
The tricky one is the second case, where we try to guess the vendor.

Before, the code would take only the first email found in the body;
if it found a matching partner, then it used that partner anyway,
even if that partner belonged to a user and was skipped before.

After the fix, we get the partners for all emails
and take arbitrarily the first vendor, then backup on the first non-user.

Note also that email_addresses would duplicate every address read in the body;
we make a set to avoid duplicate processing.

opw 1885070

closes odoo/odoo#36399

Signed-off-by: Nans Lefebvre (len) <len@odoo.com>
This commit is contained in:
Nans Lefebvre
2019-09-04 06:21:22 +00:00
parent 450269b268
commit 116dda06a7
+9 -6
View File
@@ -693,17 +693,22 @@ class AccountInvoice(models.Model):
email_from = email_escape_char(email_split(email_from)[0])
partner_id = self._search_on_partner(email_from, extra_domain=[('supplier', '=', True)])
is_internal = lambda p: (p.user_ids and
all(p.user_ids.mapped(lambda u: u.has_group('base.group_user'))))
# 2) otherwise, if the email sender is from odoo internal users then it is likely that the vendor sent the bill
# by mail to the internal user who, inturn, forwarded that email to the alias to automatically generate the bill
# on behalf of the vendor.
if not partner_id:
user_partner_id = self._search_on_user(email_from)
if user_partner_id and user_partner_id in self.env.ref('base.group_user').users.mapped('partner_id').ids:
# In this case, we will look for the vendor's email address in email's body and assume if will come first
email_addresses = email_re.findall(msg_dict.get('body'))
# In this case, we will look for the vendor's email address in email's body
email_addresses = set(email_re.findall(msg_dict.get('body')))
if email_addresses:
partner_ids = [pid for pid in self._find_partner_from_emails([email_addresses[0]], force_create=False) if pid]
partner_id = partner_ids and partner_ids[0]
pids_list = [self._find_partner_from_emails([email], force_create=False) for email in email_addresses]
partner_ids = set(pid for pids in pids_list for pid in pids if pid)
potential_vendors = self.env['res.partner'].browse(partner_ids).filtered(lambda x: not is_internal(x))
partner_id = ((potential_vendors.filtered('supplier') and potential_vendors.filtered('supplier')[0].id)
or (potential_vendors and potential_vendors[0].id))
# otherwise, there's no fallback on the partner_id found for the regular author of the mail.message as we want
# the partner_id to stay empty
@@ -727,8 +732,6 @@ class AccountInvoice(models.Model):
# Subscribe internal users on the newly created bill
partners = self.env['res.partner'].browse(seen_partner_ids)
is_internal = lambda p: (p.user_ids and
all(p.user_ids.mapped(lambda u: u.has_group('base.group_user'))))
partners_to_subscribe = partners.filtered(is_internal)
if partners_to_subscribe:
invoice.message_subscribe([p.id for p in partners_to_subscribe])