Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions mpt_api_client/resources/accounts/accounts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
from mpt_api_client.resources.accounts.account import AccountsService, AsyncAccountsService
from mpt_api_client.resources.accounts.api_tokens import ApiTokensService, AsyncApiTokensService
from mpt_api_client.resources.accounts.buyers import AsyncBuyersService, BuyersService
from mpt_api_client.resources.accounts.cloud_tenants import (
AsyncCloudTenantsService,
CloudTenantsService,
Expand Down Expand Up @@ -61,6 +62,11 @@ def cloud_tenants(self) -> CloudTenantsService:
"""Cloud Tenants service."""
return CloudTenantsService(http_client=self.http_client)

@property
def buyers(self) -> BuyersService:
"""Buyers service."""
return BuyersService(http_client=self.http_client)


class AsyncAccounts:
"""Async Accounts MPT API Module."""
Expand Down Expand Up @@ -107,3 +113,8 @@ def modules(self) -> AsyncModulesService:
def cloud_tenants(self) -> AsyncCloudTenantsService:
"""Cloud Tenants service."""
return AsyncCloudTenantsService(http_client=self.http_client)

@property
def buyers(self) -> AsyncBuyersService:
"""Buyers service."""
return AsyncBuyersService(http_client=self.http_client)
95 changes: 95 additions & 0 deletions mpt_api_client/resources/accounts/buyers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from mpt_api_client.http import AsyncService, Service
from mpt_api_client.http.mixins import (
AsyncCreateMixin,
AsyncDeleteMixin,
AsyncUpdateMixin,
CreateMixin,
DeleteMixin,
UpdateMixin,
)
from mpt_api_client.models import Model
from mpt_api_client.models.model import ResourceData
from mpt_api_client.resources.accounts.mixins import (
ActivatableMixin,
AsyncActivatableMixin,
AsyncEnablableMixin,
AsyncValidateMixin,
EnablableMixin,
ValidateMixin,
)


class Buyer(Model):
"""Buyer Model."""


class BuyersServiceConfig:
"""Buyers Service Configuration."""

_endpoint = "/public/v1/accounts/buyers"
_model_class = Buyer
_collection_key = "data"


class BuyersService(
CreateMixin[Buyer],
DeleteMixin,
UpdateMixin[Buyer],
ActivatableMixin[Buyer],
EnablableMixin[Buyer],
ValidateMixin[Buyer],
Service[Buyer],
BuyersServiceConfig,
):
"""Buyers Service."""

def synchronize(self, resource_id: str, resource_data: ResourceData | None = None) -> Buyer:
"""Synchronize a buyer.

Args:
resource_id: Resource ID
resource_data: Resource data will be updated
"""
return self._resource_action(resource_id, "POST", "synchronize", json=resource_data)

def transfer(self, resource_id: str, resource_data: ResourceData | None = None) -> Buyer:
"""Transfer a buyer.

Args:
resource_id: Resource ID
resource_data: Resource data will be updated
"""
return self._resource_action(resource_id, "POST", "transfer", json=resource_data)


class AsyncBuyersService(
AsyncCreateMixin[Buyer],
AsyncDeleteMixin,
AsyncUpdateMixin[Buyer],
AsyncActivatableMixin[Buyer],
AsyncEnablableMixin[Buyer],
AsyncValidateMixin[Buyer],
AsyncService[Buyer],
BuyersServiceConfig,
):
"""Async Buyers Service."""

async def synchronize(
self, resource_id: str, resource_data: ResourceData | None = None
) -> Buyer:
"""Synchronize a buyer.

Args:
resource_id: Resource ID
resource_data: Resource data will be updated
"""
return await self._resource_action(resource_id, "POST", "synchronize", json=resource_data)

async def transfer(self, resource_id: str, resource_data: ResourceData | None = None) -> Buyer:
"""Transfer a buyer.

Args:
resource_id: Resource ID
resource_data: Resource data will be updated
"""
return await self._resource_action(resource_id, "POST", "transfer", json=resource_data)
3 changes: 3 additions & 0 deletions tests/resources/accounts/test_accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
ApiTokensService,
AsyncApiTokensService,
)
from mpt_api_client.resources.accounts.buyers import AsyncBuyersService, BuyersService
from mpt_api_client.resources.accounts.cloud_tenants import (
AsyncCloudTenantsService,
CloudTenantsService,
Expand Down Expand Up @@ -41,6 +42,7 @@ def async_accounts(async_http_client):
("api_tokens", ApiTokensService),
("modules", ModulesService),
("cloud_tenants", CloudTenantsService),
("buyers", BuyersService),
],
)
def test_accounts_properties(accounts, property_name, expected_service_class):
Expand All @@ -62,6 +64,7 @@ def test_accounts_properties(accounts, property_name, expected_service_class):
("api_tokens", AsyncApiTokensService),
("modules", AsyncModulesService),
("cloud_tenants", AsyncCloudTenantsService),
("buyers", AsyncBuyersService),
],
)
def test_async_accounts_properties(async_accounts, property_name, expected_service_class):
Expand Down
161 changes: 161 additions & 0 deletions tests/resources/accounts/test_buyers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import httpx
import pytest
import respx

from mpt_api_client.resources.accounts.buyers import AsyncBuyersService, Buyer, BuyersService


@pytest.fixture
def buyers_service(http_client):
return BuyersService(http_client=http_client)


@pytest.fixture
def async_buyers_service(async_http_client):
return AsyncBuyersService(http_client=async_http_client)


@pytest.mark.parametrize(
"method",
[
"get",
"create",
"update",
"delete",
"activate",
"deactivate",
"enable",
"disable",
"validate",
"synchronize",
"transfer",
],
)
def test_mixins_present(buyers_service, method):
assert hasattr(buyers_service, method)


@pytest.mark.parametrize(
"method",
[
"get",
"create",
"update",
"delete",
"activate",
"deactivate",
"enable",
"disable",
"validate",
"synchronize",
"transfer",
],
)
def test_async_mixins_present(async_buyers_service, method):
assert hasattr(async_buyers_service, method)


@pytest.mark.parametrize(
("action", "input_status"),
[
("synchronize", {"id": "OBJ-0000-0001", "status": "update"}),
("transfer", {"id": "OBJ-0000-0001", "status": "update"}),
],
)
def test_buyers_resource_action(buyers_service, action, input_status):
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/accounts/buyers/OBJ-0000-0001/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
json=response_expected_data,
)
)
buyers_obj = getattr(buyers_service, action)("OBJ-0000-0001", input_status)

request = mock_route.calls[0].request

assert request.content == request_expected_content
assert buyers_obj.to_dict() == response_expected_data
assert isinstance(buyers_obj, Buyer)


@pytest.mark.parametrize(
("action", "input_status"),
[("synchronize", None), ("transfer", None)],
)
def test_buyers_resouce_action_no_data(buyers_service, action, input_status):
request_expected_content = b""
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/accounts/buyers/OBJ-0000-0001/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
json=response_expected_data,
)
)
buyers_obj = getattr(buyers_service, action)("OBJ-0000-0001", None)

request = mock_route.calls[0].request

assert request.content == request_expected_content
assert buyers_obj.to_dict() == response_expected_data
assert isinstance(buyers_obj, Buyer)


@pytest.mark.parametrize(
("action", "input_status"),
[
("synchronize", {"id": "OBJ-0000-0001", "status": "update"}),
("transfer", {"id": "OBJ-0000-0001", "status": "update"}),
],
)
async def test_async_buyers_resource_action(async_buyers_service, action, input_status):
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/accounts/buyers/OBJ-0000-0001/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
json=response_expected_data,
)
)
buyers_obj = await getattr(async_buyers_service, action)("OBJ-0000-0001", input_status)

request = mock_route.calls[0].request

assert request.content == request_expected_content
assert buyers_obj.to_dict() == response_expected_data
assert isinstance(buyers_obj, Buyer)


@pytest.mark.parametrize(
("action", "input_status"),
[("synchronize", None), ("transfer", None)],
)
async def test_async_buyers_resource_action_no_data(async_buyers_service, action, input_status):
request_expected_content = b""
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
with respx.mock:
mock_route = respx.post(
f"https://api.example.com/public/v1/accounts/buyers/OBJ-0000-0001/{action}"
).mock(
return_value=httpx.Response(
status_code=httpx.codes.OK,
json=response_expected_data,
)
)
buyers_obj = await getattr(async_buyers_service, action)("OBJ-0000-0001", None)

request = mock_route.calls[0].request

assert request.content == request_expected_content
assert buyers_obj.to_dict() == response_expected_data
assert isinstance(buyers_obj, Buyer)