Record income receipts as a user receivable, not an entity asset
When a user submits income, the money is physically in *their* pocket,
not the entity's cash drawer. The original income endpoint posted DR
on a configurable payment-method asset account (Cash/Bank/Lightning),
which implicitly assumed the entity already had the funds.
Mirror the expense flow instead: DR Assets:Receivable:User-{id[:8]}
(via get_or_create_user_account), CR the revenue account. The user
now owes the entity until they hand the cash over via the existing
/settle-receivable workflow. With this, the per-user Outstanding
Balances card correctly nets expenses (entity owes user, -liability)
against income receipts (user owes entity, +receivable).
Drops payment_method_account from IncomeEntry — no longer needed.
This commit is contained in:
parent
61952d0015
commit
0f2a38ee7f
3 changed files with 21 additions and 23 deletions
27
views_api.py
27
views_api.py
|
|
@ -1235,21 +1235,6 @@ async def api_create_income_entry(
|
|||
detail=f"Account '{revenue_account.name}' is not a revenue account (type: {revenue_account.account_type.value})",
|
||||
)
|
||||
|
||||
# Resolve payment method account by name or ID
|
||||
payment_account = await get_account_by_name(data.payment_method_account)
|
||||
if not payment_account:
|
||||
payment_account = await get_account(data.payment_method_account)
|
||||
if not payment_account:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.NOT_FOUND,
|
||||
detail=f"Payment account '{data.payment_method_account}' not found",
|
||||
)
|
||||
if payment_account.account_type != AccountType.ASSET:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.BAD_REQUEST,
|
||||
detail=f"Account '{payment_account.name}' is not an asset account (type: {payment_account.account_type.value})",
|
||||
)
|
||||
|
||||
# Permission check on the revenue account
|
||||
from .crud import get_user_permissions_with_inheritance
|
||||
|
||||
|
|
@ -1262,6 +1247,12 @@ async def api_create_income_entry(
|
|||
detail=f"You do not have permission to submit income to account '{revenue_account.name}'. Please contact an administrator to request access.",
|
||||
)
|
||||
|
||||
# Income lands on the user as a receivable — they're holding cash on
|
||||
# behalf of the entity until they hand it over via /settle-receivable.
|
||||
user_account = await get_or_create_user_account(
|
||||
wallet.wallet.user, AccountType.ASSET, "Accounts Receivable"
|
||||
)
|
||||
|
||||
# Convert fiat to sats
|
||||
fiat_currency = data.currency.upper()
|
||||
amount_sats = await fiat_amount_as_satoshis(float(data.amount), data.currency)
|
||||
|
|
@ -1288,7 +1279,7 @@ async def api_create_income_entry(
|
|||
|
||||
entry = format_income_entry(
|
||||
user_id=wallet.wallet.user,
|
||||
payment_account=payment_account.name,
|
||||
user_account=user_account.name,
|
||||
revenue_account=revenue_account.name,
|
||||
amount_sats=amount_sats,
|
||||
description=data.description,
|
||||
|
|
@ -1323,9 +1314,9 @@ async def api_create_income_entry(
|
|||
EntryLine(
|
||||
id=f"line-1-{entry_id}",
|
||||
journal_entry_id=entry_id,
|
||||
account_id=payment_account.id,
|
||||
account_id=user_account.id,
|
||||
amount=amount_sats,
|
||||
description=f"Income received into {payment_account.name}",
|
||||
description=f"User holds cash receivable to entity ({user_account.name})",
|
||||
metadata=metadata,
|
||||
),
|
||||
EntryLine(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue