I need a projection which is used to store the total amount of money paid into an account, and the total amount withdrawn, over time. (NOT the balance, e.g. if 500 is pay in, and then 200 withdrawn, I'd want to know 500 was paid in, and 200 was taken out, not just the balance).
Each transaction is an aggregate document, and creating it raises a CreateTransactionEvent in Marten. I was thinking of a multistream projection that looks something like:
public InOutOverTime Create(IEvent<CreateTransactionEvent> @event, IQuerySession ops)
{
var totalMoneyIn = ops.Query<AccountTransaction>()
.Where(x => x.Amount > 0)
.Where(x => x.Date <= @event.Data.Date)
.Sum(x => x.Amount);
var totalMoneyOut = ops.Query<AccountTransaction>()
.Where(x => x.Amount < 0)
.Where(x => x.Date <= @event.Data.Date)
.Sum(x => x.Amount);
return new()
{
Date = @event.Data.Date,
Id = Guid.NewGuid(),
TotalMoneyIn = @event.Data.Amount > 0 ? @event.Data.Amount + totalMoneyIn : 0,
TotalMoneyOut = @event.Data.Amount < 0 ? @event.Data.Amount - totalMoneyIn : 0,
};
}
Which kinda works. However, in this particular case it is possible that a transaction can be added in the past. So given transactions like this:
2024-01-01 IN 500
2024-01-02 OUT 200
2024-01-05 IN 100
I'd want 3 InOutOverTime records like this:
2024-01-01, In: 500, out 0
2024-01-02, In: 500, out 200
2024-01-05, In: 600, out 200
If I then added a transaction 2024-01-03 OUT 100 the projection correctly creates this:
2024-01-03 IN: 500, out: 300 BUT I don't know how to specify that future projections need to be recalculated (e.g the 2024-01-05 row should update out to be 300).