59 lines
2.0 KiB
C#
59 lines
2.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
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<Account> AffectedAccounts,
|
|
DateTimeOffset TimeStamp);
|
|
|
|
public interface IReversalQuery
|
|
{
|
|
Task<ReversalData?> GetReversalDataAsync(Guid journalEntryId);
|
|
}
|
|
|
|
public static class ReverseJournalHandler
|
|
{
|
|
public static async Task<ReversalData?> 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");
|
|
}
|
|
|
|
public static (
|
|
IStorageAction<JournalEntry> JournalWrite,
|
|
UnitOfWork<Account> AccountWrites,
|
|
JournalReversedEvent Event) Handle(ReverseJournalCommand cmd, ReversalData data)
|
|
{
|
|
var reversalJournal =
|
|
BalancedJournal.CreateReversal(data.OriginalJournalEntry, $"Reversal: {cmd.Reason}", data.TimeStamp);
|
|
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<Account>();
|
|
foreach (var account in accountState.Values)
|
|
{
|
|
accountUow.Update(account);
|
|
}
|
|
|
|
return (
|
|
Storage.Insert(reversalJournal.Entry),
|
|
accountUow,
|
|
new JournalReversedEvent(cmd.OriginalJournalId, reversalJournal.Entry.Id)
|
|
);
|
|
}
|
|
} |