Manual Accounts Ownership Logic Audit
Date: 2025-10-14Status: ✅ CONSISTENT - All logic verified
Overview
This document audits all logic related tobalance, total_balance, and ownership_percentage columns in the manual_accounts table.
Key Concepts
balance: The user’s actual portion (what they’re responsible for). This is the source of truth for calculations.total_balance: The full balance before applying ownership percentage. Only populated whenownership_percentage < 100.ownership_percentage: The percentage the user owns (e.g., 50.5%). Only populated when less than 100%.- 100% ownership: Both
total_balanceandownership_percentageare NULL. - Partial ownership:
balance = total_balance × (ownership_percentage / 100)
Important Note
total_balance and ownership_percentage are NEW columns. Historical data will have NULL values, which correctly represents 100% ownership.
File-by-File Analysis
1. ✅ /components/add-manual-account-dialog.tsx
Lines 170-198: Account Creation Logic
- User enters the FULL balance amount
- Dialog sends full balance to backend
- Hook recalculates user’s portion
- UI shows preview of user’s portion
2. ✅ /hooks/queries/use-manual-accounts.ts
Add Account (Lines 165-175)
- Calculates user’s portion from total_balance
- If ownership is 100% (NULL), uses balance as-is
Update Account (Lines 228-262)
Handles three cases: Case 1: Removing ownership (both NULL)- Handles all three cases properly
- Maintains consistency between balance and total_balance
- Works with historical NULL values
3. ✅ /components/edit-manual-account-dialog.tsx
Display Logic (Lines 148-155)
- Shows total_balance (full amount) when ownership < 100%
- Shows balance (user’s portion) when ownership = 100% (NULL)
- Works correctly with historical NULL values
Submit Logic (Lines 301-325)
- Follows same pattern as add dialog
- Sets to NULL for 100% ownership
4. ✅ /lib/loan-payments.ts
Process Payment (Lines 246-264)
- When loan payment reduces balance, proportionally reduces total_balance
- Formula:
total_balance = balance / (percentage / 100)is correct - Works with historical NULL values (doesn’t update if NULL)
5. ✅ /app/api/cron/process-daily-snapshot/route.ts
Manual Account Processing (Lines 1036-1120)
- Uses
balance(user’s portion) for all net worth calculations - Stores ownership fields for historical tracking
- Works correctly with historical NULL values
6. ✅ /app/api/manual-transactions/route.ts
Create Transaction (Lines 77-143)
- Updates balance based on transaction
- Proportionally updates total_balance if ownership < 100%
- Works with historical NULL values
7. ✅ /app/api/manual-transactions/[id]/route.ts
Update Transaction (Lines 31, 66-95)
Delete Transaction (Lines 117-158)
- Edit: Updates balance by difference, adjusts total_balance proportionally
- Delete: Reverses balance change, adjusts total_balance proportionally
- Works with historical NULL values
8. ✅ /app/api/manual-transactions/batch/route.ts
Batch Import (Lines 46-158)
- Accumulates all transaction amounts
- Updates balance and total_balance proportionally
- Works with historical NULL values
9. ✅ /app/liabilities/page.tsx
Account Filtering (Lines 177-184)
- Uses
balance_currentfor Plaid accounts (not manual accounts) - Manual accounts are handled by
useAccountshook which provides proper balances
10. ✅ /lib/financial-data-cache.ts
Manual Accounts Query (Line 294)
Balance Usage (Lines 352-360)
- Fetches ownership fields for context
- Uses
balance(user’s portion) for all calculations - Works correctly with historical NULL values
11. ✅ /app/api/chat/pdf-export-tool.ts (Financial Statement Generation)
Manual Investment Accounts (Lines 317-328)
Manual Loan Accounts (Lines 902-912)
Manual Credit Cards (Lines 817-827)
Cash Accounts (Lines 263-276)
- Displays:
total_balancewhenownership_percentage < 100% - Shows: Ownership percentage in account name (e.g., “50% ownership”)
- Consistent with: Add/Edit dialogs where users enter/view full balance
- Purpose: Financial statements show full liability/asset amounts (what banks want)
- Net Worth: Still calculated correctly using
balanceingetFinancialMetrics - Works with historical NULL values (100% ownership - no annotation shown)
Summary
✅ All Logic is Consistent
Key Findings:- Balance Column: Always contains the user’s actual portion across all files
- Total Balance: Only populated when ownership < 100%, NULL means 100%
- Ownership Percentage: Only populated when < 100%, NULL means 100%
- Historical Data: NULL values correctly represent 100% ownership everywhere
- Calculations: All balance updates proportionally update total_balance when ownership < 100%
Formula Consistency
When setting ownership:Recommendations
✅ Current Implementation is Solid
The current implementation correctly:- Uses
balanceas the source of truth for calculations - Maintains
total_balancefor reference/display when ownership < 100% - Treats NULL values as 100% ownership
- Proportionally updates both fields when balance changes
Optional: Migration Script for Display
If you want to backfilltotal_balance for display purposes on old records where ownership was intended to be partial:
Conclusion
Status: ✅ VERIFIED - All logic is consistent and correct. All files properly handle:- New accounts with partial ownership
- Historical accounts with NULL values (100% ownership)
- Balance updates (transactions, payments, edits)
- Display logic (showing full balance vs user’s portion)
- Net worth calculations (always using user’s portion)
Recent Updates (2025-10-14)
Fixed:/app/api/chat/pdf-export-tool.ts to display total_balance with ownership percentage when ownership_percentage < 100%
Result: Financial statement PDFs now show:
- Full balance (what banks want to see)
- Ownership percentage clearly noted (e.g., “50% ownership”)
- Consistent with Add/Edit dialog behavior
- Joint mortgage: Shows “200,000”
- Net worth still correctly uses $200,000 (user’s portion) via
getFinancialMetrics