Refactors user entry retrieval from Fava
Switches to retrieving all journal entries from Fava and filtering in the application to allow filtering by account type and user. This provides more flexibility and control over the data being presented to the user. Also extracts and includes relevant metadata such as entry ID, fiat amounts, and references for improved frontend display.
This commit is contained in:
parent
7f545ea88e
commit
63d851ce94
1 changed files with 121 additions and 28 deletions
151
views_api.py
151
views_api.py
|
|
@ -315,38 +315,131 @@ async def api_get_user_entries(
|
|||
# Regular user can only see their own entries
|
||||
target_user_id = wallet.wallet.user
|
||||
|
||||
# Query Fava for transactions
|
||||
if target_user_id:
|
||||
# Build account pattern based on account_type filter
|
||||
if filter_account_type:
|
||||
# Filter by account type (asset = receivable, liability = payable)
|
||||
if filter_account_type.lower() == "asset":
|
||||
account_pattern = f"Receivable:User-{target_user_id[:8]}"
|
||||
elif filter_account_type.lower() == "liability":
|
||||
account_pattern = f"Payable:User-{target_user_id[:8]}"
|
||||
else:
|
||||
account_pattern = f"User-{target_user_id[:8]}"
|
||||
else:
|
||||
# All user accounts
|
||||
account_pattern = f"User-{target_user_id[:8]}"
|
||||
# Get all journal entries from Fava (full transaction objects)
|
||||
all_entries = await fava.get_journal_entries()
|
||||
|
||||
entries = await fava.query_transactions(
|
||||
account_pattern=account_pattern,
|
||||
limit=limit + offset # Fava doesn't support offset, so fetch more and slice
|
||||
)
|
||||
# Apply offset
|
||||
entries = entries[offset:offset + limit]
|
||||
total = len(entries) # Note: This is approximate since we don't know the true total
|
||||
else:
|
||||
# Super user viewing all entries
|
||||
entries = await fava.query_transactions(limit=limit + offset)
|
||||
entries = entries[offset:offset + limit]
|
||||
total = len(entries)
|
||||
# Filter and transform entries
|
||||
filtered_entries = []
|
||||
for e in all_entries:
|
||||
if e.get("t") != "Transaction":
|
||||
continue
|
||||
|
||||
# Skip voided transactions
|
||||
if "voided" in e.get("tags", []):
|
||||
continue
|
||||
|
||||
# Extract user ID from metadata or account names
|
||||
user_id_match = None
|
||||
entry_meta = e.get("meta", {})
|
||||
if "user-id" in entry_meta:
|
||||
user_id_match = entry_meta["user-id"]
|
||||
else:
|
||||
# Try to extract from account names in postings
|
||||
for posting in e.get("postings", []):
|
||||
account = posting.get("account", "")
|
||||
if "User-" in account:
|
||||
# Extract user ID from account name (e.g., "Liabilities:Payable:User-abc123")
|
||||
parts = account.split("User-")
|
||||
if len(parts) > 1:
|
||||
user_id_match = parts[1] # Just the short ID after User-
|
||||
break
|
||||
|
||||
# Filter by target user if specified
|
||||
if target_user_id and user_id_match:
|
||||
if not user_id_match.startswith(target_user_id[:8]):
|
||||
continue
|
||||
|
||||
# Filter by account type if specified
|
||||
if filter_account_type and user_id_match:
|
||||
postings = e.get("postings", [])
|
||||
has_matching_account = False
|
||||
for posting in postings:
|
||||
account = posting.get("account", "")
|
||||
if filter_account_type.lower() == "asset" and "Receivable" in account:
|
||||
has_matching_account = True
|
||||
break
|
||||
elif filter_account_type.lower() == "liability" and "Payable" in account:
|
||||
has_matching_account = True
|
||||
break
|
||||
if not has_matching_account:
|
||||
continue
|
||||
|
||||
# Extract data for frontend
|
||||
# Extract entry ID from links
|
||||
entry_id = None
|
||||
links = e.get("links", [])
|
||||
if isinstance(links, (list, set)):
|
||||
for link in links:
|
||||
if isinstance(link, str):
|
||||
link_clean = link.lstrip('^')
|
||||
if "castle-" in link_clean:
|
||||
parts = link_clean.split("castle-")
|
||||
if len(parts) > 1:
|
||||
entry_id = parts[-1]
|
||||
break
|
||||
|
||||
# Extract amount from postings
|
||||
amount_sats = 0
|
||||
fiat_amount = None
|
||||
fiat_currency = None
|
||||
|
||||
postings = e.get("postings", [])
|
||||
if postings:
|
||||
first_posting = postings[0]
|
||||
if isinstance(first_posting, dict):
|
||||
amount_field = first_posting.get("amount")
|
||||
if isinstance(amount_field, dict):
|
||||
amount_sats = abs(int(float(amount_field.get("number", 0))))
|
||||
|
||||
cost = first_posting.get("cost")
|
||||
if isinstance(cost, dict):
|
||||
fiat_amount = float(cost.get("number", 0))
|
||||
fiat_currency = cost.get("currency")
|
||||
|
||||
# Extract reference from links (first non-castle link)
|
||||
reference = None
|
||||
if isinstance(links, (list, set)):
|
||||
for link in links:
|
||||
if isinstance(link, str):
|
||||
link_clean = link.lstrip('^')
|
||||
if not link_clean.startswith("castle-") and not link_clean.startswith("ln-"):
|
||||
reference = link_clean
|
||||
break
|
||||
|
||||
# Get username from user ID (first 8 chars for display)
|
||||
username = f"User-{user_id_match[:8]}" if user_id_match else None
|
||||
|
||||
entry_data = {
|
||||
"id": entry_id or e.get("entry_hash", "unknown"),
|
||||
"date": e.get("date", ""),
|
||||
"entry_date": e.get("date", ""),
|
||||
"flag": e.get("flag"),
|
||||
"description": e.get("narration", ""),
|
||||
"payee": e.get("payee"),
|
||||
"tags": e.get("tags", []),
|
||||
"links": links,
|
||||
"amount": amount_sats,
|
||||
"user_id": user_id_match,
|
||||
"username": username,
|
||||
"reference": reference,
|
||||
"meta": entry_meta, # Include metadata for frontend
|
||||
}
|
||||
|
||||
if fiat_amount and fiat_currency:
|
||||
entry_data["fiat_amount"] = fiat_amount
|
||||
entry_data["fiat_currency"] = fiat_currency
|
||||
|
||||
filtered_entries.append(entry_data)
|
||||
|
||||
# Sort by date descending
|
||||
filtered_entries.sort(key=lambda x: x.get("date", ""), reverse=True)
|
||||
|
||||
# Apply pagination
|
||||
total = len(filtered_entries)
|
||||
paginated_entries = filtered_entries[offset:offset + limit]
|
||||
|
||||
# Fava transactions already contain the data we need
|
||||
# Metadata includes user-id, account information, etc.
|
||||
return {
|
||||
"entries": entries,
|
||||
"entries": paginated_entries,
|
||||
"total": total,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue