Skip to content

Commit 8b6c81b

Browse files
committed
[IMP] edi_mail_import_oca: Move logic to backend
1 parent 12991dd commit 8b6c81b

10 files changed

Lines changed: 225 additions & 167 deletions

edi_mail_import_oca/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"website": "https://github.com/OCA/edi-framework",
1111
"depends": ["edi_core_oca", "mail"],
1212
"data": [
13-
"views/edi_exchange_type.xml",
13+
"views/edi_backend.xml",
1414
],
1515
"demo": [],
1616
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from . import edi_exchange_type
1+
from . import edi_backend
22
from . import edi_exchange_record
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2026 Dixmit
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
import ast
4+
5+
from odoo import fields, models
6+
7+
8+
class EdiBackend(models.Model):
9+
_name = "edi.backend"
10+
_inherit = ["edi.backend", "mail.alias.mixin"]
11+
12+
full_mail_exchange_type_id = fields.Many2one(
13+
"edi.exchange.type",
14+
)
15+
16+
def _alias_get_creation_values(self):
17+
values = super()._alias_get_creation_values()
18+
values["alias_model_id"] = self.env["ir.model"]._get("edi.exchange.record").id
19+
if self.id:
20+
values["alias_defaults"] = defaults = ast.literal_eval(
21+
self.alias_defaults or "{}"
22+
)
23+
defaults["backend_id"] = self.id
24+
return values
25+
26+
def _mail_exchange_type_pending_input_domain(self):
27+
"""Domain for retrieving input exchange types for emails."""
28+
return [
29+
("backend_type_id", "=", self.backend_type_id.id),
30+
("direction", "=", "input"),
31+
"|",
32+
("backend_id", "=", False),
33+
("backend_id", "=", self.id),
34+
("exchange_filename_pattern", "!=", False),
35+
]

edi_mail_import_oca/models/edi_exchange_record.py

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import re
88

99
from odoo import api, models
10+
from odoo.exceptions import UserError
1011

1112
_logger = logging.getLogger(__name__)
1213

@@ -16,42 +17,69 @@ class EdiExchangeRecord(models.Model):
1617

1718
@api.model
1819
def message_new(self, msg_dict, custom_values=None):
20+
backend_id = custom_values.get("backend_id") if custom_values else None
21+
if backend_id:
22+
backend = self.env["edi.backend"].browse(backend_id)
23+
content = False
24+
filename = False
25+
if (
26+
not custom_values.get("type_id")
27+
and not backend.full_mail_exchange_type_id
28+
):
29+
types = self.env["edi.exchange.type"].search(
30+
backend._mail_exchange_type_pending_input_domain()
31+
)
32+
for exchange_type in types:
33+
for attachment in msg_dict.get("attachments", []):
34+
if re.match(
35+
exchange_type.exchange_filename_pattern,
36+
attachment.fname,
37+
re.IGNORECASE,
38+
):
39+
content = self._process_email_attachment(attachment)
40+
filename = attachment.fname
41+
custom_values["type_id"] = exchange_type.id
42+
break
43+
if content:
44+
custom_values["type_id"] = exchange_type.id
45+
break
46+
else:
47+
if backend.full_mail_exchange_type_id:
48+
custom_values["type_id"] = backend.full_mail_exchange_type_id.id
49+
new_message_dict = msg_dict.copy()
50+
attachments = new_message_dict.pop("attachments", [])
51+
new_message_dict["attachments"] = []
52+
for attachment in attachments:
53+
new_message_dict["attachments"].append(
54+
{
55+
"info": attachment.info,
56+
"data": self._process_email_attachment(attachment),
57+
"fname": attachment.fname,
58+
}
59+
)
60+
content = json.dumps(new_message_dict)
61+
filename = "email_message.json"
62+
if not custom_values or "type_id" not in custom_values:
63+
_logger.warning(
64+
"No exchange type found for incoming email with subject '%s'",
65+
msg_dict.get("subject"),
66+
)
67+
raise UserError(
68+
self.env._(
69+
"No exchange type found for incoming email with subject '%s'",
70+
msg_dict.get("subject"),
71+
)
72+
)
1973
record = super().message_new(
2074
msg_dict,
2175
custom_values=custom_values,
2276
)
23-
if record.type_id.mail_as_attachment:
24-
new_message_dict = msg_dict.copy()
25-
attachments = new_message_dict.pop("attachments", [])
26-
new_message_dict["attachments"] = []
27-
for attachment in attachments:
28-
new_message_dict["attachments"].append(
29-
{
30-
"info": attachment.info,
31-
"data": self._process_email_attachment(attachment),
32-
"fname": attachment.fname,
33-
}
34-
)
35-
record._set_file_content(json.dumps(new_message_dict))
36-
record.edi_exchange_state = "input_received"
37-
else:
38-
content = False
39-
filename = False
40-
for attachment in msg_dict.get("attachments", []):
41-
if re.match(
42-
record.type_id.exchange_filename_pattern or ".*",
43-
attachment.fname,
44-
re.IGNORECASE,
45-
):
46-
content = self._process_email_attachment(attachment)
47-
filename = attachment.fname
48-
break
49-
if content:
50-
record._set_file_content(content)
51-
record.exchange_filename = filename
52-
record.edi_exchange_state = "input_received"
77+
record._set_file_content(content)
78+
record.exchange_filename = filename
79+
record.edi_exchange_state = "input_received"
5380
return record
5481

82+
@api.model
5583
def _process_email_attachment(self, attachment):
5684
"""Process email attachment to be stored as file content."""
5785
data = attachment[1]

edi_mail_import_oca/models/edi_exchange_type.py

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from . import test_mail_import_oca
2+
from . import test_mail_import_oca_no_file
Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2-
1+
# Copyright 2026 Dixmit
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
33
import json
44

5-
from odoo.exceptions import ValidationError
6-
from odoo.tests import tagged
7-
85
from odoo.addons.mail.tests.common import MailCommon
96
from odoo.addons.test_mail.data.test_mail_data import MAIL_EML_ATTACHMENT
107

118

12-
@tagged("mail_gateway")
139
class TestEmailParsing(MailCommon):
1410
"""Test email parsing and import via mail gateway"""
1511

@@ -26,31 +22,22 @@ def setUpClass(cls):
2622
{
2723
"name": "Mail Import OCA Test Backend",
2824
"backend_type_id": cls.backend_type.id,
25+
"alias_name": "edi-input",
2926
}
3027
)
3128
cls.exchange_type = cls.env["edi.exchange.type"].create(
3229
{
3330
"name": "Test Exchange Type",
3431
"code": "test_exchange_type",
3532
"direction": "input",
36-
"alias_name": "edi-input",
3733
"backend_type_id": cls.backend_type.id,
3834
"backend_id": cls.backend.id,
3935
}
4036
)
4137

42-
def test_constraint(self):
43-
with self.assertRaises(ValidationError):
44-
self.exchange_type.direction = "output"
45-
46-
def test_constraint_no_error_on_no_alias(self):
47-
self.exchange_type.alias_name = False
48-
self.exchange_type.direction = "output"
49-
self.assertFalse(self.exchange_type.alias_email)
50-
5138
def test_import_full(self):
52-
self.assertTrue(self.exchange_type.alias_email)
53-
self.exchange_type.mail_as_attachment = True
39+
self.assertTrue(self.backend.alias_email)
40+
self.backend.full_mail_exchange_type_id = self.exchange_type
5441
self.assertFalse(
5542
self.env["edi.exchange.record"].search(
5643
[
@@ -60,7 +47,7 @@ def test_import_full(self):
6047
)
6148
mail = self.format(
6249
MAIL_EML_ATTACHMENT,
63-
to=self.exchange_type.alias_email,
50+
to=self.backend.alias_email,
6451
subject="purchase test mail",
6552
target_model="account.move",
6653
msg_id="<test-account-move-alias-id>",
@@ -79,8 +66,8 @@ def test_import_full(self):
7966
self.assertIn("body", data)
8067

8168
def test_import_specific_file(self):
82-
self.assertTrue(self.exchange_type.alias_email)
83-
self.exchange_type.mail_as_attachment = False
69+
self.assertTrue(self.backend.alias_email)
70+
self.backend.full_mail_exchange_type_id = False
8471
self.exchange_type.exchange_filename_pattern = ".*eml"
8572
self.assertFalse(
8673
self.env["edi.exchange.record"].search(
@@ -91,7 +78,7 @@ def test_import_specific_file(self):
9178
)
9279
mail = self.format(
9380
MAIL_EML_ATTACHMENT,
94-
to=self.exchange_type.alias_email,
81+
to=self.backend.alias_email,
9582
subject="purchase test mail",
9683
target_model="account.move",
9784
msg_id="<test-account-move-alias-id>",
@@ -105,30 +92,3 @@ def test_import_specific_file(self):
10592
self.assertTrue(record)
10693
self.assertEqual(record.edi_exchange_state, "input_received")
10794
self.assertEqual(record.exchange_filename, "original_msg.eml")
108-
109-
def test_import_no_file_found(self):
110-
self.assertTrue(self.exchange_type.alias_email)
111-
self.exchange_type.mail_as_attachment = False
112-
self.exchange_type.exchange_filename_pattern = ".*xml"
113-
self.assertFalse(
114-
self.env["edi.exchange.record"].search(
115-
[
116-
("type_id", "=", self.exchange_type.id),
117-
]
118-
)
119-
)
120-
mail = self.format(
121-
MAIL_EML_ATTACHMENT,
122-
to=self.exchange_type.alias_email,
123-
subject="purchase test mail",
124-
target_model="account.move",
125-
msg_id="<test-account-move-alias-id>",
126-
)
127-
self.env["mail.thread"].message_process("mail.thread", mail)
128-
record = self.env["edi.exchange.record"].search(
129-
[
130-
("type_id", "=", self.exchange_type.id),
131-
]
132-
)
133-
self.assertTrue(record)
134-
self.assertEqual(record.edi_exchange_state, "new")
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2026 Dixmit
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import api
5+
from odoo.exceptions import UserError
6+
from odoo.tools import mute_logger
7+
8+
from odoo.addons.mail.tests.common import MailCommon
9+
from odoo.addons.test_mail.data.test_mail_data import MAIL_EML_ATTACHMENT
10+
11+
12+
class TestEmailParsing(MailCommon):
13+
"""Test email parsing and import via mail gateway"""
14+
15+
def setUp(self):
16+
super().setUp()
17+
self.registry_enter_test_mode()
18+
# now we make a test cursor for self.cr
19+
self.cr = self.registry.cursor()
20+
self.addCleanup(self.cr.close)
21+
self.env = api.Environment(self.cr, api.SUPERUSER_ID, {})
22+
self.backend_type = self.env["edi.backend.type"].create(
23+
{
24+
"name": "Mail Import OCA Test Backend Type",
25+
"code": "mail_import_oca_test_backend_type",
26+
}
27+
)
28+
self.backend = self.env["edi.backend"].create(
29+
{
30+
"name": "Mail Import OCA Test Backend",
31+
"backend_type_id": self.backend_type.id,
32+
"alias_name": "edi-input",
33+
}
34+
)
35+
self.exchange_type = self.env["edi.exchange.type"].create(
36+
{
37+
"name": "Test Exchange Type",
38+
"code": "test_exchange_type",
39+
"direction": "input",
40+
"backend_type_id": self.backend_type.id,
41+
"backend_id": self.backend.id,
42+
}
43+
)
44+
45+
@mute_logger("odoo.addons.edi_mail_import_oca.models.edi_exchange_record")
46+
def test_import_no_file_found(self):
47+
self.assertTrue(self.backend.alias_email)
48+
self.backend.full_mail_exchange_type_id = False
49+
self.exchange_type.exchange_filename_pattern = ".*xml"
50+
self.assertFalse(
51+
self.env["edi.exchange.record"].search(
52+
[
53+
("type_id", "=", self.exchange_type.id),
54+
]
55+
)
56+
)
57+
mail = self.format(
58+
MAIL_EML_ATTACHMENT,
59+
to=self.backend.alias_email,
60+
subject="purchase test mail",
61+
target_model="account.move",
62+
msg_id="<test-account-move-alias-id>",
63+
)
64+
with self.assertRaises(UserError):
65+
self.env["mail.thread"].message_process("mail.thread", mail)

0 commit comments

Comments
 (0)