Rename Castle Accounting extension to Libra
Full identifier rename: module path lnbits.extensions.castle →
lnbits.extensions.libra, DB ext_castle → ext_libra, URL prefix
/castle/ → /libra/, manifest id castle → libra, fava ledger slug
default castle-ledger → libra-ledger, Beancount source metadata
castle-api → libra-api and link prefixes castle-{entry,tx}- →
libra-{entry,tx}-, column castle_wallet_id → libra_wallet_id, all
Python/JS/HTML identifiers (castle_ext, CastleSettings,
castle_reference, castleWalletConfigured, etc.).
Display name "Castle Accounting" → "Libra" (the scales/balance
metaphor — fits double-entry bookkeeping).
No backward compat: production hosts will be force-updated. Old
castle-prefixed Beancount metadata in existing Fava ledgers is
historical; new entries use libra-* prefixes going forward.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9c577c740c
commit
c174cda48d
44 changed files with 953 additions and 953 deletions
64
crud.py
64
crud.py
|
|
@ -14,7 +14,7 @@ from .models import (
|
|||
AssertionStatus,
|
||||
AssignUserRole,
|
||||
BalanceAssertion,
|
||||
CastleSettings,
|
||||
LibraSettings,
|
||||
CreateAccount,
|
||||
CreateAccountPermission,
|
||||
CreateBalanceAssertion,
|
||||
|
|
@ -32,7 +32,7 @@ from .models import (
|
|||
StoredUserWalletSettings,
|
||||
UpdateRole,
|
||||
UserBalance,
|
||||
UserCastleSettings,
|
||||
UserLibraSettings,
|
||||
UserEquityStatus,
|
||||
UserRole,
|
||||
UserWalletSettings,
|
||||
|
|
@ -49,7 +49,7 @@ from .core.validation import (
|
|||
validate_payment_entry,
|
||||
)
|
||||
|
||||
db = Database("ext_castle")
|
||||
db = Database("ext_libra")
|
||||
|
||||
# ===== CACHING =====
|
||||
# Cache for account and permission lookups to reduce DB queries
|
||||
|
|
@ -197,7 +197,7 @@ async def get_or_create_user_account(
|
|||
Get or create a user-specific account with hierarchical naming.
|
||||
|
||||
This function checks if the account exists in Fava/Beancount and creates it
|
||||
if it doesn't exist. The account is also registered in Castle's database for
|
||||
if it doesn't exist. The account is also registered in Libra's database for
|
||||
metadata tracking (permissions, descriptions, etc.).
|
||||
|
||||
Examples:
|
||||
|
|
@ -214,7 +214,7 @@ async def get_or_create_user_account(
|
|||
# Generate hierarchical account name
|
||||
account_name = format_hierarchical_account_name(account_type, base_name, user_id)
|
||||
|
||||
# Try to find existing account with this hierarchical name in Castle DB
|
||||
# Try to find existing account with this hierarchical name in Libra DB
|
||||
account = await db.fetchone(
|
||||
"""
|
||||
SELECT * FROM accounts
|
||||
|
|
@ -224,9 +224,9 @@ async def get_or_create_user_account(
|
|||
Account,
|
||||
)
|
||||
|
||||
logger.info(f"[ACCOUNT CHECK] User {user_id[:8]}, Account: {account_name}, In Castle DB: {account is not None}")
|
||||
logger.info(f"[ACCOUNT CHECK] User {user_id[:8]}, Account: {account_name}, In Libra DB: {account is not None}")
|
||||
|
||||
# Always check/create in Fava, even if account exists in Castle DB
|
||||
# Always check/create in Fava, even if account exists in Libra DB
|
||||
# This ensures Beancount has the Open directive
|
||||
fava_account_exists = False
|
||||
if True: # Always check Fava
|
||||
|
|
@ -262,23 +262,23 @@ async def get_or_create_user_account(
|
|||
|
||||
except Exception as e:
|
||||
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
|
||||
# Continue anyway - account creation in Libra DB is still useful for metadata
|
||||
|
||||
# Ensure account exists in Castle DB (sync from Beancount if needed)
|
||||
# Ensure account exists in Libra DB (sync from Beancount if needed)
|
||||
# This uses the account sync module for consistency
|
||||
if not account:
|
||||
logger.info(f"[CASTLE DB] Syncing account from Beancount to Castle DB: {account_name}")
|
||||
logger.info(f"[LIBRA DB] Syncing account from Beancount to Libra DB: {account_name}")
|
||||
from .account_sync import sync_single_account_from_beancount
|
||||
|
||||
# Sync from Beancount to Castle DB
|
||||
# Sync from Beancount to Libra DB
|
||||
created = await sync_single_account_from_beancount(account_name)
|
||||
|
||||
if created:
|
||||
logger.info(f"[CASTLE DB] Account synced from Beancount: {account_name}")
|
||||
logger.info(f"[LIBRA DB] Account synced from Beancount: {account_name}")
|
||||
else:
|
||||
logger.warning(f"[CASTLE DB] Failed to sync account from Beancount: {account_name}")
|
||||
logger.warning(f"[LIBRA DB] Failed to sync account from Beancount: {account_name}")
|
||||
|
||||
# Fetch the account from Castle DB
|
||||
# Fetch the account from Libra DB
|
||||
account = await db.fetchone(
|
||||
"""
|
||||
SELECT * FROM accounts
|
||||
|
|
@ -289,9 +289,9 @@ async def get_or_create_user_account(
|
|||
)
|
||||
|
||||
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}")
|
||||
logger.error(f"[LIBRA DB] Account still not found after sync: {account_name}")
|
||||
# Fallback: create directly in Libra DB if sync failed
|
||||
logger.info(f"[LIBRA DB] Creating account directly in Libra DB: {account_name}")
|
||||
try:
|
||||
account = await create_account(
|
||||
CreateAccount(
|
||||
|
|
@ -304,7 +304,7 @@ async def get_or_create_user_account(
|
|||
except Exception as e:
|
||||
# Handle UNIQUE constraint error - account already exists
|
||||
if "UNIQUE constraint failed" in str(e) and "accounts.name" in str(e):
|
||||
logger.warning(f"[CASTLE DB] Account already exists (UNIQUE constraint), fetching by name: {account_name}")
|
||||
logger.warning(f"[LIBRA DB] Account already exists (UNIQUE constraint), fetching by name: {account_name}")
|
||||
# Fetch existing account by name only (ignore user_id in query)
|
||||
account = await db.fetchone(
|
||||
"""
|
||||
|
|
@ -315,10 +315,10 @@ async def get_or_create_user_account(
|
|||
Account,
|
||||
)
|
||||
if account:
|
||||
logger.info(f"[CASTLE DB] Found existing account: {account_name} (user_id: {account.user_id})")
|
||||
logger.info(f"[LIBRA DB] Found existing account: {account_name} (user_id: {account.user_id})")
|
||||
# Update user_id if it's NULL or different
|
||||
if account.user_id != user_id:
|
||||
logger.info(f"[CASTLE DB] Updating account user_id from {account.user_id} to {user_id}")
|
||||
logger.info(f"[LIBRA DB] Updating account user_id from {account.user_id} to {user_id}")
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE accounts
|
||||
|
|
@ -340,7 +340,7 @@ async def get_or_create_user_account(
|
|||
# Re-raise if it's a different error
|
||||
raise
|
||||
else:
|
||||
logger.info(f"[CASTLE DB] Account already exists in Castle DB: {account_name}")
|
||||
logger.info(f"[LIBRA DB] Account already exists in Libra DB: {account_name}")
|
||||
|
||||
return account
|
||||
|
||||
|
|
@ -351,7 +351,7 @@ async def get_or_create_user_account(
|
|||
# ===== JOURNAL ENTRY OPERATIONS (REMOVED) =====
|
||||
#
|
||||
# All journal entry operations have been moved to Fava/Beancount.
|
||||
# Castle no longer maintains its own journal_entries and entry_lines tables.
|
||||
# Libra no longer maintains its own journal_entries and entry_lines tables.
|
||||
#
|
||||
# For journal entry operations, see:
|
||||
# - views_api.py: api_create_journal_entry() - writes to Fava via FavaClient
|
||||
|
|
@ -375,29 +375,29 @@ async def get_or_create_user_account(
|
|||
# ===== SETTINGS =====
|
||||
|
||||
|
||||
async def create_castle_settings(
|
||||
user_id: str, data: CastleSettings
|
||||
) -> CastleSettings:
|
||||
settings = UserCastleSettings(**data.dict(), id=user_id)
|
||||
async def create_libra_settings(
|
||||
user_id: str, data: LibraSettings
|
||||
) -> LibraSettings:
|
||||
settings = UserLibraSettings(**data.dict(), id=user_id)
|
||||
await db.insert("extension_settings", settings)
|
||||
return settings
|
||||
|
||||
|
||||
async def get_castle_settings(user_id: str) -> Optional[CastleSettings]:
|
||||
async def get_libra_settings(user_id: str) -> Optional[LibraSettings]:
|
||||
return await db.fetchone(
|
||||
"""
|
||||
SELECT * FROM extension_settings
|
||||
WHERE id = :user_id
|
||||
""",
|
||||
{"user_id": user_id},
|
||||
CastleSettings,
|
||||
LibraSettings,
|
||||
)
|
||||
|
||||
|
||||
async def update_castle_settings(
|
||||
user_id: str, data: CastleSettings
|
||||
) -> CastleSettings:
|
||||
settings = UserCastleSettings(**data.dict(), id=user_id)
|
||||
async def update_libra_settings(
|
||||
user_id: str, data: LibraSettings
|
||||
) -> LibraSettings:
|
||||
settings = UserLibraSettings(**data.dict(), id=user_id)
|
||||
await db.update("extension_settings", settings)
|
||||
return settings
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue