Skip to content

Commit 8a8cce3

Browse files
authored
[MPT-13826] Added billing statements endpoints and mixin (#54)
Added billing statements endpoints and mixin https://softwareone.atlassian.net/browse/MPT-13826
2 parents 4a90af0 + a848f64 commit 8a8cce3

File tree

6 files changed

+415
-0
lines changed

6 files changed

+415
-0
lines changed

mpt_api_client/resources/billing/billing.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from mpt_api_client.http import AsyncHTTPClient, HTTPClient
22
from mpt_api_client.resources.billing.journals import AsyncJournalsService, JournalsService
33
from mpt_api_client.resources.billing.ledgers import AsyncLedgersService, LedgersService
4+
from mpt_api_client.resources.billing.statements import AsyncStatementsService, StatementsService
45

56

67
class Billing:
@@ -19,6 +20,11 @@ def ledgers(self) -> LedgersService:
1920
"""Ledgers service."""
2021
return LedgersService(http_client=self.http_client)
2122

23+
@property
24+
def statements(self) -> StatementsService:
25+
"""Statements service."""
26+
return StatementsService(http_client=self.http_client)
27+
2228

2329
class AsyncBilling:
2430
"""Billing MPT API Module."""
@@ -35,3 +41,8 @@ def journals(self) -> AsyncJournalsService:
3541
def ledgers(self) -> AsyncLedgersService:
3642
"""Ledgers service."""
3743
return AsyncLedgersService(http_client=self.http_client)
44+
45+
@property
46+
def statements(self) -> AsyncStatementsService:
47+
"""Statements service."""
48+
return AsyncStatementsService(http_client=self.http_client)

mpt_api_client/resources/billing/mixins.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33

44
# TODO: Consider moving Regeneratable mixins to http/mixins if publishable and activatable are moved
5+
# TODO: Consider reorganizing functions in mixins to reduce duplication and differences amongst
6+
# different domains
57
class RegeneratableMixin[Model]:
68
"""Regeneratable mixin adds the ability to regenerate resources."""
79

@@ -174,3 +176,167 @@ async def queue(self, resource_id: str, resource_data: ResourceData | None = Non
174176
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
175177
resource_id, "POST", "queue", json=resource_data
176178
)
179+
180+
181+
class IssuableMixin[Model]:
182+
"""Issuable mixin adds the ability to issue resources."""
183+
184+
def issue(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
185+
"""Issue resource.
186+
187+
Args:
188+
resource_id: Resource ID
189+
resource_data: Resource data will be updated
190+
"""
191+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
192+
resource_id, "POST", "issue", json=resource_data
193+
)
194+
195+
def cancel(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
196+
"""Cancel resource.
197+
198+
Args:
199+
resource_id: Resource ID
200+
resource_data: Resource data will be updated
201+
"""
202+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
203+
resource_id, "POST", "cancel", json=resource_data
204+
)
205+
206+
def error(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
207+
"""Error resource.
208+
209+
Args:
210+
resource_id: Resource ID
211+
resource_data: Resource data will be updated
212+
"""
213+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
214+
resource_id, "POST", "error", json=resource_data
215+
)
216+
217+
def pending(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
218+
"""Pending resource.
219+
220+
Args:
221+
resource_id: Resource ID
222+
resource_data: Resource data will be updated
223+
"""
224+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
225+
resource_id, "POST", "pending", json=resource_data
226+
)
227+
228+
def queue(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
229+
"""Queue resource.
230+
231+
Args:
232+
resource_id: Resource ID
233+
resource_data: Resource data will be updated
234+
"""
235+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
236+
resource_id, "POST", "queue", json=resource_data
237+
)
238+
239+
def retry(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
240+
"""Retry resource.
241+
242+
Args:
243+
resource_id: Resource ID
244+
resource_data: Resource data will be updated
245+
"""
246+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
247+
resource_id, "POST", "retry", json=resource_data
248+
)
249+
250+
def recalculate(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
251+
"""Recalculate resource.
252+
253+
Args:
254+
resource_id: Resource ID
255+
resource_data: Resource data will be updated
256+
"""
257+
return self._resource_action( # type: ignore[attr-defined, no-any-return]
258+
resource_id, "POST", "recalculate", json=resource_data
259+
)
260+
261+
262+
class AsyncIssuableMixin[Model]:
263+
"""Issuable mixin adds the ability to issue resources."""
264+
265+
async def issue(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
266+
"""Issue resource.
267+
268+
Args:
269+
resource_id: Resource ID
270+
resource_data: Resource data will be updated
271+
"""
272+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
273+
resource_id, "POST", "issue", json=resource_data
274+
)
275+
276+
async def cancel(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
277+
"""Cancel resource.
278+
279+
Args:
280+
resource_id: Resource ID
281+
resource_data: Resource data will be updated
282+
"""
283+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
284+
resource_id, "POST", "cancel", json=resource_data
285+
)
286+
287+
async def error(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
288+
"""Error resource.
289+
290+
Args:
291+
resource_id: Resource ID
292+
resource_data: Resource data will be updated
293+
"""
294+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
295+
resource_id, "POST", "error", json=resource_data
296+
)
297+
298+
async def pending(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
299+
"""Pending resource.
300+
301+
Args:
302+
resource_id: Resource ID
303+
resource_data: Resource data will be updated
304+
"""
305+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
306+
resource_id, "POST", "pending", json=resource_data
307+
)
308+
309+
async def queue(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
310+
"""Queue resource.
311+
312+
Args:
313+
resource_id: Resource ID
314+
resource_data: Resource data will be updated
315+
"""
316+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
317+
resource_id, "POST", "queue", json=resource_data
318+
)
319+
320+
async def retry(self, resource_id: str, resource_data: ResourceData | None = None) -> Model:
321+
"""Retry resource.
322+
323+
Args:
324+
resource_id: Resource ID
325+
resource_data: Resource data will be updated
326+
"""
327+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
328+
resource_id, "POST", "retry", json=resource_data
329+
)
330+
331+
async def recalculate(
332+
self, resource_id: str, resource_data: ResourceData | None = None
333+
) -> Model:
334+
"""Recalculate resource.
335+
336+
Args:
337+
resource_id: Resource ID
338+
resource_data: Resource data will be updated
339+
"""
340+
return await self._resource_action( # type: ignore[attr-defined, no-any-return]
341+
resource_id, "POST", "recalculate", json=resource_data
342+
)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from mpt_api_client.http import AsyncService, Service
2+
from mpt_api_client.http.mixins import AsyncUpdateMixin, UpdateMixin
3+
from mpt_api_client.models import Model
4+
from mpt_api_client.resources.billing.mixins import AsyncIssuableMixin, IssuableMixin
5+
6+
7+
class Statement(Model):
8+
"""Statement resource."""
9+
10+
11+
class StatementsServiceConfig:
12+
"""Statements service configuration."""
13+
14+
_endpoint = "/public/v1/billing/statements"
15+
_model_class = Statement
16+
_collection_key = "data"
17+
18+
19+
class StatementsService(
20+
UpdateMixin[Statement],
21+
IssuableMixin[Statement],
22+
Service[Statement],
23+
StatementsServiceConfig,
24+
):
25+
"""Statements service."""
26+
27+
28+
class AsyncStatementsService(
29+
AsyncUpdateMixin[Statement],
30+
AsyncIssuableMixin[Statement],
31+
AsyncService[Statement],
32+
StatementsServiceConfig,
33+
):
34+
"""Async Statements service."""

tests/resources/billing/test_billing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from mpt_api_client.resources.billing.billing import AsyncBilling, Billing
44
from mpt_api_client.resources.billing.journals import AsyncJournalsService, JournalsService
55
from mpt_api_client.resources.billing.ledgers import AsyncLedgersService, LedgersService
6+
from mpt_api_client.resources.billing.statements import AsyncStatementsService, StatementsService
67

78

89
@pytest.fixture
@@ -20,6 +21,7 @@ def async_billing(async_http_client):
2021
[
2122
("journals", JournalsService),
2223
("ledgers", LedgersService),
24+
("statements", StatementsService),
2325
],
2426
)
2527
def test_billing_properties(billing, property_name, expected_service_class):
@@ -35,6 +37,7 @@ def test_billing_properties(billing, property_name, expected_service_class):
3537
[
3638
("journals", AsyncJournalsService),
3739
("ledgers", AsyncLedgersService),
40+
("statements", AsyncStatementsService),
3841
],
3942
)
4043
def test_async_billing_properties(async_billing, property_name, expected_service_class):

0 commit comments

Comments
 (0)