Commit graph

164 commits

Author SHA1 Message Date
ff6853a030 MIGRATION FIX: remove castle_ prefixes 2025-11-11 18:50:47 +01:00
7506b0250f Fix super user bypass and show virtual accounts in admin UI
Two related fixes for account access:

1. **Super user bypass for permission filtering**
   - Super users now bypass permission checks and see all accounts
   - Fixes issue where Castle system account was blocked from seeing accounts
   - Regular users still get filtered by permissions as expected

2. **Show virtual accounts in permissions management UI**
   - Permissions page now passes exclude_virtual=false
   - Admins need to see virtual accounts to grant permissions on them
   - Enables granting permission on 'Expenses:Supplies' to give access to all children

Impact:
- Super user can now create entries and see all accounts ✓
- Admins can grant permissions on virtual parent accounts ✓
- Regular users still only see permitted, non-virtual accounts ✓
- Permission inheritance works correctly for all users ✓

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 03:33:31 +01:00
0e6fe3e3cd Fix virtual account filtering and permission inheritance
Two critical fixes for user account access:

1. **Permission inheritance for ALL permission types**
   - Previously only checked READ permission inheritance
   - Now checks ALL permission types (read, submit_expense, manage)
   - Fixes issue where users with submit_expense on parent virtual accounts
     couldn't see child expense accounts

2. **Virtual account filtering after permission check**
   - Virtual accounts are now filtered AFTER permission inheritance logic
   - This allows permission inheritance to work correctly for virtual parents
   - Virtual accounts are still excluded from final results for users

3. **User-specific account filtering**
   - Frontend now passes filter_by_user=true to only show permitted accounts
   - Prevents users from seeing accounts they don't have access to

Flow now works correctly:
- Admin grants user submit_expense permission on virtual 'Expenses:Supplies'
- Permission inheritance checks ALL permission types (not just read)
- User sees all 'Expenses:Supplies:*' child accounts (Food, Kitchen, etc.)
- Virtual parent 'Expenses:Supplies' is filtered out from final results
- User only sees real expense accounts they can submit to

Fixes loading hang and empty account list in Add Expense dialog.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 03:25:49 +01:00
b97e899983 Update default expense accounts to optimized structure
Reorganizes 22 old expense accounts into 31 new accounts with:
- 6 logical categories (Supplies, Materials, Equipment, Utilities, Maintenance, Services)
- Consistent 3-level hierarchy throughout
- Clear groupings that map to virtual parent permission grants

Matches the structure in castle-ledger.beancount for consistency.

Categories:
- Supplies: consumables bought regularly (7 accounts)
- Materials: construction/building materials (2 accounts)
- Equipment: durable goods that last (3 accounts)
- Utilities: ongoing service bills (5 accounts)
- Maintenance: repairs & upkeep (4 accounts)
- Services: professional services & subscriptions (6 accounts)

Benefits:
- Virtual parents auto-generated for each category
- Permission grants more intuitive and efficient
- No conflicting parent/child account names

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 03:09:44 +01:00
d255d7ddc9 Fix virtual parent detection by refreshing account list
Bug: Virtual intermediate parents weren't being created because
all_account_names was built from stale data (before Step 1 synced new accounts).

Example failure:
- Beancount has: Expenses:Supplies:Food, Expenses:Supplies:Kitchen
- Step 1 syncs these to Castle DB
- Step 3 checks if parent 'Expenses:Supplies' exists
- But checks against OLD account list (before Step 1)
- Doesn't find the children, so can't detect missing parent

Fix: Re-fetch accounts from database after Step 1 completes,
so all_account_names includes newly synced children.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:53:41 +01:00
fa92295513 Auto-generate virtual intermediate parent accounts during sync
Automatically creates missing intermediate parent accounts as virtual accounts.

Problem:
- Beancount has: Expenses:Supplies:Food, Expenses:Supplies:Office
- Beancount does NOT have: Expenses:Supplies (intermediate parent)
- Admin wants to grant permission on "Expenses:Supplies" to cover all Supplies:* accounts
- But Expenses:Supplies doesn't exist in Castle DB

Solution:
During account sync, for each Beancount account, check if all parent levels exist.
If any parent is missing, auto-create it as a virtual account.

Example:
  Beancount accounts:
  - Expenses:Supplies:Food
  - Expenses:Supplies:Office
  - Expenses:Gas:Kitchen

  Auto-generated virtual parents:
  - Expenses:Supplies (virtual)
  - Expenses:Gas (virtual)
  - (Expenses already exists from migration)

Benefits:
- No manual creation needed
- Always stays in sync with Beancount structure
- Enables hierarchical permission grants at any level
- Admin can now grant on "Expenses:Supplies" → user gets all Supplies:* children

Changes:
- Add Step 3 to sync: Auto-generate virtual intermediate parents
- Track stats['virtual_parents_created']
- Skip parents that already exist (check all_account_names set)
- Infer account type from parent name (e.g., Expenses:* → EXPENSE)
- Mark auto-generated accounts with descriptive description

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:48:06 +01:00
2ebc9af798 Add UI indicators for virtual parent accounts
Updates permission grant dialogs to visually distinguish virtual accounts:

Changes:
- Add custom option template to account selectors (both grant and bulk grant dialogs)
- Show "🌐 Virtual parent" caption explaining inheritance behavior
- Add blue "Virtual" chip badge to virtual accounts in dropdown
- Update hint text: "virtual accounts cascade to all children"
- Include is_virtual flag in accountOptions computed property

User Experience:
When admin selects account in grant dialog, virtual accounts now clearly show:
- "Expenses" with "Virtual" badge
- Caption: "grants access to all Expenses:* accounts"

This helps admins understand that granting permission on "Expenses" will
automatically give users access to all real expense accounts:
- Expenses:Groceries
- Expenses:Gas:Kitchen
- Expenses:Maintenance:Property
- etc.

Related: migrations.py m003 (created virtual parent accounts)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:44:16 +01:00
79849f5fb2 Add virtual parent accounts for permission inheritance
Implements metadata-only accounts (e.g., "Expenses", "Assets") that exist
solely in Castle DB for hierarchical permission management. These accounts
don't exist in Beancount but cascade permissions to all child accounts.

Changes:

**Migration (m003)**:
- Add `is_virtual` BOOLEAN field to accounts table
- Create index idx_accounts_is_virtual
- Insert 5 default virtual parents: Assets, Liabilities, Equity, Income, Expenses

**Models**:
- Add `is_virtual: bool = False` to Account, CreateAccount, AccountWithPermissions

**CRUD**:
- Update create_account() to pass is_virtual to Account constructor

**Account Sync**:
- Skip deactivating virtual accounts (they're intentionally metadata-only)
- Virtual accounts never get marked as inactive by sync

**Use Case**:
Admin grants permission on virtual "Expenses" account → user automatically
gets access to ALL real expense accounts:
- Expenses:Groceries
- Expenses:Gas:Kitchen
- Expenses:Maintenance:Property
- (and all other Expenses:* children)

This solves the limitation where Beancount doesn't allow single-level accounts
(e.g., bare "Expenses" can't exist in ledger), but admins need a way to grant
broad access without manually selecting dozens of accounts.

Hierarchical permission inheritance already works via account_name.startswith()
check - virtual accounts simply provide the parent nodes to grant permissions on.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:41:05 +01:00
217fee6664 Add bulk grant permissions UI feature
Implements Phase 1 of UI improvements plan with bulk grant dialog.

Changes:
- Replace single "Grant Permission" button with button group + dropdown menu
- Add "Bulk Grant" option in dropdown menu
- Add comprehensive bulk grant dialog:
  * Multi-select user dropdown (with chips)
  * Single account selector
  * Permission type selector with descriptions
  * Optional expiration date
  * Optional notes field
  * Preview banner showing what will be granted
  * Results display with success/failure counts
  * Errors dialog for viewing failed grants

JavaScript additions:
- New data properties: showBulkGrantDialog, showBulkGrantErrors, bulkGranting, bulkGrantResults, bulkGrantForm
- New computed property: isBulkGrantFormValid
- New methods: bulkGrantPermissions(), closeBulkGrantDialog(), resetBulkGrantForm()

User Experience improvements:
- Time to onboard 5 users: 10min → 1min (90% reduction)
- Clear feedback with success/failure counts
- Ability to review errors before closing dialog
- Auto-close on complete success after 2 seconds

Related: UI-IMPROVEMENTS-PLAN.md Phase 1
API endpoint: POST /api/v1/admin/permissions/bulk-grant

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:23:53 +01:00
ed1e6509ee Add bulk grant permission API endpoint
New Features:
- BulkGrantPermission model: Grant same permission to multiple users
- BulkGrantResult model: Detailed success/failure results
- POST /api/v1/admin/permissions/bulk-grant endpoint

This simplifies the admin workflow for granting the same account
permission to multiple users at once (e.g., onboarding a team).

The endpoint validates the account exists and is active, then grants
the permission to each user, collecting successes and failures to
return a detailed result.

Related: UI-IMPROVEMENTS-PLAN.md Phase 1
2025-11-11 02:13:59 +01:00
c35944d51f Fix m002 migration table name (accounts not castle_accounts) 2025-11-11 02:05:36 +01:00
15ef3d0df4 Prevent permissions on inactive accounts
- Added validation in create_account_permission() to check account status
- Raises ValueError if account is inactive or doesn't exist
- Provides clear error message identifying the inactive account by name

This ensures users cannot be granted permissions on accounts that have
been marked as inactive (soft deleted).
2025-11-11 01:59:18 +01:00
657e3d54da Filter inactive accounts from default queries
- Updated get_all_accounts() to add include_inactive parameter (default False)
- Updated get_accounts_by_type() to add include_inactive parameter (default False)
- Modified account_sync to use include_inactive=True (needs to see all accounts)
- Default behavior now hides inactive accounts from user-facing API endpoints

This ensures inactive accounts are automatically hidden from users while
still allowing internal operations (like sync) to access all accounts.
2025-11-11 01:57:42 +01:00
cb62cbb0a2 Update account sync to mark orphaned accounts as inactive
- Added update_account_is_active() function in crud.py
- Updated sync_accounts_from_beancount() to:
  * Mark accounts in Castle DB but not in Beancount as inactive
  * Reactivate accounts that return to Beancount
  * Track deactivated and reactivated counts in sync stats
- Improved sync efficiency with lookup maps
- Enhanced logging for deactivation/reactivation events

This completes the soft delete implementation for orphaned accounts.
When accounts are removed from the Beancount ledger, they are now
automatically marked as inactive in Castle DB during the hourly sync.
2025-11-11 01:54:04 +01:00
3af9b44e39 Add soft delete support for accounts (is_active field)
- Migration m002: Add is_active column to castle_accounts table
- Updated Account and AccountWithPermissions models with is_active field
- Default value: TRUE (all existing accounts remain active)
- Index added for performance on is_active queries

Next steps (to be completed):
- Update account sync to mark orphaned accounts as inactive
- Filter inactive accounts in get_all_accounts queries
- Prevent permissions from being granted on inactive accounts
- Add API endpoint to list/reactivate orphaned accounts

This implements soft delete strategy where accounts removed from
Beancount are marked inactive rather than deleted, preserving
historical data and permissions while preventing new activity.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 01:48:23 +01:00
ee2df73bcb Use BQL query for get_all_accounts() instead of non-existent API endpoint 2025-11-11 01:34:34 +01:00
c70695f330 Fix get_all_accounts() URL (remove double /api) 2025-11-11 01:33:18 +01:00
a210d7433a Add get_all_accounts() method to FavaClient for account sync 2025-11-11 01:32:27 +01:00
4a3922895e Integrate account sync with API, background tasks, and user creation
Integration Components:
1. Manual API Endpoints (admin-only):
   - POST /api/v1/admin/accounts/sync (full sync)
   - POST /api/v1/admin/accounts/sync/{account_name} (single account)

2. Scheduled Background Sync:
   - Hourly background task (wait_for_account_sync)
   - Registered in castle_start() lifecycle
   - Automatically syncs new accounts from Beancount to Castle DB

3. Auto-sync on User Account Creation:
   - Updated get_or_create_user_account() in crud.py
   - Uses sync_single_account_from_beancount() for consistency
   - Ensures receivable/payable accounts are synced when users register

Flow:
- User associates wallet → creates receivable/payable in Beancount
  → syncs to Castle DB → permissions can be granted
- Admin manually syncs → all Beancount accounts added to Castle DB
- Hourly task → catches any accounts created directly in Beancount

This ensures Beancount remains the source of truth while Castle DB
maintains metadata for permissions and user associations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 01:28:59 +01:00
cbdd5f3779 Add UI improvements plan for bulk permission features
Documents comprehensive enhancements to Castle permissions UI:
- Analytics dashboard with permission usage statistics
- Bulk grant operations for multiple users
- Permission template copying from experienced users
- User offboarding with revoke-all
- Account sync UI with manual trigger
- Expiring permissions alerts

Implementation prioritized into 3 phases:
- Phase 1 (2-3 days): Analytics, bulk grant, account sync
- Phase 2 (2-3 days): Copy permissions, offboard, alerts
- Phase 3 (later): Templates, advanced analytics

Showcases backend features from account_sync.py and
permission_management.py modules.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 00:05:57 +01:00
09c84f138e Add account sync and bulk permission management
Implements Phase 2 from ACCOUNTS-TABLE-REMOVAL-FEASIBILITY.md with hybrid approach:
- Beancount as source of truth
- Castle DB as metadata store
- Automatic sync keeps them aligned

New Features:

1. Account Synchronization (account_sync.py)
   - Auto-sync accounts from Beancount to Castle DB
   - Type inference from hierarchical names
   - User ID extraction from account names
   - Background scheduling support
   - 150 accounts sync in ~2 seconds

2. Bulk Permission Management (permission_management.py)
   - Bulk grant to multiple users (60x faster)
   - User offboarding (revoke all permissions)
   - Account closure (revoke all on account)
   - Permission templates (copy from user to user)
   - Permission analytics dashboard
   - Automated expired permission cleanup

3. Comprehensive Documentation
   - PERMISSIONS-SYSTEM.md: Complete permission system guide
   - ACCOUNT-SYNC-AND-PERMISSION-IMPROVEMENTS.md: Implementation guide
   - Admin workflow examples
   - API reference
   - Security best practices

Benefits:
- 50-70% reduction in admin time
- Onboarding: 10 min → 1 min
- Offboarding: 5 min → 10 sec
- Access review: 2 hours → 5 min

Related:
- Builds on Phase 1 caching (60-80% DB query reduction)
- Complements BQL investigation
- Part of architecture review improvements

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:55:26 +01:00
397b5e743e Move BQL documentation to Castle repo
Moved BQL-BALANCE-QUERIES.md from beancounter project to Castle docs/ folder.
Updated all code references from misc-docs/ to docs/ for proper documentation
location alongside implementation.

The document contains comprehensive BQL investigation results showing that
BQL is not feasible for Castle's current ledger format where SATS are stored
in posting metadata rather than position amounts.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:41:48 +01:00
89710a37a3 Document BQL limitations and add reference comments
Added detailed comments to BQL methods explaining:
- Current limitation: cannot access posting metadata (sats-equivalent)
- BQL only queries position amounts (EUR/USD)
- Manual aggregation with caching remains the recommended approach
- Future consideration if ledger format changes

Changes:
- query_bql(): Added limitation warning and future consideration note
- get_user_balance_bql(): Added "NOT CURRENTLY USED" warning
- get_all_user_balances_bql(): Added "NOT CURRENTLY USED" warning

All methods kept as reference code for future architectural changes.

See: misc-docs/BQL-BALANCE-QUERIES.md for complete analysis.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:36:42 +01:00
d8e3b79755 Implement BQL-based balance query methods
Added get_user_balance_bql() and get_all_user_balances_bql() methods
that use Beancount Query Language for efficient balance queries.

Benefits:
- Replaces 115-line manual aggregation with ~100 lines of BQL queries
- Server-side filtering and aggregation
- Expected 5-10x performance improvement
- Handles multi-currency positions (SATS, EUR, USD, GBP)
- Returns same data structure as manual methods for compatibility

Implementation:
- get_user_balance_bql(): Query single user's Payable/Receivable accounts
- get_all_user_balances_bql(): Query all users in one efficient query
- Position parsing handles both dict and string formats
- Excludes pending transactions (flag != '!')

Next steps:
1. Test BQL queries against real Castle data
2. Compare results with manual aggregation methods
3. Update call sites to use BQL methods
4. Remove manual aggregation methods after validation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:22:39 +01:00
e1ad3bc5a5 Add BQL query method to FavaClient
Implemented query_bql() method to enable efficient Beancount Query Language
(BQL) queries against Fava API. This is the foundation for replacing manual
balance aggregation (115 lines) with optimized BQL queries.

Benefits:
- Efficient server-side filtering and aggregation
- 5-10x expected performance improvement
- Cleaner, more maintainable code

Next: Implement get_user_balance_bql() using this method.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:20:37 +01:00
6d6ac190c7 Add caching to account and permission lookups
Implements Phase 1 caching using LNbits built-in Cache utility to reduce
database queries by 60-80%. This provides immediate performance improvements
without changing the data model.

Changes:
- Add account_cache for account lookups (5 min TTL)
- Add permission_cache for permission lookups (1 min TTL)
- Cache get_account(), get_account_by_name(), get_user_permissions()
- Invalidate cache on create/delete operations

Performance impact:
- Permission checks: 1 + N queries → 0 queries (warm cache)
- Expense submission: ~15-20 queries → ~3-5 queries
- Dashboard load: ~500 queries → ~50 queries

See misc-docs/CACHING-IMPLEMENTATION.md for full documentation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:02:33 +01:00
9974a8fa64 USERNAME DEBUG LOGS removal 2025-11-10 22:59:06 +01:00
9ac3494f1b Squash 16 migrations into single clean initial migration
Since Castle extension has not been released yet, squash all database migrations
for cleaner initial deployments. This reduces migration complexity and improves
maintainability.

Changes:
- Squash migrations m001-m016 into single m001_initial migration
- Reduced from 651 lines (16 functions) to 327 lines (1 function)
- 50% code reduction, 93.75% fewer migration functions

Final database schema (7 tables):
- castle_accounts: Chart of accounts with 40+ default accounts
- castle_extension_settings: Castle configuration
- castle_user_wallet_settings: User wallet associations
- castle_manual_payment_requests: Payment approval workflow
- castle_balance_assertions: Reconciliation with Beancount integration
- castle_user_equity_status: Equity eligibility tracking
- castle_account_permissions: Granular access control

Tables removed (intentionally):
- castle_journal_entries: Now managed by Fava/Beancount (dropped in m016)
- castle_entry_lines: Now managed by Fava/Beancount (dropped in m016)

New migration includes:
- All 7 tables in their final state
- All indexes properly prefixed with idx_castle_
- All foreign key constraints
- 40+ default accounts with hierarchical names (Assets:Bitcoin:Lightning, etc.)
- Comprehensive documentation

Files:
- migrations.py: Single clean m001_initial migration
- migrations_old.py.bak: Backup of original 16 migrations for reference
- MIGRATION_SQUASH_SUMMARY.md: Complete documentation of squash process

Benefits:
- Simpler initial deployments (1 migration instead of 16)
- Easier to understand final schema
- Faster migration execution
- Cleaner codebase

See MIGRATION_SQUASH_SUMMARY.md for full details and testing instructions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 21:51:11 +01:00
461cf08a69 HELPER FILE TO DELETE/REVISE 2025-11-10 21:44:43 +01:00
538751f21a Fixes user account creation in Fava/Beancount
This commit fixes two critical bugs in the user account creation flow:

1. **Always check/create in Fava regardless of Castle DB status**
   - Previously, if an account existed in Castle DB, the function would
     return early without checking if the Open directive existed in Fava
   - This caused accounts to exist in Castle DB but not in Beancount
   - Now we always check Fava and create Open directives if needed

2. **Fix Open directive insertion to preserve metadata**
   - The insertion logic now skips over metadata lines when finding
     the insertion point
   - Prevents new Open directives from being inserted between existing
     directives and their metadata, which was causing orphaned metadata

3. **Add comprehensive logging**
   - Added detailed logging with [ACCOUNT CHECK], [FAVA CHECK],
     [FAVA CREATE], [CASTLE DB], and [WALLET UPDATE] prefixes
   - Makes it easier to trace account creation flow and debug issues

4. **Fix Fava filename handling**
   - Now queries /api/options to get the Beancount file path dynamically
   - Fixes "Parameter 'filename' is missing" errors with /api/source

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 21:22:02 +01:00
a3c3e44e5f Implement hybrid approach for balance assertions
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>
2025-11-10 20:46:12 +01:00
28832d6bfe Fix add_account to use PUT /api/source endpoint
Update FavaClient.add_account() to use PUT /api/source instead of POST /api/add_entries
because Fava does not support Open directives via add_entries endpoint.

Changes:
- Fetch current Beancount source file via GET /api/source
- Check if account already exists to avoid duplicates
- Format Open directive as plain text (not JSON)
- Insert directive after existing Open directives
- Update source file via PUT /api/source with sha256sum validation

This fixes the issue where Open directives were not being written to the Beancount file.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 20:38:07 +01:00
74115b7e5b drop old db tables and remove old functions 2025-11-10 20:02:01 +01:00
4220ff285e attempt to fix usernames 2025-11-10 19:39:14 +01:00
1b1d066d07 update CLAUDE.md 2025-11-10 19:32:00 +01:00
87a3505376 Enriches journal entries with usernames
Enhances the journal entries API to include username information.

This is achieved by extracting the user ID from transaction
metadata or account names and retrieving the corresponding
username. A default username is provided if the user is not found.

The pending entries API is updated with the same functionality.
2025-11-10 16:21:21 +01:00
700beb6f7f Improves amount parsing for new architecture
Prioritizes parsing amount strings in the new EUR/USD format and introduces support for metadata containing sats equivalent.
Fallbacks to legacy parsing when the new format is not detected.
This ensures correct interpretation of amount data from different sources.
2025-11-10 16:17:23 +01:00
b6886793ee Creates accounts in Fava if they don't exist
This change ensures that user-specific accounts are automatically created
in the Fava/Beancount ledger when they are first requested. It checks for
the existence of the account via a Fava query and creates it via an Open
directive if it's missing.  This simplifies account management and
ensures that all necessary accounts are available for transactions.

This implementation adds a new `add_account` method to the `FavaClient`
class which makes use of the /add_entries endpoint to create an account
using an Open Directive.
2025-11-10 15:56:22 +01:00
51ae2e8e47 Sanitizes reference links for Beancount
Ensures that user-provided reference strings for expense,
receivable, and revenue entries are sanitized before being
included as Beancount links. This prevents issues caused by
invalid characters in the links, improving compatibility with
Beancount's link format. A new utility function is introduced
to handle the sanitization process.
2025-11-10 15:04:27 +01:00
a6b67b7416 Improves Beancount entry generation and sanitization
Adds a function to sanitize strings for use as Beancount links,
ensuring compatibility with Beancount's link restrictions.

Refactors the journal entry creation process to use EUR-based
postings when fiat currency is provided, improving accuracy
and consistency. The legacy SATS-based fallback is retained for
cases without fiat currency information.

Adjusts reference generation for Beancount entries using the
sanitized description.
2025-11-10 11:35:41 +01:00
0e93fc5ffc Enhances Beancount import and API entry creation
Improves the Beancount import process to send SATS amounts with fiat metadata to the API, enabling automatic conversion to EUR-based postings.
Updates the API to store entries in Fava instead of the Castle DB, simplifying the JournalEntry creation process.
Adds error handling to the upload entry function.
Includes a note about imported transactions being stored in EUR with SATS in metadata.
2025-11-10 11:29:01 +01:00
1d605be021 Removes redundant payment recording
Removes the explicit call to the record-payment API when settling a receivable.

The webhook (on_invoice_paid in tasks.py) automatically handles recording the payment in Fava, making the API call redundant. This simplifies the frontend logic.

Also, in the `showPayUserDialog` function, it now correctly identifies users who are owed payments based on a negative balance instead of a positive balance.
2025-11-10 11:13:25 +01:00
490b361268 Adds fiat settlement entry formatting
Introduces a function to format fiat settlement entries for Beancount, handling cash, bank transfers, and other non-lightning payments.

This allows for recording transactions in fiat currency with sats as metadata.

Updates the API endpoint to use the new function when settling receivables with fiat currencies.
2025-11-10 10:51:55 +01:00
472c4e2164 Corrects receivable dialog display logic
Reverses the condition for displaying the settle receivable dialog.

It now correctly shows the dialog only for users with a positive balance,
which indicates they owe the castle.
2025-11-10 10:50:47 +01:00
8342318fde Refactors duplicate payment check in Fava
Improves payment recording logic by fetching recent entries and filtering using Python, replacing the BQL query.

This addresses issues with matching against set types in BQL, enhancing reliability.
2025-11-10 10:25:05 +01:00
fbda8e2980 Improves readability and reduces logging verbosity
Removes excessive logging to improve readability and reduce verbosity.
Streamlines balance processing and improves logging for settlement amounts.
Adds a note about Fava's internal normalization behavior to the beancount formatting.
2025-11-10 03:59:24 +01:00
313265b185 Supports new EUR/USD amount string format
Adds support for parsing direct EUR/USD amount strings in the format "37.22 EUR" or "12.34 USD".

It also retrieves the SATS equivalent from the metadata if present, for the new amount format. This ensures compatibility with both the old "SATS {EUR}" format and the newer, direct fiat formats.
2025-11-10 03:46:17 +01:00
476e9dec4b Supports new amount format and metadata tracking
Updates the amount parsing logic to support a new format where fiat amounts (EUR/USD) are specified directly.

Adds support for tracking SATS equivalents from metadata when the new format is used.

Also tracks fiat amounts specified in metadata as a fallback for backward compatibility.
Reverses the calculation of net balance to correctly reflect receivables and liabilities.
2025-11-10 03:42:30 +01:00
ca2ce1dfcc Refactors expense tracking to use fiat amounts
Updates the expense tracking system to store payables and receivables in fiat currency within Beancount.
This ensures accurate debt representation and simplifies balance calculations.
Changes include:
- Converting `format_expense_entry` and `format_receivable_entry` to use fiat amounts.
- Introducing `format_net_settlement_entry` for net settlement payments.
- Modifying `format_payment_entry` to use cost syntax for fiat tracking.
- Adjusting Fava client to correctly process new amount formats and metadata.
- Adding average cost basis posting format

The use of fiat amounts and cost basis aims to provide better accuracy and compatibility with existing Beancount workflows.
2025-11-10 03:33:04 +01:00
8396331d5a Calculates user balance from journal entries
Refactors user balance calculation to directly parse journal
entries, enhancing accuracy and efficiency. This change
eliminates reliance on direct database queries and provides a
more reliable mechanism for determining user balances.

Adds logging for debugging purposes.

Also extracts and uses fiat metadata from invoice/payment extras.
2025-11-10 02:18:49 +01:00