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>
This commit is contained in:
parent
cbdd5f3779
commit
4a3922895e
4 changed files with 173 additions and 10 deletions
44
crud.py
44
crud.py
|
|
@ -209,18 +209,42 @@ async def get_or_create_user_account(
|
|||
logger.error(f"[FAVA ERROR] Could not check/create account in Fava: {e}", exc_info=True)
|
||||
# Continue anyway - account creation in Castle DB is still useful for metadata
|
||||
|
||||
# Create account in Castle DB for metadata tracking (only if it doesn't exist)
|
||||
# Ensure account exists in Castle DB (sync from Beancount if needed)
|
||||
# This uses the account sync module for consistency
|
||||
if not account:
|
||||
logger.info(f"[CASTLE DB] Creating account in Castle DB: {account_name}")
|
||||
account = await create_account(
|
||||
CreateAccount(
|
||||
name=account_name,
|
||||
account_type=account_type,
|
||||
description=f"User-specific {account_type.value} account",
|
||||
user_id=user_id,
|
||||
)
|
||||
logger.info(f"[CASTLE DB] Syncing account from Beancount to Castle DB: {account_name}")
|
||||
from .account_sync import sync_single_account_from_beancount
|
||||
|
||||
# Sync from Beancount to Castle DB
|
||||
created = await sync_single_account_from_beancount(account_name)
|
||||
|
||||
if created:
|
||||
logger.info(f"[CASTLE DB] Account synced from Beancount: {account_name}")
|
||||
else:
|
||||
logger.warning(f"[CASTLE DB] Failed to sync account from Beancount: {account_name}")
|
||||
|
||||
# Fetch the account from Castle DB
|
||||
account = await db.fetchone(
|
||||
"""
|
||||
SELECT * FROM accounts
|
||||
WHERE user_id = :user_id AND account_type = :type AND name = :name
|
||||
""",
|
||||
{"user_id": user_id, "type": account_type.value, "name": account_name},
|
||||
Account,
|
||||
)
|
||||
logger.info(f"[CASTLE DB] Created account in Castle DB: {account_name}")
|
||||
|
||||
if not account:
|
||||
logger.error(f"[CASTLE DB] Account still not found after sync: {account_name}")
|
||||
# Fallback: create directly in Castle DB if sync failed
|
||||
logger.info(f"[CASTLE DB] Creating account directly in Castle DB: {account_name}")
|
||||
account = await create_account(
|
||||
CreateAccount(
|
||||
name=account_name,
|
||||
account_type=account_type,
|
||||
description=f"User-specific {account_type.value} account",
|
||||
user_id=user_id,
|
||||
)
|
||||
)
|
||||
else:
|
||||
logger.info(f"[CASTLE DB] Account already exists in Castle DB: {account_name}")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue