using Microsoft.EntityFrameworkCore; using MoneyMap.Data; using MoneyMap.Models; namespace MoneyMap.Services; /// /// Service for core transaction operations including duplicate detection, /// retrieval, and deletion. /// public interface ITransactionService { /// /// Checks if a transaction is a duplicate based on date, amount, name, memo, /// account, and card. /// Task IsDuplicateAsync(Transaction transaction); /// /// Gets a transaction by ID with optional related data. /// Task GetTransactionByIdAsync(long id, bool includeRelated = false); /// /// Deletes a transaction and all related data (receipts, parse logs, line items). /// Task DeleteTransactionAsync(long id); } public class TransactionService : ITransactionService { private readonly MoneyMapContext _db; public TransactionService(MoneyMapContext db) { _db = db; } public async Task IsDuplicateAsync(Transaction transaction) { return await _db.Transactions.AnyAsync(t => t.Date == transaction.Date && t.Amount == transaction.Amount && t.Name == transaction.Name && t.Memo == transaction.Memo && t.AccountId == transaction.AccountId && t.CardId == transaction.CardId); } public async Task GetTransactionByIdAsync(long id, bool includeRelated = false) { var query = _db.Transactions.AsQueryable(); if (includeRelated) { query = query .Include(t => t.Card) .ThenInclude(c => c!.Account) .Include(t => t.Account) .Include(t => t.TransferToAccount) .Include(t => t.Merchant) .Include(t => t.Receipts) .ThenInclude(r => r.LineItems); } return await query.FirstOrDefaultAsync(t => t.Id == id); } public async Task DeleteTransactionAsync(long id) { var transaction = await _db.Transactions.FindAsync(id); if (transaction == null) return false; _db.Transactions.Remove(transaction); await _db.SaveChangesAsync(); return true; } }