Feature: Add budget tracking with period-based spending limits

- Budget model with Weekly/Monthly/Yearly periods
- BudgetService for CRUD and spending calculations
- New /Budgets page for managing budgets
- Dashboard integration with progress bars
- Support for category-specific or total spending budgets
- Period boundaries calculated from budget start date

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-10 22:24:01 -05:00
parent f5cfd982cd
commit 33a664a3e1
12 changed files with 1963 additions and 64 deletions

View File

@@ -55,7 +55,7 @@ MoneyMap follows a clean, service-oriented architecture:
│ SQL Server Database │
│ Cards, Accounts, Transactions, Receipts, │
│ ReceiptLineItems, ReceiptParseLogs, │
│ CategoryMappings, Merchants
│ CategoryMappings, Merchants, Budgets
└─────────────────────────────────────────────┘
```
@@ -183,6 +183,29 @@ Pattern-based rules for auto-categorization with merchant linking.
- `MerchantId` (int?) - Foreign key to Merchant (optional)
- `Priority` (int) - Higher priority checked first (default 0)
### Budget (Models/Budget.cs)
Represents a spending budget for a category or total spending.
**Properties:**
- `Id` (int) - Primary key
- `Category` (string?, 100) - Category name (null = total spending budget)
- `Amount` (decimal) - Budget limit amount
- `Period` (BudgetPeriod) - Weekly, Monthly, or Yearly
- `StartDate` (DateTime) - When budget becomes effective (used for period boundaries)
- `IsActive` (bool) - Whether budget is currently active
- `Notes` (string?, 500) - Optional notes
**Computed Properties:**
- `IsTotalBudget` - Returns true if Category is null
- `DisplayName` - Returns Category or "Total Spending"
**Unique Index:** Category + Period (filtered WHERE IsActive = 1, prevents duplicate active budgets)
**BudgetPeriod Enum:**
- `Weekly` (0) - 7-day periods from StartDate
- `Monthly` (1) - Monthly periods based on StartDate day-of-month
- `Yearly` (2) - Annual periods from StartDate anniversary
## Service Layer
### TransactionImporter (Pages/Upload.cshtml.cs)
@@ -451,6 +474,48 @@ Pattern-based rules for auto-categorization with merchant linking.
**Location:** Services/MerchantService.cs
### BudgetService (Services/BudgetService.cs)
**Interface:** `IBudgetService`
**Responsibility:** Budget management including CRUD operations and spending calculations.
**Key Methods:**
- `GetAllBudgetsAsync(bool activeOnly = true)` - Get all budgets, optionally filtered to active only
- `GetBudgetByIdAsync(int id)` - Get budget by ID
- `CreateBudgetAsync(Budget budget)` - Create new budget with duplicate validation
- `UpdateBudgetAsync(Budget budget)` - Update existing budget
- `DeleteBudgetAsync(int id)` - Delete budget
- `GetAllBudgetStatusesAsync(DateTime? asOfDate = null)` - Get spending status for all active budgets
- `GetBudgetStatusAsync(int budgetId, DateTime? asOfDate = null)` - Get spending status for specific budget
- `GetAvailableCategoriesAsync()` - Get list of categories for budget creation
- `GetPeriodBoundaries(BudgetPeriod period, DateTime startDate, DateTime asOfDate)` - Calculate period start/end dates
**Period Boundary Logic:**
- **Weekly:** 7-day periods starting from StartDate
- **Monthly:** Periods run from StartDate's day-of-month (e.g., 15th to 14th)
- **Yearly:** Annual periods from StartDate anniversary
**DTOs:**
- `BudgetOperationResult` - CRUD operation result with success/message
- `BudgetStatus` - Budget with calculated spending data:
- `Budget` - The budget entity
- `PeriodStart`, `PeriodEnd` - Current period boundaries
- `Spent` - Total spending in period
- `Remaining` - Budget amount minus spent
- `PercentUsed` - Percentage of budget consumed
- `IsOverBudget` - Whether spending exceeds budget
- `StatusClass` - CSS class (success/warning/danger)
**Design Pattern:**
- Follows service layer pattern with interface
- Uses DTOs for complex return types
- Calculates spending by querying transactions within period boundaries
- Excludes transfers from spending calculations
**Location:** Services/BudgetService.cs
### TransactionStatisticsService (Services/TransactionStatisticsService.cs)
**Interface:** `ITransactionStatisticsService`
@@ -913,6 +978,34 @@ EF Core DbContext managing all database entities.
**Location:** Pages/Merchants.cshtml.cs
### Budgets.cshtml / BudgetsModel
**Route:** `/Budgets`
**Purpose:** Manage spending budgets and track budget status.
**Features:**
- Create budgets for specific categories or total spending
- Support for Weekly, Monthly, and Yearly periods
- Real-time spending vs budget tracking with progress bars
- Color-coded status (green/yellow/red based on % used)
- Pause/resume budgets without deleting
- Edit budget amounts and periods
- View active and inactive budgets separately
**Budget Types:**
- **Category Budget:** Track spending for a specific category (e.g., "Dining Out")
- **Total Budget:** Track all spending combined (Category = null)
**Period Boundaries:**
- Periods are calculated relative to the budget's StartDate
- Monthly budgets run from the StartDate's day (e.g., if StartDate is Jan 15, periods run 15th to 14th)
- Weekly budgets run in 7-day increments from StartDate
- Yearly budgets run from the StartDate anniversary
**Dependencies:** `IBudgetService`
**Location:** Pages/Budgets.cshtml.cs
### Recategorize.cshtml / RecategorizeModel
**Route:** `/Recategorize`
@@ -1111,6 +1204,18 @@ CreatedBy (nvarchar(max), NULL) -- "AI" or "User"
CreatedAt (datetime2, NULL) -- Rule creation timestamp
```
### Budgets Table
```sql
Id (int, PK)
Category (nvarchar(100), NULL) -- NULL = total spending budget
Amount (decimal(18,2), NOT NULL)
Period (int, NOT NULL) -- 0=Weekly, 1=Monthly, 2=Yearly
StartDate (datetime2, NOT NULL)
IsActive (bit, NOT NULL)
Notes (nvarchar(500), NULL)
UNIQUE INDEX: (Category, Period) WHERE IsActive = 1
```
## Key Workflows
### 1. Import Transactions from CSV
@@ -1424,15 +1529,14 @@ var importer = new TransactionImporter(mockDb.Object, mockCardResolver.Object);
### Potential Features
1. **Multi-user support**: Add authentication/authorization
2. **Budget tracking**: Monthly budget limits per category
3. **Recurring transactions**: Auto-detect and predict recurring expenses
4. **Data export**: Export transactions to Excel/CSV
5. **Charts/graphs**: Spending trends over time
6. **Mobile app**: React Native or .NET MAUI
7. **Bank API integration**: Direct import from bank APIs (Plaid, Yodlee)
8. **Receipt search**: Full-text search on parsed line items
9. **Split transactions**: Divide single transaction across categories
10. **Tags**: Tag transactions with multiple labels
2. **Recurring transactions**: Auto-detect and predict recurring expenses
3. **Data export**: Export transactions to Excel/CSV
4. **Charts/graphs**: Spending trends over time
5. **Mobile app**: React Native or .NET MAUI
6. **Bank API integration**: Direct import from bank APIs (Plaid, Yodlee)
7. **Receipt search**: Full-text search on parsed line items
8. **Split transactions**: Divide single transaction across categories
9. **Tags**: Tag transactions with multiple labels
### Technical Debt
1. Move inline service implementations to separate files (Upload.cshtml.cs is 333 lines)
@@ -1498,10 +1602,27 @@ MoneyMap demonstrates a well-architected ASP.NET Core application with clear sep
---
**Last Updated:** 2025-10-12
**Version:** 1.2
**Last Updated:** 2025-12-11
**Version:** 1.3
**Framework:** ASP.NET Core 8.0 / EF Core 9.0
## Recent Changes (v1.3)
### Budget Tracking Feature
- **Budget Model**: New `Budget` entity with support for Weekly, Monthly, and Yearly periods
- **Category & Total Budgets**: Create budgets for specific categories or track total spending
- **Period Boundaries**: Smart calculation of period start/end dates based on budget start date
- **Budget Service**: Full CRUD operations plus spending calculations via `IBudgetService`
- **Budgets Page**: New `/Budgets` page for managing budgets with progress bars
- **Dashboard Integration**: Budget status displayed on dashboard with color-coded progress
- **Pause/Resume**: Deactivate budgets without deleting them
### Technical Details
- Added `Budgets` table with filtered unique index on (Category, Period) WHERE IsActive = 1
- `BudgetPeriod` enum: Weekly (0), Monthly (1), Yearly (2)
- Period boundary calculations handle edge cases (month boundaries, leap years)
- Spending calculated by summing debits within period, excluding transfers
## Recent Changes (v1.2)
### Receipt Management Enhancements