chore: hygiene sweep — dead code, role race, user lookup, stale files
One pass over the LOW-tier review items plus two folded issues: - Delete validate_journal_entry (dead since the Fava migration; it validated the pre-string-amount model) with its exports, unused crud imports, and tests. Beancount validates entries now. - Migration m006: UNIQUE index on user_roles(user_id, role_id) after deduping; assign_user_role inserts with ON CONFLICT DO NOTHING and returns the existing assignment — closes the auto-assign check-then-act race on concurrent logins. - Extract _get_username_from_user_id (110 lines in views_api, fresh LNbits Database per call inside per-row hot paths) into user_lookup.py with one shared core-DB handle, a 60s TTL cache and a batch get_usernames API (review #18). - Receivable-entry responses report CLEARED, matching the flag the formatter actually writes; PENDING misled the UI (libra-#35). - Replace the remaining print() calls in tasks.py with logger. - get_all_accounts derives valid roots from account_utils.ACCOUNT_TYPE_ROOTS instead of a hardcoded tuple, and the no-op per-test rate-limit reset is gone (libra-#54). - Delete migrations_old.py.bak, MIGRATION_SQUASH_SUMMARY.md, docs/PHASE*_COMPLETE.md and the rendered .html; .gitignore data/ (it holds the runtime .lnbits_auth_key secret). - Track docs/CODE-REVIEW-2026-06.md with finding statuses updated for the PR #55-#59 + chore/hygiene series. - CLAUDE.md notes LNbits pins Pydantic v1: keep .dict(), don't "modernize" to .model_dump(). Note: format_payment_entry's is_payable docstring (flagged in review follow-up) turned out to be consistent with the body — no change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c0d371036b
commit
ec6cac51f0
19 changed files with 454 additions and 2942 deletions
|
|
@ -16,10 +16,9 @@ Note: Balance calculation and inventory tracking have been migrated to Fava/Bean
|
|||
All accounting calculations are now performed via Fava's query API.
|
||||
"""
|
||||
|
||||
from .validation import ValidationError, validate_journal_entry, validate_balance
|
||||
from .validation import ValidationError, validate_balance
|
||||
|
||||
__all__ = [
|
||||
"ValidationError",
|
||||
"validate_journal_entry",
|
||||
"validate_balance",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -18,81 +18,6 @@ class ValidationError(Exception):
|
|||
self.details = details or {}
|
||||
|
||||
|
||||
def validate_journal_entry(
|
||||
entry: Dict[str, Any],
|
||||
entry_lines: List[Dict[str, Any]]
|
||||
) -> None:
|
||||
"""
|
||||
Validate a journal entry and its lines (Beancount-style with single amount field).
|
||||
|
||||
Checks:
|
||||
1. Entry must have at least 2 lines (double-entry requirement)
|
||||
2. Entry must be balanced (sum of amounts = 0)
|
||||
3. All lines must have account_id
|
||||
4. No line should have amount = 0 (would serve no purpose)
|
||||
|
||||
Args:
|
||||
entry: Journal entry dict with keys:
|
||||
- id: str
|
||||
- description: str
|
||||
- entry_date: datetime
|
||||
entry_lines: List of entry line dicts with keys:
|
||||
- account_id: str
|
||||
- amount: int (positive = debit, negative = credit)
|
||||
|
||||
Raises:
|
||||
ValidationError: If validation fails
|
||||
"""
|
||||
# Check minimum number of lines
|
||||
if len(entry_lines) < 2:
|
||||
raise ValidationError(
|
||||
"Journal entry must have at least 2 lines",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_count": len(entry_lines),
|
||||
}
|
||||
)
|
||||
|
||||
# Validate each line
|
||||
for i, line in enumerate(entry_lines):
|
||||
# Check account_id exists
|
||||
if not line.get("account_id"):
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} missing account_id",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
}
|
||||
)
|
||||
|
||||
# Get amount (Beancount-style: positive = debit, negative = credit)
|
||||
amount = line.get("amount", 0)
|
||||
|
||||
# Check that amount is non-zero (zero amounts serve no purpose)
|
||||
if amount == 0:
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} has amount = 0 (serves no purpose)",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
}
|
||||
)
|
||||
|
||||
# Check entry is balanced (sum of amounts must equal 0)
|
||||
# Beancount-style: positive amounts cancel out negative amounts
|
||||
total_amount = sum(line.get("amount", 0) for line in entry_lines)
|
||||
|
||||
if total_amount != 0:
|
||||
raise ValidationError(
|
||||
"Journal entry is not balanced (sum of amounts must equal 0)",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"total_amount": total_amount,
|
||||
"line_count": len(entry_lines),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def validate_balance(
|
||||
account_id: str,
|
||||
expected_balance_sats: int,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue