Balance assertions now use a hybrid architecture where Beancount is the source
of truth for validation, while Castle stores metadata for UI convenience.
Backend changes:
- Add format_balance() function to beancount_format.py for formatting balance directives
- Update POST /api/v1/assertions to write balance directive to Beancount first (via Fava)
- Store metadata in Castle DB (created_by, tolerance, notes) for UI features
- Validate assertions immediately by querying Fava for actual balance
Frontend changes:
- Update dialog description to explain Beancount validation
- Update button tooltip to clarify balance assertions are written to Beancount
- Update empty state message to mention Beancount checkpoints
Benefits:
- Single source of truth (Beancount ledger file)
- Automatic validation by Beancount
- Best of both worlds: robust validation + friendly UI
See misc-docs/BALANCE-ASSERTIONS-HYBRID-APPROACH.md for full documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes the displayed balance perspective to reflect the castle's point of view instead of the user's.
This involves:
- Displaying balances as positive when the user owes the castle
- Displaying balances as negative when the castle owes the user.
This change affects how balances are calculated and displayed in both the backend logic and the frontend templates.
Improvements to equity account handling across the Castle extension:
Transaction Categorization (views_api.py):
- Prioritize equity accounts when enriching transaction entries
- Use two-pass lookup: first search for equity accounts, then fall back to liability/asset accounts
- Ensures transactions with Equity:User-<id> accounts are correctly categorized as equity
UI Enhancements (index.html, index.js):
- Add 'Equity' filter option to Recent Transactions table
- Display blue "Equity" badge for equity entries (before receivable/payable badges)
- Add isEquity() helper function to identify equity account entries
Beancount Import (import_beancount.py):
- Support importing Beancount Equity:<name> accounts
- Map Beancount "Equity:Pat" to Castle "Equity:User-<id>" accounts
- Update extract_user_from_user_account() to handle Equity: prefix
- Improve error messages to include equity account examples
- Add equity account lookup in get_account_id() with helpful error if equity not enabled
These changes ensure equity accounts (representing user capital contributions) are properly distinguished from payables and receivables throughout the system.
Add account type filtering to Recent Transactions table and fix pagination issue where filters were applied after fetching results, causing incomplete data display.
Database layer (crud.py):
- Add get_journal_entries_by_user_and_account_type() to filter entries by
both user_id and account_type at SQL query level
- Add count_journal_entries_by_user_and_account_type() for accurate counts
- Filters apply before pagination, ensuring all matching records are fetched
API layer (views_api.py):
- Add filter_account_type parameter ('asset' for receivable, 'liability' for payable)
- Refactor filtering logic to use new database-level filter functions
- Support filter combinations: user only, account_type only, user+account_type, or all
- Enrich entries with account_type metadata for UI display
Frontend (index.js):
- Add account_type to transactionFilter state
- Add accountTypeOptions computed property with receivable/payable choices
- Reorder table columns to show User before Date
- Update loadTransactions to send account_type filter parameter
- Update clearTransactionFilter to clear both user and account_type filters
UI (index.html):
- Add second filter dropdown for account type (Receivable/Payable)
- Show clear button when either filter is active
- Update button label from "Clear Filter" to "Clear Filters"
This fixes the critical bug where filtering for receivables would only show a subset of results (e.g., 2 out of 20 entries fetched) instead of all matching receivables. Now filters are applied at the database level before pagination, ensuring users see all relevant transactions.
Convert the Recent Transactions card from a list view to a paginated table
with enhanced filtering capabilities for super users.
Frontend changes:
- Replace q-list with q-table for better data presentation
- Add pagination with configurable page size (default: 20 items)
- Add transaction filter dropdown for super users to filter by username
- Define table columns: Status, Date, Description, User, Amount, Fiat, Reference
- Implement prev/next page navigation with page info display
- Add filter controls with clear filter button
Backend changes (views_api.py):
- Add pagination support with limit/offset parameters
- Add filter_user_id parameter for filtering by user (super user only)
- Enrich transaction entries with user_id and username from account lookups
- Return paginated response with total count and pagination metadata
Database changes (crud.py):
- Update get_all_journal_entries() to support offset parameter
- Update get_journal_entries_by_user() to support offset parameter
- Add count_all_journal_entries() for total count
- Add count_journal_entries_by_user() for user-specific count
This improves the Recent Transactions UX by providing better organization, easier navigation through large transaction lists, and the ability for admins to filter transactions by user.
Implements pagination for the transaction history, enabling users
to navigate through their transactions in manageable chunks. This
improves performance and user experience, especially for users
with a large number of transactions. It also introduces total entry counts.
Allows superusers to grant and revoke equity eligibility for users.
Adds UI components for managing equity eligibility.
Equity-eligible users can then contribute expenses as equity.
Replaces the user ID input field with a user selection dropdown,
allowing administrators to search and select users for permission
management. This simplifies the process of assigning permissions
and improves user experience.
Fetches Castle users via a new API endpoint and filters them
based on search input. Only users with Castle accounts
(receivables, payables, equity, or permissions) are listed.
Expands the default chart of accounts with a more
detailed hierarchical structure. This includes new
accounts for fixed assets, livestock, equity
contributions, and detailed expense categories.
The migration script only adds accounts that don't
already exist, ensuring a smooth update process.
Implements an admin permissions management page.
This change allows superusers to manage permissions directly from the castle interface, providing a more streamlined experience for administrative tasks.
Implements a Vue-based UI for managing user permissions, allowing administrators to grant and revoke access to expense accounts.
Provides views for managing permissions by user and by account, along with dialogs for granting and revoking permissions.
Integrates with the LNbits API to load accounts and permissions and to persist changes.
Uses usernames instead of user IDs in the audit log and
approval request listings to improve readability. If a user
is not found, it displays a truncated version of the user ID.
Adds a date field to expense entries for better tracking and reporting.
This allows users to specify the date of the expense transaction,
providing more accurate financial records.
Implements the ability for the super user (Castle) to pay other users for expenses or liabilities.
Introduces a new `PayUser` model to represent these payments, along with API endpoints to process and record them.
Integrates a "Pay User" button into the user list, allowing the super user to initiate payments through either lightning or manual methods (cash, bank transfer, check).
Adds UI elements and logic for handling both lightning payments (generating invoices and paying them) and manual payment recording.
This functionality allows Castle to manage and settle debts with its users directly through the application.
Enhances the receivable settlement dialog by providing a default description based on the selected payment method, improving clarity for users.
Filters the user balance display to only show users with outstanding balances, making the interface cleaner and more focused for super users.
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.
Replaces the generic QR code generation with the lnbits-qrcode component.
This simplifies the code and utilizes a component specifically designed for LNbits applications.
Removes the input field for the invoice string as it is no longer necessary.
Implements the ability for users to settle their outstanding balance
using a Lightning Network invoice.
Generates an invoice on the Castle wallet and polls for payment,
automatically recording the transaction once payment is detected.
The UI is updated to display the invoice and handle the payment process.
Implements a "Settle Receivable" feature for super users to record manual payments from users who owe money.
Introduces a dialog for inputting payment details (amount, method, description, reference), triggers an API call to record the transaction, and updates user balances and transaction history.
This is for non-lightning payments like cash, bank transfers, or checks.
Moves the "Quick Actions" card to the top of the dashboard for better user accessibility and discoverability.
Removes the duplicate card at the bottom.
Implements balance assertions, reconciliation API endpoints, a reconciliation UI dashboard, and automated daily balance checks.
This provides comprehensive reconciliation tools to ensure accounting accuracy and catch discrepancies early.
Updates roadmap to mark Phase 2 as complete.
Improves balance assertion creation by handling Decimal types correctly for database insertion.
It also fixes a validation issue in the UI where the expected balance was not correctly validated as a required field and initializes the value to 0.
Adds balance assertion functionality to enable admins to verify accounting accuracy.
This includes:
- A new `balance_assertions` table in the database
- CRUD operations for balance assertions (create, get, list, check, delete)
- API endpoints for managing balance assertions (admin only)
- UI elements for creating, viewing, and re-checking assertions
Also, reorders the implementation roadmap in the documentation to reflect better the dependencies between phases.
Implements expense approval functionality, allowing superusers to review and approve or reject expense entries.
This includes:
- Filtering account balance calculations and user balance calculations to only include cleared journal entries.
- Adding API endpoints to retrieve pending expense entries and approve/reject them.
- Updating the UI to display pending expenses to superusers and provide actions to approve or reject them.
This ensures better control over expenses within the system.
Marks Phase 1 as complete in the documentation.
Updates the transaction list in the UI to display transaction status flags and metadata, enhancing user understanding of each transaction.
Improves clarity by displaying "Payable" or "Receivable" badges on entries
in the transaction list.
The badge color depends on whether the user is a superuser, indicating
the direction of the transaction from the user's perspective.
This helps users quickly understand which transactions are owed to them
and which they owe.
Improves the display of user balances in the admin panel by including the username alongside the user ID. This provides a more user-friendly and easily identifiable representation of user data.
The username is fetched from the user table, and if no username is set the first 16 characters of the user id is shown.
Enables users to request manual payments from the Castle and provides admin functions to approve or reject these requests.
Introduces the `manual_payment_requests` table and related CRUD operations.
Adds API endpoints for creating, retrieving, approving, and rejecting manual payment requests.
Updates the UI to allow users to request payments and for admins to review pending requests.
Improves user experience by visually indicating entries that represent outstanding payments owed by users.
This change introduces a "Pending Payment" badge for receivable entries in the transaction list. A receivable entry is determined by checking if the entry contains a debit line item against an account receivable account. This provides immediate visual feedback to the user, highlighting transactions requiring their action.
Updates journal entry retrieval to filter entries based on
the user's accounts rather than the user ID.
This ensures that users only see journal entries that
directly affect their accounts.
Also displays fiat amount in journal entries if available in
the metadata.
Extends user balance information to include fiat currency balances,
calculated based on entry line metadata and account types.
This allows for a more comprehensive view of user balances,
including both satoshi and fiat currency holdings.
Updates the castle index template and API to display fiat balances.
Implements a feature that allows users to pay their outstanding balance via Lightning.
The changes include:
- Adds the UI elements for invoice generation and display, including QR code.
- Integrates backend endpoints to generate and record payments.
- Adds polling mechanism to track payments and update balance.
- Creates new database models to support manual payment requests.
Implements the ability to record receivables (user owes the castle).
Adds API endpoint for creating receivable entries, which includes currency conversion to satoshis if fiat currency is provided.
Integrates a UI component (receivable dialog) for superusers to record debts owed by users, enhancing financial tracking capabilities.
Implements functionality for super users to view a breakdown of outstanding balances for all users.
This includes:
- Adding an API endpoint to fetch all user balances.
- Updating the frontend to display these balances in a table, accessible only to super users.
- Modifying the balance calculation for the current user to reflect the total owed by or to the castle for super users.
This provides super users with a comprehensive view of the castle's financial position.
Simplifies the user experience for super users by automatically using the Castle wallet for transactions, removing the need to configure a separate user wallet.
This change streamlines the workflow for super users by:
- Automatically assigning the Castle wallet to super users
- Hiding the user wallet configuration options in the UI
- Reloading user wallet settings to reflect the Castle wallet
Updates the castle wallet ID input to a select field populated with available wallet options.
This change improves usability by providing a predefined list of wallet options.
It also disables the save button if no wallet is selected.
Allows users to configure their own wallet ID, enabling
the system to track expenses and receivables on a per-user basis.
Introduces new database table, models, API endpoints, and UI elements
to manage user-specific wallet settings.
Adds super user role to restrict settings changes.
Improves the settings screen to only allow super users to make modifications.
Adds a warning banner if the Castle wallet is not configured.
Changes admin key to inkey for fetching settings.
This fixes an issue where settings weren't accessible.
Adds a validation to require the Castle wallet ID when updating settings.
Adds functionality to configure the Castle extension, including a wallet ID.
This allows administrators to customize the extension's behavior by specifying a dedicated wallet for castle operations.
Extends expense entry functionality to support fiat currencies.
Users can now specify a currency (e.g., EUR, USD) when creating expense entries. The specified amount is converted to satoshis using exchange rates. The converted amount and currency information are stored in the journal entry metadata. Also adds an API endpoint to retrieve allowed currencies and updates the UI to allow currency selection when creating expense entries.
Improves the UI of the "Add Expense" and "Pay Balance" dialogs by using `q-input` and `q-select` components with `filled` and `dense` properties.
This provides a cleaner and more modern look and feel.
Ensures dialog content is only rendered when the dialog is visible.