fix(accounts): 409 when admin-adding an account that already exists
add_account no-ops if the Open directive is already present but returned
a normal-looking dict, so the admin endpoint reported success ('created
(sync pending)') for a duplicate. Return an already_existed flag and
raise 409 from the endpoint. Also anchor the existence check on the Open
directive with a trailing-boundary match so a prefix (Expenses:Gas)
doesn't match a longer sibling (Expenses:GasStation). The flag is
additive, so the idempotent user-account path keeps no-opping silently.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7456574f65
commit
caef3cf5e8
2 changed files with 23 additions and 5 deletions
|
|
@ -1643,10 +1643,22 @@ class FavaClient:
|
||||||
sha256sum = source_data["sha256sum"]
|
sha256sum = source_data["sha256sum"]
|
||||||
source = source_data["source"]
|
source = source_data["source"]
|
||||||
|
|
||||||
# Step 2: Check if account already exists (may have been created by concurrent request)
|
# Step 2: Check if account already exists (may have been
|
||||||
if f"open {account_name}" in source:
|
# created by a concurrent request). Anchor on the Open
|
||||||
|
# directive and require the account to be followed by
|
||||||
|
# whitespace/end-of-line so a prefix (Expenses:Gas) does
|
||||||
|
# not match a longer sibling (Expenses:GasStation).
|
||||||
|
if re.search(
|
||||||
|
rf"open {re.escape(account_name)}(?:\s|$)",
|
||||||
|
source,
|
||||||
|
re.MULTILINE,
|
||||||
|
):
|
||||||
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", ""),
|
||||||
|
"already_existed": True,
|
||||||
|
}
|
||||||
|
|
||||||
# Step 3: Always append at end of file.
|
# Step 3: Always append at end of file.
|
||||||
# Post-split layout, each include file has one mutation
|
# Post-split layout, each include file has one mutation
|
||||||
|
|
@ -1700,7 +1712,7 @@ class FavaClient:
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
|
||||||
logger.info(f"Added account {account_name} to {target_file} with currencies {currencies}")
|
logger.info(f"Added account {account_name} to {target_file} with currencies {currencies}")
|
||||||
return result
|
return {**result, "already_existed": False}
|
||||||
|
|
||||||
except httpx.HTTPStatusError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
# Check for checksum conflict (HTTP 412 Precondition Failed or similar)
|
# Check for checksum conflict (HTTP 412 Precondition Failed or similar)
|
||||||
|
|
|
||||||
|
|
@ -3695,13 +3695,19 @@ async def api_admin_add_chart_account(
|
||||||
if payload.description:
|
if payload.description:
|
||||||
metadata["description"] = payload.description
|
metadata["description"] = payload.description
|
||||||
|
|
||||||
await fava.add_account(
|
result = await fava.add_account(
|
||||||
account_name=payload.name,
|
account_name=payload.name,
|
||||||
currencies=payload.currencies,
|
currencies=payload.currencies,
|
||||||
target_file="accounts/chart.beancount",
|
target_file="accounts/chart.beancount",
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if result.get("already_existed"):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.CONFLICT,
|
||||||
|
detail=f"Account {payload.name} already exists",
|
||||||
|
)
|
||||||
|
|
||||||
# Mirror into libra DB so permissions / metadata layer sees it.
|
# Mirror into libra DB so permissions / metadata layer sees it.
|
||||||
from .account_sync import sync_single_account_from_beancount
|
from .account_sync import sync_single_account_from_beancount
|
||||||
synced = await sync_single_account_from_beancount(payload.name)
|
synced = await sync_single_account_from_beancount(payload.name)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue