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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dev = [
"flake8>=6.0.0",
"isort>=5.12.0",
"mypy>=1.0.0",
"types-requests>=2.31.0",
]

[build-system]
Expand Down
13 changes: 12 additions & 1 deletion src/tmo_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@
ValidationError,
)
from .models import BaseModel, BaseResponse
from .resources import PoolsResource, PoolType
from .resources import (
CertificatesResource,
DistributionsResource,
HistoryResource,
PartnersResource,
PoolsResource,
PoolType,
)

__version__ = "0.0.1"

Expand All @@ -27,4 +34,8 @@
"BaseResponse",
"PoolsResource",
"PoolType",
"PartnersResource",
"DistributionsResource",
"CertificatesResource",
"HistoryResource",
]
26 changes: 18 additions & 8 deletions src/tmo_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@

from .environments import DEFAULT_ENVIRONMENT, Environment
from .exceptions import APIError, AuthenticationError, NetworkError
from .resources import PoolsResource
from .resources import (
CertificatesResource,
DistributionsResource,
HistoryResource,
PartnersResource,
PoolsResource,
)


class TheMortgageOfficeClient:
Expand Down Expand Up @@ -62,16 +68,20 @@ def __init__(

# Initialize Shares resources
self.shares_pools: PoolsResource = PoolsResource(self, PoolType.SHARES)
self.shares_partners: PoolsResource = PoolsResource(self, PoolType.SHARES)
self.shares_distributions: PoolsResource = PoolsResource(self, PoolType.SHARES)
self.shares_certificates: PoolsResource = PoolsResource(self, PoolType.SHARES)
self.shares_history: PoolsResource = PoolsResource(self, PoolType.SHARES)
self.shares_partners: PartnersResource = PartnersResource(self, PoolType.SHARES)
self.shares_distributions: DistributionsResource = DistributionsResource(
self, PoolType.SHARES
)
self.shares_certificates: CertificatesResource = CertificatesResource(self, PoolType.SHARES)
self.shares_history: HistoryResource = HistoryResource(self, PoolType.SHARES)

# Initialize Capital resources
self.capital_pools: PoolsResource = PoolsResource(self, PoolType.CAPITAL)
self.capital_partners: PoolsResource = PoolsResource(self, PoolType.CAPITAL)
self.capital_distributions: PoolsResource = PoolsResource(self, PoolType.CAPITAL)
self.capital_history: PoolsResource = PoolsResource(self, PoolType.CAPITAL)
self.capital_partners: PartnersResource = PartnersResource(self, PoolType.CAPITAL)
self.capital_distributions: DistributionsResource = DistributionsResource(
self, PoolType.CAPITAL
)
self.capital_history: HistoryResource = HistoryResource(self, PoolType.CAPITAL)

def _debug_log(self, message: str) -> None:
"""Log debug message to stderr if debug mode is enabled."""
Expand Down
13 changes: 12 additions & 1 deletion src/tmo_api/resources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
"""Resources package for The Mortgage Office SDK."""

from .certificates import CertificatesResource
from .distributions import DistributionsResource
from .history import HistoryResource
from .partners import PartnersResource
from .pools import PoolsResource, PoolType

__all__ = ["PoolsResource", "PoolType"]
__all__ = [
"PoolsResource",
"PoolType",
"PartnersResource",
"DistributionsResource",
"CertificatesResource",
"HistoryResource",
]
91 changes: 91 additions & 0 deletions src/tmo_api/resources/certificates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""Certificates resource for The Mortgage Office SDK."""

from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast

from .pools import PoolType

if TYPE_CHECKING:
from ..client import TheMortgageOfficeClient


class CertificatesResource:
"""Resource for managing share certificates."""

def __init__(
self, client: "TheMortgageOfficeClient", pool_type: PoolType = PoolType.SHARES
) -> None:
"""Initialize the certificates resource.

Args:
client: The base client instance
pool_type: The type of pool (Shares or Capital) - Note: Certificates
are only available for Shares
"""
self.client = client
self.pool_type = pool_type
self.base_path = f"LSS.svc/{pool_type.value}"

def get_certificates(
self,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
partner_account: Optional[str] = None,
pool_account: Optional[str] = None,
) -> List[Any]:
"""Get share certificates with optional filtering.

Args:
start_date: Start date for filtering (MM/DD/YYYY format)
end_date: End date for filtering (MM/DD/YYYY format)
partner_account: Partner account filter
pool_account: Pool account filter

Returns:
List of share certificates

Raises:
APIError: If the API returns an error
ValidationError: If date format is invalid
"""
endpoint = f"{self.base_path}/Certificates"
params: Dict[str, str] = {}

if start_date:
if not self._validate_date_format(start_date):
from ..exceptions import ValidationError

raise ValidationError("start_date must be in MM/DD/YYYY format")
params["from-date"] = start_date

if end_date:
if not self._validate_date_format(end_date):
from ..exceptions import ValidationError

raise ValidationError("end_date must be in MM/DD/YYYY format")
params["to-date"] = end_date

if partner_account:
params["partner-account"] = partner_account

if pool_account:
params["pool-account"] = pool_account

response_data = self.client.get(endpoint, params=params if params else None)
return cast(List[Any], response_data.get("Data", []))

def _validate_date_format(self, date_str: str) -> bool:
"""Validate date format MM/DD/YYYY.

Args:
date_str: Date string to validate

Returns:
True if format is valid, False otherwise
"""
try:
from datetime import datetime

datetime.strptime(date_str, "%m/%d/%Y")
return True
except ValueError:
return False
107 changes: 107 additions & 0 deletions src/tmo_api/resources/distributions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""Distributions resource for The Mortgage Office SDK."""

from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast

from .pools import PoolType

if TYPE_CHECKING:
from ..client import TheMortgageOfficeClient


class DistributionsResource:
"""Resource for managing pool distributions."""

def __init__(
self, client: "TheMortgageOfficeClient", pool_type: PoolType = PoolType.SHARES
) -> None:
"""Initialize the distributions resource.

Args:
client: The base client instance
pool_type: The type of pool (Shares or Capital)
"""
self.client = client
self.pool_type = pool_type
self.base_path = f"LSS.svc/{pool_type.value}"

def get_distribution(self, rec_id: str) -> Dict[str, Any]:
"""Get distribution details by RecID.

Args:
rec_id: The distribution record ID

Returns:
Distribution data dictionary

Raises:
APIError: If the API returns an error
ValidationError: If rec_id is invalid
"""
if not rec_id:
from ..exceptions import ValidationError

raise ValidationError("RecID parameter is required")

endpoint = f"{self.base_path}/Distributions/{rec_id}"
response_data = self.client.get(endpoint)
return cast(Dict[str, Any], response_data.get("Data", {}))

def list_all(
self,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
pool_account: Optional[str] = None,
) -> List[Any]:
"""List all distributions with optional filtering.

Args:
start_date: Start date for filtering (MM/DD/YYYY format)
end_date: End date for filtering (MM/DD/YYYY format)
pool_account: Pool account filter

Returns:
List of distributions

Raises:
APIError: If the API returns an error
ValidationError: If date format is invalid
"""
endpoint = f"{self.base_path}/Distributions"
params: Dict[str, str] = {}

if start_date:
if not self._validate_date_format(start_date):
from ..exceptions import ValidationError

raise ValidationError("start_date must be in MM/DD/YYYY format")
params["from-date"] = start_date

if end_date:
if not self._validate_date_format(end_date):
from ..exceptions import ValidationError

raise ValidationError("end_date must be in MM/DD/YYYY format")
params["to-date"] = end_date

if pool_account:
params["pool-account"] = pool_account

response_data = self.client.get(endpoint, params=params if params else None)
return cast(List[Any], response_data.get("Data", []))

def _validate_date_format(self, date_str: str) -> bool:
"""Validate date format MM/DD/YYYY.

Args:
date_str: Date string to validate

Returns:
True if format is valid, False otherwise
"""
try:
from datetime import datetime

datetime.strptime(date_str, "%m/%d/%Y")
return True
except ValueError:
return False
90 changes: 90 additions & 0 deletions src/tmo_api/resources/history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""History resource for The Mortgage Office SDK."""

from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast

from .pools import PoolType

if TYPE_CHECKING:
from ..client import TheMortgageOfficeClient


class HistoryResource:
"""Resource for managing share transaction history."""

def __init__(
self, client: "TheMortgageOfficeClient", pool_type: PoolType = PoolType.SHARES
) -> None:
"""Initialize the history resource.

Args:
client: The base client instance
pool_type: The type of pool (Shares or Capital)
"""
self.client = client
self.pool_type = pool_type
self.base_path = f"LSS.svc/{pool_type.value}"

def get_history(
self,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
partner_account: Optional[str] = None,
pool_account: Optional[str] = None,
) -> List[Any]:
"""Get share transaction history with optional filtering.

Args:
start_date: Start date for filtering (MM/DD/YYYY format)
end_date: End date for filtering (MM/DD/YYYY format)
partner_account: Partner account filter
pool_account: Pool account filter

Returns:
List of share transaction history records

Raises:
APIError: If the API returns an error
ValidationError: If date format is invalid
"""
endpoint = f"{self.base_path}/History"
params: Dict[str, str] = {}

if start_date:
if not self._validate_date_format(start_date):
from ..exceptions import ValidationError

raise ValidationError("start_date must be in MM/DD/YYYY format")
params["from-date"] = start_date

if end_date:
if not self._validate_date_format(end_date):
from ..exceptions import ValidationError

raise ValidationError("end_date must be in MM/DD/YYYY format")
params["to-date"] = end_date

if partner_account:
params["partner-account"] = partner_account

if pool_account:
params["pool-account"] = pool_account

response_data = self.client.get(endpoint, params=params if params else None)
return cast(List[Any], response_data.get("Data", []))

def _validate_date_format(self, date_str: str) -> bool:
"""Validate date format MM/DD/YYYY.

Args:
date_str: Date string to validate

Returns:
True if format is valid, False otherwise
"""
try:
from datetime import datetime

datetime.strptime(date_str, "%m/%d/%Y")
return True
except ValueError:
return False
Loading
Loading