Skip to content

Commit f7ec47f

Browse files
[IMP] edi_endpoint_oca: exec_mode=create_exchange_record
1 parent be0aee0 commit f7ec47f

8 files changed

Lines changed: 115 additions & 18 deletions

File tree

edi_endpoint_oca/README.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ Configuration
4545

4646
Go to "EDI -> Config -> Endpoints".
4747

48+
Exec modes
49+
----------
50+
51+
Each endpoint must pick an "Exec mode" that decides how the incoming
52+
request is turned into work for the EDI framework:
53+
54+
- **Create exchange record** (default): persists the raw HTTP body as a
55+
new exchange record on the configured backend / exchange type and
56+
returns ``{"status": "queued", "id": <identifier>}`` with HTTP 200.
57+
Use this for "receive and queue" endpoints — no per-endpoint code
58+
snippet is required, and request validation (e.g. JSON Schema) is
59+
handled by the endpoint mixin before the handler runs.
60+
- **Execute code**: runs the user-provided code snippet, giving full
61+
control over how the request is processed and what is returned.
62+
4863
Bug Tracker
4964
===========
5065

edi_endpoint_oca/demo/edi_backend_demo.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,15 @@ record = endpoint.create_exchange_record()
2626
result = {"response": Response("Created record: %s" % record.identifier)}
2727
</field>
2828
</record>
29+
30+
<record id="edi_endpoint_demo_2" model="edi.endpoint">
31+
<field name="backend_id" ref="edi_backend_demo" />
32+
<field name="backend_type_id" ref="edi_core_oca.demo_edi_backend_type" />
33+
<field name="exchange_type_id" ref="edi_exchange_type_demo" />
34+
<field name="name">EDI Demo Endpoint 2 (queue)</field>
35+
<field name="route">/demo/queue</field>
36+
<field name="request_method">POST</field>
37+
<field name="request_content_type">application/json</field>
38+
<field name="exec_mode">create_exchange_record</field>
39+
</record>
2940
</odoo>

edi_endpoint_oca/models/edi_endpoint.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ class EDIEndpoint(models.Model):
3333
comodel_name="edi.exchange.type",
3434
domain="[('backend_type_id','=', backend_type_id)]",
3535
)
36+
exec_mode = fields.Selection(default="create_exchange_record")
37+
38+
def _selection_exec_mode(self):
39+
return super()._selection_exec_mode() + [
40+
("create_exchange_record", self.env._("Create exchange record")),
41+
]
42+
43+
def _handle_exec__create_exchange_record(self, request):
44+
"""Persist the raw HTTP body as an exchange record and acknowledge.
45+
46+
Covers the "receive and queue" case for incoming EDI endpoints,
47+
avoiding the need for a per-endpoint code snippet.
48+
"""
49+
record = self.create_exchange_record(
50+
file_content=request.httprequest.get_data(),
51+
)
52+
return {
53+
"payload": {"status": "queued", "id": record.identifier},
54+
"status_code": 200,
55+
}
3656

3757
def create_exchange_record(self, file_content=None, encoding="utf-8", **vals):
3858
"""Create an EDI exchange record from current endpoint.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
11
Go to "EDI -\> Config -\> Endpoints".
2+
3+
## Exec modes
4+
5+
Each endpoint must pick an "Exec mode" that decides how the incoming
6+
request is turned into work for the EDI framework:
7+
8+
- **Create exchange record** (default): persists the raw HTTP body as a
9+
new exchange record on the configured backend / exchange type and
10+
returns `{"status": "queued", "id": <identifier>}` with HTTP 200. Use
11+
this for "receive and queue" endpoints — no per-endpoint code snippet
12+
is required, and request validation (e.g. JSON Schema) is handled by
13+
the endpoint mixin before the handler runs.
14+
- **Execute code**: runs the user-provided code snippet, giving full
15+
control over how the request is processed and what is returned.

edi_endpoint_oca/static/description/index.html

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -380,44 +380,62 @@ <h1>EDI endpoint</h1>
380380
<p><strong>Table of contents</strong></p>
381381
<div class="contents local topic" id="contents">
382382
<ul class="simple">
383-
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
384-
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
385-
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
386-
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
387-
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
388-
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
383+
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a><ul>
384+
<li><a class="reference internal" href="#exec-modes" id="toc-entry-2">Exec modes</a></li>
385+
</ul>
386+
</li>
387+
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
388+
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
389+
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
390+
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
391+
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
389392
</ul>
390393
</li>
391394
</ul>
392395
</div>
393396
<div class="section" id="configuration">
394397
<h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
395398
<p>Go to “EDI -&gt; Config -&gt; Endpoints”.</p>
399+
<div class="section" id="exec-modes">
400+
<h3><a class="toc-backref" href="#toc-entry-2">Exec modes</a></h3>
401+
<p>Each endpoint must pick an “Exec mode” that decides how the incoming
402+
request is turned into work for the EDI framework:</p>
403+
<ul class="simple">
404+
<li><strong>Create exchange record</strong> (default): persists the raw HTTP body as a
405+
new exchange record on the configured backend / exchange type and
406+
returns <tt class="docutils literal">{&quot;status&quot;: &quot;queued&quot;, &quot;id&quot;: &lt;identifier&gt;}</tt> with HTTP 200.
407+
Use this for “receive and queue” endpoints — no per-endpoint code
408+
snippet is required, and request validation (e.g. JSON Schema) is
409+
handled by the endpoint mixin before the handler runs.</li>
410+
<li><strong>Execute code</strong>: runs the user-provided code snippet, giving full
411+
control over how the request is processed and what is returned.</li>
412+
</ul>
413+
</div>
396414
</div>
397415
<div class="section" id="bug-tracker">
398-
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
416+
<h2><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h2>
399417
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/edi-framework/issues">GitHub Issues</a>.
400418
In case of trouble, please check there if your issue has already been reported.
401419
If you spotted it first, help us to smash it by providing a detailed and welcomed
402420
<a class="reference external" href="https://github.com/OCA/edi-framework/issues/new?body=module:%20edi_endpoint_oca%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
403421
<p>Do not contact contributors directly about support or help with technical issues.</p>
404422
</div>
405423
<div class="section" id="credits">
406-
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
424+
<h2><a class="toc-backref" href="#toc-entry-4">Credits</a></h2>
407425
<div class="section" id="authors">
408-
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
426+
<h3><a class="toc-backref" href="#toc-entry-5">Authors</a></h3>
409427
<ul class="simple">
410428
<li>Camptocamp</li>
411429
</ul>
412430
</div>
413431
<div class="section" id="contributors">
414-
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
432+
<h3><a class="toc-backref" href="#toc-entry-6">Contributors</a></h3>
415433
<ul class="simple">
416434
<li>Simone Orsi &lt;<a class="reference external" href="mailto:simone.orsi&#64;camptocamp.com">simone.orsi&#64;camptocamp.com</a>&gt;</li>
417435
</ul>
418436
</div>
419437
<div class="section" id="maintainers">
420-
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
438+
<h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
421439
<p>This module is maintained by the OCA.</p>
422440
<a class="reference external image-reference" href="https://odoo-community.org">
423441
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />

edi_endpoint_oca/tests/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def _setup_records(cls):
5454
)
5555
or cls._get_endpoint()
5656
)
57+
cls.endpoint_create_record = cls.env.ref("edi_endpoint_oca.edi_endpoint_demo_2")
5758

5859
@classmethod
5960
def _get_backend_type(cls):

edi_endpoint_oca/tests/test_edi_endpoint.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ def test_route(self):
2929

3030
def test_endpoint_count(self):
3131
backend = self.endpoint.backend_id
32-
self.assertEqual(backend.endpoints_count, 1)
32+
initial = backend.endpoints_count
3333
rec = self.endpoint.copy(
3434
{
3535
"route": "/another",
3636
}
3737
)
38-
self.assertEqual(backend.endpoints_count, 2)
38+
self.assertEqual(backend.endpoints_count, initial + 1)
3939
rec.active = False
40-
self.assertEqual(backend.endpoints_count, 1)
40+
self.assertEqual(backend.endpoints_count, initial)
4141

4242
def test_archive_check(self):
4343
backend = self.endpoint.backend_id

edi_endpoint_oca/tests/test_edi_endpoint_controller.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# @author: Simone Orsi <simone.orsi@camptocamp.com>
33
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
44

5+
import base64
6+
import json
57
import os
68
import unittest
79

@@ -17,18 +19,18 @@ def setUpClass(cls):
1719
super().setUpClass()
1820
cls._setup_env()
1921
cls._setup_records()
20-
# Sync only the endpoint under test to avoid re-registering unrelated
22+
# Sync only the endpoints under test to avoid re-registering unrelated
2123
# demo routes that may already exist in the route registry.
22-
cls.endpoint._handle_registry_sync()
24+
(cls.endpoint | cls.endpoint_create_record)._handle_registry_sync()
2325

2426
def tearDown(self):
2527
# Clear routing cache so each test starts clean
2628
self.env.registry.clear_cache("routing")
2729
super().tearDown()
2830

29-
def _make_request(self, route, headers=None):
31+
def _make_request(self, route, headers=None, data=None):
3032
headers = dict(headers or {})
31-
return self.url_open(route, headers=headers, timeout=60)
33+
return self.url_open(route, headers=headers, data=data, timeout=60)
3234

3335
def test_call1(self):
3436
endpoint = "/edi/demo/try"
@@ -39,3 +41,19 @@ def test_call1(self):
3941
response = self._make_request(endpoint)
4042
self.assertEqual(response.status_code, 200)
4143
self.assertIn("Created record:", response.content.decode())
44+
45+
def test_handle_exec_create_exchange_record(self):
46+
self.authenticate("admin", "admin")
47+
body = json.dumps({"hello": "world"}).encode()
48+
response = self._make_request(
49+
"/edi/demo/queue",
50+
headers={"Content-Type": "application/json"},
51+
data=body,
52+
)
53+
self.assertEqual(response.status_code, 200)
54+
payload = response.json()
55+
self.assertEqual(payload["status"], "queued")
56+
record = self.env["edi.exchange.record"].search(
57+
[("identifier", "=", payload["id"])]
58+
)
59+
self.assertEqual(base64.b64decode(record.exchange_file), body)

0 commit comments

Comments
 (0)