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>
This commit is contained in:
AJ
2025-10-12 19:17:16 -04:00
parent 047f1e49b1
commit c7089dba98
3 changed files with 31 additions and 7 deletions

View File

@@ -314,7 +314,7 @@
{ {
<span>Showing recent transactions without receipts.</span> <span>Showing recent transactions without receipts.</span>
} }
Rows highlighted in <span class="badge bg-success">green</span> have matching amounts. Rows highlighted in <span class="badge bg-success">green</span> have matching amounts (within ±2%). Only showing transactions within ±10% of receipt total.
</div> </div>
<input type="hidden" id="transactionId@(r.Id)" name="transactionId" required /> <input type="hidden" id="transactionId@(r.Id)" name="transactionId" required />
<div id="transactionListContainer@(r.Id)" style="max-height: 400px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 0.25rem;"> <div id="transactionListContainer@(r.Id)" style="max-height: 400px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 0.25rem;">

View File

@@ -294,6 +294,23 @@ namespace MoneyMap.Pages
.ToList(); .ToList();
} }
// Filter by amount (±10% tolerance) if receipt has a total
if (receipt.Total.HasValue)
{
var receiptTotal = Math.Abs(receipt.Total.Value);
var tolerance = receiptTotal * 0.10m; // 10% tolerance
var minAmount = receiptTotal - tolerance;
var maxAmount = receiptTotal + tolerance;
candidates = candidates
.Where(t =>
{
var transactionAmount = Math.Abs(t.Amount);
return transactionAmount >= minAmount && transactionAmount <= maxAmount;
})
.ToList();
}
// Calculate match scores and mark close amount matches // Calculate match scores and mark close amount matches
var options = candidates.Select(t => var options = candidates.Select(t =>
{ {
@@ -308,12 +325,13 @@ namespace MoneyMap.Pages
IsAmountMatch = false IsAmountMatch = false
}; };
// Check if amount matches within tolerance // Check if amount matches within tighter tolerance for highlighting (±2%)
if (receipt.Total.HasValue) if (receipt.Total.HasValue)
{ {
var receiptTotal = Math.Abs(receipt.Total.Value); var receiptTotal = Math.Abs(receipt.Total.Value);
var transactionAmount = Math.Abs(t.Amount); var transactionAmount = Math.Abs(t.Amount);
option.IsAmountMatch = Math.Abs(transactionAmount - receiptTotal) <= 0.10m; var tightTolerance = receiptTotal * 0.02m; // 2% for green highlighting
option.IsAmountMatch = Math.Abs(transactionAmount - receiptTotal) <= tightTolerance;
} }
return option; return option;

View File

@@ -130,14 +130,20 @@ namespace MoneyMap.Services
// Get candidates // Get candidates
var candidates = await query.ToListAsync(); var candidates = await query.ToListAsync();
// If we have a total amount, filter by amount match // If we have a total amount, filter by amount match (±10% tolerance)
if (receipt.Total.HasValue) if (receipt.Total.HasValue)
{ {
// Allow for slight variations in amount (e.g., due to rounding)
// Match if transaction amount is within $0.10 of receipt total
var receiptTotal = Math.Abs(receipt.Total.Value); var receiptTotal = Math.Abs(receipt.Total.Value);
var tolerance = receiptTotal * 0.10m; // 10% tolerance
var minAmount = receiptTotal - tolerance;
var maxAmount = receiptTotal + tolerance;
candidates = candidates candidates = candidates
.Where(t => Math.Abs(Math.Abs(t.Amount) - receiptTotal) <= 0.10m) .Where(t =>
{
var transactionAmount = Math.Abs(t.Amount);
return transactionAmount >= minAmount && transactionAmount <= maxAmount;
})
.ToList(); .ToList();
} }