Skip to content

Commit cf74950

Browse files
committed
Add acocunts
1 parent c437945 commit cf74950

File tree

5 files changed

+271
-3
lines changed

5 files changed

+271
-3
lines changed

src/pyfirefly/models.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,70 @@ class About(DataClassORJSONMixin):
1717
php_version: str = field(metadata=field_options(alias="php_version"))
1818
os: str = field(metadata=field_options(alias="os"))
1919
driver: str = field(metadata=field_options(alias="driver"))
20+
21+
22+
@dataclass
23+
class Accounts(DataClassORJSONMixin):
24+
"""Model for the Firefly Accounts information."""
25+
26+
id: int = field(metadata=field_options(alias="id"))
27+
name: str = field(metadata=field_options(alias="name"))
28+
type: str = field(metadata=field_options(alias="type"))
29+
balance: float = field(metadata=field_options(alias="balance"))
30+
currency: str = field(metadata=field_options(alias="currency"))
31+
active: bool = field(metadata=field_options(alias="active"))
32+
33+
34+
@dataclass
35+
class AccountAttributes(DataClassORJSONMixin): # pylint: disable=too-many-instance-attributes
36+
"""Attributes of a Firefly account."""
37+
38+
created_at: str | None = None
39+
updated_at: str | None = None
40+
active: bool | None = None
41+
42+
name: str | None = None
43+
type: str | None = None
44+
account_role: str | None = None
45+
currency_id: str | None = None
46+
currency_code: str | None = None
47+
currency_symbol: str | None = None
48+
currency_decimal_places: int | None = None
49+
native_currency_id: str | None = None
50+
native_currency_code: str | None = None
51+
native_currency_symbol: str | None = None
52+
native_currency_decimal_places: int | None = None
53+
current_balance: str | None = None
54+
native_current_balance: str | None = None
55+
current_balance_date: str | None = None
56+
order: int | None = None
57+
notes: str | None = None
58+
monthly_payment_date: str | None = None
59+
credit_card_type: str | None = None
60+
account_number: str | None = None
61+
iban: str | None = None
62+
bic: str | None = None
63+
virtual_balance: str | None = None
64+
native_virtual_balance: str | None = None
65+
opening_balance: str | None = None
66+
native_opening_balance: str | None = None
67+
opening_balance_date: str | None = None
68+
liability_type: str | None = None
69+
liability_direction: str | None = None
70+
interest: str | None = None
71+
interest_period: str | None = None
72+
current_debt: str | None = None
73+
include_net_worth: bool | None = None
74+
longitude: float | None = None
75+
latitude: float | None = None
76+
zoom_level: int | None = None
77+
last_activity: str | None = None
78+
79+
80+
@dataclass
81+
class Account(DataClassORJSONMixin):
82+
"""Model for a Firefly account."""
83+
84+
type: str
85+
id: str
86+
attributes: AccountAttributes

src/pyfirefly/pyfirefly.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
FireflyNotFoundError,
2121
FireflyTimeoutError,
2222
)
23-
from pyfirefly.models import About
23+
from pyfirefly.models import About, Account
2424

2525
try:
2626
VERSION = metadata.version(__package__)
@@ -132,7 +132,7 @@ async def _request(
132132
raise FireflyConnectionError(msg) from err
133133

134134
content_type = response.headers.get("Content-Type", "")
135-
if "application/json" not in content_type:
135+
if "application/json" not in content_type and "application/vnd.api+json" not in content_type:
136136
text = await response.text()
137137
msg = "Unexpected content type response from the Firefly API"
138138
raise FireflyError(
@@ -153,6 +153,35 @@ async def get_about(self) -> About:
153153
about = await self._request("about")
154154
return About.from_dict(about["data"])
155155

156+
async def get_accounts(self) -> list[Account]:
157+
"""Get a list of accounts from the Firefly server.
158+
159+
Returns
160+
-------
161+
A list of Account objects containing account information.
162+
163+
"""
164+
accounts: list[dict[str, str]] = []
165+
next_page: int | None = 1
166+
167+
while next_page:
168+
response = await self._request(
169+
uri="accounts",
170+
method="GET",
171+
params={"page": next_page},
172+
)
173+
174+
accounts.extend(response["data"])
175+
176+
# Check for the next page in the pagination metadata
177+
pagination = response.get("meta", {}).get("pagination", {})
178+
current_page = int(pagination.get("current_page", 1) or 1)
179+
total_pages = int(pagination.get("total_pages", 1) or 1)
180+
181+
next_page = current_page + 1 if current_page < total_pages else None
182+
183+
return [Account.from_dict(acc) for acc in accounts]
184+
156185
async def close(self) -> None:
157186
"""Close open client session."""
158187
if self._session and self._close_session:

tests/__snapshots__/test_models.ambr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@
22
# name: test_about_model
33
About(version='5.8.0-alpha.1', api_version='5.8.0-alpha.1', php_version='8.1.5', os='Linux', driver='mysql')
44
# ---
5+
# name: test_accounts_model
6+
list([
7+
Account(type='accounts', id='2', attributes=AccountAttributes(created_at='2018-09-17T12:46:47+01:00', updated_at='2018-09-17T12:46:47+01:00', active=False, name='My checking account', type='asset', account_role='defaultAsset', currency_id='12', currency_code='EUR', currency_symbol='$', currency_decimal_places=2, native_currency_id='12', native_currency_code='EUR', native_currency_symbol='$', native_currency_decimal_places=2, current_balance='123.45', native_current_balance='123.45', current_balance_date='2018-09-17T12:46:47+01:00', order=1, notes='Some example notes', monthly_payment_date='2018-09-17T12:46:47+01:00', credit_card_type='monthlyFull', account_number='7009312345678', iban='GB98MIDL07009312345678', bic='BOFAUS3N', virtual_balance='123.45', native_virtual_balance='123.45', opening_balance='-1012.12', native_opening_balance='-1012.12', opening_balance_date='2018-09-17T12:46:47+01:00', liability_type='loan', liability_direction='credit', interest='5.3', interest_period='monthly', current_debt='1012.12', include_net_worth=True, longitude=5.916667, latitude=51.983333, zoom_level=6, last_activity=None)),
8+
Account(type='accounts', id='3', attributes=AccountAttributes(created_at='2019-01-01T10:00:00+01:00', updated_at='2020-01-01T10:00:00+01:00', active=True, name='Savings Account', type='asset', account_role='savingsAsset', currency_id='13', currency_code='USD', currency_symbol='$', currency_decimal_places=2, native_currency_id='13', native_currency_code='USD', native_currency_symbol='$', native_currency_decimal_places=2, current_balance='5000.00', native_current_balance='5000.00', current_balance_date='2020-01-01T10:00:00+01:00', order=2, notes='Main savings account', monthly_payment_date=None, credit_card_type=None, account_number='1234567890', iban='US12345678901234567890', bic='CITIUS33', virtual_balance='0.00', native_virtual_balance='0.00', opening_balance='1000.00', native_opening_balance='1000.00', opening_balance_date='2019-01-01T10:00:00+01:00', liability_type=None, liability_direction=None, interest='1.2', interest_period='yearly', current_debt=None, include_net_worth=True, longitude=-74.006, latitude=40.7128, zoom_level=8, last_activity=None)),
9+
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)),
10+
])
11+
# ---

tests/fixtures/accounts.json

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
{
2+
"data": [
3+
{
4+
"type": "accounts",
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+
"active": false,
10+
"order": 1,
11+
"name": "My checking account",
12+
"type": "asset",
13+
"account_role": "defaultAsset",
14+
"currency_id": "12",
15+
"currency_code": "EUR",
16+
"currency_symbol": "$",
17+
"currency_decimal_places": 2,
18+
"native_currency_id": "12",
19+
"native_currency_code": "EUR",
20+
"native_currency_symbol": "$",
21+
"native_currency_decimal_places": 2,
22+
"current_balance": "123.45",
23+
"native_current_balance": "123.45",
24+
"current_balance_date": "2018-09-17T12:46:47+01:00",
25+
"notes": "Some example notes",
26+
"monthly_payment_date": "2018-09-17T12:46:47+01:00",
27+
"credit_card_type": "monthlyFull",
28+
"account_number": "7009312345678",
29+
"iban": "GB98MIDL07009312345678",
30+
"bic": "BOFAUS3N",
31+
"virtual_balance": "123.45",
32+
"native_virtual_balance": "123.45",
33+
"opening_balance": "-1012.12",
34+
"native_opening_balance": "-1012.12",
35+
"opening_balance_date": "2018-09-17T12:46:47+01:00",
36+
"liability_type": "loan",
37+
"liability_direction": "credit",
38+
"interest": "5.3",
39+
"interest_period": "monthly",
40+
"current_debt": "1012.12",
41+
"include_net_worth": true,
42+
"longitude": 5.916667,
43+
"latitude": 51.983333,
44+
"zoom_level": 6
45+
}
46+
},
47+
{
48+
"type": "accounts",
49+
"id": "3",
50+
"attributes": {
51+
"created_at": "2019-01-01T10:00:00+01:00",
52+
"updated_at": "2020-01-01T10:00:00+01:00",
53+
"active": true,
54+
"order": 2,
55+
"name": "Savings Account",
56+
"type": "asset",
57+
"account_role": "savingsAsset",
58+
"currency_id": "13",
59+
"currency_code": "USD",
60+
"currency_symbol": "$",
61+
"currency_decimal_places": 2,
62+
"native_currency_id": "13",
63+
"native_currency_code": "USD",
64+
"native_currency_symbol": "$",
65+
"native_currency_decimal_places": 2,
66+
"current_balance": "5000.00",
67+
"native_current_balance": "5000.00",
68+
"current_balance_date": "2020-01-01T10:00:00+01:00",
69+
"notes": "Main savings account",
70+
"monthly_payment_date": null,
71+
"credit_card_type": null,
72+
"account_number": "1234567890",
73+
"iban": "US12345678901234567890",
74+
"bic": "CITIUS33",
75+
"virtual_balance": "0.00",
76+
"native_virtual_balance": "0.00",
77+
"opening_balance": "1000.00",
78+
"native_opening_balance": "1000.00",
79+
"opening_balance_date": "2019-01-01T10:00:00+01:00",
80+
"liability_type": null,
81+
"liability_direction": null,
82+
"interest": "1.2",
83+
"interest_period": "yearly",
84+
"current_debt": null,
85+
"include_net_worth": true,
86+
"longitude": -74.006,
87+
"latitude": 40.7128,
88+
"zoom_level": 8
89+
}
90+
},
91+
{
92+
"type": "accounts",
93+
"id": "4",
94+
"attributes": {
95+
"created_at": "2021-05-10T09:30:00+01:00",
96+
"updated_at": "2022-05-10T09:30:00+01:00",
97+
"active": true,
98+
"order": 3,
99+
"name": "Credit Card",
100+
"type": "liability",
101+
"account_role": "creditCard",
102+
"currency_id": "14",
103+
"currency_code": "GBP",
104+
"currency_symbol": "£",
105+
"currency_decimal_places": 2,
106+
"native_currency_id": "14",
107+
"native_currency_code": "GBP",
108+
"native_currency_symbol": "£",
109+
"native_currency_decimal_places": 2,
110+
"current_balance": "-250.00",
111+
"native_current_balance": "-250.00",
112+
"current_balance_date": "2022-05-10T09:30:00+01:00",
113+
"notes": "Credit card account",
114+
"monthly_payment_date": "2022-05-15T09:30:00+01:00",
115+
"credit_card_type": "monthlyFull",
116+
"account_number": "9876543210",
117+
"iban": "GB29NWBK60161331926819",
118+
"bic": "NWBKGB2L",
119+
"virtual_balance": "0.00",
120+
"native_virtual_balance": "0.00",
121+
"opening_balance": "0.00",
122+
"native_opening_balance": "0.00",
123+
"opening_balance_date": "2021-05-10T09:30:00+01:00",
124+
"liability_type": "credit",
125+
"liability_direction": "debit",
126+
"interest": "19.99",
127+
"interest_period": "monthly",
128+
"current_debt": "250.00",
129+
"include_net_worth": false,
130+
"longitude": 0.1278,
131+
"latitude": 51.5074,
132+
"zoom_level": 10
133+
}
134+
}
135+
],
136+
"meta": {
137+
"pagination": {
138+
"total": 3,
139+
"count": 20,
140+
"per_page": 100,
141+
"current_page": 1,
142+
"total_pages": 1
143+
}
144+
}
145+
}

tests/test_models.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,24 @@ async def test_about_model(
3333

3434
about: About = await firefly_client.get_about()
3535
assert about == snapshot
36-
await firefly_client.close()
36+
37+
38+
async def test_accounts_model(
39+
aresponses: ResponsesMockServer,
40+
firefly_client: Firefly,
41+
snapshot: SnapshotAssertion,
42+
) -> None:
43+
"""Test the Accounts model."""
44+
aresponses.add(
45+
"localhost:9000",
46+
"/api/v1/accounts",
47+
"GET",
48+
aresponses.Response(
49+
status=200,
50+
headers={"Content-Type": "application/vnd.api+json"},
51+
text=load_fixtures("accounts.json"),
52+
),
53+
)
54+
55+
accounts = await firefly_client.get_accounts()
56+
assert accounts == snapshot

0 commit comments

Comments
 (0)