using FinancialApi.Domain; using Wolverine.Persistence; namespace FinancialApi.Application; public record ReverseJournalCommand(Guid OriginalJournalId, string Reason); public record JournalReversedEvent(Guid OriginalJournalId, Guid ReversalJournalId); public record ReversalData(JournalEntry OriginalJournalEntry, IReadOnlyList AffectedAccounts); public interface IReversalQuery { Task GetReversalDataAsync(Guid journalEntryId); } public static class ReverseJournalHandler { public static async Task LoadAsync(ReverseJournalCommand cmd, IReversalQuery query) { var data = await query.GetReversalDataAsync(cmd.OriginalJournalId); return data ?? throw new InvalidOperationException($"Journal Entry {cmd.OriginalJournalId} does not exist"); } public static ( IStorageAction JournalWrite, UnitOfWork AccountWrites, JournalReversedEvent Event) Handle(ReverseJournalCommand cmd, ReversalData data) { var reversalJournal = BalancedJournal.CreateReversal(data.OriginalJournalEntry, $"Reversal: {cmd.Reason}", DateTimeOffset.UtcNow); var accountState = data.AffectedAccounts.ToDictionary(a => a.Id); reversalJournal.Entry.Lines.ForEach(l => { var currentAccount = accountState[l.AccountId]; accountState[l.AccountId] = currentAccount.ApplyPosting(l.Amount, l.Type); }); var accountUow = new UnitOfWork(); foreach (var account in accountState.Values) { accountUow.Update(account); } return ( Storage.Insert(reversalJournal.Entry), accountUow, new JournalReversedEvent(cmd.OriginalJournalId, reversalJournal.Entry.Id) ); } }