Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][ADD] edi_sale_ubl_oca #1090

Open
wants to merge 37 commits into
base: 14.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
250cdbf
Add edi_sale_ubl_oca
simahawk Aug 14, 2022
c56b00a
edi_sale_ubl: improve order response data
simahawk Sep 14, 2022
fdea5ca
edi_sale_ubl: make exc type demo FIXME
simahawk Nov 15, 2022
3970889
edi_sale_ubl: depend on party data
simahawk Dec 6, 2022
4106ccc
edi_sale_ubl: move data to demo
simahawk Dec 6, 2022
b8095e9
edi_sale_ubl: imp OrderResponse data
simahawk Dec 6, 2022
a39c287
edi_sale_ubl: fix tests
simahawk Dec 6, 2022
f26902c
edi_sale_ubl: ease data override via info
simahawk Dec 17, 2022
e4d26ad
edi_sale_ubl: fix demo data
simahawk May 19, 2023
da004ad
edi_sale_ubl: introduce states
simahawk May 19, 2023
2c5f992
edi_sale_ubl: improve tests common
simahawk May 19, 2023
4764cae
edi_sale: add edi_exchange_ready
simahawk May 23, 2023
49de2ad
edi_sale_ubl: fix state mapping
simahawk May 24, 2023
8f0a2a3
edi_sale_ubl: fix order state handling
simahawk May 26, 2023
9d417d2
edi_sale_ubl: do not use Form for tests
simahawk May 26, 2023
e73e23a
edi_sale_ubl: fix state update
simahawk May 26, 2023
48b5790
edi_sale_ubl: improve line state test
simahawk Jun 22, 2023
9793f1a
edi_sale_ubl: trigger state update on line create/write
simahawk Jun 23, 2023
fc518f4
edi_sale_ubl: fix line state compute
simahawk Jul 3, 2023
0854d91
edi_sale_ubl: fix order state compute
simahawk Jul 3, 2023
928c5e2
edi_sale_ubl: adapt to type rule
simahawk Jul 6, 2023
af53266
edi_sale_ubl: make state readonly
simahawk Jul 6, 2023
dda575b
edi_sale_ubl: fix line state compute
simahawk Jul 6, 2023
28d2dfe
edi_sale_ubl: fix tests order setup
simahawk Jul 6, 2023
ad4f587
edi_sale_ubl: fix line state compute on order create
simahawk Jul 10, 2023
109148f
edi_sale_ubl: fix ordrsp tmpl
simahawk Jul 10, 2023
80b17fb
edi_sale_ubl: fix line state for qty=0
simahawk Jul 10, 2023
1431da6
edi_sale_ubl: fix tests, handle increased qty
simahawk Jul 31, 2023
8be69d4
edi_sale: move OrderMixin from edi_sale_ubl
simahawk Aug 7, 2023
6194f49
edi_sale_ubl: use @api.multi on create method
May 23, 2024
75ad6ea
edi_sale_ubl: use edi.config
simahawk Nov 14, 2024
4a3188a
edi_xml: improve base test class
simahawk Nov 18, 2024
fc41c1b
edi_sale_ubl: adapt tests
simahawk Nov 18, 2024
a3fd9b9
edi_sale_ubl: split input/output
simahawk Nov 29, 2024
65e5020
sale_order_import: add confirm_order flag
simahawk Dec 4, 2024
f66dc81
edi_sale_input: add support for legacy conf
simahawk Dec 4, 2024
db56210
edi: fix _edi_send_via_edi w/ quick exec
simahawk Dec 15, 2024
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
3 changes: 2 additions & 1 deletion edi_oca/models/edi_exchange_consumer_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ def _edi_send_via_edi(self, exchange_type, backend=None, force=False, **kw):
exchange_record = self._edi_create_exchange_record(
exchange_type, backend=backend
)
if exchange_record:
# If quick exec is on, `exchange_generate_send` already ran
if exchange_record and not exchange_type.quick_exec:
exchange_record.action_exchange_generate_send(**kw)

# TODO: full unit test coverage
Expand Down
30 changes: 30 additions & 0 deletions edi_sale_input_oca/components/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).


import logging

from odoo import _
from odoo.exceptions import UserError

from odoo.addons.component.core import Component

_logger = logging.getLogger(__name__)


class EDIExchangeSOInput(Component):
"""Process sale orders."""
Expand All @@ -16,6 +20,21 @@ class EDIExchangeSOInput(Component):
_inherit = "edi.component.input.mixin"
_usage = "input.process.sale.order"

def __init__(self, work_context):
super().__init__(work_context)
self.settings = {}
# Suppor legacy key `self.type_settings`
for key in ("sale_order", "sale_order_import"):
if key in self.type_settings:
_logger.warning(
"Deprecated key %s for %s. "
"Please use default field values in env_ctx",
key,
self._usage,
)
self.settings = self.type_settings.get(key, {})
break

def process(self):
wiz = self._setup_wizard()
res = wiz.import_order_button()
Expand Down Expand Up @@ -53,8 +72,19 @@ def _setup_wizard(self):
wiz.order_file = self.exchange_record._get_file_content(binary=False)
wiz.order_filename = self.exchange_record.exchange_filename
wiz.order_file_change()
wiz.price_source = self._get_default_price_source()
wiz.confirm_order = self._order_should_be_confirmed()
return wiz

# Deprecated: use default field values in env_ctx
# as these settings are supported by sale_order_import model.
def _get_default_price_source(self):
return self.settings.get("price_source", "pricelist")

# Deprecated: use default field values in env_ctx
def _order_should_be_confirmed(self):
return self.settings.get("confirm_order", False)

def _handle_create_order(self, order_id):
order = self.env["sale.order"].browse(order_id)
self.exchange_record._set_related_record(order)
Expand Down
28 changes: 28 additions & 0 deletions edi_sale_input_oca/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

import base64
import textwrap
from unittest import mock

from odoo.tools import mute_logger

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

Expand Down Expand Up @@ -45,6 +48,31 @@ def test_wizard_setup(self):
self.assertEqual(wiz.price_source, "pricelist")
md_onchange.assert_called()

@mute_logger("odoo.addons.edi_sale_input_oca.components.process")
def test_wizard_setup_deprecated_settings(self):
self.exc_type.advanced_settings_edit = textwrap.dedent(
"""
components:
process:
usage: input.process.sale.order
sale_order_import:
confirm_order: true
"""
)
comp = self.backend._get_component(self.record, "process")
with mock.patch.object(
type(self.wiz_model), "order_file_change"
) as md_onchange:
wiz = comp._setup_wizard()
self.assertEqual(wiz._name, self.wiz_model._name)
self.assertEqual(
base64.b64decode(wiz.order_file), b"<fake><order></order></fake>"
)
self.assertEqual(wiz.order_filename, self.record.exchange_filename)
self.assertEqual(wiz.price_source, "pricelist")
self.assertEqual(wiz.confirm_order, True)
md_onchange.assert_called()

# In both tests here we don"t care about the specific format of the import.
# We only care that the wizard plugged with the component works as expected.
def test_existing_order(self):
Expand Down
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_input_oca",
"edi_sale_ubl_oca",
"edi_ubl_oca",
"edi_xml_oca",
],
"data": [],
"demo": [
"demo/edi_exchange_type.xml",
],
}
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_sale_ubl_input_so_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_edi_sale_ubl_input_so_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_sale_ubl_input_so_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_sale_ubl_input_so_out" />
<field name="name">Demo UBL Sale Order (edi_sale_ubl_input_oca)</field>
<field name="code">demo_edi_sale_ubl_input_so_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
2 changes: 2 additions & 0 deletions edi_sale_ubl_input_oca/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import test_order_in
from . import test_order_in_full_flow
87 changes: 87 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,87 @@
# 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 odoo.addons.edi_sale_ubl_oca.tests.common import OrderInboundTestMixin


class TestOrderInbound(EDIBackendCommonComponentTestCase, OrderInboundTestMixin):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.exc_type_in = cls.env.ref(
"edi_sale_ubl_input_oca.demo_edi_sale_ubl_input_so_in"
)
cls._setup_inbound_order(cls.backend, cls.exc_type_in)

@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"])

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)
74 changes: 74 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,74 @@
# 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.addons.edi_oca.tests.common import EDIBackendCommonComponentTestCase
from odoo.addons.edi_sale_ubl_oca.tests.common import OrderInboundTestMixin

# TODO: split in different tests w/ SingleTransaction


class TestOrderInboundFull(EDIBackendCommonComponentTestCase, 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.exc_type_out = cls.env.ref(
"edi_sale_ubl_input_oca.demo_edi_sale_ubl_input_so_out"
)
cls.exc_type_in = cls.env.ref(
"edi_sale_ubl_input_oca.demo_edi_sale_ubl_input_so_in"
)
cls._setup_inbound_order(cls.backend, cls.exc_type_in)
cls.edi_conf = cls.env.ref(
"edi_sale_oca.demo_edi_configuration_confirmed"
).copy(
{
"name": "UBL IN EDI Conf",
"type_id": cls.exc_type_out.id,
"backend_id": cls.backend.id,
}
)

@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):
order = self._find_order()
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
with mock.patch.object(
type(self.backend), "_exchange_generate"
) as mock_generate:
mock_generate.return_value = "<xml>fake</xml>"
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.assertEqual(file_content, "<xml>fake</xml>")
self.assertEqual(ack_exc_record.edi_exchange_state, "output_sent")
1 change: 1 addition & 0 deletions edi_sale_ubl_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bot, please, take care of this!
2 changes: 2 additions & 0 deletions edi_sale_ubl_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import components
from . import models
29 changes: 29 additions & 0 deletions edi_sale_ubl_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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": [
"edi_sale_oca",
"edi_state_oca",
"edi_ubl_oca",
# This could be made optional
# but the delivery part would need another source of data
"sale_stock",
],
"data": [
"data/edi_state.xml",
"views/sale_order.xml",
],
"demo": [
"demo/edi_exchange_type.xml",
],
}
1 change: 1 addition & 0 deletions edi_sale_ubl_oca/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import listeners
Loading
Loading