Skip to content

Commit 2e4344a

Browse files
committed
MPT-12845 Add subscriptions
1 parent 5f9112c commit 2e4344a

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,6 +1,10 @@
11
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
22
from mpt_api_client.resources.commerce.agreements import AgreementsService, AsyncAgreementsService
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
class Commerce:
@@ -19,6 +23,11 @@ def orders(self) -> OrdersService:
1923
"""Order service."""
2024
return OrdersService(http_client=self.http_client)
2125

26+
@property
27+
def subscriptions(self) -> SubscriptionsService:
28+
"""Subscription service."""
29+
return SubscriptionsService(http_client=self.http_client)
30+
2231

2332
class AsyncCommerce:
2433
"""Commerce MPT API Module."""
@@ -35,3 +44,8 @@ def agreements(self) -> AsyncAgreementsService:
3544
def orders(self) -> AsyncOrdersService:
3645
"""Order service."""
3746
return AsyncOrdersService(http_client=self.http_client)
47+
48+
@property
49+
def subscriptions(self) -> AsyncSubscriptionsService:
50+
"""Subscription service."""
51+
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
@@ -2,6 +2,10 @@
22
from mpt_api_client.resources.commerce import AsyncCommerce, Commerce
33
from mpt_api_client.resources.commerce.agreements import AgreementsService, AsyncAgreementsService
44
from mpt_api_client.resources.commerce.orders import AsyncOrdersService, OrdersService
5+
from mpt_api_client.resources.commerce.subscriptions import (
6+
AsyncSubscriptionsService,
7+
SubscriptionsService,
8+
)
59

610

711
def test_commerce_init(http_client):
@@ -74,3 +78,17 @@ def test_agreements(http_client):
7478

7579
assert isinstance(agreements, AgreementsService)
7680
assert agreements.http_client is http_client
81+
82+
83+
def test_async_subscriptions(async_http_client: AsyncHTTPClient):
84+
commerce = AsyncCommerce(http_client=async_http_client)
85+
subscriptions = commerce.subscriptions
86+
87+
assert isinstance(subscriptions, AsyncSubscriptionsService)
88+
89+
90+
def test_subscriptions(http_client):
91+
commerce = Commerce(http_client=http_client)
92+
subscriptions = commerce.subscriptions
93+
94+
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)