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>
This commit is contained in:
padreug 2025-11-10 21:22:02 +01:00
parent a3c3e44e5f
commit 538751f21a
3 changed files with 45 additions and 13 deletions

View file

@ -724,12 +724,22 @@ class FavaClient:
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
# Step 1: Get current source file
response = await client.get(f"{self.base_url}/source")
# Step 1: Get the main Beancount file path from Fava
options_response = await client.get(f"{self.base_url}/options")
options_response.raise_for_status()
options_data = options_response.json()["data"]
file_path = options_data["beancount_options"]["filename"]
logger.debug(f"Fava main file: {file_path}")
# Step 2: Get current source file
response = await client.get(
f"{self.base_url}/source",
params={"filename": file_path}
)
response.raise_for_status()
source_data = response.json()["data"]
file_path = source_data["file_path"]
sha256sum = source_data["sha256sum"]
source = source_data["source"]
@ -738,12 +748,16 @@ class FavaClient:
logger.info(f"Account {account_name} already exists in Beancount file")
return {"data": sha256sum, "mtime": source_data.get("mtime", "")}
# Step 3: Find insertion point (after last Open directive)
# Step 3: Find insertion point (after last Open directive AND its metadata)
lines = source.split('\n')
insert_index = 0
for i, line in enumerate(lines):
if line.strip().startswith(('open ', f'{opening_date.year}-')) and 'open' in line:
# Found an Open directive, now skip over any metadata lines
insert_index = i + 1
# Skip metadata lines (lines starting with whitespace)
while insert_index < len(lines) and lines[insert_index].startswith((' ', '\t')) and lines[insert_index].strip():
insert_index += 1
# Step 4: Format Open directive as Beancount text
currencies_str = ", ".join(currencies)