Skip to content

Commit 256905e

Browse files
committed
MPT-12845 Add subscriptions
1 parent f053c54 commit 256905e

File tree

4 files changed

+207
-0
lines changed

4 files changed

+207
-0
lines changed

mpt_api_client/resources/commerce/commerce.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
22
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
3+
from mpt_api_client.resources.commerce.subscriptions import (
4+
AsyncSubscriptionsService,
5+
SubscriptionsService,
6+
)
37

48

59
class Commerce:
@@ -13,6 +17,11 @@ def orders(self) -> OrdersService:
1317
"""Order service."""
1418
return OrdersService(http_client=self.http_client)
1519

20+
@property
21+
def subscriptions(self) -> SubscriptionsService:
22+
"""Subscription service."""
23+
return SubscriptionsService(http_client=self.http_client)
24+
1625

1726
class AsyncCommerce:
1827
"""Commerce MPT API Module."""
@@ -24,3 +33,8 @@ def __init__(self, http_client: AsyncHTTPClient):
2433
def orders(self) -> AsyncOrdersService:
2534
"""Order service."""
2635
return AsyncOrdersService(http_client=self.http_client)
36+
37+
@property
38+
def subscriptions(self) -> AsyncSubscriptionsService:
39+
"""Subscription service."""
40+
return AsyncSubscriptionsService(http_client=self.http_client)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from mpt_api_client.http import (
2+
AsyncCreateMixin,
3+
AsyncDeleteMixin,
4+
AsyncService,
5+
CreateMixin,
6+
DeleteMixin,
7+
Service,
8+
)
9+
from mpt_api_client.models import Model, ResourceData
10+
11+
12+
class Subscription(Model):
13+
"""Subscription resource."""
14+
15+
16+
class SubscriptionsServiceConfig:
17+
"""Subscription service config."""
18+
19+
_endpoint = "/public/v1/commerce/subscriptions"
20+
_model_class = Subscription
21+
_collection_key = "data"
22+
23+
24+
class SubscriptionsService( # noqa: WPS215
25+
CreateMixin[Subscription],
26+
DeleteMixin,
27+
Service[Subscription],
28+
SubscriptionsServiceConfig,
29+
):
30+
"""Subscription service."""
31+
32+
def render(self, resource_id: str) -> str:
33+
"""Render subscription template.
34+
35+
Args:
36+
resource_id: Subscription resource ID
37+
38+
Returns:
39+
Order template text in markdown format.
40+
"""
41+
response = self._resource_do_request(resource_id, "GET", "render")
42+
return response.text
43+
44+
def terminate(self, resource_id: str, resource_data: ResourceData) -> Subscription:
45+
"""Terminate subscription.
46+
47+
Args:
48+
resource_id: Order resource ID
49+
resource_data: Order resource data
50+
51+
Returns:
52+
Subscription template text in markdown format.
53+
"""
54+
return self._resource_action(resource_id, "POST", "terminate", json=resource_data)
55+
56+
57+
class AsyncSubscriptionsService( # noqa: WPS215
58+
AsyncCreateMixin[Subscription],
59+
AsyncDeleteMixin,
60+
AsyncService[Subscription],
61+
SubscriptionsServiceConfig,
62+
):
63+
"""Async Subscription service."""
64+
65+
async def render(self, resource_id: str) -> str:
66+
"""Render subscription template.
67+
68+
Args:
69+
resource_id: Subscription resource ID
70+
71+
Returns:
72+
Order template text in markdown format.
73+
"""
74+
response = await self._resource_do_request(resource_id, "GET", "render")
75+
return response.text
76+
77+
async def terminate(self, resource_id: str, resource_data: ResourceData) -> Subscription:
78+
"""Terminate subscription.
79+
80+
Args:
81+
resource_id: Order resource ID
82+
resource_data: Order resource data
83+
84+
Returns:
85+
Subscription template text in markdown format.
86+
"""
87+
return await self._resource_action(resource_id, "POST", "terminate", json=resource_data)

tests/resources/commerce/test_commerce.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from mpt_api_client.http import AsyncHTTPClient
22
from mpt_api_client.resources.commerce import AsyncCommerce, Commerce
33
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
4+
from mpt_api_client.resources.commerce.subscriptions import (
5+
AsyncSubscriptionsService,
6+
SubscriptionsService,
7+
)
48

59

610
def test_commerce_init(http_client):
@@ -55,3 +59,17 @@ def test_async_commerce_orders_multiple_calls(async_http_client: AsyncHTTPClient
5559
assert orders_service is not orders_service_additional
5660
assert isinstance(orders_service, AsyncOrdersService)
5761
assert isinstance(orders_service_additional, AsyncOrdersService)
62+
63+
64+
def test_async_subscriptions(async_http_client: AsyncHTTPClient):
65+
commerce = AsyncCommerce(http_client=async_http_client)
66+
subscriptions = commerce.subscriptions
67+
68+
assert isinstance(subscriptions, AsyncSubscriptionsService)
69+
70+
71+
def test_subscriptions(http_client):
72+
commerce = Commerce(http_client=http_client)
73+
subscriptions = commerce.subscriptions
74+
75+
assert isinstance(subscriptions, SubscriptionsService)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import httpx
2+
import pytest
3+
import respx
4+
5+
from mpt_api_client.resources.commerce.subscriptions import (
6+
AsyncSubscriptionsService,
7+
SubscriptionsService,
8+
)
9+
10+
11+
@pytest.fixture
12+
def subscriptions_service(http_client):
13+
return SubscriptionsService(http_client=http_client)
14+
15+
16+
@pytest.fixture
17+
def async_subscriptions_service(async_http_client):
18+
return AsyncSubscriptionsService(http_client=async_http_client)
19+
20+
21+
async def test_async_terminate(async_subscriptions_service):
22+
subscription_expected = {"id": "SUB-123", "status": "Terminated", "name": "Terminated SUB-123"}
23+
with respx.mock:
24+
respx.post(
25+
"https://api.example.com/public/v1/commerce/subscriptions/SUB-123/terminate"
26+
).mock(
27+
return_value=httpx.Response(
28+
status_code=httpx.codes.OK,
29+
json=subscription_expected,
30+
)
31+
)
32+
33+
subscription_updated = await async_subscriptions_service.terminate(
34+
"SUB-123", {"name": "Terminated SUB-123"}
35+
)
36+
37+
assert subscription_updated.to_dict() == subscription_expected
38+
39+
40+
async def test_async_render(async_subscriptions_service):
41+
template_content = "# Subscription Template\n\nThis is a markdown template."
42+
with respx.mock:
43+
respx.get("https://api.example.com/public/v1/commerce/subscriptions/SUB-123/render").mock(
44+
return_value=httpx.Response(
45+
status_code=httpx.codes.OK,
46+
headers={"content-type": "text/markdown"},
47+
content=template_content,
48+
)
49+
)
50+
51+
template = await async_subscriptions_service.render("SUB-123")
52+
53+
assert template == template_content
54+
55+
56+
def test_terminate(subscriptions_service):
57+
subscription_expected = {"id": "SUB-123", "status": "Terminated", "name": "Terminated SUB-123"}
58+
with respx.mock:
59+
respx.post(
60+
"https://api.example.com/public/v1/commerce/subscriptions/SUB-123/terminate"
61+
).mock(
62+
return_value=httpx.Response(
63+
status_code=httpx.codes.OK,
64+
json=subscription_expected,
65+
)
66+
)
67+
68+
subscription_updated = subscriptions_service.terminate(
69+
"SUB-123", {"name": "Terminated SUB-123"}
70+
)
71+
72+
assert subscription_updated.to_dict() == subscription_expected
73+
74+
75+
def test_render(subscriptions_service):
76+
template_content = "# Subscription Template\n\nThis is a markdown template."
77+
with respx.mock:
78+
respx.get("https://api.example.com/public/v1/commerce/subscriptions/SUB-123/render").mock(
79+
return_value=httpx.Response(
80+
status_code=httpx.codes.OK,
81+
headers={"content-type": "text/markdown"},
82+
content=template_content,
83+
)
84+
)
85+
86+
template = subscriptions_service.render("SUB-123")
87+
88+
assert template == template_content

0 commit comments

Comments
 (0)