diff --git a/edi_endpoint_oca/README.rst b/edi_endpoint_oca/README.rst index 88e65de9d..c3bdf680c 100644 --- a/edi_endpoint_oca/README.rst +++ b/edi_endpoint_oca/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ============ EDI endpoint ============ @@ -17,7 +13,7 @@ EDI endpoint .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi--framework-lightgray.png?logo=github @@ -45,6 +41,21 @@ Configuration Go to "EDI -> Config -> Endpoints". +Exec modes +---------- + +Each endpoint must pick an "Exec mode" that decides how the incoming +request is turned into work for the EDI framework: + +- **Create exchange record** (default): persists the raw HTTP body as a + new exchange record on the configured backend / exchange type and + returns ``{"status": "queued", "id": }`` with HTTP 200. + Use this for "receive and queue" endpoints — no per-endpoint code + snippet is required, and request validation (e.g. JSON Schema) is + handled by the endpoint mixin before the handler runs. +- **Execute code**: runs the user-provided code snippet, giving full + control over how the request is processed and what is returned. + Bug Tracker =========== diff --git a/edi_endpoint_oca/demo/edi_backend_demo.xml b/edi_endpoint_oca/demo/edi_backend_demo.xml index cea2db0e8..e211b69f9 100644 --- a/edi_endpoint_oca/demo/edi_backend_demo.xml +++ b/edi_endpoint_oca/demo/edi_backend_demo.xml @@ -26,4 +26,15 @@ record = endpoint.create_exchange_record() result = {"response": Response("Created record: %s" % record.identifier)} + + + + + + EDI Demo Endpoint 2 + /demo/create + POST + application/json + create_exchange_record + diff --git a/edi_endpoint_oca/models/edi_endpoint.py b/edi_endpoint_oca/models/edi_endpoint.py index 06e7bff26..36c7e449a 100644 --- a/edi_endpoint_oca/models/edi_endpoint.py +++ b/edi_endpoint_oca/models/edi_endpoint.py @@ -33,6 +33,26 @@ class EDIEndpoint(models.Model): comodel_name="edi.exchange.type", domain="[('backend_type_id','=', backend_type_id)]", ) + exec_mode = fields.Selection(default="create_exchange_record") + + def _selection_exec_mode(self): + return super()._selection_exec_mode() + [ + ("create_exchange_record", self.env._("Create exchange record")), + ] + + def _handle_exec__create_exchange_record(self, request): + """Persist the raw HTTP body as an exchange record and acknowledge. + + Covers the "receive and queue" case for incoming EDI endpoints, + avoiding the need for a per-endpoint code snippet. + """ + record = self.create_exchange_record( + file_content=request.httprequest.get_data(), + ) + return { + "payload": {"status": "queued", "id": record.identifier}, + "status_code": 200, + } def create_exchange_record(self, file_content=None, encoding="utf-8", **vals): """Create an EDI exchange record from current endpoint. @@ -46,6 +66,7 @@ def create_exchange_record(self, file_content=None, encoding="utf-8", **vals): if not isinstance(file_content, bytes): file_content = bytes(file_content, encoding) vals["exchange_file"] = base64.b64encode(file_content) + vals["edi_exchange_state"] = "input_received" rec = self.backend_id.create_record(self.exchange_type_id.code, vals) return rec diff --git a/edi_endpoint_oca/readme/CONFIGURE.md b/edi_endpoint_oca/readme/CONFIGURE.md index 040110335..1064882a8 100644 --- a/edi_endpoint_oca/readme/CONFIGURE.md +++ b/edi_endpoint_oca/readme/CONFIGURE.md @@ -1 +1,15 @@ Go to "EDI -\> Config -\> Endpoints". + +## Exec modes + +Each endpoint must pick an "Exec mode" that decides how the incoming +request is turned into work for the EDI framework: + +- **Create exchange record** (default): persists the raw HTTP body as a + new exchange record on the configured backend / exchange type and + returns `{"status": "queued", "id": }` with HTTP 200. Use + this for "receive and queue" endpoints — no per-endpoint code snippet + is required, and request validation (e.g. JSON Schema) is handled by + the endpoint mixin before the handler runs. +- **Execute code**: runs the user-provided code snippet, giving full + control over how the request is processed and what is returned. diff --git a/edi_endpoint_oca/static/description/index.html b/edi_endpoint_oca/static/description/index.html index 52824a930..1ec8e679b 100644 --- a/edi_endpoint_oca/static/description/index.html +++ b/edi_endpoint_oca/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +EDI endpoint -
+
+

EDI endpoint

- - -Odoo Community Association - -
-

EDI endpoint

-

Beta License: LGPL-3 OCA/edi-framework Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/edi-framework Translate me on Weblate Try me on Runboat

Base module allowing configuration of custom endpoints for EDI framework.

Table of contents

-

Configuration

+

Configuration

Go to “EDI -> Config -> Endpoints”.

+
+

Exec modes

+

Each endpoint must pick an “Exec mode” that decides how the incoming +request is turned into work for the EDI framework:

+
    +
  • Create exchange record (default): persists the raw HTTP body as a +new exchange record on the configured backend / exchange type and +returns {"status": "queued", "id": <identifier>} with HTTP 200. +Use this for “receive and queue” endpoints — no per-endpoint code +snippet is required, and request validation (e.g. JSON Schema) is +handled by the endpoint mixin before the handler runs.
  • +
  • Execute code: runs the user-provided code snippet, giving full +control over how the request is processed and what is returned.
  • +
+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -403,21 +416,21 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-
diff --git a/edi_endpoint_oca/tests/test_edi_endpoint.py b/edi_endpoint_oca/tests/test_edi_endpoint.py index ca4ed1d01..994d41e89 100644 --- a/edi_endpoint_oca/tests/test_edi_endpoint.py +++ b/edi_endpoint_oca/tests/test_edi_endpoint.py @@ -34,15 +34,15 @@ def test_route(self): def test_endpoint_count(self): backend = self.endpoint.backend_id - self.assertEqual(backend.endpoints_count, 1) + initial = backend.endpoints_count rec = self.endpoint.copy( { "route": "/another", } ) - self.assertEqual(backend.endpoints_count, 2) + self.assertEqual(backend.endpoints_count, initial + 1) rec.active = False - self.assertEqual(backend.endpoints_count, 1) + self.assertEqual(backend.endpoints_count, initial) def test_archive_check(self): backend = self.endpoint.backend_id diff --git a/edi_endpoint_oca/tests/test_edi_endpoint_controller.py b/edi_endpoint_oca/tests/test_edi_endpoint_controller.py index c71a39d9e..9bd48d2bc 100644 --- a/edi_endpoint_oca/tests/test_edi_endpoint_controller.py +++ b/edi_endpoint_oca/tests/test_edi_endpoint_controller.py @@ -2,10 +2,12 @@ # @author: Simone Orsi # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +import base64 +import json import os import unittest -from odoo.tests.common import HttpCase +from odoo.tests import HttpCase, RecordCapturer @unittest.skipIf(os.getenv("SKIP_HTTP_CASE"), "EDIEndpointHttpCase skipped") @@ -25,3 +27,22 @@ def test_call1(self): response = self.url_open(endpoint) self.assertEqual(response.status_code, 200) self.assertIn("Created record:", response.content.decode()) + + def test_handle_exec_create_exchange_record(self): + self.authenticate("admin", "admin") + body = json.dumps({"hello": "world"}).encode() + with RecordCapturer(self.env["edi.exchange.record"], []) as capture: + response = self.url_open( + "/edi/demo/create", + headers={"Content-Type": "application/json"}, + data=body, + timeout=10, + ) + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertEqual(payload["status"], "queued") + self.assertEqual(len(capture.records), 1) + record = capture.records + self.assertEqual(record.identifier, payload["id"]) + self.assertEqual(record.edi_exchange_state, "input_received") + self.assertEqual(base64.b64decode(record.exchange_file), body) diff --git a/test-requirements.txt b/test-requirements.txt index a8133e4b5..86815eb54 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,4 @@ odoo-test-helper xmlunittest + +odoo-addon-endpoint @git+https://github.com/OCA/web-api@refs/pull/132/head#subdirectory=endpoint