Skip to content

Commit 5f9112c

Browse files
authored
MPT-12839 Commerce agreements add agreements (#24)
2 parents f053c54 + 753e77e commit 5f9112c

8 files changed

Lines changed: 187 additions & 67 deletions

File tree

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
from mpt_api_client.resources.commerce.commerce import AsyncCommerce, Commerce
2-
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
32

4-
__all__ = ["AsyncCommerce", "AsyncOrdersService", "Commerce", "OrdersService"] # noqa: WPS410
3+
__all__ = ["AsyncCommerce", "Commerce"] # noqa: WPS410
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.models import Model
3+
4+
5+
class Agreement(Model):
6+
"""Agreement resource."""
7+
8+
9+
class AgreementsServiceConfig:
10+
"""Orders service config."""
11+
12+
_endpoint = "/public/v1/commerce/agreements"
13+
_model_class = Agreement
14+
_collection_key = "data"
15+
16+
17+
class AgreementsService(Service[Agreement], AgreementsServiceConfig):
18+
"""Agreements service."""
19+
20+
def template(self, agreement_id: str) -> str:
21+
"""Renders the template for the given Agreement id.
22+
23+
Args:
24+
agreement_id: Agreement ID.
25+
26+
Returns:
27+
Agreement template.
28+
"""
29+
response = self._resource_do_request(agreement_id, action="template")
30+
return response.text
31+
32+
33+
class AsyncAgreementsService(AsyncService[Agreement], AgreementsServiceConfig):
34+
"""Agreements service."""
35+
36+
async def template(self, agreement_id: str) -> str:
37+
"""Renders the template for the given Agreement id.
38+
39+
Args:
40+
agreement_id: Agreement ID.
41+
42+
Returns:
43+
Agreement template.
44+
"""
45+
response = await self._resource_do_request(agreement_id, action="template")
46+
return response.text

mpt_api_client/resources/commerce/commerce.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
2+
from mpt_api_client.resources.commerce.agreements import AgreementsService, AsyncAgreementsService
23
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
34

45

@@ -8,6 +9,11 @@ class Commerce:
89
def __init__(self, http_client: HTTPClient):
910
self.http_client = http_client
1011

12+
@property
13+
def agreements(self) -> AgreementsService:
14+
"""Agreement service."""
15+
return AgreementsService(http_client=self.http_client)
16+
1117
@property
1218
def orders(self) -> OrdersService:
1319
"""Order service."""
@@ -20,6 +26,11 @@ class AsyncCommerce:
2026
def __init__(self, http_client: AsyncHTTPClient):
2127
self.http_client = http_client
2228

29+
@property
30+
def agreements(self) -> AsyncAgreementsService:
31+
"""Agreement service."""
32+
return AsyncAgreementsService(http_client=self.http_client)
33+
2334
@property
2435
def orders(self) -> AsyncOrdersService:
2536
"""Order service."""

tests/http/test_async_service.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,6 @@
88
from tests.http.conftest import AsyncDummyService
99

1010

11-
async def test_async_create_mixin(async_dummy_service): # noqa: WPS210
12-
resource_data = {"name": "Test Resource", "status": "active"}
13-
new_resource_data = {"id": "new-resource-id", "name": "Test Resource", "status": "active"}
14-
create_response = httpx.Response(httpx.codes.OK, json=new_resource_data)
15-
16-
with respx.mock:
17-
mock_route = respx.post("https://api.example.com/api/v1/test").mock(
18-
return_value=create_response
19-
)
20-
21-
created_resource = await async_dummy_service.create(resource_data)
22-
23-
assert created_resource.to_dict() == new_resource_data
24-
assert mock_route.call_count == 1
25-
request = mock_route.calls[0].request
26-
assert request.method == "POST"
27-
assert request.url == "https://api.example.com/api/v1/test"
28-
assert json.loads(request.content.decode()) == resource_data
29-
30-
31-
async def test_async_delete_mixin(async_dummy_service): # noqa: WPS210
32-
delete_response = httpx.Response(httpx.codes.NO_CONTENT, json=None)
33-
34-
with respx.mock:
35-
mock_route = respx.delete("https://api.example.com/api/v1/test/RES-123").mock(
36-
return_value=delete_response
37-
)
38-
39-
await async_dummy_service.delete("RES-123")
40-
41-
assert mock_route.call_count == 1
42-
43-
4411
async def test_async_fetch_one_success(async_dummy_service, single_result_response):
4512
with respx.mock:
4613
mock_route = respx.get("https://api.example.com/api/v1/test").mock(

tests/http/test_mixins.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import json
2+
3+
import httpx
4+
import respx
5+
6+
7+
async def test_async_create_mixin(async_dummy_service): # noqa: WPS210
8+
resource_data = {"name": "Test Resource", "status": "active"}
9+
new_resource_data = {"id": "new-resource-id", "name": "Test Resource", "status": "active"}
10+
create_response = httpx.Response(httpx.codes.OK, json=new_resource_data)
11+
12+
with respx.mock:
13+
mock_route = respx.post("https://api.example.com/api/v1/test").mock(
14+
return_value=create_response
15+
)
16+
17+
created_resource = await async_dummy_service.create(resource_data)
18+
19+
assert created_resource.to_dict() == new_resource_data
20+
assert mock_route.call_count == 1
21+
request = mock_route.calls[0].request
22+
assert request.method == "POST"
23+
assert request.url == "https://api.example.com/api/v1/test"
24+
assert json.loads(request.content.decode()) == resource_data
25+
26+
27+
async def test_async_delete_mixin(async_dummy_service): # noqa: WPS210
28+
delete_response = httpx.Response(httpx.codes.NO_CONTENT, json=None)
29+
30+
with respx.mock:
31+
mock_route = respx.delete("https://api.example.com/api/v1/test/RES-123").mock(
32+
return_value=delete_response
33+
)
34+
35+
await async_dummy_service.delete("RES-123")
36+
37+
assert mock_route.call_count == 1
38+
39+
40+
def test_sync_create_mixin(dummy_service): # noqa: WPS210
41+
resource_data = {"name": "Test Resource", "status": "active"}
42+
new_resource_data = {"id": "new-resource-id", "name": "Test Resource", "status": "active"}
43+
create_response = httpx.Response(httpx.codes.OK, json=new_resource_data)
44+
45+
with respx.mock:
46+
mock_route = respx.post("https://api.example.com/api/v1/test").mock(
47+
return_value=create_response
48+
)
49+
50+
created_resource = dummy_service.create(resource_data)
51+
52+
assert created_resource.to_dict() == new_resource_data
53+
assert mock_route.call_count == 1
54+
request = mock_route.calls[0].request
55+
assert request.method == "POST"
56+
assert request.url == "https://api.example.com/api/v1/test"
57+
assert json.loads(request.content.decode()) == resource_data
58+
59+
60+
def test_sync_delete_mixin(dummy_service):
61+
delete_response = httpx.Response(httpx.codes.NO_CONTENT, json=None)
62+
with respx.mock:
63+
mock_route = respx.delete("https://api.example.com/api/v1/test/RES-123").mock(
64+
return_value=delete_response
65+
)
66+
67+
dummy_service.delete("RES-123")
68+
69+
assert mock_route.call_count == 1

tests/http/test_service.py

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,6 @@
99
from tests.http.conftest import DummyService
1010

1111

12-
def test_sync_create_mixin(dummy_service): # noqa: WPS210
13-
resource_data = {"name": "Test Resource", "status": "active"}
14-
new_resource_data = {"id": "new-resource-id", "name": "Test Resource", "status": "active"}
15-
create_response = httpx.Response(httpx.codes.OK, json=new_resource_data)
16-
17-
with respx.mock:
18-
mock_route = respx.post("https://api.example.com/api/v1/test").mock(
19-
return_value=create_response
20-
)
21-
22-
created_resource = dummy_service.create(resource_data)
23-
24-
assert created_resource.to_dict() == new_resource_data
25-
assert mock_route.call_count == 1
26-
request = mock_route.calls[0].request
27-
assert request.method == "POST"
28-
assert request.url == "https://api.example.com/api/v1/test"
29-
assert json.loads(request.content.decode()) == resource_data
30-
31-
32-
def test_sync_delete_mixin(dummy_service):
33-
delete_response = httpx.Response(httpx.codes.NO_CONTENT, json=None)
34-
with respx.mock:
35-
mock_route = respx.delete("https://api.example.com/api/v1/test/RES-123").mock(
36-
return_value=delete_response
37-
)
38-
39-
dummy_service.delete("RES-123")
40-
41-
assert mock_route.call_count == 1
42-
43-
4412
def test_sync_fetch_one_success(dummy_service, single_result_response):
4513
with respx.mock:
4614
mock_route = respx.get("https://api.example.com/api/v1/test").mock(
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import httpx
2+
import respx
3+
4+
from mpt_api_client.resources.commerce.agreements import AgreementsService, AsyncAgreementsService
5+
6+
7+
async def test_async_template(async_http_client):
8+
async_agreements_service = AsyncAgreementsService(http_client=async_http_client)
9+
template_content = "# Order Template\n\nThis is a markdown template."
10+
with respx.mock:
11+
respx.get("https://api.example.com/public/v1/commerce/agreements/AGR-123/template").mock(
12+
return_value=httpx.Response(
13+
status_code=200,
14+
headers={"content-type": "text/markdown"},
15+
content=template_content,
16+
)
17+
)
18+
19+
template = await async_agreements_service.template("AGR-123")
20+
21+
assert template == template_content
22+
23+
24+
def test_template(http_client):
25+
agreements_service = AgreementsService(http_client=http_client)
26+
with respx.mock:
27+
mock_route = respx.get(
28+
"https://api.example.com/public/v1/commerce/agreements/AGR-123/template"
29+
).mock(
30+
return_value=httpx.Response(
31+
status_code=200,
32+
headers={"content-type": "text/markdown"},
33+
content="# Order Template\n\nThis is a markdown template.",
34+
)
35+
)
36+
37+
markdown_template = agreements_service.template("AGR-123")
38+
39+
assert mock_route.called
40+
assert mock_route.call_count == 1
41+
assert markdown_template == "# Order Template\n\nThis is a markdown template."

tests/resources/commerce/test_commerce.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from mpt_api_client.http import AsyncHTTPClient
22
from mpt_api_client.resources.commerce import AsyncCommerce, Commerce
3+
from mpt_api_client.resources.commerce.agreements import AgreementsService, AsyncAgreementsService
34
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
45

56

@@ -55,3 +56,21 @@ def test_async_commerce_orders_multiple_calls(async_http_client: AsyncHTTPClient
5556
assert orders_service is not orders_service_additional
5657
assert isinstance(orders_service, AsyncOrdersService)
5758
assert isinstance(orders_service_additional, AsyncOrdersService)
59+
60+
61+
def test_async_agreements(async_http_client):
62+
commerce = AsyncCommerce(http_client=async_http_client)
63+
64+
agreements = commerce.agreements
65+
66+
assert isinstance(agreements, AsyncAgreementsService)
67+
assert agreements.http_client is async_http_client
68+
69+
70+
def test_agreements(http_client):
71+
commerce = Commerce(http_client=http_client)
72+
73+
agreements = commerce.agreements
74+
75+
assert isinstance(agreements, AgreementsService)
76+
assert agreements.http_client is http_client

0 commit comments

Comments
 (0)