diff --git a/MoneyMap/Pages/Receipts.cshtml.cs b/MoneyMap/Pages/Receipts.cshtml.cs index 1d57308..89f0ee3 100644 --- a/MoneyMap/Pages/Receipts.cshtml.cs +++ b/MoneyMap/Pages/Receipts.cshtml.cs @@ -232,7 +232,7 @@ namespace MoneyMap.Pages .Where(t => !transactionsWithReceipts.Contains(t.Id)) .AsQueryable(); - // If receipt has a date, filter by +/- 3 days + // If receipt has a date, filter by +/- 3 days (this is the primary filter) if (receipt.ReceiptDate.HasValue) { var minDate = receipt.ReceiptDate.Value.AddDays(-3); @@ -240,20 +240,50 @@ namespace MoneyMap.Pages query = query.Where(t => t.Date >= minDate && t.Date <= maxDate); } - // If receipt has merchant, filter by merchant name - if (!string.IsNullOrWhiteSpace(receipt.Merchant)) - { - query = query.Where(t => - (t.Merchant != null && t.Merchant.Name.Contains(receipt.Merchant)) || - t.Name.Contains(receipt.Merchant)); - } - + // Get all candidates within date range (don't filter by merchant in query) var candidates = await query .OrderByDescending(t => t.Date) .ThenByDescending(t => t.Id) - .Take(50) // Limit to 50 matches + .Take(100) // Get more candidates for sorting .ToListAsync(); + // If receipt has merchant, sort matches by relevance (but don't exclude) + if (!string.IsNullOrWhiteSpace(receipt.Merchant)) + { + var merchantLower = receipt.Merchant.ToLower(); + + // Sort: exact matches first, then partial matches, then others + candidates = candidates + .OrderByDescending(t => + { + var merchantName = t.Merchant?.Name?.ToLower() ?? ""; + var transactionName = t.Name?.ToLower() ?? ""; + + // Exact match on merchant or transaction name + if (merchantName == merchantLower || transactionName == merchantLower) + return 3; + + // Contains match on merchant + if (merchantName.Contains(merchantLower)) + return 2; + + // Contains match on transaction name + if (transactionName.Contains(merchantLower)) + return 1; + + // No match + return 0; + }) + .ThenByDescending(t => t.Date) + .Take(50) + .ToList(); + } + else + { + // No merchant filter, just take top 50 by date + candidates = candidates.Take(50).ToList(); + } + // Calculate match scores and mark close amount matches var options = candidates.Select(t => {