Commit Graph

116 Commits

Author SHA1 Message Date
7b0853b74c Feature: Add pagination to Receipts page
- Add PageNumber and PageSize query parameters (default 25 per page)
- Implement server-side pagination with Skip/Take
- Display "Showing X-Y of Z" count in header
- Add Bootstrap pagination controls with sliding page window

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 21:33:05 -05:00
101a340d8c Chore: Add Docker containerization support
- Add Dockerfile with multi-stage build for .NET 8
- Include ImageMagick dependencies for Magick.NET
- Add docker-compose.yml with volume mount for receipts
- Add .dockerignore to exclude build artifacts

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:01:03 -05:00
3a817e0f3f UI: Convert receipt upload panel to modal dialog
Move the upload form from a card panel at the top of the page
to a modal triggered by an "Upload Receipt" button in the header.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:00:55 -05:00
36a044da4f Feature: Add category pie chart and case-insensitive search
- Add doughnut chart showing spending by category
- Fix search to use EF.Functions.Like for explicit case-insensitivity
- Include Chart.js CDN for chart rendering

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:12:13 -05:00
f42d5e87f9 Config: Update Program.cs with new service registrations
- Add AddMemoryCache() for TransactionCategorizer caching
- Register IPdfToImageConverter
- Register OpenAIVisionClient and ClaudeVisionClient with HttpClient
- Update AIReceiptParser registration to use scoped instead of HttpClient

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:12:04 -05:00
9f64c7784a Refactor: Extract AI vision clients from AIReceiptParser
Extract for better separation of concerns:
- Services/PdfToImageConverter.cs - PDF to image conversion using ImageMagick
- Services/AIVisionClient.cs - OpenAI and Claude vision API clients
  - IAIVisionClient interface
  - OpenAIVisionClient, ClaudeVisionClient implementations

AIReceiptParser now orchestrates using injected services.
Adds proper logging for auto-mapping operations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:56 -05:00
ea7b2c2a3c Refactor: Extract dashboard services from Index page
Extract to separate files for better maintainability:
- Models/Dashboard/DashboardModels.cs - Dashboard DTOs
- Services/DashboardService.cs - All dashboard-related services
  - IDashboardService, IDashboardStatsCalculator
  - ITopCategoriesProvider, IRecentTransactionsProvider
  - ISpendTrendsProvider

Reduces Index.cshtml.cs from 355 lines to 37 lines.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:48 -05:00
2ceb3a7b57 Refactor: Extract import services from Upload page
Extract to separate files for better maintainability:
- Models/Import/ImportContext.cs - Import context and PaymentSelectMode enum
- Models/Import/ImportResults.cs - Import result DTOs and TransactionKey
- Models/Import/PaymentResolutionResult.cs - Payment resolution DTO
- Services/TransactionImporter.cs - CSV import logic
- Services/CardResolver.cs - Payment method resolution

Reduces Upload.cshtml.cs from 615 lines to 216 lines.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:39 -05:00
a30e6ff089 Refactor: Extract CategoryMapping model and add caching
- Move CategoryMapping class to Models/CategoryMapping.cs
- Add IMemoryCache with 10-minute TTL for category mappings
- Add InvalidateMappingsCache() method for cache invalidation
- Reduces repeated DB queries during bulk categorization

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:29 -05:00
625314d167 Refactor: Add structured error logging to TransactionAICategorizer
- Add ILogger for proper error logging
- Differentiate between HTTP, JSON parsing, and general errors
- Log errors with descriptive messages for debugging

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:21 -05:00
d9e883a9f3 Security: Add MIME type validation and logging to ReceiptManager
- Add magic bytes validation to prevent file extension spoofing
- Add ILogger for proper error logging in background parsing
- Log background parsing success/failure with receipt ID

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:13 -05:00
1de3920db4 Perf: Add composite database indexes for common queries
Add indexes for:
- (AccountId, Category) - account spending by category
- (AccountId, Date) - account transaction timelines
- (MerchantId, Date) - merchant spending trends
- (CardId, Date) - card activity analysis
- FileHashSha256 on Receipts - duplicate detection
- (TransactionId, ReceiptDate) on Receipts - receipt lookups

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:11:05 -05:00
53c674c6e0 Perf: Fix N+1 queries in entity services
- CardService.GetAllCardsWithStatsAsync: Use single query with Select projection
- AccountService.GetAccountDetailsAsync: Use single query with Select projection
- TransactionStatisticsService: Calculate stats at DB level, fix N+1 in GetCardStatsForAccountAsync

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:10:56 -05:00
AJ
a85de793d7 Feature: disable preview button until CSV file is selected
Added validation to prevent users from submitting the upload form without
selecting a file first. The preview button is now disabled by default and
only enables when a file is selected, improving user experience and
preventing empty form submissions.

Changes:
- Added IDs to file input and preview button
- Button starts in disabled state
- JavaScript listener enables button when file is selected
- Button disables again if file selection is cleared
2025-11-16 12:07:17 -05:00
AJ
e0638039d8 Feature: order upload transaction preview by date descending
Transaction previews on the upload page now display with newest transactions
first, making it easier to review recent imports at the top of the list.
2025-11-16 11:54:13 -05:00
AJ
51c2ce2965 Config: exclude receipts folder from compilation
Added wwwroot/receipts to compilation exclusions to prevent build warnings
and improve build performance. Receipt files are user-uploaded content and
should not be included in the build process.
2025-11-16 11:54:07 -05:00
AJ
0a15d09db4 Refactor: separate JavaScript from HTML into external files
Extracted all inline JavaScript from Razor pages into dedicated external
files for better code organization and browser caching:
- upload.js: transaction preview, pagination, form handling
- transactions.js: date range filters, Bootstrap tooltips
- edit-transaction.js: category/merchant dropdowns, copy functionality
- merchants.js: modal handling for merchant management
- category-mappings.js: modal handling for category rules

Updated all affected .cshtml files to reference external scripts instead
of inline script blocks. This improves maintainability, enables browser
caching, and provides better separation of concerns.
2025-11-16 11:54:00 -05:00
AJ
1c28d9cc88 Refactor: remove unnecessary using directives
Removed unused using statements from page models and test files:
- Removed unused Microsoft.EntityFrameworkCore and MoneyMap.Data imports
- Removed redundant Xunit usings (already declared as global)

Fixes CS8019 and CS8933 hidden diagnostics.
2025-11-16 11:53:50 -05:00
AJ
22c60602df Fix: make Receipt property nullable in ViewReceiptModel
Changed Receipt property from non-nullable (null!) to nullable (?) to properly
handle cases where receipt is not found. Fixes CS8601 null reference assignment
warning.
2025-11-16 11:53:42 -05:00
AJ
f9cf709206 Fix: remove unnecessary async from OnPostRejectProposalAsync methods
Removed async/await keywords from methods that don't perform any async
operations. The methods were triggering CS1998 warnings and running
synchronously despite being marked async.
2025-11-16 11:53:36 -05:00
AJ
ea14466f57 Fix: add null checks in AIReceiptParser to prevent null reference warnings
Added validation to ensure messageContent is not null or whitespace before
deserializing JSON responses from OpenAI and Claude vision APIs. This fixes
CS8604 warnings about possible null reference arguments.
2025-11-16 11:53:28 -05:00
AJ
56089cc437 Fix: improve EditTransaction form handling and validation
- Add hidden fields for immutable transaction properties to preserve values during form submission
- Make category field optional by removing validation for empty values
- Simplify category input handling by removing duplicate hidden field
- Clean up JavaScript by using proper element IDs instead of querySelector

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 01:59:50 -04:00
AJ
4bd89a0ab5 Config: add dotnet test permissions to Claude Code settings
Add auto-approve permissions for dotnet test, new, and add commands to support test-driven development workflow.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:41 -04:00
AJ
af4a638b81 Test: add comprehensive unit test project for services
Add MoneyMap.Tests project with xUnit tests for all new services:

- AccountServiceTests: Account retrieval, stats, validation, deletion
- CardServiceTests: Card retrieval, stats, validation, deletion
- MerchantServiceTests: Merchant CRUD operations
- ReferenceDataServiceTests: Reference data retrieval
- TransactionServiceTests: Duplicate detection, retrieval, deletion
- TransactionStatisticsServiceTests: Statistics calculations
- ReceiptMatchingServiceTests: Receipt-to-transaction matching logic
- DbContextHelper: In-memory database context factory for test isolation

Uses xUnit, Moq, and EF Core InMemory database. Solution file updated to include test project.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:28 -04:00
AJ
f8bb5d5a82 Feature: add ability to unmap receipts from transactions
Add unmap functionality to allow users to disassociate receipts from transactions without deleting them:

- ReceiptManager: Add UnmapReceiptAsync method
- Receipts page: Add OnPostUnmapAsync handler
- Receipts view: Add Unmap button for mapped receipts with confirmation dialog

This provides a non-destructive alternative to deleting receipts when they need to be remapped to different transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:11 -04:00
AJ
b4a91d8b7f Docs: update ARCHITECTURE.md with new services and reorganization
Document the expanded service layer architecture:

- Reorganize service layer diagram by functional groups (Core Transaction, Entity Management, Receipt, Reference & Dashboard)
- Add comprehensive documentation for AccountService, CardService, ReferenceDataService, and TransactionStatisticsService
- Update MerchantService documentation with new CRUD operations
- Document all DTOs and design patterns

Maintains architectural documentation consistency as the service layer continues to grow.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:08:42 -04:00
AJ
04a7e92bc9 Refactor: migrate PageModels to use new service layer
Refactor 7 PageModels to delegate business logic to services:

- AccountDetails: Use AccountService for account details retrieval
- Accounts: Use AccountService for listing and deletion
- Cards: Use CardService for listing and deletion
- EditTransaction: Use ReferenceDataService for dropdowns
- Merchants: Use MerchantService for CRUD operations
- Recategorize: Use ReferenceDataService and TransactionStatisticsService
- Transactions: Use ReferenceDataService and TransactionStatisticsService

Significantly simplifies PageModels (229 lines removed, 97 added) by extracting data access and business logic into testable services. Pages now focus solely on HTTP request/response handling.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:08:28 -04:00
AJ
c09a8c36a8 Feature: expand MerchantService with full CRUD operations
Extend MerchantService with additional operations:
- GetMerchantByIdAsync: Retrieve merchant with optional related data
- GetAllMerchantsWithStatsAsync: Get all merchants with transaction/mapping counts
- UpdateMerchantAsync: Update merchant name with duplicate validation
- DeleteMerchantAsync: Delete merchant (unlinks transactions and mappings)

Includes DTOs for merchant stats, update results, and delete results. Consolidates merchant management logic previously scattered across PageModels.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:08:13 -04:00
AJ
77cab2595f Feature: add entity management and statistics services
Add four new services to extract business logic from PageModels:

- AccountService: Account retrieval, stats, and deletion with validation
- CardService: Card retrieval, stats, and deletion with validation
- ReferenceDataService: Centralized reference data for dropdowns (categories, merchants, cards, accounts)
- TransactionStatisticsService: Transaction statistics and aggregate calculations

All services follow the established service layer pattern with interfaces for DI and improved testability. Includes comprehensive DTOs for stats and validation results.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:07:57 -04:00
AJ
51a51f9b27 Config: add Claude Code auto-approve permissions
Add auto-approve permissions for roslyn-bridge skill, curl commands, and dotnet build variants to improve Claude Code workflow efficiency.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:54:10 -04:00
AJ
1509bcd130 Docs: update ARCHITECTURE.md with new services
Document TransactionService and ReceiptMatchingService in the architecture documentation, including their responsibilities, key methods, matching algorithms, and design patterns.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:53:57 -04:00
AJ
f4f7faaccc Refactor: use ReceiptMatchingService in Receipts page
Extract 140+ lines of receipt-to-transaction matching logic into ReceiptMatchingService. The PageModel now delegates matching to the service, simplifying the code and improving testability.

The matching algorithm (date filtering, merchant word-based scoring, amount tolerance) remains unchanged but is now centralized in a dedicated service.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:53:46 -04:00
AJ
cedfe98789 Refactor: use TransactionService for duplicate detection in Upload
Replace inline duplicate detection logic with TransactionService.IsDuplicateAsync(), consolidating duplicate checking into a single, testable service method. Removes duplicate IsDuplicate() method implementations from UploadModel.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:53:33 -04:00
AJ
f5aef547cc Feature: add TransactionService and ReceiptMatchingService
Add two new services to extract business logic from PageModels:

- TransactionService: Handles core transaction operations including duplicate detection, retrieval, and deletion
- ReceiptMatchingService: Implements intelligent receipt-to-transaction matching using date, merchant, and amount scoring

Both services follow the established service layer pattern with interfaces for dependency injection and improved testability.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:53:20 -04:00
AJ
ff1d7ff0b0 Feature: add Unmap button to prevent accidental receipt deletion
Add safer workflow for fixing incorrectly mapped receipts:
- Add OnPostUnmapReceiptAsync handler that sets TransactionId to null
- Add "Unmap" button (warning color) before Delete button
- Update Delete confirmation to emphasize PERMANENT deletion
- Unmap success message guides user to Receipts page

This prevents accidental loss of receipt files when users just want to remap them to a different transaction.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 16:57:29 -04:00
AJ
86b7312dd6 Refactor: rename OpenAIReceiptParser to AIReceiptParser
Rename to reflect multi-provider support (OpenAI + Anthropic):
- Rename Services/OpenAIReceiptParser.cs to Services/AIReceiptParser.cs
- Update class name from OpenAIReceiptParser to AIReceiptParser
- Update DI registration in Program.cs

The parser now supports both OpenAI and Anthropic models, so the more generic name better reflects its capabilities.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 16:19:27 -04:00
AJ
f7c6b2691b Feature: add Anthropic Claude model support for receipt parsing
Add Claude 3.5 Haiku and Sonnet as parsing options:
- Add Claude models to AI Model dropdown (Haiku for fast, Sonnet for best quality)
- Update OpenAIReceiptParser to detect provider based on model name (claude-* prefix)
- Add CallClaudeVisionAsync method using Anthropic Messages API
- Support ANTHROPIC_API_KEY environment variable or Anthropic:ApiKey config
- Parse logs now correctly show "Anthropic" or "OpenAI" as provider
- Both providers use the same prompt template and return structure

Users can now choose from 4 models:
- GPT-4o Mini (fast & cheap)
- GPT-4o (smarter)
- Claude 3.5 Haiku (fast)
- Claude 3.5 Sonnet (best quality)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 16:15:25 -04:00
AJ
f09d19ec5c Receipt parser improvements: voided items, UPC, quantity defaults, and model selection
Major improvements to receipt parsing:

Voided Item Handling:
- Add Voided boolean field to ReceiptLineItem model and database
- Never skip any line items - include voided items with voided=true and lineTotal=0.00
- Strong parser hints: "CONTINUE reading", "do NOT stop parsing", "Read ENTIRE receipt"
- Ensures all items after void markers are captured

UPC/Barcode Extraction:
- Extract UPC codes (12-13 digits) and store in Sku field
- Enables price tracking over time even when descriptions change

Quantity Defaults:
- ALWAYS default to 1.0 for ALL retail products (groceries, goods, merchandise)
- Only use null for utility bills, service fees, or taxes
- Emphatic instructions: "MUST be 1.0", "do NOT leave it null"
- Prevents missing quantities on retail items

Model Selection:
- Add AI model dropdown in ViewReceipt UI (gpt-4o-mini vs gpt-4o)
- Update IReceiptParser interface to accept optional model parameter
- Pass selected model through to OpenAI API
- Store model name in parse logs for history tracking
- Allows using smarter model for complex receipts

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 16:08:56 -04:00
AJ
d0f4b420f8 Refactor: externalize OpenAI receipt parser prompt to text file
Move hardcoded prompt from OpenAIReceiptParser.cs to Prompts/ReceiptParserPrompt.txt for easier maintenance and editing without recompilation. Add caching to LoadPromptTemplateAsync for performance. Configure .csproj to copy Prompts folder to output directory.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 15:05:59 -04:00
AJ
c31e88f07c Receipts: highlight exact amount matches in green, close (±10%) in yellow; update legend and scroll target preference 2025-10-19 01:03:26 -04:00
AJ
cf1266e86d UI: replace garbled emoji with plain counts/labels for badges (receipt count, notes) 2025-10-19 00:54:11 -04:00
AJ
134a1b8c9f Transactions: make rows clickable to open Edit; remove Edit button; keep name as link 2025-10-19 00:47:44 -04:00
AJ
ed0d82a549 Remove manual Transfers page and nav link (bank-only data preference) 2025-10-19 00:33:24 -04:00
AJ
7e785e5647 Dashboard: wire up SpendTrends in DI and add chart canvases on dashboard; include Chart.js script to render graphs 2025-10-19 00:26:17 -04:00
AJ
ef88d03c95 Dashboard: add graphs (Chart.js) with category donut and 30-day cash flow; add SpendTrends provider and DI registration 2025-10-19 00:22:18 -04:00
AJ
23421bcc99 Dashboard: make recent transactions clickable and add Open action; include Id and ReceiptCount in recent data
Co-authored-by:Codex-CLI-Agent
codex-cli@users.noreply.local
2025-10-19 00:07:48 -04:00
AJ
bfe9ee5f08 Receipts: fix manual mapping (mirror manual ID, submit guard), allow remapping, and add clearer duplicate message; add Edit link in map modal and show mapped ID link
Co-authored-by:Codex-CLI-Agent
codex-cli@users.noreply.local
2025-10-19 00:07:45 -04:00
AJ
eb31039bc8 Transactions: show ID on Edit page and add Copy ID button
Co-authored-by:Codex-CLI-Agent
codex-cli@users.noreply.local
2025-10-19 00:07:41 -04:00
AJ
fa142288b6 Add intelligent word-based merchant matching for receipt mapping
Implemented word-based relevance scoring to intelligently sort transactions when multiple matches exist within the amount tolerance. The system now:

1. Splits receipt merchant name into words (handling spaces, dashes, underscores, dots)
2. Compares each word against transaction merchant name and transaction name
3. Scores based on matching word count (bidirectional substring matching)
4. Exact matches get highest priority (score 1000)
5. Word matches get scored (10 points per matching word)
6. Sorts by relevance score, then by date

Examples:
- Receipt "Duke Energy" matches "DUKE ENERGY CORPORATION" better than "WALMART"
- Receipt "McDonald's" matches "MCDONALD'S #12345" better than "BURGER KING"
- Receipt "Comcast" matches "COMCAST CABLE" better than "VERIZON"

This dramatically improves auto-mapping success rate and puts the most likely transaction at the top of the manual selection list.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 19:33:47 -04:00
AJ
c7089dba98 Filter transactions by ±10% amount tolerance for receipt mapping
Changed amount matching from a fixed ±$0.10 tolerance to a percentage-based ±10% tolerance. This dramatically narrows down the transaction list for manual mapping, often to just 1-2 transactions.

Changes:
- Manual mapping: Filters candidates to ±10% of receipt total
- Manual mapping: Green highlighting for very close matches (±2%)
- Auto-mapping: Uses same ±10% tolerance for filtering
- UI: Updated help text to explain the filtering

Example: A $100 receipt will only show transactions between $90-$110, making it much easier to find the correct match.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 19:17:16 -04:00