Coverage for src/usaspending/models/recipient_spending.py: 96%
23 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-03 17:15 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-03 17:15 -0700
1"""Recipient spending model for USASpending spending by recipient data."""
3from __future__ import annotations
5from typing import Optional, TYPE_CHECKING
6from ..utils.formatter import to_float, round_to_millions
7from .recipient import Recipient
9if TYPE_CHECKING:
10 from ..client import USASpending
13class RecipientSpending(Recipient):
14 """Model for spending by recipient data.
16 Represents spending data grouped by recipient with recipient-specific
17 fields like recipient_id and UEI.
18 """
20 def __init__(self, data: dict, client: Optional["USASpending"] = None):
21 """Initialize RecipientSpending model.
23 Args:
24 data: Raw recipient spending data from API
25 client: USASpending client instance
26 """
27 super().__init__(data, client)
29 @property
30 def duns(self) -> Optional[str]:
31 """DUNS number from spending data (stored in 'code' field)."""
32 return self.get_value(["code"], default=None)
34 @property
35 def amount(self) -> Optional[float]:
36 """Total spending amount for this record."""
37 return to_float(self.get_value(["amount"]))
39 @property
40 def total_outlays(self) -> Optional[float]:
41 """Total outlays for this spending record."""
42 return to_float(self.get_value(["total_outlays"]))
44 @property
45 def spending_level(self) -> Optional[str]:
46 """The spending level used for this data (transactions, awards, subawards)."""
47 return self.get_value(["spending_level"])
49 def __repr__(self) -> str:
50 """String representation of RecipientSpending."""
51 name = self.name or "Unknown Recipient"
52 formatted_amount = round_to_millions(self.amount) or 0
53 return f"<RecipientSpending {name}: {formatted_amount}>"