Skip to main content

Manual Accounts Ownership Logic Audit

Date: 2025-10-14
Status: ✅ CONSISTENT - All logic verified

Overview

This document audits all logic related to balance, 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 when ownership_percentage < 100.
  • ownership_percentage: The percentage the user owns (e.g., 50.5%). Only populated when less than 100%.
  • 100% ownership: Both total_balance and ownership_percentage are 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
UI Display (Lines 413-424):
Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)
Case 2: Setting/updating ownership < 100%
Case 3: Updating balance when ownership exists
Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • Follows same pattern as add dialog
  • Sets to NULL for 100% ownership

4. ✅ /lib/loan-payments.ts

Process Payment (Lines 246-264)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT
  • Uses balance_current for Plaid accounts (not manual accounts)
  • Manual accounts are handled by useAccounts hook which provides proper balances

10. ✅ /lib/financial-data-cache.ts

Manual Accounts Query (Line 294)

Balance Usage (Lines 352-360)

Status: ✅ CORRECT
  • 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)

Status: ✅ CORRECT & CONSISTENT
  • Displays: total_balance when ownership_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 balance in getFinancialMetrics
  • Works with historical NULL values (100% ownership - no annotation shown)

Summary

✅ All Logic is Consistent

Key Findings:
  1. Balance Column: Always contains the user’s actual portion across all files
  2. Total Balance: Only populated when ownership < 100%, NULL means 100%
  3. Ownership Percentage: Only populated when < 100%, NULL means 100%
  4. Historical Data: NULL values correctly represent 100% ownership everywhere
  5. Calculations: All balance updates proportionally update total_balance when ownership < 100%

Formula Consistency

When setting ownership:
When updating balance:
Both formulas are algebraically equivalent and consistently applied across all files.

Recommendations

✅ Current Implementation is Solid

The current implementation correctly:
  • Uses balance as the source of truth for calculations
  • Maintains total_balance for 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 backfill total_balance for display purposes on old records where ownership was intended to be partial:
Note: This is NOT necessary - NULL correctly means 100% ownership.

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
Example:
  • Joint mortgage: Shows “400,000(50400,000 (50% ownership)" instead of "200,000”
  • Net worth still correctly uses $200,000 (user’s portion) via getFinancialMetrics