Skip to content

Commit e150a6c

Browse files
committed
Add budgets
1 parent 6e8ab6c commit e150a6c

File tree

5 files changed

+165
-1
lines changed

5 files changed

+165
-1
lines changed

src/pyfirefly/models.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,48 @@ class Category(DataClassORJSONMixin):
209209
type: str
210210
id: str
211211
attributes: CategoryAttributes
212+
213+
214+
@dataclass
215+
class BudgetSpent(DataClassORJSONMixin):
216+
"""Model for a Firefly budget spent."""
217+
218+
sum: str | None = None
219+
currency_id: str | None = None
220+
currency_code: str | None = None
221+
currency_symbol: str | None = None
222+
currency_decimal_places: int | None = None
223+
224+
225+
@dataclass
226+
class BudgetAttributes(DataClassORJSONMixin):
227+
"""Attributes of a Firefly budget."""
228+
229+
created_at: str | None = None
230+
updated_at: str | None = None
231+
name: str | None = None
232+
active: bool | None = None
233+
notes: str | None = None
234+
order: int | None = None
235+
auto_budget_type: str | None = None
236+
currency_id: str | None = None
237+
currency_code: str | None = None
238+
currency_symbol: str | None = None
239+
currency_decimal_places: int | None = None
240+
native_currency_id: str | None = None
241+
native_currency_code: str | None = None
242+
native_currency_symbol: str | None = None
243+
native_currency_decimal_places: int | None = None
244+
auto_budget_amount: str | None = None
245+
native_auto_budget_amount: str | None = None
246+
auto_budget_period: str | None = None
247+
spent: list[BudgetSpent] | None = None
248+
249+
250+
@dataclass
251+
class Budget(DataClassORJSONMixin):
252+
"""Model for a Firefly budget."""
253+
254+
type: str
255+
id: str
256+
attributes: BudgetAttributes

src/pyfirefly/pyfirefly.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
FireflyNotFoundError,
2121
FireflyTimeoutError,
2222
)
23-
from pyfirefly.models import About, Account, Category, Transaction
23+
from pyfirefly.models import About, Account, Budget, Category, Transaction
2424

2525
try:
2626
VERSION = metadata.version(__package__)
@@ -252,6 +252,31 @@ async def get_categories(self, category_id: int, start: str | None = None, end:
252252
category = await self._request(uri=f"categories/{category_id}", params=params)
253253
return Category.from_dict(category["data"])
254254

255+
async def get_budgets(self, start: str | None = None, end: str | None = None) -> list[Budget]:
256+
"""Get budgets for the Firefly server.
257+
258+
Args:
259+
start: The start date for the budgets.
260+
end: The end date for the budgets.
261+
262+
Returns:
263+
A list of Budget objects containing budget information.
264+
265+
"""
266+
params: dict[str, str] = {}
267+
if start:
268+
params["start"] = start
269+
if end:
270+
params["end"] = end
271+
272+
budgets = await self._request(uri="budgets", params=params)
273+
return [Budget.from_dict(budget) for budget in budgets["data"]]
274+
275+
@property
276+
def api_url(self) -> str:
277+
"""Return the API URL."""
278+
return f"{self._api_scheme}://{self._api_host}:{self._api_port}"
279+
255280
async def close(self) -> None:
256281
"""Close open client session."""
257282
if self._session and self._close_session:

tests/__snapshots__/test_models.ambr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@
1919
Account(type='accounts', id='4', attributes=AccountAttributes(created_at='2021-05-10T09:30:00+01:00', updated_at='2022-05-10T09:30:00+01:00', active=True, name='Credit Card', type='liability', account_role='creditCard', currency_id='14', currency_code='GBP', currency_symbol='£', currency_decimal_places=2, native_currency_id='14', native_currency_code='GBP', native_currency_symbol='£', native_currency_decimal_places=2, current_balance='-250.00', native_current_balance='-250.00', current_balance_date='2022-05-10T09:30:00+01:00', order=3, notes='Credit card account', monthly_payment_date='2022-05-15T09:30:00+01:00', credit_card_type='monthlyFull', account_number='9876543210', iban='GB29NWBK60161331926819', bic='NWBKGB2L', virtual_balance='0.00', native_virtual_balance='0.00', opening_balance='0.00', native_opening_balance='0.00', opening_balance_date='2021-05-10T09:30:00+01:00', liability_type='credit', liability_direction='debit', interest='19.99', interest_period='monthly', current_debt='250.00', include_net_worth=False, longitude=0.1278, latitude=51.5074, zoom_level=10, last_activity=None)),
2020
])
2121
# ---
22+
# name: test_budgets_model
23+
list([
24+
Budget(type='budgets', id='2', attributes=BudgetAttributes(created_at='2018-09-17T12:46:47+01:00', updated_at='2018-09-17T12:46:47+01:00', name='Bills', active=False, notes='Some notes', order=5, auto_budget_type='reset', currency_id='12', currency_code='EUR', currency_symbol='$', currency_decimal_places=2, native_currency_id='5', native_currency_code='EUR', native_currency_symbol='$', native_currency_decimal_places=2, auto_budget_amount='-1012.12', native_auto_budget_amount='-1012.12', auto_budget_period='monthly', spent=[BudgetSpent(sum='123.45', currency_id='5', currency_code='USD', currency_symbol='$', currency_decimal_places=2)])),
25+
])
26+
# ---
27+
# name: test_budgets_model.1
28+
list([
29+
Budget(type='budgets', id='2', attributes=BudgetAttributes(created_at='2018-09-17T12:46:47+01:00', updated_at='2018-09-17T12:46:47+01:00', name='Bills', active=False, notes='Some notes', order=5, auto_budget_type='reset', currency_id='12', currency_code='EUR', currency_symbol='$', currency_decimal_places=2, native_currency_id='5', native_currency_code='EUR', native_currency_symbol='$', native_currency_decimal_places=2, auto_budget_amount='-1012.12', native_auto_budget_amount='-1012.12', auto_budget_period='monthly', spent=[BudgetSpent(sum='123.45', currency_id='5', currency_code='USD', currency_symbol='$', currency_decimal_places=2)])),
30+
])
31+
# ---
2232
# name: test_category_model
2333
Category(type='categories', id='2', attributes=CategoryAttributes(created_at='2018-09-17T12:46:47+01:00', updated_at='2018-09-17T12:46:47+01:00', name='Lunch', notes='Some example notes', native_currency_id='5', native_currency_code='EUR', native_currency_symbol='$', native_currency_decimal_places=2, spent=[CategoryAmount(currency_id='5', currency_code='USD', currency_symbol='$', currency_decimal_places=2, sum='-12423.45')], earned=[CategoryAmount(currency_id='5', currency_code='USD', currency_symbol='$', currency_decimal_places=2, sum='123.45')]))
2434
# ---

tests/fixtures/budgets.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"data": [
3+
{
4+
"type": "budgets",
5+
"id": "2",
6+
"attributes": {
7+
"created_at": "2018-09-17T12:46:47+01:00",
8+
"updated_at": "2018-09-17T12:46:47+01:00",
9+
"name": "Bills",
10+
"active": false,
11+
"notes": "Some notes",
12+
"order": 5,
13+
"auto_budget_type": "reset",
14+
"currency_id": "12",
15+
"currency_code": "EUR",
16+
"currency_symbol": "$",
17+
"currency_decimal_places": 2,
18+
"native_currency_id": "5",
19+
"native_currency_code": "EUR",
20+
"native_currency_symbol": "$",
21+
"native_currency_decimal_places": 2,
22+
"auto_budget_amount": "-1012.12",
23+
"native_auto_budget_amount": "-1012.12",
24+
"auto_budget_period": "monthly",
25+
"spent": [
26+
{
27+
"sum": "123.45",
28+
"currency_id": "5",
29+
"currency_code": "USD",
30+
"currency_symbol": "$",
31+
"currency_decimal_places": 2
32+
}
33+
]
34+
}
35+
}
36+
],
37+
"meta": {
38+
"pagination": {
39+
"total": 3,
40+
"count": 20,
41+
"per_page": 100,
42+
"current_page": 1,
43+
"total_pages": 1
44+
}
45+
}
46+
}

tests/test_models.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,41 @@ async def test_category_model(
126126

127127
categories = await firefly_client.get_categories(category_id=1)
128128
assert categories == snapshot
129+
130+
131+
async def test_budgets_model(
132+
aresponses: ResponsesMockServer,
133+
firefly_client: Firefly,
134+
snapshot: SnapshotAssertion,
135+
) -> None:
136+
"""Test the Budgets model."""
137+
aresponses.add(
138+
"localhost:9000",
139+
"/api/v1/budgets",
140+
"GET",
141+
aresponses.Response(
142+
status=200,
143+
headers={"Content-Type": "application/vnd.api+json"},
144+
text=load_fixtures("budgets.json"),
145+
),
146+
)
147+
148+
budgets = await firefly_client.get_budgets(start="2025-01-01", end="2025-12-31")
149+
assert budgets == snapshot
150+
151+
# Now without a date range
152+
aresponses.add(
153+
"localhost:9000",
154+
"/api/v1/budgets",
155+
"GET",
156+
aresponses.Response(
157+
status=200,
158+
headers={"Content-Type": "application/vnd.api+json"},
159+
text=load_fixtures("budgets.json"),
160+
),
161+
)
162+
163+
budgets = await firefly_client.get_budgets()
164+
assert budgets == snapshot
165+
166+
# Now for all budgets

0 commit comments

Comments
 (0)