Add user-facing asset purchase entry (parallel to expense/income) #20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Libra has user-facing endpoints for expense (out-of-pocket spend that gets consumed) and income (money received on the org's behalf), but no way for a user to record that they bought an asset on the org's behalf — something the org now owns.
Concrete scenario: a member buys a flock of sheep for €2,000 on the org's behalf. Today they'd have to either (a) submit it as an expense (wrong — expenses are P&L; the org still owns €2,000 worth of value, that's a balance-sheet asset, not a consumed cost), or (b) wait for an admin to create the entry directly via
POST /api/v1/entries. Neither is right.Posting shape
The accounting itself is structurally identical to the expense flow, but the debit lands on an asset account instead of an expense account:
The user is out €2,000 (org owes them), and the org's balance sheet has €2,000 of new asset value. Settlement of the resulting payable goes through the existing
POST /api/v1/pay-userflow — no new settlement code needed.Why a distinct entry type rather than overloading expense
Expense vs asset purchase isn't just a labelling difference; the books need to reflect it:
Expenses:*) — value consumed, reduces net income.Assets:*) — value retained, doesn't touch P&L until disposal or depreciation.Letting users pick whether their submission is "expense" or "asset" — instead of training them to know that
Assets:Livestockexists and route there — is the cleanest separation. A submission against anAssets:*account in the expense endpoint should arguably be rejected (related to #15's account-type mismatch).Proposed scaffolding (backend, libra ext)
POST /api/v1/entries/asset— mirrors the expense flow exactly:require_invoice_keyauth.!flag, reuses existing approve/reject endpoints (entry-type-agnostic).AssetEntryrequest model:description,amount(Decimal),asset_account(must resolve to anAccountType.ASSETaccount, excluding user receivables and Lightning/cash operating accounts — see open question 3 below),currency(required),reference?,entry_date?.PermissionType.SUBMIT_ASSETgranted on specific Asset accounts. Don't reuseSUBMIT_EXPENSE; the two operations target distinct account types and should be grantable independently (same reasoning that gave usSUBMIT_INCOME).format_asset_entry()inbeancount_format.py, fiat-first@@ SATSnotation (current convention; pending #18),flag="!", tag#asset-entry, link^ast-{entry_id}for tracking.account_utils.pyso installations have something to point at out of the box (suggestions in open question 4).Proposed scaffolding (frontend)
templates/libra/index.html): a third Quick Action button "Add Asset" next to Add Expense, with a parallel dialog. Account picker filtered toAccountType.ASSETminus operating/receivable accounts.SUBMIT_ASSETrow; the role view should render the matching badge. (This is the same surface that issue #15 also touches — worth bundling.)Open design questions
Assets:*accounts should accept user purchase entries.Assets:Receivable:User-*is a per-user accounting construct, not something a user buys;Assets:Cash/Assets:Bank/Assets:Bitcoin:Lightningare operating cash buckets where "buying" something into them is semantically wrong. The endpoint should accept only "capital asset" accounts — likely modelled as either:is_capital_asset: bool), orAssets:Capital:*orAssets:Inventory:*qualify), orSUBMIT_ASSETonAssets:Livestockis obvious; do we want a parent-account grant (SUBMIT_ASSETonAssets:*) for trusted users?get_user_permissions_with_inheritancealready handles parent-child cascading, so this likely works without code changes.Assets:Inventory(parent)Assets:Inventory:LivestockAssets:Inventory:Supplies(consumables held for resale or use)Assets:Equipment(long-lived tools, furniture)Assets:VehiclesCommunities can extend as needed; we just need credible defaults so the UI isn't empty.
Liabilities:Payable:User-Xentry behaves identically to an expense-derived payable. Existing pay-user / outstanding balances logic should handle it without changes. Confirm with a manual test path before closing.Severity / priority
Medium feature — unblocks legitimate use cases that today either route through the wrong account type or require admin intervention. Conceptually close to the expense flow, so the implementation cost is small (an endpoint + a model + a formatter + UI tile + permission), but the design questions above (especially "which accounts qualify") deserve a decision before code lands.
Related: #15 (permission-type/account-type dropdown filter — would also gain a
SUBMIT_ASSETarm), #18 (unit-of-account convention — affects how cost basis is recorded for the asset).