Commit Graph
100 Commits
Author SHA1 Message Date
ajandClaude Opus 4.5 65601c1fcb Chore: Improve Docker deployment configuration
- 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>
2025-12-05 21:33:17 -05:00
ajandClaude Opus 4.5 a5435b1549 Config: Set default culture to en-US for currency formatting
Ensures consistent $ currency display regardless of server locale

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 21:33:11 -05:00
ajandClaude Opus 4.5 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 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
ajandClaude 047f1e49b1 Fix date range filtering to show all transactions from bill date
Fixed bug where manual receipt mapping was only showing transactions near the due date instead of the full range from bill date to due date + 5 days. The issue was that we were taking only the top 100 most recent transactions before applying merchant relevance sorting, which cut off older transactions near the bill date.

Now the query retrieves ALL transactions within the date range (bill date to due date + 5), then sorts by merchant relevance and date. This ensures bills like electric bills show all transactions from the bill date through the payment date.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 19:15:09 -04:00
ajandClaude d5852f2bb3 Add automatic receipt parsing after upload
Receipts are now automatically parsed using OpenAI Vision API immediately after upload. The parsing runs in the background and triggers auto-mapping if successful. This streamlines the workflow - users just upload a receipt and it's automatically parsed and mapped to the matching transaction without any additional clicks.

The parsing happens asynchronously via Task.Run to not block the upload response. If parsing fails, the upload is still considered successful.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 17:51:19 -04:00
ajandClaude c29c94ab62 Update ARCHITECTURE.md with recent receipt management features
Updated documentation to reflect v1.2 changes:
- Unmapped receipts with nullable TransactionId
- Duplicate detection with blocking modal
- Auto-mapping service with intelligent date range logic
- Due date support for bills (bill date to due date + 5 days)
- Enhanced manual mapping UI with transaction selector
- Transactions page improvements (search, filters, ID column)
- New Receipts page with comprehensive workflow
- Updated service layer, database schema, and workflows sections

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 16:34:44 -04:00
ajandClaude c4c01ce8c6 Extend bill date range to include 5 days after due date
Updated both auto-mapping and manual mapping logic to search for transactions from bill date to due date + 5 days. This accounts for auto-pay processing delays, weekends, and bank processing times when bills are auto-paid on the due date.

This fixes the issue where electric bills and other auto-paid utilities were missing their matching transactions because the payment posted a few days after the due date.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 15:37:10 -04:00
ajandClaude 127c629d01 Move Upload CSV from navigation menu to Transactions page
Removed "Upload CSV" from the main navigation menu and added an "Upload CSV" button to the Transactions page header. This makes CSV upload more contextual since it's primarily used when viewing/managing transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 15:31:38 -04:00
ajandClaude bec2483583 Add auto-scroll to first amount match in receipt mapping modal
When opening the map receipt modal, the transaction list now automatically scrolls to center on the first green-highlighted amount match (if one exists). This makes it easier to quickly find and select the most likely matching transaction without having to manually scroll through the list.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 15:05:17 -04:00
ajandClaude 3b175753f4 Add due date support for bills and utility receipts
Enhanced receipt parsing and mapping to support bills with due dates (like utility bills):
- Updated OpenAI prompt to extract due date from bills
- Added DueDate property to Receipt model with database migration
- Modified auto-mapping logic to use bill date to due date range when both dates are present
- For regular receipts without due dates, continues to use ±3 day window
- Updated manual mapping UI to display due dates and adjust date range explanation
- Receipt list now shows due dates in orange "Due:" text for clarity

This allows electric bills and similar documents with 20+ day payment windows to be properly matched to their payment transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 14:52:44 -04:00
ajandClaude 3b2978dc9b Add transaction ID column to transactions page
Added ID column as the first column in the transactions table to make it easy to reference transaction IDs when manually mapping receipts. The ID is displayed with a "#" prefix in a small, muted style.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 14:19:51 -04:00
ajandClaude 3f97b34c54 Fix merchant filtering in receipt mapping to be non-exclusive
Changed merchant filtering from exclusionary to relevance-based sorting.
This fixes the issue where transactions don't appear if the merchant
name doesn't exactly match.

Changes:
- Date range (±3 days) remains the primary hard filter
- Merchant name now sorts results by relevance instead of excluding
- Retrieves 100 candidates, sorts by match quality, returns top 50
- Case-insensitive matching using ToLower()

Relevance Scoring:
- Score 3: Exact match on merchant or transaction name
- Score 2: Partial match on merchant name (Contains)
- Score 1: Partial match on transaction name (Contains)
- Score 0: No match (still included if within date range)

Results sorted by: Match score → Date → ID

Benefits:
- McDonald's receipt will show all transactions in date range
- Best matches appear at top
- No transactions excluded due to name variations
- More forgiving for typos, abbreviations, etc.
- User can still see and select any transaction in date window

Example: Receipt says "McDonald's" but transaction says "MCDONALD'S #1234"
- Before: Excluded (no exact Contains match)
- After: Included, sorted to top (partial match score 2)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 14:11:40 -04:00
ajandClaude 123367c7bf Convert duplicate warnings to blocking modal dialog
Changed duplicate detection from informational alert to a modal dialog
that requires user decision before proceeding with upload.

Upload Flow Changes:
1. Initial upload detects duplicates and uploads temporarily
2. If duplicates found:
   - Deletes the uploaded file
   - Stores warnings and filename in TempData
   - Redirects to show modal
3. Modal blocks with two options:
   - Cancel: Don't upload (returns to page)
   - Upload Anyway: Re-upload with confirmation flag

Modal Features:
- Non-dismissible (static backdrop, no keyboard close)
- Yellow warning header
- Table showing all potential duplicates with:
  - Receipt ID and filename
  - Upload timestamp
  - Reason for match (hash/name+size)
  - Transaction mapping status
  - View button to compare
- Clear explanation of options
- Prompts user to re-select file for confirmed upload

Benefits:
- Prevents accidental duplicate uploads
- Forces user acknowledgment
- Provides context for decision-making
- Links to view existing receipts for comparison
- Better UX than passive alert banner

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:39:43 -04:00
ajandClaude 7ac80ab8d0 Fix ToHashSet() compatibility issue in Receipts page
Changed from using .ToHashSet() extension method (which may not be
available in some EF Core versions) to .ToListAsync() followed by
creating a HashSet from the list.

This ensures compatibility across different EF Core versions while
maintaining the same performance characteristics.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:33:17 -04:00
ajandClaude cd7ca679ac Improve receipt mapping with smart filtering and table UI
Enhanced the receipt mapping modal with intelligent transaction filtering
and a clean table-based selection interface.

Smart Filtering (per receipt):
- If receipt has a date: Show transactions within ±3 days
- If receipt has merchant: Filter by merchant name match
- Calculate amount matches (within $0.10 tolerance)
- Only show transactions without receipts
- Limit to 50 most recent matches
- Fallback to recent 50 transactions if no matches

UI Improvements:
- Replaced confusing listbox with formatted data table
- Proper column alignment with fixed widths
- Sticky header for scrollable table (max 400px height)
- Clickable rows with radio button selection
- Visual feedback:
  - Green highlight for amount matches
  - Blue highlight for selected row
  - Hover effect on rows
- Context-aware helper text explaining filter criteria
- Shows which transactions match the receipt date range

Features:
- Click anywhere on row to select
- Radio buttons for explicit selection
- Hidden input field stores selected transaction ID
- Manual ID entry still available as fallback
- Clear visual indicators for best matches

This provides a much better UX for manual mapping by showing only
relevant transactions and making it easy to identify likely matches.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:31:14 -04:00
ajandClaude c6a01e120f Improve receipt mapping UI with transaction selector
Replaced the manual transaction ID input with a user-friendly
transaction selector dropdown in the map receipt modal.

Changes:
- Added RecentTransactions list to Receipts page model
- Load last 100 transactions without receipts for dropdown
- Updated modal dialog:
  - Larger modal (modal-lg) for better visibility
  - Multi-select dropdown showing formatted transaction details:
    - Date | Amount | Name | (Merchant)
  - Monospace font for aligned columns
  - Size 10 to show multiple options at once
  - Receipt info displayed in styled info box
  - Manual ID input field as fallback option
  - Link to Transactions page for finding IDs
  - Two-way binding between selector and manual input

User Experience:
- Users can now visually browse and select transactions
- Transaction details are formatted for easy scanning
- Only shows transactions that don't already have receipts
- Fallback to manual ID entry for edge cases
- Receipt parsed data clearly displayed for comparison

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:16:02 -04:00
ajandClaude a5bda6f94f Fix naming conflict in ReceiptAutoMapResult
Renamed static factory method from 'MultipleMatches' to
'WithMultipleMatches' to avoid conflict with the 'MultipleMatches'
property in the same class.

This resolves the compilation error: "The type 'ReceiptAutoMapResult'
already contains a definition for 'MultipleMatches'".

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:13:09 -04:00
ajandClaude 5511709a86 Add receipt auto-mapping functionality
Implemented automatic mapping of parsed receipts to matching
transactions, with both automatic (after parsing) and manual
(via button) triggers.

New Service - ReceiptAutoMapper:
- AutoMapReceiptAsync: Maps a single receipt to a transaction
- AutoMapUnmappedReceiptsAsync: Bulk maps all unmapped receipts
- FindMatchingTransactionsAsync: Smart matching algorithm using:
  - Receipt date (+/- 3 days for processing delays)
  - Merchant name (matches against transaction merchant or name)
  - Total amount (within $0.10 tolerance)
  - Excludes transactions that already have receipts
  - Returns single match, multiple matches, or no match

Matching Strategy:
- Single match: Automatically maps
- Multiple matches: Reports count for manual review
- No match: Reports for manual intervention
- Not parsed: Skips (requires merchant, date, or total)

Integration Points:
- OpenAIReceiptParser: Triggers auto-mapping after successful parse
  (only for unmapped receipts, errors ignored to not fail parse)
- Receipts page: Added "Auto-Map Unmapped Receipts" button
  - Only shows when unmapped parsed receipts exist
  - Displays detailed results (mapped count, no match, multi-match)

This enables a streamlined workflow:
1. Upload receipt → 2. Parse receipt → 3. Auto-map to transaction
Users can also trigger bulk auto-mapping for all unmapped receipts.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 13:07:35 -04:00
ajandClaude c0a6b1690f Add duplicate detection for receipt uploads
Implemented duplicate detection to warn users when uploading receipts
that may already exist in the system.

Changes:
- Extended ReceiptUploadResult to include DuplicateWarning list
- Added CheckForDuplicatesAsync method to ReceiptManager that checks:
  1. Identical file content (same SHA256 hash)
  2. Same file name and size (potential duplicate saved/edited)
- Updated upload flow to check for duplicates before saving
- Enhanced Receipts page to:
  - Display warning alert when duplicates are detected
  - Show details of each potential duplicate (receipt ID, filename,
    upload date, mapped transaction, and reason)
  - Provide quick link to view the duplicate receipt
  - Use TempData to persist warnings across redirect

Duplicate detection runs on every upload and provides actionable
information to help users avoid uploading the same receipt multiple
times. The check uses hash-based detection for exact duplicates and
name+size matching for potential duplicates.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 12:58:39 -04:00
ajandClaude c306ced9f0 Fix Receipt TransactionId nullable database migrations
The previous commit had the model changes but the database wasn't
properly migrated. This commit adds the missing migrations to make
TransactionId nullable in the Receipts table.

Changes:
- Updated MoneyMapContext to make Transaction relationship optional
  for Receipt (IsRequired(false))
- Created additional migrations to properly handle:
  - Making TransactionId column nullable
  - Updating the unique index to handle NULL values with WHERE clause
- Applied all migrations to database successfully

The Receipts page should now work correctly for uploading unmapped
receipts without a TransactionId.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 12:32:42 -04:00
ajandClaude 8eb07c43e0 Add Receipts page for managing unmapped receipts
Added functionality to upload and manage receipts without initially
associating them to a transaction, with the ability to map them later.

Changes:
- Modified Receipt model to make TransactionId nullable
- Updated ReceiptManager service with new methods:
  - UploadUnmappedReceiptAsync: Upload receipts without a transaction
  - MapReceiptToTransactionAsync: Map an existing receipt to a transaction
- Created Receipts page (Receipts.cshtml) with:
  - Upload form for new receipts
  - List view of all receipts (mapped and unmapped)
  - Status badges (Mapped/Unmapped)
  - Map to Transaction modal dialog
  - Delete receipt functionality
- Added "Receipts" link to navigation menu
- Fixed Transactions page receipt count query for nullable TransactionId
- Created migration: MakeReceiptTransactionIdNullable

This enables workflows where receipts are uploaded first and matched
to transactions later, useful for batch receipt processing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 11:28:33 -04:00
ajandClaude eb6d83f589 Add quick date range selectors to transactions page
Added convenient buttons for common date ranges:
- Last 30 Days
- Last 60 Days
- Last 90 Days
- Last Year
- This Month
- Last Month

Clicking these buttons automatically populates the Start Date and End
Date filter fields. Users can still manually adjust the dates or use
the Filter button to apply the selected range.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 11:10:43 -04:00
ajandClaude 61c9490eeb Add search functionality to transactions page
Added a search bar that allows users to filter transactions by:
- Transaction name
- Memo
- Category
- Notes
- Merchant name

The search uses a case-sensitive contains filter across all these
fields. The search parameter is preserved across pagination links and
included in the "Clear Filters" button logic.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 11:06:50 -04:00
ajandClaude 158ae139f0 Fix category filter for uncategorized transactions
Previously, selecting "(blank)" from the category dropdown would submit
an empty string value, causing no transactions to appear. The backend
expects the literal string "(blank)" to filter for uncategorized items.

Updated the dropdown to submit "(blank)" as the value when the category
is empty, matching the backend's filter logic in Transactions.cshtml.cs.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 11:04:05 -04:00
ajandClaude 1aecbf14fe Fix decimal precision for CategoryMapping.Confidence field
Add explicit column type configuration for Confidence field to avoid
SQL Server truncation warnings. Use decimal(5,4) to store values from
0.0000 to 1.0000 with 4 decimal places of precision.

Also add MaxLength constraint for CreatedBy field.

Migration applied successfully to database.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:51:47 -04:00
ajandClaude 5723ac26da Implement Phase 1: AI-powered categorization with manual review
Add AI categorization service that suggests categories, merchants, and
rules for uncategorized transactions. Users can review and approve
suggestions before applying them.

Features:
- TransactionAICategorizer service using OpenAI GPT-4o-mini
- Batch processing (5 transactions at a time) to avoid rate limits
- Confidence scoring (0-100%) for each suggestion
- AI suggests category, canonical merchant name, and pattern rule
- ReviewAISuggestions page to list uncategorized transactions
- ReviewAISuggestionsWithProposals page for manual review
- Apply individual suggestions or bulk apply high confidence (≥80%)
- Optional rule creation for future auto-categorization
- Cost: ~$0.00015 per transaction (~$0.015 per 100)

CategoryMapping enhancements:
- Confidence field to track AI confidence score
- CreatedBy field ("AI" or "User") to track rule origin
- CreatedAt timestamp for audit trail

Updated ARCHITECTURE.md with complete documentation of:
- TransactionAICategorizer service details
- ReviewAISuggestions page descriptions
- AI categorization workflow (Phase 1)
- Updated CategoryMappings schema

Next steps (Phase 2):
- Auto-apply high confidence suggestions
- Background job processing
- Batch API requests for better efficiency

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:47:31 -04:00
ajandClaude b4358fefd3 Add reminders to update ARCHITECTURE.md when making changes
Add prominent reminders in both CLAUDE.md and AGENTS.md to update
the shared ARCHITECTURE.md file when making architectural changes.
This helps ensure the documentation stays current and both AI tools
have accurate context.

Changes include:
- Added step in development workflow to update docs
- Added "Important: Keep Documentation Updated" section
- Listed specific types of changes that require doc updates
- Emphasized that this keeps both tools in sync

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:29:07 -04:00
ajandClaude cecdd63767 Restructure documentation for DRY principle
Split documentation into three files to eliminate duplication:
- ARCHITECTURE.md: Shared technical documentation (domain models,
  services, database schema, workflows, patterns)
- CLAUDE.md: Claude Code-specific context referencing ARCHITECTURE.md
- AGENTS.md: Codex agent context referencing ARCHITECTURE.md

This allows both Claude Code and Codex CLI to share the same source
of truth for architecture details while maintaining tool-specific
configuration in separate files.

Benefits:
- Single source of truth for technical details
- Easier maintenance (update once, not twice)
- Consistent documentation across tools
- Clear separation of concerns

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:24:08 -04:00
ajandClaude b2fa1d47a8 Add average cost per transaction to top expense categories
Display the average spend per transaction for each category on the
dashboard's top expense categories table. This helps users understand
spending patterns beyond just total amounts.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:11:17 -04:00
ajandClaude 98df8b6240 Include Merchant relationship when loading transactions
Ensure merchant data is eagerly loaded when querying transactions
on the Transactions page to avoid N+1 queries.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:08:47 -04:00
ajandClaude 6f307be026 Add merchant selection to EditTransaction page
Allow users to set or change the merchant for a transaction from the
EditTransaction page. Users can select from existing merchants or
create new ones on the fly.

Changes:
- Add merchant dropdown with existing merchants
- Support creating new merchants via custom input
- Update transaction merchant when saving
- Rename "Merchant Name" label to "Transaction Name" for clarity

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:08:31 -04:00
ajandClaude 1e060c10f5 Add Merchants management page with modal edit/delete
Created a dedicated page for viewing and managing merchants:

**Backend (Merchants.cshtml.cs):**
- List all merchants with transaction and mapping counts
- Add new merchant with duplicate name validation
- Edit merchant name (updates all linked transactions/mappings)
- Delete merchant (unlinks from transactions/mappings via SET NULL)
- Full CRUD operations with proper validation

**Frontend (Merchants.cshtml):**
- Clean table view showing merchant name, transaction count, mapping count
- Add modal for creating new merchants
- Edit modal for renaming merchants (click row or Edit button)
- Delete with confirmation showing impact (# of transactions/mappings)
- Success/error message display
- Responsive Bootstrap layout

**Navigation:**
- Added "Merchants" link to main navigation bar
- Positioned between "Categories" and "Recategorize"

**Features:**
- Shows transaction count per merchant (useful for seeing merchant usage)
- Shows mapping count per merchant (useful for seeing pattern coverage)
- Inline edit with modal dialog (consistent with CategoryMappings UI)
- Safe delete with SET NULL (transactions/mappings remain, just unlinked)
- Duplicate name prevention on add/edit

**Benefits:**
- Easy merchant management without SQL queries
- Visual feedback on merchant usage
- Rename propagates to all transactions/mappings automatically
- Consistent UI with rest of application

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 04:03:23 -04:00
ajandClaude 45077a0029 Add autocomplete dropdowns for category and merchant in CategoryMappings
Improved UX for adding/editing category mappings:

**Backend Changes:**
- Added AvailableCategories list (distinct categories from existing mappings)
- Added AvailableMerchants list (all merchants from Merchants table)
- Updated LoadDataAsync() to populate both lists

**UI Changes:**
- Replaced plain text input with HTML5 datalist for Category field
- Replaced plain text input with HTML5 datalist for Merchant field
- Both fields support autocomplete while allowing new values
- Added "required" attribute to Category field for validation
- Added helper text to guide users
- Removed custom JavaScript dropdown logic (now using native datalist)

**Benefits:**
- Consistent category naming (autocomplete suggests existing categories)
- Consistent merchant naming (autocomplete suggests existing merchants)
- Better UX with native browser autocomplete behavior
- Still allows creating new categories/merchants on the fly
- Cleaner, simpler code without custom dropdown implementation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 03:58:56 -04:00
ajandClaude b1143ad484 Convert merchant from string to entity with foreign keys
This refactors the merchant field from a simple string column to a normalized
entity with proper foreign key relationships:

**Database Changes:**
- Created Merchant entity/table with unique Name constraint
- Replaced Transaction.Merchant (string) with Transaction.MerchantId (FK)
- Replaced CategoryMapping.Merchant (string) with CategoryMapping.MerchantId (FK)
- Added proper foreign key constraints with SET NULL on delete
- Added indexes on MerchantId columns for performance

**Backend Changes:**
- Created MerchantService for finding/creating merchants
- Updated CategorizationResult to return MerchantId instead of merchant name
- Modified TransactionCategorizer to return MerchantId from pattern matches
- Updated Upload, Recategorize, and CategoryMappings to use merchant service
- Updated OpenAIReceiptParser to create/link merchants from parsed receipts
- Registered IMerchantService in dependency injection

**UI Changes:**
- Updated CategoryMappings UI to handle merchant entities (display as Merchant.Name)
- Updated Transactions page merchant filter to query by merchant entity
- Modified category mapping add/edit/import to create merchants on-the-fly
- Updated JavaScript to pass merchant names for edit modal

**Migration:**
- ConvertMerchantToEntity migration handles schema conversion
- Drops old string columns and creates new FK relationships
- All existing merchant data is lost (acceptable for this refactoring)

**Benefits:**
- Database normalization - merchants stored once, referenced many times
- Referential integrity with foreign keys
- Easier merchant management (rename once, updates everywhere)
- Foundation for future merchant features (logos, categories, etc.)
- Improved query performance with proper indexes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 03:52:05 -04:00
ajandClaude 675ffa6509 Add merchant field to transactions and category mappings
This feature enables easy filtering and identification of transactions by merchant name:
- Added Merchant column to Transaction model (nullable, max 100 chars)
- Added Merchant field to CategoryMapping model
- Modified ITransactionCategorizer to return CategorizationResult (category + merchant)
- Updated auto-categorization logic to assign merchant from category mappings
- Updated category mappings UI to include merchant field in add/edit forms
- Added merchant filter dropdown to transactions page with full pagination support
- Updated receipt parser to set transaction merchant from parsed receipt data
- Created two database migrations for the schema changes
- Updated helper methods to support merchant names in default mappings

Benefits:
- Consistent merchant naming across variant patterns (e.g., "Walmart" for all "WAL-MART*" patterns)
- Easy filtering by merchant on transactions page
- No CSV changes required - merchant is derived from category mapping patterns
- Receipt parsing can also populate merchant field automatically

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 03:21:31 -04:00
ajandClaude ecb7851a62 Add percentage of total to top expense categories on dashboard
Show what percentage of total expenses each category represents in the top categories table. This helps quickly identify which categories consume the largest portion of spending.

Changes:
- Add PercentageOfTotal property to TopCategoryRow
- Calculate percentage based on total expenses in the period
- Display percentage as a badge in the table (e.g., "23.5%")
- Add new "% of Total" column header
- Format to 1 decimal place for clarity

Example: If "Groceries" is $500 and total expenses are $2000, it shows 25.0%

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 02:13:57 -04:00
ajandClaude 52615eeb75 Add JSON export/import functionality for category mappings
Add the ability to export and import category mappings as JSON files:

Export:
- Downloads all category mappings as a formatted JSON file
- Ordered by category and priority

Import:
- Upload JSON file with category mappings
- Option to replace all existing mappings or merge with current ones
- Validates JSON format and data integrity
- Shows clear error messages for invalid files

UI additions:
- Export to JSON button in header
- Import from JSON button with modal dialog
- Shows example JSON format in import modal
- Replace/merge option with clear explanation

This allows users to:
- Backup their custom category mappings
- Share mappings between instances
- Version control their categorization rules
- Easily restore default or custom configurations

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 01:27:19 -04:00
ajandClaude 977a8de9f9 Include transaction name in receipt parsing prompt
Pass the transaction name from the bank statement to OpenAI when parsing receipts. This helps identify merchants when receipts have cryptic or unclear merchant names (e.g., Arby's receipts).

The transaction name is included as additional context in the prompt: "This transaction was recorded as 'XXX' in the bank statement, which may help identify the merchant if the receipt is unclear."

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:35:54 -04:00
ajandClaude 07fb1d1452 Remove Cards link from main navigation
Remove the Cards navigation item since card management is now nested under the Accounts page. Users access cards by navigating to Accounts -> View Account -> Manage Cards.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:30:34 -04:00
ajandClaude c409e7ad5b Update card editing to redirect to account details
Modify EditCard page to:
- Accept optional accountId parameter to pre-select account for new cards
- Redirect to AccountDetails page after save (if card has linked account)
- Update navigation to go back to Accounts instead of Cards page

This integrates card management into the account-centric workflow.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:30:25 -04:00
ajandClaude be12d9e53e Update Accounts page to link to account details
Make account rows clickable and add View button to navigate to the new AccountDetails page where users can see account info and manage linked cards.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:30:14 -04:00
ajandClaude e0dabdc46d Add account details page with card management
Create a new AccountDetails page that shows account information and all linked cards. This replaces the standalone Cards page and nests card management under accounts, as cards are always linked to accounts.

Features:
- View account details (institution, type, owner, etc.)
- List all cards linked to the account
- Add new cards directly from the account page
- Edit and delete cards within the account context
- Click-through navigation from Accounts list

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:30:05 -04:00
ajandClaude 3153bd50aa Filter duplicate check by date range for better performance
Optimize duplicate detection to only query existing transactions within the date range of the uploaded CSV file (plus 1-day buffer). This prevents loading the entire transaction history into memory when checking duplicates.

For example, uploading 2800 transactions from Jan-Mar 2024 will now only load existing transactions from that period rather than all historical transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:22:02 -04:00
ajandClaude e481c58464 Increase session timeout for large transaction uploads
Extend session IOTimeout to 5 minutes to accommodate serialization and storage of large transaction preview datasets (e.g., 2800+ transactions).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:17:54 -04:00
ajandClaude c44929afe1 Add pagination to transaction preview for large imports
When uploading files with more than 100 transactions, the preview now displays transactions in pages of 100 rows at a time. This prevents browser freezing when rendering thousands of form inputs and dramatically improves page load performance.

- Show first 100 transactions by default with pagination controls
- All transactions remain in DOM but hidden for instant page switching
- Update counters and form submission to work across all pages

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:17:46 -04:00
ajandClaude 3d6b47d537 Optimize transaction preview duplicate checking for large imports
Improve performance when uploading thousands of transactions by loading all existing transactions into memory once for duplicate detection, rather than running individual database queries for each transaction. This reduces database calls from O(n) to O(1) for n transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 22:17:37 -04:00
ajandClaude 40135ab6d6 Update UI for account-card relationship and transfers
- Updated EditTransaction to handle account selection and card filtering
- Added Transfers link to navigation menu
- Updated Transactions page to properly display account labels
- Refined Upload preview UI for account/card selection

These changes support the new account-centric model where every
transaction belongs to an account and optionally uses a card.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 20:54:20 -04:00
ajandClaude 7f74cd8c29 Add transfer support between accounts
- Added TransferToAccountId to Transaction model for linking transfers
- Created CreateTransfer page for recording account-to-account transfers
- Migration adds the new foreign key relationship
- Transfers are created as paired transactions (debit and credit)

This enables tracking of money movement between bank accounts while
maintaining proper accounting with matching transaction pairs.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 20:54:09 -04:00
ajandClaude 83ef8480c1 Add migration to make AccountId required on transactions
Changed Transaction.AccountId from optional to required, reflecting that
every transaction must belong to an account (the source of the CSV file).
Cards remain optional as they represent the payment method used.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 20:53:58 -04:00
ajandClaude 338374f831 Enhance card management with account linking and nicknames
- Added account linking functionality to cards with dropdown selector
- Added optional nickname field for easier card identification
- Updated Cards list page to show linked accounts with badges
- Reorganized card display to show issuer and last4 together
- Include account relationship when loading cards

This allows cards to be properly associated with their bank accounts,
which is essential for the transaction import and categorization flow.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 20:53:46 -04:00
ajandClaude eb3e9c5407 Simplify payment column display in transactions table
Condensed the verbose payment method labels to show only the essential
information:
- Card transactions: Show just the card name (e.g., "AJ's Debit Card")
- Direct account transactions: Show just the account name
- Transfers: Show "Transfer → [Destination]"

Removed duplicate display of account information since cards are
already linked to accounts. This makes the Payment/Account column
much less crowded and easier to read.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 20:50:34 -04:00