From bf6f4ecaa2c03ca585f16db3b67ff350b5a67022 Mon Sep 17 00:00:00 2001 From: scaleway-bot Date: Fri, 7 Aug 2026 14:23:32 +0000 Subject: [PATCH] feat(billing): add electronic billing api --- .../scaleway_async/billing/v2/__init__.py | 18 ++ .../scaleway_async/billing/v2/api.py | 240 ++++++++++++++++++ .../scaleway_async/billing/v2/marshalling.py | 124 +++++++++ .../scaleway_async/billing/v2/types.py | 151 +++++++++++ scaleway/scaleway/billing/v2/__init__.py | 18 ++ scaleway/scaleway/billing/v2/api.py | 240 ++++++++++++++++++ scaleway/scaleway/billing/v2/marshalling.py | 124 +++++++++ scaleway/scaleway/billing/v2/types.py | 151 +++++++++++ 8 files changed, 1066 insertions(+) diff --git a/scaleway-async/scaleway_async/billing/v2/__init__.py b/scaleway-async/scaleway_async/billing/v2/__init__.py index 6536074cd..5508f5327 100644 --- a/scaleway-async/scaleway_async/billing/v2/__init__.py +++ b/scaleway-async/scaleway_async/billing/v2/__init__.py @@ -1,39 +1,57 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. from .types import BudgetAlertNotificationType +from .types import ListElectronicAddressesRequestOrderBy from .types import BudgetAlertNotification from .types import BudgetAlert from .types import Budget +from .types import ElectronicAddress from .types import CreateBudgetAlertNotificationRequest from .types import CreateBudgetAlertRequest from .types import CreateBudgetRequest from .types import DeleteBudgetAlertNotificationRequest from .types import DeleteBudgetAlertRequest from .types import DeleteBudgetRequest +from .types import ElectronicBillingApiCreateElectronicAddressRequest +from .types import ElectronicBillingApiDeleteElectronicAddressRequest +from .types import ElectronicBillingApiGetElectronicAddressRequest +from .types import ElectronicBillingApiListElectronicAddressesRequest +from .types import ElectronicBillingApiUpdateElectronicAddressRequest from .types import GetBudgetRequest from .types import ListBudgetsRequest from .types import ListBudgetsResponse +from .types import ListElectronicAddressesResponse from .types import UpdateBudgetAlertNotificationRequest from .types import UpdateBudgetAlertRequest from .types import UpdateBudgetRequest from .api import BillingV2API +from .api import BillingV2ElectronicBillingAPI __all__ = [ "BudgetAlertNotificationType", + "ListElectronicAddressesRequestOrderBy", "BudgetAlertNotification", "BudgetAlert", "Budget", + "ElectronicAddress", "CreateBudgetAlertNotificationRequest", "CreateBudgetAlertRequest", "CreateBudgetRequest", "DeleteBudgetAlertNotificationRequest", "DeleteBudgetAlertRequest", "DeleteBudgetRequest", + "ElectronicBillingApiCreateElectronicAddressRequest", + "ElectronicBillingApiDeleteElectronicAddressRequest", + "ElectronicBillingApiGetElectronicAddressRequest", + "ElectronicBillingApiListElectronicAddressesRequest", + "ElectronicBillingApiUpdateElectronicAddressRequest", "GetBudgetRequest", "ListBudgetsRequest", "ListBudgetsResponse", + "ListElectronicAddressesResponse", "UpdateBudgetAlertNotificationRequest", "UpdateBudgetAlertRequest", "UpdateBudgetRequest", "BillingV2API", + "BillingV2ElectronicBillingAPI", ] diff --git a/scaleway-async/scaleway_async/billing/v2/api.py b/scaleway-async/scaleway_async/billing/v2/api.py index 6cb1f272b..821501804 100644 --- a/scaleway-async/scaleway_async/billing/v2/api.py +++ b/scaleway-async/scaleway_async/billing/v2/api.py @@ -1,6 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from datetime import datetime from typing import Optional from scaleway_core.api import API @@ -9,13 +10,18 @@ fetch_all_pages_async, ) from .types import ( + ListElectronicAddressesRequestOrderBy, Budget, BudgetAlert, BudgetAlertNotification, CreateBudgetAlertNotificationRequest, CreateBudgetAlertRequest, CreateBudgetRequest, + ElectronicAddress, + ElectronicBillingApiCreateElectronicAddressRequest, + ElectronicBillingApiUpdateElectronicAddressRequest, ListBudgetsResponse, + ListElectronicAddressesResponse, UpdateBudgetAlertNotificationRequest, UpdateBudgetAlertRequest, UpdateBudgetRequest, @@ -24,10 +30,14 @@ unmarshal_BudgetAlertNotification, unmarshal_BudgetAlert, unmarshal_Budget, + unmarshal_ElectronicAddress, unmarshal_ListBudgetsResponse, + unmarshal_ListElectronicAddressesResponse, marshal_CreateBudgetAlertNotificationRequest, marshal_CreateBudgetAlertRequest, marshal_CreateBudgetRequest, + marshal_ElectronicBillingApiCreateElectronicAddressRequest, + marshal_ElectronicBillingApiUpdateElectronicAddressRequest, marshal_UpdateBudgetAlertNotificationRequest, marshal_UpdateBudgetAlertRequest, marshal_UpdateBudgetRequest, @@ -456,3 +466,233 @@ async def delete_budget_alert_notification( ) self._throw_on_error(res) + + +class BillingV2ElectronicBillingAPI(API): + """ + This API allows you to query electronic billing related objects. + """ + + async def list_electronic_addresses( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListElectronicAddressesRequestOrderBy] = None, + organization_id: Optional[str] = None, + starts_after: Optional[datetime] = None, + stops_before: Optional[datetime] = None, + ) -> ListElectronicAddressesResponse: + """ + List electronic addresses. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Electronic Address to return per page. + :param order_by: Sort order of Electronic address in the response. + :param organization_id: The Organization ID to set electronic address. + :param starts_after: Filter services where electronic address start_date is greater or equal to starts_after. + :param stops_before: Filter services where electronic address stop_date is before stops_before. + :return: :class:`ListElectronicAddressesResponse ` + + Usage: + :: + + result = await api.list_electronic_addresses() + """ + + res = self._request( + "GET", + "/billing/v2/electronic-address", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "starts_after": starts_after, + "stops_before": stops_before, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListElectronicAddressesResponse(res.json()) + + async def list_electronic_addresses_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListElectronicAddressesRequestOrderBy] = None, + organization_id: Optional[str] = None, + starts_after: Optional[datetime] = None, + stops_before: Optional[datetime] = None, + ) -> list[ElectronicAddress]: + """ + List electronic addresses. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Electronic Address to return per page. + :param order_by: Sort order of Electronic address in the response. + :param organization_id: The Organization ID to set electronic address. + :param starts_after: Filter services where electronic address start_date is greater or equal to starts_after. + :param stops_before: Filter services where electronic address stop_date is before stops_before. + :return: :class:`list[ElectronicAddress] ` + + Usage: + :: + + result = await api.list_electronic_addresses_all() + """ + + return await fetch_all_pages_async( + type=ListElectronicAddressesResponse, + key="electronic_addresses", + fetcher=self.list_electronic_addresses, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "organization_id": organization_id, + "starts_after": starts_after, + "stops_before": stops_before, + }, + ) + + async def get_electronic_address( + self, + *, + electronic_address_id: str, + ) -> ElectronicAddress: + """ + Fetch an electronic address. + :param electronic_address_id: The ID of the electronic address we want to retrieve. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = await api.get_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "GET", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + async def create_electronic_address( + self, + *, + value: str, + organization_id: Optional[str] = None, + starts_at: Optional[datetime] = None, + stops_at: Optional[datetime] = None, + ) -> ElectronicAddress: + """ + Create a new electronic address. + :param value: Electronic address to set. + :param organization_id: The Organization ID to set electronic address. + :param starts_at: When electronic address should be active. + :param stops_at: When electronic address should stop being active. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = await api.create_electronic_address( + value="example", + ) + """ + + res = self._request( + "POST", + "/billing/v2/electronic-address", + body=marshal_ElectronicBillingApiCreateElectronicAddressRequest( + ElectronicBillingApiCreateElectronicAddressRequest( + value=value, + organization_id=organization_id, + starts_at=starts_at, + stops_at=stops_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + async def update_electronic_address( + self, + *, + electronic_address_id: str, + value: Optional[str] = None, + stops_at: Optional[datetime] = None, + ) -> ElectronicAddress: + """ + Update an electronic address. + :param electronic_address_id: The ID of the electronic address we want to update. + :param value: Electronic address to set. + :param stops_at: When electronic address should stop being active. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = await api.update_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "PATCH", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + body=marshal_ElectronicBillingApiUpdateElectronicAddressRequest( + ElectronicBillingApiUpdateElectronicAddressRequest( + electronic_address_id=electronic_address_id, + value=value, + stops_at=stops_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + async def delete_electronic_address( + self, + *, + electronic_address_id: str, + ) -> None: + """ + Delete an electronic address. + :param electronic_address_id: The ID of the electronic address to delete. + + Usage: + :: + + result = await api.delete_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "DELETE", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway-async/scaleway_async/billing/v2/marshalling.py b/scaleway-async/scaleway_async/billing/v2/marshalling.py index c2a2f16af..2a3d63f8a 100644 --- a/scaleway-async/scaleway_async/billing/v2/marshalling.py +++ b/scaleway-async/scaleway_async/billing/v2/marshalling.py @@ -17,10 +17,14 @@ BudgetAlertNotification, BudgetAlert, Budget, + ElectronicAddress, ListBudgetsResponse, + ListElectronicAddressesResponse, CreateBudgetAlertNotificationRequest, CreateBudgetAlertRequest, CreateBudgetRequest, + ElectronicBillingApiCreateElectronicAddressRequest, + ElectronicBillingApiUpdateElectronicAddressRequest, UpdateBudgetAlertNotificationRequest, UpdateBudgetAlertRequest, UpdateBudgetRequest, @@ -168,6 +172,59 @@ def unmarshal_Budget(data: Any) -> Budget: return Budget(**args) +def unmarshal_ElectronicAddress(data: Any) -> ElectronicAddress: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ElectronicAddress' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + else: + args["id"] = None + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + else: + args["organization_id"] = None + + field = data.get("value", None) + if field is not None: + args["value"] = field + else: + args["value"] = None + + field = data.get("starts_at", None) + if field is not None: + args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None + + field = data.get("stops_at", None) + if field is not None: + args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ElectronicAddress(**args) + + def unmarshal_ListBudgetsResponse(data: Any) -> ListBudgetsResponse: if not isinstance(data, dict): raise TypeError( @@ -193,6 +250,35 @@ def unmarshal_ListBudgetsResponse(data: Any) -> ListBudgetsResponse: return ListBudgetsResponse(**args) +def unmarshal_ListElectronicAddressesResponse( + data: Any, +) -> ListElectronicAddressesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListElectronicAddressesResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("electronic_addresses", None) + if field is not None: + args["electronic_addresses"] = ( + [unmarshal_ElectronicAddress(v) for v in field] + if field is not None + else None + ) + else: + args["electronic_addresses"] = [] + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + else: + args["total_count"] = 0 + + return ListElectronicAddressesResponse(**args) + + def marshal_CreateBudgetAlertNotificationRequest( request: CreateBudgetAlertNotificationRequest, defaults: ProfileDefaults, @@ -259,6 +345,44 @@ def marshal_CreateBudgetRequest( return output +def marshal_ElectronicBillingApiCreateElectronicAddressRequest( + request: ElectronicBillingApiCreateElectronicAddressRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.value is not None: + output["value"] = request.value + + if request.organization_id is not None: + output["organization_id"] = request.organization_id + else: + output["organization_id"] = defaults.default_organization_id + + if request.starts_at is not None: + output["starts_at"] = request.starts_at.isoformat() + + if request.stops_at is not None: + output["stops_at"] = request.stops_at.isoformat() + + return output + + +def marshal_ElectronicBillingApiUpdateElectronicAddressRequest( + request: ElectronicBillingApiUpdateElectronicAddressRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.value is not None: + output["value"] = request.value + + if request.stops_at is not None: + output["stops_at"] = request.stops_at.isoformat() + + return output + + def marshal_UpdateBudgetAlertNotificationRequest( request: UpdateBudgetAlertNotificationRequest, defaults: ProfileDefaults, diff --git a/scaleway-async/scaleway_async/billing/v2/types.py b/scaleway-async/scaleway_async/billing/v2/types.py index 4dada05d3..424ba560f 100644 --- a/scaleway-async/scaleway_async/billing/v2/types.py +++ b/scaleway-async/scaleway_async/billing/v2/types.py @@ -25,6 +25,14 @@ def __str__(self) -> str: return str(self.value) +class ListElectronicAddressesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + STARTS_AT_ASC = "starts_at_asc" + STARTS_AT_DESC = "starts_at_desc" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class BudgetAlertNotification: id: str @@ -119,6 +127,44 @@ class Budget: """ +@dataclass +class ElectronicAddress: + id: str + """ + The id of the electronic address. + """ + + organization_id: str + """ + The organization ID of the electronic address. + """ + + value: str + """ + Current value of electronic address. + """ + + starts_at: Optional[datetime] = None + """ + The start date of the electronic address. + """ + + stops_at: Optional[datetime] = None + """ + The stop date of the electronic address. + """ + + created_at: Optional[datetime] = None + """ + The creation date of the electronic address. + """ + + updated_at: Optional[datetime] = None + """ + The last modification date of the electronic address. + """ + + @dataclass class CreateBudgetAlertNotificationRequest: budget_alert_id: str @@ -188,6 +234,98 @@ class DeleteBudgetRequest: """ +@dataclass +class ElectronicBillingApiCreateElectronicAddressRequest: + value: str + """ + Electronic address to set. + """ + + organization_id: Optional[str] = None + """ + The Organization ID to set electronic address. + """ + + starts_at: Optional[datetime] = None + """ + When electronic address should be active. + """ + + stops_at: Optional[datetime] = None + """ + When electronic address should stop being active. + """ + + +@dataclass +class ElectronicBillingApiDeleteElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address to delete. + """ + + +@dataclass +class ElectronicBillingApiGetElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address we want to retrieve. + """ + + +@dataclass +class ElectronicBillingApiListElectronicAddressesRequest: + page: Optional[int] = 0 + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] = 0 + """ + Number of Electronic Address to return per page. + """ + + order_by: Optional[ListElectronicAddressesRequestOrderBy] = ( + ListElectronicAddressesRequestOrderBy.STARTS_AT_ASC + ) + """ + Sort order of Electronic address in the response. + """ + + organization_id: Optional[str] = None + """ + The Organization ID to set electronic address. + """ + + starts_after: Optional[datetime] = None + """ + Filter services where electronic address start_date is greater or equal to starts_after. + """ + + stops_before: Optional[datetime] = None + """ + Filter services where electronic address stop_date is before stops_before. + """ + + +@dataclass +class ElectronicBillingApiUpdateElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address we want to update. + """ + + value: Optional[str] = None + """ + Electronic address to set. + """ + + stops_at: Optional[datetime] = None + """ + When electronic address should stop being active. + """ + + @dataclass class GetBudgetRequest: budget_id: str @@ -227,6 +365,19 @@ class ListBudgetsResponse: """ +@dataclass +class ListElectronicAddressesResponse: + electronic_addresses: list[ElectronicAddress] + """ + List of electronic addresses. + """ + + total_count: int + """ + Total Number of returned electronic addresses. + """ + + @dataclass class UpdateBudgetAlertNotificationRequest: budget_alert_notification_id: str diff --git a/scaleway/scaleway/billing/v2/__init__.py b/scaleway/scaleway/billing/v2/__init__.py index 6536074cd..5508f5327 100644 --- a/scaleway/scaleway/billing/v2/__init__.py +++ b/scaleway/scaleway/billing/v2/__init__.py @@ -1,39 +1,57 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. from .types import BudgetAlertNotificationType +from .types import ListElectronicAddressesRequestOrderBy from .types import BudgetAlertNotification from .types import BudgetAlert from .types import Budget +from .types import ElectronicAddress from .types import CreateBudgetAlertNotificationRequest from .types import CreateBudgetAlertRequest from .types import CreateBudgetRequest from .types import DeleteBudgetAlertNotificationRequest from .types import DeleteBudgetAlertRequest from .types import DeleteBudgetRequest +from .types import ElectronicBillingApiCreateElectronicAddressRequest +from .types import ElectronicBillingApiDeleteElectronicAddressRequest +from .types import ElectronicBillingApiGetElectronicAddressRequest +from .types import ElectronicBillingApiListElectronicAddressesRequest +from .types import ElectronicBillingApiUpdateElectronicAddressRequest from .types import GetBudgetRequest from .types import ListBudgetsRequest from .types import ListBudgetsResponse +from .types import ListElectronicAddressesResponse from .types import UpdateBudgetAlertNotificationRequest from .types import UpdateBudgetAlertRequest from .types import UpdateBudgetRequest from .api import BillingV2API +from .api import BillingV2ElectronicBillingAPI __all__ = [ "BudgetAlertNotificationType", + "ListElectronicAddressesRequestOrderBy", "BudgetAlertNotification", "BudgetAlert", "Budget", + "ElectronicAddress", "CreateBudgetAlertNotificationRequest", "CreateBudgetAlertRequest", "CreateBudgetRequest", "DeleteBudgetAlertNotificationRequest", "DeleteBudgetAlertRequest", "DeleteBudgetRequest", + "ElectronicBillingApiCreateElectronicAddressRequest", + "ElectronicBillingApiDeleteElectronicAddressRequest", + "ElectronicBillingApiGetElectronicAddressRequest", + "ElectronicBillingApiListElectronicAddressesRequest", + "ElectronicBillingApiUpdateElectronicAddressRequest", "GetBudgetRequest", "ListBudgetsRequest", "ListBudgetsResponse", + "ListElectronicAddressesResponse", "UpdateBudgetAlertNotificationRequest", "UpdateBudgetAlertRequest", "UpdateBudgetRequest", "BillingV2API", + "BillingV2ElectronicBillingAPI", ] diff --git a/scaleway/scaleway/billing/v2/api.py b/scaleway/scaleway/billing/v2/api.py index 10496f733..3b9ec3ac2 100644 --- a/scaleway/scaleway/billing/v2/api.py +++ b/scaleway/scaleway/billing/v2/api.py @@ -1,6 +1,7 @@ # This file was automatically generated. DO NOT EDIT. # If you have any remark or suggestion do not hesitate to open an issue. +from datetime import datetime from typing import Optional from scaleway_core.api import API @@ -9,13 +10,18 @@ fetch_all_pages, ) from .types import ( + ListElectronicAddressesRequestOrderBy, Budget, BudgetAlert, BudgetAlertNotification, CreateBudgetAlertNotificationRequest, CreateBudgetAlertRequest, CreateBudgetRequest, + ElectronicAddress, + ElectronicBillingApiCreateElectronicAddressRequest, + ElectronicBillingApiUpdateElectronicAddressRequest, ListBudgetsResponse, + ListElectronicAddressesResponse, UpdateBudgetAlertNotificationRequest, UpdateBudgetAlertRequest, UpdateBudgetRequest, @@ -24,10 +30,14 @@ unmarshal_BudgetAlertNotification, unmarshal_BudgetAlert, unmarshal_Budget, + unmarshal_ElectronicAddress, unmarshal_ListBudgetsResponse, + unmarshal_ListElectronicAddressesResponse, marshal_CreateBudgetAlertNotificationRequest, marshal_CreateBudgetAlertRequest, marshal_CreateBudgetRequest, + marshal_ElectronicBillingApiCreateElectronicAddressRequest, + marshal_ElectronicBillingApiUpdateElectronicAddressRequest, marshal_UpdateBudgetAlertNotificationRequest, marshal_UpdateBudgetAlertRequest, marshal_UpdateBudgetRequest, @@ -456,3 +466,233 @@ def delete_budget_alert_notification( ) self._throw_on_error(res) + + +class BillingV2ElectronicBillingAPI(API): + """ + This API allows you to query electronic billing related objects. + """ + + def list_electronic_addresses( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListElectronicAddressesRequestOrderBy] = None, + organization_id: Optional[str] = None, + starts_after: Optional[datetime] = None, + stops_before: Optional[datetime] = None, + ) -> ListElectronicAddressesResponse: + """ + List electronic addresses. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Electronic Address to return per page. + :param order_by: Sort order of Electronic address in the response. + :param organization_id: The Organization ID to set electronic address. + :param starts_after: Filter services where electronic address start_date is greater or equal to starts_after. + :param stops_before: Filter services where electronic address stop_date is before stops_before. + :return: :class:`ListElectronicAddressesResponse ` + + Usage: + :: + + result = api.list_electronic_addresses() + """ + + res = self._request( + "GET", + "/billing/v2/electronic-address", + params={ + "order_by": order_by, + "organization_id": organization_id + or self.client.default_organization_id, + "page": page, + "page_size": page_size or self.client.default_page_size, + "starts_after": starts_after, + "stops_before": stops_before, + }, + ) + + self._throw_on_error(res) + return unmarshal_ListElectronicAddressesResponse(res.json()) + + def list_electronic_addresses_all( + self, + *, + page: Optional[int] = None, + page_size: Optional[int] = None, + order_by: Optional[ListElectronicAddressesRequestOrderBy] = None, + organization_id: Optional[str] = None, + starts_after: Optional[datetime] = None, + stops_before: Optional[datetime] = None, + ) -> list[ElectronicAddress]: + """ + List electronic addresses. + :param page: Page number to return, from the paginated results. + :param page_size: Number of Electronic Address to return per page. + :param order_by: Sort order of Electronic address in the response. + :param organization_id: The Organization ID to set electronic address. + :param starts_after: Filter services where electronic address start_date is greater or equal to starts_after. + :param stops_before: Filter services where electronic address stop_date is before stops_before. + :return: :class:`list[ElectronicAddress] ` + + Usage: + :: + + result = api.list_electronic_addresses_all() + """ + + return fetch_all_pages( + type=ListElectronicAddressesResponse, + key="electronic_addresses", + fetcher=self.list_electronic_addresses, + args={ + "page": page, + "page_size": page_size, + "order_by": order_by, + "organization_id": organization_id, + "starts_after": starts_after, + "stops_before": stops_before, + }, + ) + + def get_electronic_address( + self, + *, + electronic_address_id: str, + ) -> ElectronicAddress: + """ + Fetch an electronic address. + :param electronic_address_id: The ID of the electronic address we want to retrieve. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = api.get_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "GET", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + def create_electronic_address( + self, + *, + value: str, + organization_id: Optional[str] = None, + starts_at: Optional[datetime] = None, + stops_at: Optional[datetime] = None, + ) -> ElectronicAddress: + """ + Create a new electronic address. + :param value: Electronic address to set. + :param organization_id: The Organization ID to set electronic address. + :param starts_at: When electronic address should be active. + :param stops_at: When electronic address should stop being active. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = api.create_electronic_address( + value="example", + ) + """ + + res = self._request( + "POST", + "/billing/v2/electronic-address", + body=marshal_ElectronicBillingApiCreateElectronicAddressRequest( + ElectronicBillingApiCreateElectronicAddressRequest( + value=value, + organization_id=organization_id, + starts_at=starts_at, + stops_at=stops_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + def update_electronic_address( + self, + *, + electronic_address_id: str, + value: Optional[str] = None, + stops_at: Optional[datetime] = None, + ) -> ElectronicAddress: + """ + Update an electronic address. + :param electronic_address_id: The ID of the electronic address we want to update. + :param value: Electronic address to set. + :param stops_at: When electronic address should stop being active. + :return: :class:`ElectronicAddress ` + + Usage: + :: + + result = api.update_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "PATCH", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + body=marshal_ElectronicBillingApiUpdateElectronicAddressRequest( + ElectronicBillingApiUpdateElectronicAddressRequest( + electronic_address_id=electronic_address_id, + value=value, + stops_at=stops_at, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ElectronicAddress(res.json()) + + def delete_electronic_address( + self, + *, + electronic_address_id: str, + ) -> None: + """ + Delete an electronic address. + :param electronic_address_id: The ID of the electronic address to delete. + + Usage: + :: + + result = api.delete_electronic_address( + electronic_address_id="example", + ) + """ + + param_electronic_address_id = validate_path_param( + "electronic_address_id", electronic_address_id + ) + + res = self._request( + "DELETE", + f"/billing/v2/electronic-address/{param_electronic_address_id}", + ) + + self._throw_on_error(res) diff --git a/scaleway/scaleway/billing/v2/marshalling.py b/scaleway/scaleway/billing/v2/marshalling.py index c2a2f16af..2a3d63f8a 100644 --- a/scaleway/scaleway/billing/v2/marshalling.py +++ b/scaleway/scaleway/billing/v2/marshalling.py @@ -17,10 +17,14 @@ BudgetAlertNotification, BudgetAlert, Budget, + ElectronicAddress, ListBudgetsResponse, + ListElectronicAddressesResponse, CreateBudgetAlertNotificationRequest, CreateBudgetAlertRequest, CreateBudgetRequest, + ElectronicBillingApiCreateElectronicAddressRequest, + ElectronicBillingApiUpdateElectronicAddressRequest, UpdateBudgetAlertNotificationRequest, UpdateBudgetAlertRequest, UpdateBudgetRequest, @@ -168,6 +172,59 @@ def unmarshal_Budget(data: Any) -> Budget: return Budget(**args) +def unmarshal_ElectronicAddress(data: Any) -> ElectronicAddress: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ElectronicAddress' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("id", None) + if field is not None: + args["id"] = field + else: + args["id"] = None + + field = data.get("organization_id", None) + if field is not None: + args["organization_id"] = field + else: + args["organization_id"] = None + + field = data.get("value", None) + if field is not None: + args["value"] = field + else: + args["value"] = None + + field = data.get("starts_at", None) + if field is not None: + args["starts_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["starts_at"] = None + + field = data.get("stops_at", None) + if field is not None: + args["stops_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["stops_at"] = None + + field = data.get("created_at", None) + if field is not None: + args["created_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["created_at"] = None + + field = data.get("updated_at", None) + if field is not None: + args["updated_at"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["updated_at"] = None + + return ElectronicAddress(**args) + + def unmarshal_ListBudgetsResponse(data: Any) -> ListBudgetsResponse: if not isinstance(data, dict): raise TypeError( @@ -193,6 +250,35 @@ def unmarshal_ListBudgetsResponse(data: Any) -> ListBudgetsResponse: return ListBudgetsResponse(**args) +def unmarshal_ListElectronicAddressesResponse( + data: Any, +) -> ListElectronicAddressesResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ListElectronicAddressesResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("electronic_addresses", None) + if field is not None: + args["electronic_addresses"] = ( + [unmarshal_ElectronicAddress(v) for v in field] + if field is not None + else None + ) + else: + args["electronic_addresses"] = [] + + field = data.get("total_count", None) + if field is not None: + args["total_count"] = field + else: + args["total_count"] = 0 + + return ListElectronicAddressesResponse(**args) + + def marshal_CreateBudgetAlertNotificationRequest( request: CreateBudgetAlertNotificationRequest, defaults: ProfileDefaults, @@ -259,6 +345,44 @@ def marshal_CreateBudgetRequest( return output +def marshal_ElectronicBillingApiCreateElectronicAddressRequest( + request: ElectronicBillingApiCreateElectronicAddressRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.value is not None: + output["value"] = request.value + + if request.organization_id is not None: + output["organization_id"] = request.organization_id + else: + output["organization_id"] = defaults.default_organization_id + + if request.starts_at is not None: + output["starts_at"] = request.starts_at.isoformat() + + if request.stops_at is not None: + output["stops_at"] = request.stops_at.isoformat() + + return output + + +def marshal_ElectronicBillingApiUpdateElectronicAddressRequest( + request: ElectronicBillingApiUpdateElectronicAddressRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.value is not None: + output["value"] = request.value + + if request.stops_at is not None: + output["stops_at"] = request.stops_at.isoformat() + + return output + + def marshal_UpdateBudgetAlertNotificationRequest( request: UpdateBudgetAlertNotificationRequest, defaults: ProfileDefaults, diff --git a/scaleway/scaleway/billing/v2/types.py b/scaleway/scaleway/billing/v2/types.py index 4dada05d3..424ba560f 100644 --- a/scaleway/scaleway/billing/v2/types.py +++ b/scaleway/scaleway/billing/v2/types.py @@ -25,6 +25,14 @@ def __str__(self) -> str: return str(self.value) +class ListElectronicAddressesRequestOrderBy(str, Enum, metaclass=StrEnumMeta): + STARTS_AT_ASC = "starts_at_asc" + STARTS_AT_DESC = "starts_at_desc" + + def __str__(self) -> str: + return str(self.value) + + @dataclass class BudgetAlertNotification: id: str @@ -119,6 +127,44 @@ class Budget: """ +@dataclass +class ElectronicAddress: + id: str + """ + The id of the electronic address. + """ + + organization_id: str + """ + The organization ID of the electronic address. + """ + + value: str + """ + Current value of electronic address. + """ + + starts_at: Optional[datetime] = None + """ + The start date of the electronic address. + """ + + stops_at: Optional[datetime] = None + """ + The stop date of the electronic address. + """ + + created_at: Optional[datetime] = None + """ + The creation date of the electronic address. + """ + + updated_at: Optional[datetime] = None + """ + The last modification date of the electronic address. + """ + + @dataclass class CreateBudgetAlertNotificationRequest: budget_alert_id: str @@ -188,6 +234,98 @@ class DeleteBudgetRequest: """ +@dataclass +class ElectronicBillingApiCreateElectronicAddressRequest: + value: str + """ + Electronic address to set. + """ + + organization_id: Optional[str] = None + """ + The Organization ID to set electronic address. + """ + + starts_at: Optional[datetime] = None + """ + When electronic address should be active. + """ + + stops_at: Optional[datetime] = None + """ + When electronic address should stop being active. + """ + + +@dataclass +class ElectronicBillingApiDeleteElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address to delete. + """ + + +@dataclass +class ElectronicBillingApiGetElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address we want to retrieve. + """ + + +@dataclass +class ElectronicBillingApiListElectronicAddressesRequest: + page: Optional[int] = 0 + """ + Page number to return, from the paginated results. + """ + + page_size: Optional[int] = 0 + """ + Number of Electronic Address to return per page. + """ + + order_by: Optional[ListElectronicAddressesRequestOrderBy] = ( + ListElectronicAddressesRequestOrderBy.STARTS_AT_ASC + ) + """ + Sort order of Electronic address in the response. + """ + + organization_id: Optional[str] = None + """ + The Organization ID to set electronic address. + """ + + starts_after: Optional[datetime] = None + """ + Filter services where electronic address start_date is greater or equal to starts_after. + """ + + stops_before: Optional[datetime] = None + """ + Filter services where electronic address stop_date is before stops_before. + """ + + +@dataclass +class ElectronicBillingApiUpdateElectronicAddressRequest: + electronic_address_id: str + """ + The ID of the electronic address we want to update. + """ + + value: Optional[str] = None + """ + Electronic address to set. + """ + + stops_at: Optional[datetime] = None + """ + When electronic address should stop being active. + """ + + @dataclass class GetBudgetRequest: budget_id: str @@ -227,6 +365,19 @@ class ListBudgetsResponse: """ +@dataclass +class ListElectronicAddressesResponse: + electronic_addresses: list[ElectronicAddress] + """ + List of electronic addresses. + """ + + total_count: int + """ + Total Number of returned electronic addresses. + """ + + @dataclass class UpdateBudgetAlertNotificationRequest: budget_alert_notification_id: str