Enhance AI categorization with multi-provider support:
- Add configurable AI:CategorizationProvider setting (OpenAI/LlamaCpp)
- Add CallLlamaCppAsync() for local LLM categorization
- Improve prompt with existing categories for consistency
- Include additional transaction context (card, account, transfer info)
- Fix batch processing to avoid DbContext concurrency issues
- Add model parameter to interface methods
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add GetAvailableModelsAsync() to LlamaCppVisionClient that:
- Queries llama.cpp /v1/models endpoint for available models
- Filters out multimodal projector models (mmproj-*)
- Tracks loaded/unloaded status for each model
- Returns sorted list with loaded models first
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add new page that allows users to:
- Generate AI categorization suggestions for uncategorized transactions
- Review proposals with confidence levels before applying
- Select specific transactions from Transactions page for AI review
- Choose to create mapping rules for high-confidence matches
- Support both OpenAI and LlamaCpp providers with model selection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Store only filename in database instead of full relative path.
GetReceiptPhysicalPath now combines config base path with filename.
AIReceiptParser uses ReceiptManager for consistent path resolution.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New page shows unmapped receipts with scored transaction candidates,
allowing manual mapping or bulk auto-map. Displays confidence scores
and match quality indicators. Also shows recently mapped receipts
for verification with unmap option.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace simple matching with weighted scoring algorithm (40% amount,
25% date, 35% merchant, 10% due date). Uses confidence thresholds:
- 85%+ auto-maps immediately
- 50-85% uses LLM to decide
- Below 50% returns candidates for manual review
Transactions can no longer match before receipt date since receipts
are issued at time of purchase.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add LlamaCppVisionClient and OllamaVisionClient for local AI inference
as alternatives to OpenAI and Claude. Includes text-only prompt support
for LLM-assisted receipt matching.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add documentation for:
- FinancialAuditService responsibilities and methods
- Audit flag types and severities
- /api/audit endpoint with query parameters and response
- Version bump to 1.4 with recent changes section
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Improves readability of percentage text when progress bar
is in warning state (80-99% of budget used).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevents form submission with empty pattern, keeping modal open
for validation instead of closing and showing error after redirect.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- Add RunningBalance to SpendTrends model
- Calculate cumulative balance over 30 days
- Display as smooth filled line chart (neutral blue)
- Cleaner date labels (MMM d format)
- Better tooltip formatting with $ values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Enable data-bs-theme="dark" on html element
- Update navbar to dark variant
- Replace text-dark links with text-body (theme-aware)
- Replace bg-white/bg-light with bg-body/bg-body-secondary
- Update sticky table headers to dark theme
- Fix Chart.js legend and axis colors for dark backgrounds
- Adjust focus ring color for better visibility on dark
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use environment variables in docker-compose for secrets/paths
- Add .env.example template for required variables
- Add .env to .gitignore to prevent secret exposure
- Add docker-build-and-push.cmd helper script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- 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>
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>
- 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>
- 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>
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>
- 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>
- 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>
- 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>
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
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.
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.
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.
Changed Receipt property from non-nullable (null!) to nullable (?) to properly
handle cases where receipt is not found. Fixes CS8601 null reference assignment
warning.
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.
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.
- 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>