diff --git a/ntropy_sdk/account_holders.py b/ntropy_sdk/account_holders.py index ab73d40..231c0fb 100644 --- a/ntropy_sdk/account_holders.py +++ b/ntropy_sdk/account_holders.py @@ -1,12 +1,13 @@ +import uuid from datetime import datetime from enum import Enum -from typing import Optional, TYPE_CHECKING, Literal -import uuid +from typing import Optional, TYPE_CHECKING from pydantic import BaseModel, Field -from ntropy_sdk.utils import pydantic_json from ntropy_sdk.paging import PagedResponse +from ntropy_sdk.transactions import RecurrenceGroup, RecurrenceGroups +from ntropy_sdk.utils import pydantic_json if TYPE_CHECKING: from ntropy_sdk import ExtraKwargs @@ -107,4 +108,20 @@ def create( ) return AccountHolder(**resp.json(), request_id=request_id) - # TODO: Recurring groups + def recurring_groups( + self, + id: str, + **extra_kwargs: "Unpack[ExtraKwargs]", + ) -> RecurrenceGroups: + request_id = extra_kwargs.get("request_id") + if request_id is None: + request_id = uuid.uuid4().hex + extra_kwargs["request_id"] = request_id + resp = self._sdk.retry_ratelimited_request( + method="POST", + url=f"/v3/account_holders/{id}/recurring_groups", + **extra_kwargs, + ) + return RecurrenceGroups( + groups=[RecurrenceGroup(**r) for r in resp.json()], request_id=request_id + ) diff --git a/ntropy_sdk/transactions.py b/ntropy_sdk/transactions.py index 72b77c2..b74a99e 100644 --- a/ntropy_sdk/transactions.py +++ b/ntropy_sdk/transactions.py @@ -237,6 +237,11 @@ class RecurrenceGroup(BaseModel): ) +class RecurrenceGroups(BaseModel): + groups: List[RecurrenceGroup] + request_id: Optional[str] + + class Recurrence(BaseModel): """ The `Recurrence` object represents the recurrence pattern of a transaction. It provides information about diff --git a/tests/v3/test_sdk.py b/tests/v3/test_sdk.py index 37ff327..141547c 100644 --- a/tests/v3/test_sdk.py +++ b/tests/v3/test_sdk.py @@ -1,6 +1,12 @@ import os from itertools import islice -from ntropy_sdk import SDK + +from ntropy_sdk import ( + SDK, + TransactionInput, + AccountHolder, + NtropyValueError, +) def test_pagination(sdk: SDK): @@ -18,3 +24,37 @@ def test_readme(api_key): readme_data = readme_file.split("```python")[1].split("```")[0] readme_data = readme_data.replace("YOUR-API-KEY", api_key) exec(readme_data, globals()) + + +def test_recurrence_groups(sdk): + try: + sdk.account_holders.create( + AccountHolder( + id="Xksd9SWd", + type="consumer", + ) + ) + except NtropyValueError: + pass + + txs = [] + txs.extend( + [ + TransactionInput( + id=f"netflix-{i}", + description=f"Recurring Debit Purchase Card 1350 #{i} netflix.com Netflix.com CA", + amount=17.99, + currency="USD", + entry_type="outgoing", + date=f"2021-0{i}-01", + account_holder_id="Xksd9SWd", + ) + for i in range(1, 5) + ] + ) + + sdk.transactions.create(txs) + recurring_groups = sdk.account_holders.recurring_groups("Xksd9SWd") + + assert recurring_groups.groups[0].counterparty.website == "netflix.com" + assert recurring_groups.groups[0].periodicity == "monthly"