beancount-gocardless 0.1.10__tar.gz → 0.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/PKG-INFO +1 -1
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/pyproject.toml +1 -1
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/cli.py +47 -1
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/client.py +7 -3
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/models.py +2 -2
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/tui.py +118 -238
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/.github/workflows/publish.yml +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/.gitignore +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/.pre-commit-config.yaml +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/.readthedocs.yaml +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/LICENSE +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/README.md +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/Makefile +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/cli.rst +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/client.rst +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/conf.py +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/importer.rst +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/index.rst +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/docs/make.bat +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/__init__.py +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/importer.py +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/openapi/swagger.json +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/tests/__init__.py +0 -0
- {beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/tests/test_tui.py +0 -0
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
6
|
from beancount_gocardless.models import AccountInfo
|
|
7
|
+
from beancount_gocardless.client import GoCardlessClient
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
logging.basicConfig(level=os.environ.get("LOGLEVEL", logging.INFO))
|
|
@@ -83,7 +84,52 @@ def main():
|
|
|
83
84
|
try:
|
|
84
85
|
logger.debug("Initializing GoCardlessClient")
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
cache_options = (
|
|
88
|
+
{
|
|
89
|
+
"backend": args.cache_backend,
|
|
90
|
+
"expire_after": args.cache_expire,
|
|
91
|
+
"cache_name": args.cache_name,
|
|
92
|
+
}
|
|
93
|
+
if args.cache
|
|
94
|
+
else {}
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
client = GoCardlessClient(args.secret_id, args.secret_key, cache_options)
|
|
98
|
+
|
|
99
|
+
if args.mode == "list_banks":
|
|
100
|
+
banks = client.list_banks(args.country)
|
|
101
|
+
for bank in banks:
|
|
102
|
+
logger.info(bank)
|
|
103
|
+
elif args.mode == "create_link":
|
|
104
|
+
if not args.bank:
|
|
105
|
+
logger.error("Error: --bank is required for create_link")
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
link = client.create_bank_link(args.reference, args.bank)
|
|
108
|
+
if link:
|
|
109
|
+
logger.info(f"Bank link created: {link}")
|
|
110
|
+
else:
|
|
111
|
+
logger.info(f"Link already exists for reference '{args.reference}'")
|
|
112
|
+
elif args.mode == "list_accounts":
|
|
113
|
+
accounts = client.list_accounts()
|
|
114
|
+
for i, account in enumerate(accounts, 1):
|
|
115
|
+
display_account(i, account)
|
|
116
|
+
elif args.mode == "delete_link":
|
|
117
|
+
req = client.find_requisition_by_reference(args.reference)
|
|
118
|
+
if req:
|
|
119
|
+
client.delete_requisition(req.id)
|
|
120
|
+
logger.info(f"Deleted requisition '{args.reference}'")
|
|
121
|
+
else:
|
|
122
|
+
logger.error(f"No requisition found with reference '{args.reference}'")
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
elif args.mode == "balance":
|
|
125
|
+
if not args.account:
|
|
126
|
+
logger.error("Error: --account is required for balance")
|
|
127
|
+
sys.exit(1)
|
|
128
|
+
balances = client.get_account_balances(args.account)
|
|
129
|
+
for balance in balances.balances:
|
|
130
|
+
logger.info(
|
|
131
|
+
f"{balance.balance_type}: {balance.balance_amount.amount} {balance.balance_amount.currency}"
|
|
132
|
+
)
|
|
87
133
|
|
|
88
134
|
except Exception as e:
|
|
89
135
|
logger.error(f"Error: {e}")
|
{beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/client.py
RENAMED
|
@@ -239,9 +239,9 @@ class GoCardlessClient:
|
|
|
239
239
|
"""Get institutions for a country"""
|
|
240
240
|
logger.debug("Getting institutions for country %s", country)
|
|
241
241
|
params = {"country": country} if country else {}
|
|
242
|
-
|
|
243
|
-
logger.debug("Fetched %d institutions", len(
|
|
244
|
-
return [Institution(**inst) for inst in
|
|
242
|
+
institutions_data = self.get("/institutions/", params=params)
|
|
243
|
+
logger.debug("Fetched %d institutions", len(institutions_data))
|
|
244
|
+
return [Institution(**inst) for inst in institutions_data]
|
|
245
245
|
|
|
246
246
|
def get_institution(self, institution_id: str) -> Institution:
|
|
247
247
|
"""Get specific institution"""
|
|
@@ -422,3 +422,7 @@ class GoCardlessClient:
|
|
|
422
422
|
# Skip accounts that can't be accessed
|
|
423
423
|
continue
|
|
424
424
|
return accounts
|
|
425
|
+
|
|
426
|
+
def list_accounts(self) -> List[AccountInfo]:
|
|
427
|
+
"""Alias for get_all_accounts"""
|
|
428
|
+
return self.get_all_accounts()
|
{beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/models.py
RENAMED
|
@@ -351,7 +351,7 @@ class Requisition(BaseModel):
|
|
|
351
351
|
id: str
|
|
352
352
|
created: str
|
|
353
353
|
redirect: str
|
|
354
|
-
status:
|
|
354
|
+
status: str
|
|
355
355
|
institution_id: str
|
|
356
356
|
agreement: Optional[str] = None
|
|
357
357
|
reference: str
|
|
@@ -376,7 +376,7 @@ class SpectacularRequisition(BaseModel):
|
|
|
376
376
|
id: str
|
|
377
377
|
created: str
|
|
378
378
|
redirect: str
|
|
379
|
-
status:
|
|
379
|
+
status: str
|
|
380
380
|
institution_id: str
|
|
381
381
|
agreement: Optional[str] = None
|
|
382
382
|
reference: str
|
|
@@ -113,7 +113,7 @@ class BanksView(BaseSubView):
|
|
|
113
113
|
]
|
|
114
114
|
|
|
115
115
|
self.banks_table.update(
|
|
116
|
-
f"Loading
|
|
116
|
+
f"Loading banks... {name_filter} {country_code} {len(self.all_banks)}"
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
name_filtered = [
|
|
@@ -180,6 +180,8 @@ class AccountsView(BaseSubView):
|
|
|
180
180
|
"Loading accounts...", id="accounts_status_message"
|
|
181
181
|
)
|
|
182
182
|
self.accounts_table = Static("", id="accounts_table")
|
|
183
|
+
self.pending_delete_ref = None
|
|
184
|
+
self.accounts_list = []
|
|
183
185
|
|
|
184
186
|
def compose_content(self) -> ComposeResult:
|
|
185
187
|
yield Label("Linked Accounts", classes="view_title")
|
|
@@ -189,6 +191,23 @@ class AccountsView(BaseSubView):
|
|
|
189
191
|
id="accounts_scrollable_area",
|
|
190
192
|
classes="horizontal-scroll",
|
|
191
193
|
)
|
|
194
|
+
yield Vertical(
|
|
195
|
+
Label("Select Account by # and Delete Link"),
|
|
196
|
+
Input(placeholder="Enter account #", id="select_account_input"),
|
|
197
|
+
Button("Select", id="select_account_button"),
|
|
198
|
+
Input(placeholder="Reference", id="delete_ref_input", disabled=True),
|
|
199
|
+
Button(
|
|
200
|
+
"Delete Link", id="delete_link_button", variant="error", disabled=True
|
|
201
|
+
),
|
|
202
|
+
Button(
|
|
203
|
+
"Confirm Delete",
|
|
204
|
+
id="confirm_delete_button",
|
|
205
|
+
variant="error",
|
|
206
|
+
disabled=True,
|
|
207
|
+
),
|
|
208
|
+
Button("Cancel", id="cancel_delete_button", disabled=True),
|
|
209
|
+
id="delete_section",
|
|
210
|
+
)
|
|
192
211
|
yield Button("Back to Menu", id="back_to_menu", classes="back_button")
|
|
193
212
|
|
|
194
213
|
# Override the base class compose to avoid duplicate back button
|
|
@@ -206,6 +225,7 @@ class AccountsView(BaseSubView):
|
|
|
206
225
|
try:
|
|
207
226
|
self.status_message.update("Loading accounts...")
|
|
208
227
|
accounts = self.client.get_all_accounts()
|
|
228
|
+
self.accounts_list = accounts
|
|
209
229
|
if not accounts:
|
|
210
230
|
self.accounts_table.update("No accounts found.")
|
|
211
231
|
self.status_message.update("")
|
|
@@ -215,7 +235,7 @@ class AccountsView(BaseSubView):
|
|
|
215
235
|
table = Table(title=None, expand=True, min_width=100)
|
|
216
236
|
table.add_column("#", style="dim", width=3)
|
|
217
237
|
table.add_column("Bank", overflow="ellipsis", min_width=20)
|
|
218
|
-
table.add_column("Name", overflow="
|
|
238
|
+
table.add_column("Name", overflow="ellipsis", min_width=20)
|
|
219
239
|
table.add_column("ID", overflow="ellipsis", min_width=20)
|
|
220
240
|
table.add_column("IBAN", overflow="ellipsis", min_width=20)
|
|
221
241
|
table.add_column("Reference", overflow="ellipsis", min_width=15)
|
|
@@ -224,14 +244,12 @@ class AccountsView(BaseSubView):
|
|
|
224
244
|
|
|
225
245
|
# Format and add accounts to the table
|
|
226
246
|
for idx, account in enumerate(accounts, start=1):
|
|
227
|
-
# import pdb
|
|
228
|
-
# pdb.set_trace()
|
|
229
247
|
# Get values with fallbacks for any missing keys
|
|
230
248
|
institution_id = account.get("institution_id", "N/A")
|
|
231
249
|
name = account.get("name", account.get("owner_name", "N/A"))
|
|
232
250
|
iban = account.get("iban", "N/A")
|
|
233
|
-
account_id = account.get("
|
|
234
|
-
reference = account.get("
|
|
251
|
+
account_id = account.get("id", "N/A")
|
|
252
|
+
reference = account.get("requisition_reference", "N/A")
|
|
235
253
|
status = account.get("status", "N/A")
|
|
236
254
|
last_accessed = account.get("last_accessed", "")
|
|
237
255
|
if last_accessed:
|
|
@@ -253,6 +271,39 @@ class AccountsView(BaseSubView):
|
|
|
253
271
|
|
|
254
272
|
# Update the table content
|
|
255
273
|
self.accounts_table.update(table)
|
|
274
|
+
if not accounts:
|
|
275
|
+
self.accounts_table.add_row(
|
|
276
|
+
"No accounts found.", "", "", "", "", "", "", ""
|
|
277
|
+
)
|
|
278
|
+
self.status_message.update("")
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
# Format and add accounts to the table
|
|
282
|
+
for idx, account in enumerate(accounts, start=1):
|
|
283
|
+
# Get values with fallbacks for any missing keys
|
|
284
|
+
institution_id = account.get("institution_id", "N/A")
|
|
285
|
+
name = account.get("name", account.get("owner_name", "N/A"))
|
|
286
|
+
iban = account.get("iban", "N/A")
|
|
287
|
+
account_id = account.get("id", "N/A")
|
|
288
|
+
reference = account.get("requisition_reference", "N/A")
|
|
289
|
+
status = account.get("status", "N/A")
|
|
290
|
+
last_accessed = account.get("last_accessed", "")
|
|
291
|
+
if last_accessed:
|
|
292
|
+
try:
|
|
293
|
+
last_accessed = last_accessed.split("T")[0]
|
|
294
|
+
except Exception:
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
self.accounts_table.add_row(
|
|
298
|
+
str(idx),
|
|
299
|
+
institution_id,
|
|
300
|
+
name,
|
|
301
|
+
account_id,
|
|
302
|
+
iban,
|
|
303
|
+
reference,
|
|
304
|
+
status,
|
|
305
|
+
last_accessed,
|
|
306
|
+
)
|
|
256
307
|
self.status_message.update("")
|
|
257
308
|
|
|
258
309
|
except HttpServiceException as e:
|
|
@@ -265,245 +316,74 @@ class AccountsView(BaseSubView):
|
|
|
265
316
|
if event.button.id == "back_to_menu":
|
|
266
317
|
self.post_message(ActionMessage("show_menu"))
|
|
267
318
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
def __init__(
|
|
276
|
-
self, client: "GoCardlessClient"
|
|
277
|
-
): # Forward reference GoCardlessClient if not imported yet
|
|
278
|
-
super().__init__()
|
|
279
|
-
self.client = client
|
|
280
|
-
self.accounts_data = []
|
|
281
|
-
|
|
282
|
-
def compose(self) -> ComposeResult:
|
|
283
|
-
"""Override compose to yield widgets from compose_content."""
|
|
284
|
-
for widget in self.compose_content():
|
|
285
|
-
yield widget
|
|
286
|
-
|
|
287
|
-
def compose_content(self) -> ComposeResult:
|
|
288
|
-
yield Label("Account Balance", classes="view_title")
|
|
289
|
-
# Moved status message to be a direct child of BalanceView, and sibling to content_area
|
|
290
|
-
yield Static(
|
|
291
|
-
"", id="balance_status_message"
|
|
292
|
-
) # Initialize empty or with a generic placeholder
|
|
293
|
-
yield Vertical(
|
|
294
|
-
# The initial Static message that was here is removed
|
|
295
|
-
id="balance_content_area",
|
|
296
|
-
)
|
|
297
|
-
yield Button("Back to Menu", id="back_to_menu", classes="back_button")
|
|
298
|
-
|
|
299
|
-
async def on_mount(self) -> None:
|
|
300
|
-
# Query elements only after they are mounted
|
|
301
|
-
content_area = self.query_one("#balance_content_area", Vertical)
|
|
302
|
-
status_message = self.query_one("#balance_status_message", Static)
|
|
303
|
-
status_message.update(
|
|
304
|
-
"Loading accounts for selection..."
|
|
305
|
-
) # Set initial operational message
|
|
306
|
-
await self.load_accounts_for_selection(content_area, status_message)
|
|
307
|
-
|
|
308
|
-
async def load_accounts_for_selection(
|
|
309
|
-
self, content_area: Vertical, status_message: Static
|
|
310
|
-
):
|
|
311
|
-
try:
|
|
312
|
-
# status_message.update("Loading accounts...") # Message set by on_mount or can be refined here
|
|
313
|
-
self.accounts_data = self.client.get_all_accounts()
|
|
314
|
-
await (
|
|
315
|
-
content_area.remove_children()
|
|
316
|
-
) # Clear "Loading..." or previous content from content_area
|
|
317
|
-
|
|
318
|
-
if not self.accounts_data:
|
|
319
|
-
await content_area.mount(
|
|
320
|
-
Static("No accounts linked. Cannot fetch balance.")
|
|
321
|
-
)
|
|
322
|
-
status_message.update(
|
|
323
|
-
"No accounts available to display."
|
|
324
|
-
) # Update persistent status
|
|
325
|
-
return
|
|
326
|
-
|
|
327
|
-
table = Table(title="Select Account by Index for Balance", expand=True)
|
|
328
|
-
table.add_column("#", style="dim")
|
|
329
|
-
table.add_column("Name", overflow="fold")
|
|
330
|
-
table.add_column("Institution ID", overflow="fold")
|
|
331
|
-
for idx, a in enumerate(self.accounts_data):
|
|
332
|
-
table.add_row(str(idx), a["name"], a["institution_id"])
|
|
333
|
-
|
|
334
|
-
await content_area.mount(table) # Mount Table widget directly
|
|
335
|
-
idx_input = Input(
|
|
336
|
-
placeholder="Enter account # and press Enter", id="acct_idx_input"
|
|
337
|
-
)
|
|
338
|
-
await content_area.mount(idx_input)
|
|
339
|
-
idx_input.focus()
|
|
340
|
-
status_message.update(
|
|
341
|
-
"Please select an account from the list."
|
|
342
|
-
) # Clear or update status message
|
|
343
|
-
except HttpServiceException as e: # Make sure HttpServiceException is defined
|
|
344
|
-
status_message.update(
|
|
345
|
-
Text(f"Error loading accounts: {e}", style="bold red")
|
|
346
|
-
)
|
|
347
|
-
await content_area.remove_children()
|
|
348
|
-
await content_area.mount(
|
|
349
|
-
Static(
|
|
350
|
-
Text(
|
|
351
|
-
"Failed to load accounts. Check connection or try again later.",
|
|
352
|
-
style="yellow",
|
|
353
|
-
)
|
|
354
|
-
)
|
|
355
|
-
)
|
|
356
|
-
except Exception as e:
|
|
357
|
-
status_message.update(Text(f"Unexpected error: {e}", style="bold red"))
|
|
358
|
-
await content_area.remove_children()
|
|
359
|
-
await content_area.mount(
|
|
360
|
-
Static(
|
|
361
|
-
Text(
|
|
362
|
-
"An unexpected error occurred while loading accounts.",
|
|
363
|
-
style="yellow",
|
|
364
|
-
)
|
|
365
|
-
)
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
async def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
369
|
-
if event.input.id == "acct_idx_input":
|
|
370
|
-
content_area = self.query_one("#balance_content_area", Vertical)
|
|
371
|
-
# status_message is now persistent and queried once
|
|
372
|
-
status_message = self.query_one("#balance_status_message", Static)
|
|
373
|
-
|
|
374
|
-
await (
|
|
375
|
-
content_area.remove_children()
|
|
376
|
-
) # Clear account list and input from content_area
|
|
377
|
-
|
|
319
|
+
async def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
320
|
+
"""Handle button presses within this view."""
|
|
321
|
+
if event.button.id == "back_to_menu":
|
|
322
|
+
self.post_message(ActionMessage("show_menu"))
|
|
323
|
+
elif event.button.id == "select_account_button":
|
|
324
|
+
select_input = self.query_one("#select_account_input", Input)
|
|
378
325
|
try:
|
|
379
|
-
idx = int(
|
|
380
|
-
if
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
326
|
+
idx = int(select_input.value.strip()) - 1 # 1-based to 0-based
|
|
327
|
+
if 0 <= idx < len(self.accounts_list):
|
|
328
|
+
reference = self.accounts_list[idx].get("requisition_reference", "")
|
|
329
|
+
ref_input = self.query_one("#delete_ref_input", Input)
|
|
330
|
+
ref_input.value = reference
|
|
331
|
+
delete_btn = self.query_one("#delete_link_button", Button)
|
|
332
|
+
delete_btn.disabled = False
|
|
333
|
+
self.status_message.update(
|
|
334
|
+
f"Selected account {idx + 1}, reference: {reference}"
|
|
384
335
|
)
|
|
385
|
-
status_message.update(
|
|
386
|
-
Text(
|
|
387
|
-
"Selection out of range. Please try again.", style="yellow"
|
|
388
|
-
)
|
|
389
|
-
)
|
|
390
|
-
# Reload account selection UI
|
|
391
|
-
await self.load_accounts_for_selection(content_area, status_message)
|
|
392
|
-
return
|
|
393
|
-
|
|
394
|
-
account_to_check = self.accounts_data[idx]
|
|
395
|
-
acct_id = account_to_check["id"]
|
|
396
|
-
|
|
397
|
-
status_message.update(
|
|
398
|
-
f"Fetching balances for {account_to_check['name']} ({acct_id})..."
|
|
399
|
-
)
|
|
400
|
-
# Optionally, display a "Fetching..." message in content_area as well
|
|
401
|
-
await content_area.mount(Static("Fetching balances..."))
|
|
402
|
-
|
|
403
|
-
balances_data = self.client.get_account_balances(acct_id)
|
|
404
|
-
await content_area.remove_children() # Clear "Fetching..." message
|
|
405
|
-
|
|
406
|
-
table = Table(
|
|
407
|
-
title=f"Balances for {account_to_check['name']}", expand=True
|
|
408
|
-
)
|
|
409
|
-
table.add_column("Type", overflow="fold")
|
|
410
|
-
table.add_column("Amount")
|
|
411
|
-
table.add_column("Currency")
|
|
412
|
-
if balances_data.balances:
|
|
413
|
-
for b in balances_data.balances:
|
|
414
|
-
table.add_row(
|
|
415
|
-
b.balance_type,
|
|
416
|
-
b.balance_amount.amount,
|
|
417
|
-
b.balance_amount.currency,
|
|
418
|
-
)
|
|
419
336
|
else:
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
await content_area.mount(table) # Mount the results table
|
|
423
|
-
status_message.update(
|
|
424
|
-
f"Balances for {account_to_check['name']} displayed."
|
|
425
|
-
)
|
|
426
|
-
# Consider how the user navigates back to account selection (e.g., a button, or re-selecting the view)
|
|
427
|
-
|
|
337
|
+
self.status_message.update("Invalid account number.")
|
|
428
338
|
except ValueError:
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
status_message.update(
|
|
436
|
-
Text(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
content_area, status_message
|
|
440
|
-
) # Reload selection
|
|
441
|
-
except (
|
|
442
|
-
HttpServiceException
|
|
443
|
-
) as e: # Make sure HttpServiceException is defined
|
|
444
|
-
status_message.update(
|
|
445
|
-
Text(f"API Error fetching balances: {e}", style="bold red")
|
|
446
|
-
)
|
|
447
|
-
await content_area.mount(
|
|
448
|
-
Static(
|
|
449
|
-
Text(
|
|
450
|
-
"Could not retrieve balances due to an API error.",
|
|
451
|
-
style="red",
|
|
452
|
-
)
|
|
339
|
+
self.status_message.update("Please enter a valid number.")
|
|
340
|
+
elif event.button.id == "delete_link_button":
|
|
341
|
+
ref_input = self.query_one("#delete_ref_input", Input)
|
|
342
|
+
reference = ref_input.value.strip()
|
|
343
|
+
if reference:
|
|
344
|
+
self.pending_delete_ref = reference
|
|
345
|
+
self.status_message.update(
|
|
346
|
+
Text(
|
|
347
|
+
f"Are you sure to delete link with reference '{reference}'?",
|
|
348
|
+
style="bold yellow",
|
|
453
349
|
)
|
|
454
350
|
)
|
|
455
|
-
#
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
Static(
|
|
463
|
-
Text(
|
|
464
|
-
"An unexpected error occurred while fetching balances.",
|
|
465
|
-
style="red",
|
|
466
|
-
)
|
|
467
|
-
)
|
|
351
|
+
confirm_btn = self.query_one("#confirm_delete_button", Button)
|
|
352
|
+
cancel_btn = self.query_one("#cancel_delete_button", Button)
|
|
353
|
+
confirm_btn.disabled = False
|
|
354
|
+
cancel_btn.disabled = False
|
|
355
|
+
else:
|
|
356
|
+
self.status_message.update(
|
|
357
|
+
Text("No reference selected.", style="bold yellow")
|
|
468
358
|
)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
id="link_form_area",
|
|
498
|
-
)
|
|
499
|
-
yield Button("Back to Menu", id="back_to_menu", classes="back_button")
|
|
500
|
-
|
|
501
|
-
async def on_mount(self) -> None:
|
|
502
|
-
self.query_one("#bank_id_input", Input).focus()
|
|
503
|
-
|
|
504
|
-
async def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
505
|
-
if event.button.id == "back_to_menu":
|
|
506
|
-
self.post_message(ActionMessage("show_menu"))
|
|
359
|
+
elif event.button.id == "confirm_delete_button":
|
|
360
|
+
if self.pending_delete_ref:
|
|
361
|
+
await self.process_delete_link(self.pending_delete_ref)
|
|
362
|
+
select_input = self.query_one("#select_account_input", Input)
|
|
363
|
+
ref_input = self.query_one("#delete_ref_input", Input)
|
|
364
|
+
select_input.value = ""
|
|
365
|
+
ref_input.value = ""
|
|
366
|
+
delete_btn = self.query_one("#delete_link_button", Button)
|
|
367
|
+
delete_btn.disabled = True
|
|
368
|
+
self.pending_delete_ref = None
|
|
369
|
+
confirm_btn = self.query_one("#confirm_delete_button", Button)
|
|
370
|
+
cancel_btn = self.query_one("#cancel_delete_button", Button)
|
|
371
|
+
confirm_btn.disabled = True
|
|
372
|
+
cancel_btn.disabled = True
|
|
373
|
+
elif event.button.id == "cancel_delete_button":
|
|
374
|
+
self.pending_delete_ref = None
|
|
375
|
+
self.status_message.update("Delete cancelled.")
|
|
376
|
+
confirm_btn = self.query_one("#confirm_delete_button", Button)
|
|
377
|
+
cancel_btn = self.query_one("#cancel_delete_button", Button)
|
|
378
|
+
confirm_btn.disabled = True
|
|
379
|
+
cancel_btn.disabled = True
|
|
380
|
+
elif event.button.id == "cancel_delete_button":
|
|
381
|
+
self.pending_delete_ref = None
|
|
382
|
+
self.status_message.update("Delete cancelled.")
|
|
383
|
+
confirm_btn = self.query_one("#confirm_delete_button", Button)
|
|
384
|
+
cancel_btn = self.query_one("#cancel_delete_button", Button)
|
|
385
|
+
confirm_btn.disabled = True
|
|
386
|
+
cancel_btn.disabled = True
|
|
507
387
|
elif event.button.id == "do_create_link_button":
|
|
508
388
|
await self.process_create_link()
|
|
509
389
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/__init__.py
RENAMED
|
File without changes
|
{beancount_gocardless-0.1.10 → beancount_gocardless-0.1.11}/src/beancount_gocardless/importer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|