Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 53 additions & 30 deletions edi_core_oca/models/edi_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import traceback
from io import StringIO

from psycopg2 import IntegrityError, OperationalError

from odoo import exceptions, fields, models
from odoo.exceptions import UserError

Expand Down Expand Up @@ -237,6 +239,11 @@ def exchange_send(self, exchange_record):
_logger.debug(
"%s send failed. Marked as errored.", exchange_record.identifier
)
except (OperationalError, IntegrityError):
# We don't want the finally block to be executed in this case as
# the cursor is already in an aborted state and any query will fail.
res = "__sql_error__"
raise
else:
# TODO: maybe the send handler should return desired message and state
message = exchange_record._exchange_status_message("send_ok")
Expand All @@ -248,16 +255,18 @@ def exchange_send(self, exchange_record):
)
res = message
finally:
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
if res != "__sql_error__":
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests
# (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
exchange_record.notify_action_complete("send", message=message)
return res

Expand Down Expand Up @@ -445,20 +454,27 @@ def exchange_process(self, exchange_record):
error = _get_exception_msg(err)
state = "input_processed_error"
res = f"Error: {error}"
except (OperationalError, IntegrityError):
# We don't want the finally block to be executed in this case as
# the cursor is already in an aborted state and any query will fail.
res = "__sql_error__"
raise
else:
error = traceback = None
state = "input_processed"
finally:
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
if res != "__sql_error__":
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests
# (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
if (
state == "input_processed_error"
and old_state != "input_processed_error"
Expand Down Expand Up @@ -506,22 +522,29 @@ def exchange_receive(self, exchange_record):
state = "input_receive_error"
message = exchange_record._exchange_status_message("receive_ko")
res = f"Input error: {error}"
except (OperationalError, IntegrityError):
# We don't want the finally block to be executed in this case as
# the cursor is already in an aborted state and any query will fail.
res = "__sql_error__"
raise
else:
message = exchange_record._exchange_status_message("receive_ok")
error = traceback = None
state = "input_received"
res = message
finally:
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
if res != "__sql_error__":
exchange_record.write(
{
"edi_exchange_state": state,
"exchange_error": error,
"exchange_error_traceback": traceback,
# FIXME: this should come from _compute_exchanged_on
# but somehow it's failing in send tests
# (in record tests it works).
"exchanged_on": fields.Datetime.now(),
}
)
exchange_record.notify_action_complete("receive", message=message)
return res

Expand Down
10 changes: 10 additions & 0 deletions edi_core_oca/tests/test_backend_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from odoo_test_helper import FakeModelLoader
from psycopg2 import OperationalError

from .common import EDIBackendCommonTestCase

Expand Down Expand Up @@ -78,3 +79,12 @@ def test_receive_allow_empty_file_record(self):
# Check the record
self.assertEqual(self.record._get_file_content(), "")
self.assertRecordValues(self.record, [{"edi_exchange_state": "input_received"}])

def test_receive_record_with_operational_error(self):
self.record.edi_exchange_state = "input_pending"
with self.assertRaises(OperationalError):
self.backend.with_context(
test_break_receive=OperationalError("SQL error")
).exchange_receive(self.record)
self.assertRecordValues(self.record, [{"edi_exchange_state": "input_pending"}])
self.assertFalse(self.record.exchange_error)
11 changes: 11 additions & 0 deletions edi_core_oca/tests/test_backend_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from freezegun import freeze_time
from odoo_test_helper import FakeModelLoader
from psycopg2 import OperationalError

from odoo import fields, tools
from odoo.exceptions import UserError
Expand Down Expand Up @@ -122,3 +123,13 @@ def test_send_not_generated_record(self):
err.exception.args[0], "Record ID=%d has no file to send!" % record.id
)
mocked.assert_not_called()

def test_send_record_with_operational_error(self):
self.record.write({"edi_exchange_state": "output_pending"})
self.record._set_file_content("TEST %d" % self.record.id)
with self.assertRaises(OperationalError):
self.backend.with_context(
test_break_send=OperationalError("SQL error")
).exchange_send(self.record)
self.assertRecordValues(self.record, [{"edi_exchange_state": "output_pending"}])
self.assertFalse(self.record.exchange_error)
10 changes: 10 additions & 0 deletions edi_core_oca/tests/test_backend_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from freezegun import freeze_time
from odoo_test_helper import FakeModelLoader
from psycopg2 import IntegrityError

from odoo import fields
from odoo.exceptions import UserError
Expand Down Expand Up @@ -103,4 +104,13 @@ def test_process_outbound_record(self):
with self.assertRaises(UserError):
record.action_exchange_process()

def test_process_record_with_integrity_error(self):
self.record.write({"edi_exchange_state": "input_received"})
with self.assertRaises(IntegrityError):
self.backend.with_context(
test_break_process=IntegrityError("SQL error")
).exchange_process(self.record)
self.assertRecordValues(self.record, [{"edi_exchange_state": "input_received"}])
self.assertFalse(self.record.exchange_error)

# TODO: test ack file are processed