refactor(api): split views_api.py into a package of domain modules
Pure move — no logic changes. The 4,100-line single file becomes views_api/ with one module per domain (accounts, entries, payments, settings_reports, reconciliation, permissions, admin), each registering full literal paths on its own APIRouter; __init__ builds the combined libra_api_router so libra/__init__.py is untouched. Shared imports/helpers live in views_api/_shared.py; _extract_entry_id and _SYSTEM_LINK_PREFIXES move to beancount_format.py (they are pure entry-dict parsing). Route behavior is pinned by tests/test_route_table.py: the 73-route set is unchanged, and the two order-sensitive families (the shadowed /accounts/hierarchy wart — deliberately preserved here, fixed in the next commit — and the admin sync literal/param pair) keep their relative order inside a single module each. Addresses CODE-REVIEW-2026-06 structure findings (views_api monolith). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9e06fa0b2a
commit
a7d7740a3a
12 changed files with 4233 additions and 4130 deletions
|
|
@ -37,6 +37,7 @@ EXPECTED_ROUTES = [
|
|||
("GET", "/api/v1/accounts/{account_id}", "api_get_account"),
|
||||
("GET", "/api/v1/accounts/{account_id}/balance", "api_get_account_balance"),
|
||||
("GET", "/api/v1/accounts/{account_id}/transactions", "api_get_account_transactions"),
|
||||
("GET", "/api/v1/accounts/hierarchy", "api_get_account_hierarchy"),
|
||||
("GET", "/api/v1/entries", "api_get_journal_entries"),
|
||||
("GET", "/api/v1/entries/user", "api_get_user_entries"),
|
||||
("GET", "/api/v1/entries/pending", "api_get_pending_entries"),
|
||||
|
|
@ -45,6 +46,8 @@ EXPECTED_ROUTES = [
|
|||
("POST", "/api/v1/entries/income", "api_create_income_entry"),
|
||||
("POST", "/api/v1/entries/receivable", "api_create_receivable_entry"),
|
||||
("POST", "/api/v1/entries/revenue", "api_create_revenue_entry"),
|
||||
("POST", "/api/v1/entries/{entry_id}/approve", "api_approve_expense_entry"),
|
||||
("POST", "/api/v1/entries/{entry_id}/reject", "api_reject_expense_entry"),
|
||||
("GET", "/api/v1/balance", "api_get_my_balance"),
|
||||
("GET", "/api/v1/balance/{user_id}", "api_get_user_balance"),
|
||||
("GET", "/api/v1/balances/all", "api_get_all_balances"),
|
||||
|
|
@ -52,6 +55,11 @@ EXPECTED_ROUTES = [
|
|||
("POST", "/api/v1/record-payment", "api_record_payment"),
|
||||
("POST", "/api/v1/receivables/settle", "api_settle_receivable"),
|
||||
("POST", "/api/v1/payables/pay", "api_pay_user"),
|
||||
("POST", "/api/v1/manual-payment-request", "api_create_manual_payment_request"),
|
||||
("GET", "/api/v1/manual-payment-requests", "api_get_manual_payment_requests"),
|
||||
("GET", "/api/v1/manual-payment-requests/all", "api_get_all_manual_payment_requests"),
|
||||
("POST", "/api/v1/manual-payment-requests/{request_id}/approve", "api_approve_manual_payment_request"),
|
||||
("POST", "/api/v1/manual-payment-requests/{request_id}/reject", "api_reject_manual_payment_request"),
|
||||
("GET", "/api/v1/settings", "api_get_settings"),
|
||||
("PUT", "/api/v1/settings", "api_update_settings"),
|
||||
("GET", "/api/v1/user-wallet/{user_id}", "api_get_user_wallet"),
|
||||
|
|
@ -62,13 +70,7 @@ EXPECTED_ROUTES = [
|
|||
("GET", "/api/v1/users/{user_id}/unsettled-entries", "api_get_unsettled_entries"),
|
||||
("GET", "/api/v1/user/wallet", "api_get_user_wallet"),
|
||||
("PUT", "/api/v1/user/wallet", "api_update_user_wallet"),
|
||||
("POST", "/api/v1/manual-payment-request", "api_create_manual_payment_request"),
|
||||
("GET", "/api/v1/manual-payment-requests", "api_get_manual_payment_requests"),
|
||||
("GET", "/api/v1/manual-payment-requests/all", "api_get_all_manual_payment_requests"),
|
||||
("POST", "/api/v1/manual-payment-requests/{request_id}/approve", "api_approve_manual_payment_request"),
|
||||
("POST", "/api/v1/manual-payment-requests/{request_id}/reject", "api_reject_manual_payment_request"),
|
||||
("POST", "/api/v1/entries/{entry_id}/approve", "api_approve_expense_entry"),
|
||||
("POST", "/api/v1/entries/{entry_id}/reject", "api_reject_expense_entry"),
|
||||
("GET", "/api/v1/user/info", "api_get_user_info"),
|
||||
("POST", "/api/v1/assertions", "api_create_balance_assertion"),
|
||||
("GET", "/api/v1/assertions", "api_get_balance_assertions"),
|
||||
("GET", "/api/v1/assertions/{assertion_id}", "api_get_balance_assertion"),
|
||||
|
|
@ -78,7 +80,6 @@ EXPECTED_ROUTES = [
|
|||
("POST", "/api/v1/reconciliation/check-all", "api_check_all_assertions"),
|
||||
("GET", "/api/v1/reconciliation/discrepancies", "api_get_discrepancies"),
|
||||
("POST", "/api/v1/tasks/daily-reconciliation", "api_run_daily_reconciliation"),
|
||||
("GET", "/api/v1/user/info", "api_get_user_info"),
|
||||
("POST", "/api/v1/admin/equity-eligibility", "api_grant_equity_eligibility"),
|
||||
("DELETE", "/api/v1/admin/equity-eligibility/{user_id}", "api_revoke_equity_eligibility"),
|
||||
("GET", "/api/v1/admin/equity-eligibility", "api_list_equity_eligible_users"),
|
||||
|
|
@ -88,7 +89,6 @@ EXPECTED_ROUTES = [
|
|||
("POST", "/api/v1/admin/permissions/bulk", "api_bulk_grant_permissions"),
|
||||
("POST", "/api/v1/admin/permissions/bulk-grant", "api_bulk_grant_permission_to_users"),
|
||||
("GET", "/api/v1/users/me/permissions", "api_get_user_permissions"),
|
||||
("GET", "/api/v1/accounts/hierarchy", "api_get_account_hierarchy"),
|
||||
("POST", "/api/v1/admin/accounts", "api_admin_add_chart_account"),
|
||||
("POST", "/api/v1/admin/accounts/sync", "api_sync_all_accounts"),
|
||||
("POST", "/api/v1/admin/accounts/sync/{account_name:path}", "api_sync_single_account"),
|
||||
|
|
@ -113,3 +113,23 @@ def test_route_table_matches_snapshot():
|
|||
for r in views_api.libra_api_router.routes
|
||||
]
|
||||
assert actual == EXPECTED_ROUTES
|
||||
|
||||
|
||||
def _index(path: str) -> int:
|
||||
paths = [p for _, p, _ in EXPECTED_ROUTES]
|
||||
return paths.index(path)
|
||||
|
||||
|
||||
def test_overlapping_route_order_is_preserved():
|
||||
"""Only relative order among OVERLAPPING patterns is behavior;
|
||||
these are the two overlap families in the table. The package split
|
||||
keeps each family inside one module so include order can't reorder
|
||||
them."""
|
||||
# Known wart carried over from before the split: hierarchy is
|
||||
# shadowed by the {account_id} route (fixed in a separate commit).
|
||||
assert _index("/api/v1/accounts/{account_id}") < _index(
|
||||
"/api/v1/accounts/hierarchy"
|
||||
)
|
||||
assert _index("/api/v1/admin/accounts/sync") < _index(
|
||||
"/api/v1/admin/accounts/sync/{account_name:path}"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue