castle/services.py
padreug 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

64 lines
2.3 KiB
Python

from .crud import (
create_castle_settings,
create_user_wallet_settings,
get_castle_settings,
get_or_create_user_account,
get_user_wallet_settings,
update_castle_settings,
update_user_wallet_settings,
)
from .models import AccountType, CastleSettings, UserWalletSettings
async def get_settings(user_id: str) -> CastleSettings:
settings = await get_castle_settings(user_id)
if not settings:
settings = await create_castle_settings(user_id, CastleSettings())
return settings
async def update_settings(user_id: str, data: CastleSettings) -> CastleSettings:
settings = await get_castle_settings(user_id)
if not settings:
settings = await create_castle_settings(user_id, data)
else:
settings = await update_castle_settings(user_id, data)
return settings
async def get_user_wallet(user_id: str) -> UserWalletSettings:
settings = await get_user_wallet_settings(user_id)
if not settings:
settings = await create_user_wallet_settings(user_id, UserWalletSettings())
return settings
async def update_user_wallet(
user_id: str, data: UserWalletSettings
) -> UserWalletSettings:
from loguru import logger
logger.info(f"[WALLET UPDATE] Starting update_user_wallet for user {user_id[:8]}")
settings = await get_user_wallet_settings(user_id)
if not settings:
logger.info(f"[WALLET UPDATE] Creating new wallet settings for user {user_id[:8]}")
settings = await create_user_wallet_settings(user_id, data)
else:
logger.info(f"[WALLET UPDATE] Updating existing wallet settings for user {user_id[:8]}")
settings = await update_user_wallet_settings(user_id, data)
# Proactively create core user accounts when wallet is configured
# This ensures all users have a consistent account structure from the start
logger.info(f"[WALLET UPDATE] Creating LIABILITY account for user {user_id[:8]}")
await get_or_create_user_account(
user_id, AccountType.LIABILITY, "Accounts Payable"
)
logger.info(f"[WALLET UPDATE] Creating ASSET account for user {user_id[:8]}")
await get_or_create_user_account(
user_id, AccountType.ASSET, "Accounts Receivable"
)
logger.info(f"[WALLET UPDATE] Completed update_user_wallet for user {user_id[:8]}")
return settings