Add settlement links to payment entries for traceability

- Add settled_entry_links parameter to format_payment_entry and format_net_settlement_entry
- Query unsettled expenses/receivables before creating settlement entries
- Pass original entry links to format functions so settlements reference what they settle
- Update all callers in views_api.py (5 locations) and tasks.py (1 location)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-01-02 19:34:25 +01:00
parent da74e668c8
commit e403ec223d
3 changed files with 59 additions and 9 deletions

View file

@ -1704,6 +1704,10 @@ async def api_record_payment(
status_code=HTTPStatus.NOT_FOUND, detail="Lightning account not found"
)
# Get unsettled receivable entries to link to this settlement
unsettled = await fava.get_unsettled_entries_bql(target_user_id, "receivable")
settled_links = [e["link"] for e in unsettled if e.get("link")]
# Format payment entry and submit to Fava
entry = format_payment_entry(
user_id=target_user_id,
@ -1716,7 +1720,8 @@ async def api_record_payment(
fiat_currency=fiat_currency,
fiat_amount=fiat_amount,
payment_hash=data.payment_hash,
reference=data.payment_hash
reference=data.payment_hash,
settled_entry_links=settled_links
)
logger.info(f"Formatted payment entry: {entry}")
@ -1764,6 +1769,10 @@ async def api_pay_user(
fava = get_fava_client()
# Get unsettled expense entries to link to this settlement
unsettled = await fava.get_unsettled_entries_bql(user_id, "expense")
settled_links = [e["link"] for e in unsettled if e.get("link")]
entry = format_payment_entry(
user_id=user_id,
payment_account=lightning_account.name,
@ -1772,7 +1781,8 @@ async def api_pay_user(
description=f"Payment to user {user_id[:8]}",
entry_date=datetime.now().date(),
is_payable=True, # Castle paying user
reference=f"PAY-{user_id[:8]}"
reference=f"PAY-{user_id[:8]}",
settled_entry_links=settled_links
)
# Submit to Fava
@ -1897,6 +1907,12 @@ async def api_settle_receivable(
fiat_currency = data.currency.upper() if data.currency else None
fiat_amount = Decimal(str(data.amount)) if data.currency else None
# Get settled entry links (use provided or auto-query unsettled)
settled_links = data.settled_entry_links
if not settled_links:
unsettled = await fava.get_unsettled_entries_bql(data.user_id, "receivable")
settled_links = [e["link"] for e in unsettled if e.get("link")]
entry = format_payment_entry(
user_id=data.user_id,
payment_account=payment_account.name,
@ -1908,7 +1924,8 @@ async def api_settle_receivable(
fiat_currency=fiat_currency,
fiat_amount=fiat_amount,
payment_hash=data.payment_hash,
reference=data.reference or f"MANUAL-{data.user_id[:8]}"
reference=data.reference or f"MANUAL-{data.user_id[:8]}",
settled_entry_links=settled_links
)
# Add additional metadata to entry
@ -2051,6 +2068,12 @@ async def api_pay_user(
fiat_currency = None
fiat_amount = None
# Get settled entry links (use provided or auto-query unsettled)
settled_links = data.settled_entry_links
if not settled_links:
unsettled = await fava.get_unsettled_entries_bql(data.user_id, "expense")
settled_links = [e["link"] for e in unsettled if e.get("link")]
entry = format_payment_entry(
user_id=data.user_id,
payment_account=payment_account.name,
@ -2062,7 +2085,8 @@ async def api_pay_user(
fiat_currency=fiat_currency,
fiat_amount=fiat_amount,
payment_hash=data.payment_hash,
reference=data.reference or f"PAY-{data.user_id[:8]}"
reference=data.reference or f"PAY-{data.user_id[:8]}",
settled_entry_links=settled_links
)
# Add additional metadata to entry
@ -2550,6 +2574,10 @@ async def api_approve_manual_payment_request(
fava = get_fava_client()
# Get unsettled expense entries to link to this settlement
unsettled = await fava.get_unsettled_entries_bql(request.user_id, "expense")
settled_links = [e["link"] for e in unsettled if e.get("link")]
entry = format_payment_entry(
user_id=request.user_id,
payment_account=lightning_account.name,
@ -2558,7 +2586,8 @@ async def api_approve_manual_payment_request(
description=f"Manual payment to user: {request.description}",
entry_date=datetime.now().date(),
is_payable=True, # Castle paying user
reference=f"MPR-{request.id}"
reference=f"MPR-{request.id}",
settled_entry_links=settled_links
)
# Submit to Fava