diff --git a/wolverine/a-frame-architecture/FinancialApi.Application/ApplyFeeHandler.cs b/wolverine/a-frame-architecture/FinancialApi.Application/ApplyFeeHandler.cs index 9e2f715..fc1c144 100644 --- a/wolverine/a-frame-architecture/FinancialApi.Application/ApplyFeeHandler.cs +++ b/wolverine/a-frame-architecture/FinancialApi.Application/ApplyFeeHandler.cs @@ -8,13 +8,13 @@ public record ApplyFeeCommand(int AccountId, decimal Amount); public record FeeAppliedEvent(int AccountId, decimal Amount); -public record FeePair(Account Source, Account Destination); +public record FeePair(Account Source, Account Destination, DateTimeOffset TimeStamp); public static class ApplyFeeHandler { public static async Task LoadAsync( ApplyFeeCommand cmd, - IAccountQuery query) + IAccountQuery query, TimeProvider timeProvider) { var source = await query.FindByIdAsync(cmd.AccountId); var dest = await query.FindByIdAsync(99999); @@ -22,7 +22,8 @@ public static class ApplyFeeHandler { throw new InvalidOperationException($"Cannot process transfer. Account(s) not found."); } - return new FeePair(source, dest); + + return new FeePair(source, dest, timeProvider.GetUtcNow()); } public static ( @@ -45,7 +46,7 @@ public static class ApplyFeeHandler }; var journalEntry = BalancedJournal.Create(Guid.NewGuid(), $"Service Fee Applied: {cmd.Amount} to Account {cmd.AccountId}", - DateTimeOffset.UtcNow, lines); + pair.TimeStamp, lines); var @event = new FeeAppliedEvent(cmd.AccountId, cmd.Amount); diff --git a/wolverine/a-frame-architecture/FinancialApi.Application/FinancialEventHandler.cs b/wolverine/a-frame-architecture/FinancialApi.Application/FinancialEventHandler.cs index ed11aa3..4a6fdec 100644 --- a/wolverine/a-frame-architecture/FinancialApi.Application/FinancialEventHandler.cs +++ b/wolverine/a-frame-architecture/FinancialApi.Application/FinancialEventHandler.cs @@ -5,37 +5,33 @@ namespace FinancialApi.Application; public static class FinancialEventHandler { public static void Handle( - FeeAppliedEvent @event, - IEventTracker store, + FeeAppliedEvent @event, + IEventTracker store, ILogger logger) { var message = $"FeeApplied: ${@event.Amount} moved from Account {@event.AccountId} to Account 99999."; - logger.LogInformation("BACKGROUND EVENT FIRED: {Message}", message); - - // Save to our UI bucket store.Add(message); } public static void Handle( - FundsTransferredEvent @event, - IEventTracker store, + FundsTransferredEvent @event, + IEventTracker store, ILogger logger) { - var message = $"FundsTransferred: ${@event.Amount} moved from Account {@event.SourceAccountId} to Account {@event.DestinationAccountId}."; - + var message = + $"FundsTransferred: ${@event.Amount} moved from Account {@event.SourceAccountId} to Account {@event.DestinationAccountId}."; logger.LogInformation("BACKGROUND EVENT FIRED: {Message}", message); - - // Save to our UI bucket store.Add(message); } public static void Handle( - JournalReversedEvent @event, - IEventTracker store, + JournalReversedEvent @event, + IEventTracker store, ILogger logger) { - var message = $"JournalReversed: Original Entry {@event.OriginalJournalId} was reversed by Entry {@event.ReversalJournalId}."; + var message = + $"JournalReversed: Original Entry {@event.OriginalJournalId} was reversed by Entry {@event.ReversalJournalId}."; logger.LogInformation("BACKGROUND EVENT FIRED: {Message}", message); store.Add(message); } diff --git a/wolverine/a-frame-architecture/FinancialApi.Application/ReverseJournalHandler.cs b/wolverine/a-frame-architecture/FinancialApi.Application/ReverseJournalHandler.cs index 376cb8c..5ace1a9 100644 --- a/wolverine/a-frame-architecture/FinancialApi.Application/ReverseJournalHandler.cs +++ b/wolverine/a-frame-architecture/FinancialApi.Application/ReverseJournalHandler.cs @@ -7,7 +7,10 @@ public record ReverseJournalCommand(Guid OriginalJournalId, string Reason); public record JournalReversedEvent(Guid OriginalJournalId, Guid ReversalJournalId); -public record ReversalData(JournalEntry OriginalJournalEntry, IReadOnlyList AffectedAccounts); +public record ReversalData( + JournalEntry OriginalJournalEntry, + IReadOnlyList AffectedAccounts, + DateTimeOffset TimeStamp); public interface IReversalQuery { @@ -16,7 +19,8 @@ public interface IReversalQuery public static class ReverseJournalHandler { - public static async Task LoadAsync(ReverseJournalCommand cmd, IReversalQuery query) + public static async Task LoadAsync(ReverseJournalCommand cmd, IReversalQuery query, + TimeProvider timeProvider) { var data = await query.GetReversalDataAsync(cmd.OriginalJournalId); return data ?? throw new InvalidOperationException($"Journal Entry {cmd.OriginalJournalId} does not exist"); @@ -28,7 +32,7 @@ public static class ReverseJournalHandler JournalReversedEvent Event) Handle(ReverseJournalCommand cmd, ReversalData data) { var reversalJournal = - BalancedJournal.CreateReversal(data.OriginalJournalEntry, $"Reversal: {cmd.Reason}", DateTimeOffset.UtcNow); + BalancedJournal.CreateReversal(data.OriginalJournalEntry, $"Reversal: {cmd.Reason}", data.TimeStamp); var accountState = data.AffectedAccounts.ToDictionary(a => a.Id); reversalJournal.Entry.Lines.ForEach(l => @@ -41,6 +45,7 @@ public static class ReverseJournalHandler { accountUow.Update(account); } + return ( Storage.Insert(reversalJournal.Entry), accountUow, diff --git a/wolverine/a-frame-architecture/FinancialApi.Application/TransferFundsHandler.cs b/wolverine/a-frame-architecture/FinancialApi.Application/TransferFundsHandler.cs index f1d333c..f011ceb 100644 --- a/wolverine/a-frame-architecture/FinancialApi.Application/TransferFundsHandler.cs +++ b/wolverine/a-frame-architecture/FinancialApi.Application/TransferFundsHandler.cs @@ -13,18 +13,19 @@ public record TransferFundsCommand(int SourceAccountId, int DestinationAccountId public record FundsTransferredEvent(int SourceAccountId, int DestinationAccountId, decimal Amount); -public record TransferPair(Account Source, Account Destination); +public record TransferPair(Account Source, Account Destination, DateTimeOffset TimeStamp); public static class TransferFundsHandler { - public static async Task LoadAsync(TransferFundsCommand cmd, IAccountQuery query) + public static async Task LoadAsync(TransferFundsCommand cmd, IAccountQuery query, + TimeProvider timeProvider) { var source = await query.FindByIdAsync(cmd.SourceAccountId); var dest = await query.FindByIdAsync(cmd.DestinationAccountId); if (source == null || dest == null) return null; - return new TransferPair(source, dest); + return new TransferPair(source, dest, timeProvider.GetUtcNow()); } public static ( @@ -39,14 +40,14 @@ public static class TransferFundsHandler var lines = new List { - new (pair.Source.Id, cmd.Amount, EntryType.Debit), - new (pair.Destination.Id, cmd.Amount, EntryType.Credit) + new(pair.Source.Id, cmd.Amount, EntryType.Debit), + new(pair.Destination.Id, cmd.Amount, EntryType.Credit) }; var journalEntry = BalancedJournal.Create(Guid.NewGuid(), $"Transfer: {cmd.Amount} from {cmd.SourceAccountId} to {cmd.DestinationAccountId}", - DateTimeOffset.UtcNow, lines); + pair.TimeStamp, lines); var @event = new FundsTransferredEvent(cmd.SourceAccountId, cmd.DestinationAccountId, cmd.Amount); diff --git a/wolverine/a-frame-architecture/FinancialApi.Infrastructure/ReversalQuery.cs b/wolverine/a-frame-architecture/FinancialApi.Infrastructure/ReversalQuery.cs index d8d0a65..7daeaad 100644 --- a/wolverine/a-frame-architecture/FinancialApi.Infrastructure/ReversalQuery.cs +++ b/wolverine/a-frame-architecture/FinancialApi.Infrastructure/ReversalQuery.cs @@ -3,15 +3,11 @@ using Microsoft.EntityFrameworkCore; namespace FinancialApi.Infrastructure; -public class ReversalQuery : IReversalQuery +public class ReversalQuery(AccountDbContext db, TimeProvider timeProvider) : IReversalQuery { - private readonly AccountDbContext _db; - - public ReversalQuery(AccountDbContext db) => _db = db; - public async Task GetReversalDataAsync(Guid journalEntryId) { - var entry = await _db.JournalEntries + var entry = await db.JournalEntries .Include(x => x.Lines) .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == journalEntryId); @@ -23,11 +19,11 @@ public class ReversalQuery : IReversalQuery var accountIds = entry.Lines.Select(l => l.AccountId).Distinct().ToList(); - var accounts = await _db.Accounts + var accounts = await db.Accounts .AsNoTracking() .Where(a => accountIds.Contains(a.Id)) .ToListAsync(); - return new ReversalData(entry, accounts); + return new ReversalData(entry, accounts, timeProvider.GetUtcNow()); } } \ No newline at end of file