Enables manual settlement with fiat currencies

Adds support for settling receivables with fiat currencies
like EUR and USD, in addition to sats.

Updates the settlement dialog to handle fiat amounts and
exchange rates, defaulting to cash payment when a fiat balance
exists.

Modifies the API to accept currency and amount_sats parameters
and adjust the journal entry accordingly, converting the fiat amount
to minor units (e.g., cents) for accounting purposes.
This commit is contained in:
padreug 2025-10-23 04:19:26 +02:00
parent 49f21da55a
commit 70013d1c29
4 changed files with 120 additions and 20 deletions

View file

@ -826,6 +826,26 @@ async def api_settle_receivable(
# DR Cash/Bank (asset increased), CR Accounts Receivable (asset decreased)
# This records that user paid their debt
# Convert amount to sats (minor units)
# For fiat currencies, store as cents/minor units
# For satoshis, just convert to int
from decimal import Decimal
if data.currency:
# Fiat currency payment (e.g., EUR, USD)
amount_minor_units = int(data.amount * 100) # Convert to cents
line_metadata = {
"fiat_currency": data.currency,
"fiat_amount": str(data.amount),
}
if data.amount_sats:
line_metadata["sats_equivalent"] = data.amount_sats
line_metadata["exchange_rate"] = data.amount_sats / float(data.amount)
else:
# Satoshi payment
amount_minor_units = int(data.amount)
line_metadata = {}
# Add meta information for audit trail
entry_meta = {
"source": "manual_settlement",
@ -833,6 +853,8 @@ async def api_settle_receivable(
"settled_by": wallet.wallet.user,
"payer_user_id": data.user_id,
}
if data.currency:
entry_meta["currency"] = data.currency
entry_data = CreateJournalEntry(
description=data.description,
@ -842,15 +864,17 @@ async def api_settle_receivable(
lines=[
CreateEntryLine(
account_id=payment_account.id,
debit=data.amount,
debit=amount_minor_units,
credit=0,
description=f"Payment received via {data.payment_method}",
metadata=line_metadata,
),
CreateEntryLine(
account_id=user_receivable.id,
debit=0,
credit=data.amount,
credit=amount_minor_units,
description="Receivable settled",
metadata=line_metadata,
),
],
)
@ -863,7 +887,8 @@ async def api_settle_receivable(
return {
"journal_entry_id": entry.id,
"user_id": data.user_id,
"amount_settled": data.amount,
"amount_settled": float(data.amount),
"currency": data.currency,
"payment_method": data.payment_method,
"new_balance": balance.balance,
"message": f"Receivable settled successfully via {data.payment_method}",