Skip to content

Commit

Permalink
fixup! edi_sale_ubl: split input/output
Browse files Browse the repository at this point in the history
  • Loading branch information
simahawk committed Dec 4, 2024
1 parent 1ca0481 commit 5fe75d3
Show file tree
Hide file tree
Showing 39 changed files with 1,860 additions and 0 deletions.
1 change: 1 addition & 0 deletions edi_sale_ubl_input_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bot, please, take care of this!
Empty file.
25 changes: 25 additions & 0 deletions edi_sale_ubl_input_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "EDI Sales",
"summary": """
Configuration and special behaviors for EDI on sales.
""",
"version": "14.0.1.0.0",
"development_status": "Alpha",
"license": "AGPL-3",
"author": "Camptocamp,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/edi",
"depends": [
"sale_order_import_ubl",
"edi_sale_ubl_oca",
"edi_ubl_oca",
"edi_xml_oca",
],
"data": [],
"demo": [
"demo/edi_exchange_type.xml",
"demo/edi_configuration.xml",
],
}
19 changes: 19 additions & 0 deletions edi_sale_ubl_input_oca/demo/edi_configuration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="demo_ubl_edi_configuration_confirmed" model="edi.configuration">
<field name="name">Demo UBL Sale OrderResponse - order confirmed</field>
<field
name="description"
>Show case how you can send out an order response automatically</field>
<field name="type_id" ref="demo_edi_exc_type_order_response_out" />
<field name="backend_id" ref="edi_ubl_oca.edi_backend_ubl_demo" />
<field name="model_id" ref="sale.model_sale_order" />
<field
name="trigger_id"
ref="edi_sale_oca.edi_conf_trigger_sale_order_state_sale"
/>
<field name="snippet_do">
record._edi_send_via_edi(conf.type_id)
</field>
</record>
</odoo>
50 changes: 50 additions & 0 deletions edi_sale_ubl_input_oca/demo/edi_exchange_type.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="demo_edi_exc_type_order_response_out" model="edi.exchange.type">
<field name="backend_type_id" ref="edi_ubl_oca.edi_backend_type_ubl" />
<field name="backend_id" ref="edi_ubl_oca.edi_backend_ubl_demo" />
<field name="name">Demo UBL Sale Order Response (edi_sale_ubl_input_oca)</field>
<field name="code">demo_UBL_SaleOrderResponse_out</field>
<field name="direction">output</field>
<field name="exchange_filename_pattern">{record_name}-{type.code}-{dt}</field>
<field name="exchange_file_ext">xml</field>
<field
name="state_workflow_ids"
eval="[(6, 0, [
ref('edi_sale_ubl_oca.edi_sale_order_state_workflow'),
ref('edi_sale_ubl_oca.edi_sale_order_line_state_workflow')
])]"
/>
</record>

<record id="demo_edi_exc_type_order_in" model="edi.exchange.type">
<field name="backend_type_id" ref="edi_ubl_oca.edi_backend_type_ubl" />
<field name="backend_id" ref="edi_ubl_oca.edi_backend_ubl_demo" />
<field name="ack_type_id" ref="demo_edi_exc_type_order_response_out" />
<field name="name">Demo UBL Sale Order (edi_sale_ubl_input_oca)</field>
<field name="code">demo_UBL_SaleOrder_in</field>
<field name="direction">input</field>
<field name="exchange_file_ext">xml</field>
<field
name="state_workflow_ids"
eval="[(6, 0, [
ref('edi_sale_ubl_oca.edi_sale_order_state_workflow'),
ref('edi_sale_ubl_oca.edi_sale_order_line_state_workflow')
])]"
/>
<field name="advanced_settings_edit">
components:
process:
usage: input.process.sale.order
# Pass all additional arguments to the sale.order.import wizard via ctx keys.
# To add more selective features to the wizard, it's recommended to add new fields
# and control them via default values.
# Example:
env_ctx:
# Values for the wizard
default_confirm_order: false
default_price_source: 'pricelist'
</field>
</record>

</odoo>
1 change: 1 addition & 0 deletions edi_sale_ubl_input_oca/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Simone Orsi <[email protected]>
1 change: 1 addition & 0 deletions edi_sale_ubl_input_oca/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO
4 changes: 4 additions & 0 deletions edi_sale_ubl_input_oca/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import test_order_state
from . import test_order_in
from . import test_order_response_out
from . import test_order_in_full_flow
69 changes: 69 additions & 0 deletions edi_sale_ubl_input_oca/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2022 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).


import os

from odoo.addons.sale_order_import_ubl.tests.common import get_test_data


def get_xml_handler(backend, schema_path, model=None):
model = model or backend._name
return backend._find_component(
model,
["edi.xml"],
work_ctx={"schema_path": schema_path},
safe=False,
)


def flatten(txt):
return "".join([x.strip() for x in txt.splitlines()])


def dev_write_example_file(filename, content, test_file=None):
test_file = test_file or __file__
from pathlib import Path

path = Path(test_file).parent / ("examples/test." + filename)
with open(path, "w") as out:
out.write(content)


def read_test_file(filename):
path = os.path.join(os.path.dirname(__file__), "examples", filename)
with open(path, "r") as thefile:
return thefile.read()


class OrderInboundTestMixin:
@classmethod
def _setup_inbound_order(cls, backend):
cls.exc_type_in = cls.env.ref("edi_sale_ubl_oca.demo_edi_exc_type_order_in")
cls.exc_type_out = cls.env.ref(
"edi_sale_ubl_oca.demo_edi_exc_type_order_response_out"
)
cls.exc_type_in.backend_id = backend
cls.exc_type_out.backend_id = backend
cls.exc_record_in = backend.create_record(
cls.exc_type_in.code, {"edi_exchange_state": "input_received"}
)
cls.ubl_data = get_test_data(cls.env)
# Ensure all products have a barcode
for data in cls.ubl_data.values():
for prod in data.products:
prod.barcode = prod.id * 14
fname = "UBL-Order-2.1-Example.xml"
cls.order_data = cls.ubl_data[fname]
fcontent = cls.order_data._get_content()
cls.exc_record_in._set_file_content(fcontent)
cls.err_msg_already_imported = "Sales order has already been imported before"

def _find_order(self):
return self.env["sale.order"].search(
[
("client_order_ref", "=", self.order_data.client_order_ref),
("commercial_partner_id", "=", self.order_data.partner.parent_id.id),
]
)
98 changes: 98 additions & 0 deletions edi_sale_ubl_input_oca/tests/test_order_in.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright 2022 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import exceptions

from odoo.addons.edi_oca.tests.common import EDIBackendCommonComponentTestCase

from .common import OrderInboundTestMixin


class TestOrderInbound(EDIBackendCommonComponentTestCase, OrderInboundTestMixin):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls._setup_inbound_order(cls.backend)

@classmethod
def _get_backend(cls):
return cls.env.ref("edi_ubl_oca.edi_backend_ubl_demo")

def test_existing_order_break_on_error(self):
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_received")
self.env["sale.order"].create(
{
"partner_id": self.order_data.partner.id,
"client_order_ref": self.order_data.client_order_ref,
}
)
with self.assertRaisesRegex(
exceptions.UserError, self.err_msg_already_imported
):
self.exc_record_in.with_context(
_edi_process_break_on_error=True
).action_exchange_process()
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_received")

def test_existing_order(self):
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_received")
self.env["sale.order"].create(
{
"partner_id": self.order_data.partner.id,
"client_order_ref": self.order_data.client_order_ref,
}
)
# Test w/ error handling
self.exc_record_in.action_exchange_process()
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_processed_error")
err_msg = "Sales order has already been imported before"
self.assertIn(err_msg, self.exc_record_in.exchange_error)

def test_new_order(self):
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_received")
order = self._find_order()
self.assertFalse(order)
# Test w/ error handling
# .with_context(_edi_process_break_on_error=True)
self.exc_record_in.action_exchange_process()
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_processed")
order = self._find_order()
self.assertEqual(self.exc_record_in.record, order)
order_msg = order.message_ids[0]
self.assertIn("Exchange processed successfully", order_msg.body)
self.assertIn(self.exc_record_in.identifier, order_msg.body)
self.assertIn(
f"/web#id={self.exc_record_in.id}&amp;model=edi.exchange.record&amp;view_type=form",
order_msg.body,
)
# TODO: test order data. To do so, first add such tests to sale_order_import
self.assertEqual(order.order_line.mapped("edi_id"), ["1", "2"])
self.assertTrue(order.edi_state_id.code, order.EDI_STATE_ORDER_ACCEPTED)
self.assertTrue(
order.mapped("order_line.edi_state_id").code,
order.EDI_STATE_ORDER_LINE_ACCEPTED,
)

def test_cancel(self):
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_received")
order = self.env["sale.order"].create(
{
"partner_id": self.order_data.partner.id,
"client_order_ref": self.order_data.client_order_ref,
"origin_exchange_record_id": self.exc_record_in.id,
}
)
self.exc_record_in._set_related_record(order)
order.action_confirm()
self.assertTrue(order.edi_state_id.code, order.EDI_STATE_ORDER_ACCEPTED)
order.action_cancel()
self.assertTrue(order.edi_state_id.code, order.EDI_STATE_ORDER_REJECTED)

def _find_order(self):
return self.env["sale.order"].search(
[
("client_order_ref", "=", self.order_data.client_order_ref),
("commercial_partner_id", "=", self.order_data.partner.parent_id.id),
]
)
69 changes: 69 additions & 0 deletions edi_sale_ubl_input_oca/tests/test_order_in_full_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2022 Camptocamp SA
# @author: Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from unittest import mock

from odoo.tests.common import SavepointCase

from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin

from .common import OrderInboundTestMixin, get_xml_handler

# TODO: split in different tests w/ SingleTransaction


class TestOrderInboundFull(SavepointCase, EDIBackendTestMixin, OrderInboundTestMixin):

_schema_path = "base_ubl:data/xsd-2.2/maindoc/UBL-OrderResponse-2.2.xsd"

@classmethod
def setUpClass(cls):
super().setUpClass()
cls._setup_env()
cls.backend = cls._get_backend()
cls._setup_inbound_order(cls.backend)
cls.edi_conf = cls.env.ref(
"edi_sale_ubl_oca.demo_ubl_edi_configuration_confirmed"
)

@classmethod
def _get_backend(cls):
return cls.env.ref("edi_ubl_oca.edi_backend_ubl_demo")

# No need to test sending data
@mock.patch("odoo.addons.edi_oca.models.edi_backend.EDIBackend._exchange_send")
def test_new_order(self, mock_send):
self.backend._check_input_exchange_sync()
self.assertEqual(self.exc_record_in.edi_exchange_state, "input_processed")
order = self._find_order()
order.partner_id.edi_sale_conf_ids = self.edi_conf
self.assertEqual(self.exc_record_in.record, order)
order_msg = order.message_ids[0]
self.assertIn("Exchange processed successfully", order_msg.body)
self.assertIn(self.exc_record_in.identifier, order_msg.body)
order.invalidate_cache()
# Test relations
self.assertEqual(len(order.exchange_record_ids), 1)
exc_record = order.exchange_record_ids.filtered(
lambda x: x.type_id == self.exc_type_in
)
self.assertEqual(exc_record, self.exc_record_in)
# Confirm the order
order.action_confirm()
# Should give us a valid order response ack record
ack_exc_record = order.exchange_record_ids.filtered(
lambda x: x.type_id == self.exc_type_out
)
file_content = ack_exc_record._get_file_content()
self.assertTrue(file_content)
# TMP /
# path = "/tmp/order.response.test.xml"
# with open(path, "w") as out:
# out.write(file_content)
# / TMP
handler = get_xml_handler(self.backend, self._schema_path)
# Test is a valid file
err = handler.validate(file_content)
self.assertEqual(err, None, err)
# TODO: test data
Loading

0 comments on commit 5fe75d3

Please sign in to comment.