Supports new amount format and metadata tracking
Updates the amount parsing logic to support a new format where fiat amounts (EUR/USD) are specified directly. Adds support for tracking SATS equivalents from metadata when the new format is used. Also tracks fiat amounts specified in metadata as a fallback for backward compatibility. Reverses the calculation of net balance to correctly reflect receivables and liabilities.
This commit is contained in:
parent
ca2ce1dfcc
commit
476e9dec4b
2 changed files with 48 additions and 29 deletions
|
|
@ -354,39 +354,57 @@ class FavaClient:
|
||||||
"accounts": []
|
"accounts": []
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse amount string: "36791 SATS {33.33 EUR, 2025-11-09}"
|
# Parse amount string: can be EUR/USD directly (new format) or "SATS {EUR}" (old format)
|
||||||
amount_str = posting.get("amount", "")
|
amount_str = posting.get("amount", "")
|
||||||
if not isinstance(amount_str, str) or not amount_str:
|
if not isinstance(amount_str, str) or not amount_str:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
import re
|
import re
|
||||||
# Extract SATS amount (with sign)
|
# Try to extract EUR/USD amount first (new format)
|
||||||
|
fiat_match = re.match(r'^(-?[\d.]+)\s+([A-Z]{3})$', amount_str)
|
||||||
|
if fiat_match and fiat_match.group(2) in ('EUR', 'USD', 'GBP'):
|
||||||
|
# Direct EUR/USD amount (new approach)
|
||||||
|
fiat_amount = Decimal(fiat_match.group(1))
|
||||||
|
fiat_currency = fiat_match.group(2)
|
||||||
|
|
||||||
|
if fiat_currency not in user_data[user_id]["fiat_balances"]:
|
||||||
|
user_data[user_id]["fiat_balances"][fiat_currency] = Decimal(0)
|
||||||
|
|
||||||
|
user_data[user_id]["fiat_balances"][fiat_currency] += fiat_amount
|
||||||
|
|
||||||
|
# Also track SATS equivalent from metadata if available
|
||||||
|
posting_meta = posting.get("meta", {})
|
||||||
|
sats_equiv = posting_meta.get("sats-equivalent")
|
||||||
|
if sats_equiv:
|
||||||
|
sats_amount = int(sats_equiv) if fiat_amount > 0 else -int(sats_equiv)
|
||||||
|
user_data[user_id]["balance"] += sats_amount
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Old format: SATS with cost/price notation
|
||||||
sats_match = re.match(r'^(-?\d+)\s+SATS', amount_str)
|
sats_match = re.match(r'^(-?\d+)\s+SATS', amount_str)
|
||||||
if sats_match:
|
if sats_match:
|
||||||
sats_amount = int(sats_match.group(1))
|
sats_amount = int(sats_match.group(1))
|
||||||
|
|
||||||
# For admin/castle view, use Beancount amounts as-is:
|
|
||||||
# Receivable (asset): positive in Beancount = user owes castle (positive)
|
|
||||||
# Payable (liability): negative in Beancount = castle owes user (negative)
|
|
||||||
user_data[user_id]["balance"] += sats_amount
|
user_data[user_id]["balance"] += sats_amount
|
||||||
|
|
||||||
# Extract fiat from cost syntax: {33.33 EUR, ...}
|
# Extract fiat from cost syntax or metadata (backward compatibility)
|
||||||
cost_match = re.search(r'\{([\d.]+)\s+([A-Z]+)', amount_str)
|
posting_meta = posting.get("meta", {})
|
||||||
if cost_match:
|
fiat_amount_total_str = posting_meta.get("fiat-amount-total")
|
||||||
fiat_amount_unsigned = Decimal(cost_match.group(1))
|
fiat_currency_meta = posting_meta.get("fiat-currency")
|
||||||
fiat_currency = cost_match.group(2)
|
|
||||||
|
if fiat_amount_total_str and fiat_currency_meta:
|
||||||
|
fiat_total = Decimal(fiat_amount_total_str)
|
||||||
|
fiat_currency = fiat_currency_meta
|
||||||
|
|
||||||
if fiat_currency not in user_data[user_id]["fiat_balances"]:
|
if fiat_currency not in user_data[user_id]["fiat_balances"]:
|
||||||
user_data[user_id]["fiat_balances"][fiat_currency] = Decimal(0)
|
user_data[user_id]["fiat_balances"][fiat_currency] = Decimal(0)
|
||||||
|
|
||||||
# Apply the same sign as the SATS amount
|
# Apply the same sign as the SATS amount
|
||||||
# If SATS is negative, fiat should be negative too
|
|
||||||
if sats_match:
|
if sats_match:
|
||||||
sats_amount_for_sign = int(sats_match.group(1))
|
sats_amount_for_sign = int(sats_match.group(1))
|
||||||
if sats_amount_for_sign < 0:
|
if sats_amount_for_sign < 0:
|
||||||
fiat_amount_unsigned = -fiat_amount_unsigned
|
fiat_total = -fiat_total
|
||||||
|
|
||||||
user_data[user_id]["fiat_balances"][fiat_currency] += fiat_amount_unsigned
|
user_data[user_id]["fiat_balances"][fiat_currency] += fiat_total
|
||||||
|
|
||||||
return list(user_data.values())
|
return list(user_data.values())
|
||||||
|
|
||||||
|
|
|
||||||
13
views_api.py
13
views_api.py
|
|
@ -1104,12 +1104,13 @@ async def api_get_my_balance(
|
||||||
all_balances = await fava.get_all_user_balances()
|
all_balances = await fava.get_all_user_balances()
|
||||||
|
|
||||||
# Calculate total:
|
# Calculate total:
|
||||||
# Positive balances = Castle owes users (liabilities)
|
# From get_user_balance(): positive = user owes castle, negative = castle owes user
|
||||||
# Negative balances = Users owe Castle (receivables)
|
# Positive balances = Users owe Castle (receivables for Castle)
|
||||||
# Net: positive means castle owes, negative means castle is owed
|
# Negative balances = Castle owes users (liabilities for Castle)
|
||||||
total_liabilities = sum(b["balance"] for b in all_balances if b["balance"] > 0)
|
# Net: positive means castle is owed money, negative means castle owes money
|
||||||
total_receivables = sum(abs(b["balance"]) for b in all_balances if b["balance"] < 0)
|
total_receivables = sum(b["balance"] for b in all_balances if b["balance"] > 0)
|
||||||
net_balance = total_liabilities - total_receivables
|
total_liabilities = sum(abs(b["balance"]) for b in all_balances if b["balance"] < 0)
|
||||||
|
net_balance = total_receivables - total_liabilities
|
||||||
|
|
||||||
# Aggregate fiat balances from all users
|
# Aggregate fiat balances from all users
|
||||||
total_fiat_balances = {}
|
total_fiat_balances = {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue