add_account: always append at end of file

The original "find last Open directive, insert after its metadata" logic
was a clever optimisation for the monolithic ledger where opens, txns,
and assertions all lived in one file -- you wanted new opens grouped with
existing opens, not appended after a long transaction tail.

Post-split, each include file has one mutation profile:
  - accounts/chart.beancount: only Open directives
  - accounts/users.beancount: only Open directives
  - transactions.beancount:   only Transactions

There is no longer a content shape that benefits from mid-file insertion;
the existing heuristic also had a pre-existing bug where it only matched
'open ' OR '{current_year}-' as line prefixes, so 1970-* seed opens were
invisible and the search "stuck" to the first current-year line in the
file (which on aio-demo ended up being the wrong place).

Drop the search; always append. Simpler, chronological, append-only
friendly.

Refs: aiolabs/libra#28
This commit is contained in:
Padreug 2026-06-06 19:39:55 +02:00
commit 9e7795b541

View file

@ -1626,21 +1626,15 @@ class FavaClient:
logger.info(f"Account {account_name} already exists in {target_file}") logger.info(f"Account {account_name} already exists in {target_file}")
return {"data": sha256sum, "mtime": source_data.get("mtime", "")} return {"data": sha256sum, "mtime": source_data.get("mtime", "")}
# Step 3: Find insertion point (after last Open directive AND its metadata). # Step 3: Always append at end of file.
# If the file has no Open directives yet (e.g. the empty # Post-split layout, each include file has one mutation
# accounts/users.beancount seed), append at end of file # profile (only Open directives in chart/users, only
# so the seed header comments stay at the top. # Transactions in transactions.beancount), so there's no
# reason to slot new entries mid-file. Append-only also
# keeps the seed header comments at the top and makes
# the file's evolution trivially readable.
lines = source.split('\n') lines = source.split('\n')
insert_index = None insert_index = len(lines)
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
if insert_index is None:
insert_index = len(lines)
# Step 4: Format Open directive as Beancount text # Step 4: Format Open directive as Beancount text
currencies_str = ", ".join(currencies) currencies_str = ", ".join(currencies)