feat(api): add currency extraction and account name updates

- Extract currency from balances and populate account currency field
- Add PUT /api/v1/accounts/{account_id} endpoint for updating account names
- Add AccountUpdate Pydantic model for request validation
- Modify sync service to enrich account details with balance currency

This resolves the issue where account currency and name fields were NULL
by extracting currency from GoCardless balance data and providing an API
endpoint for manual account name updates.
This commit is contained in:
Elisiário Couto
2025-09-10 21:48:07 +01:00
parent 61fafecb78
commit d9c50d1298
3 changed files with 75 additions and 9 deletions

View File

@@ -33,6 +33,15 @@ class AccountDetails(BaseModel):
json_encoders = {datetime: lambda v: v.isoformat() if v else None}
class AccountUpdate(BaseModel):
"""Account update model"""
name: Optional[str] = None
class Config:
json_encoders = {datetime: lambda v: v.isoformat() if v else None}
class Transaction(BaseModel):
"""Transaction model"""

View File

@@ -8,6 +8,7 @@ from leggend.api.models.accounts import (
AccountBalance,
Transaction,
TransactionSummary,
AccountUpdate,
)
from leggend.services.database_service import DatabaseService
@@ -287,3 +288,40 @@ async def get_account_transactions(
raise HTTPException(
status_code=404, detail=f"Failed to get transactions: {str(e)}"
) from e
@router.put("/accounts/{account_id}", response_model=APIResponse)
async def update_account_details(
account_id: str, update_data: AccountUpdate
) -> APIResponse:
"""Update account details (currently only name)"""
try:
# Get current account details
current_account = await database_service.get_account_details_from_db(account_id)
if not current_account:
raise HTTPException(
status_code=404, detail=f"Account {account_id} not found"
)
# Prepare updated account data
updated_account_data = current_account.copy()
if update_data.name is not None:
updated_account_data["name"] = update_data.name
# Persist updated account details
await database_service.persist_account_details(updated_account_data)
return APIResponse(
success=True,
data={"id": account_id, "name": update_data.name},
message=f"Account {account_id} name updated successfully",
)
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to update account {account_id}: {e}")
raise HTTPException(
status_code=500, detail=f"Failed to update account: {str(e)}"
) from e

View File

@@ -55,26 +55,45 @@ class SyncService:
account_id
)
# Persist account details to database
if account_details:
await self.database.persist_account_details(account_details)
# Get and save balances
# Get balances to extract currency information
balances = await self.gocardless.get_account_balances(account_id)
if balances and account_details:
# Enrich account details with currency and persist
if account_details and balances:
enriched_account_details = account_details.copy()
# Extract currency from first balance
balances_list = balances.get("balances", [])
if balances_list:
first_balance = balances_list[0]
balance_amount = first_balance.get("balanceAmount", {})
currency = balance_amount.get("currency")
if currency:
enriched_account_details["currency"] = currency
# Persist enriched account details to database
await self.database.persist_account_details(
enriched_account_details
)
# Merge account details into balances data for proper persistence
balances_with_account_info = balances.copy()
balances_with_account_info["institution_id"] = (
account_details.get("institution_id")
enriched_account_details.get("institution_id")
)
balances_with_account_info["iban"] = (
enriched_account_details.get("iban")
)
balances_with_account_info["iban"] = account_details.get("iban")
balances_with_account_info["account_status"] = (
account_details.get("status")
enriched_account_details.get("status")
)
await self.database.persist_balance(
account_id, balances_with_account_info
)
balances_updated += len(balances.get("balances", []))
elif account_details:
# Fallback: persist account details without currency if balances failed
await self.database.persist_account_details(account_details)
# Get and save transactions
transactions = await self.gocardless.get_account_transactions(