Skip to content

Commit

Permalink
#398 - Edit income amount.
Browse files Browse the repository at this point in the history
  • Loading branch information
maraf committed Jun 22, 2021
1 parent 7f5f9a7 commit ade679e
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/Money.Api.Shared/Api/Routing/CommandMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public CommandMapper()
Add<DeleteOutcome>("outcome-delete");

Add<CreateIncome>("income-create");
Add<ChangeIncomeAmount>("income-change-amount");
Add<DeleteIncome>("income-delete");

Add<CreateCategory>("category-create");
Expand Down
3 changes: 2 additions & 1 deletion src/Money.Api/Domain/Hubs/ApiHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class ApiHub : Hub,
IEventHandler<CurrencyCreated>, IEventHandler<CurrencyDeleted>, IEventHandler<CurrencyDefaultChanged>, IEventHandler<CurrencySymbolChanged>,
IEventHandler<CurrencyExchangeRateSet>, IEventHandler<CurrencyExchangeRateRemoved>,
IEventHandler<OutcomeCreated>, IEventHandler<OutcomeDeleted>, IEventHandler<OutcomeAmountChanged>, IEventHandler<OutcomeDescriptionChanged>, IEventHandler<OutcomeWhenChanged>,
IEventHandler<IncomeCreated>, IEventHandler<IncomeDeleted>,
IEventHandler<IncomeCreated>, IEventHandler<IncomeAmountChanged>, IEventHandler<IncomeDeleted>,
IEventHandler<PasswordChanged>, IEventHandler<EmailChanged>, IEventHandler<UserPropertyChanged>
{
private readonly FormatterContainer formatters;
Expand Down Expand Up @@ -133,6 +133,7 @@ private Task RaiseEvent<T>(T payload)
Task IEventHandler<OutcomeWhenChanged>.HandleAsync(OutcomeWhenChanged payload) => RaiseEvent(payload);

Task IEventHandler<IncomeCreated>.HandleAsync(IncomeCreated payload) => RaiseEvent(payload);
Task IEventHandler<IncomeAmountChanged>.HandleAsync(IncomeAmountChanged payload) => RaiseEvent(payload);
Task IEventHandler<IncomeDeleted>.HandleAsync(IncomeDeleted payload) => RaiseEvent(payload);

Task IEventHandler<PasswordChanged>.HandleAsync(PasswordChanged payload) => RaiseEvent(payload);
Expand Down
15 changes: 15 additions & 0 deletions src/Money.Models.Builders/IncomeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace Money.Models.Builders
{
public class IncomeBuilder : IEventHandler<IncomeCreated>,
IEventHandler<IncomeAmountChanged>,
IEventHandler<IncomeDeleted>,
IQueryHandler<GetTotalMonthIncome, Price>,
IQueryHandler<ListMonthIncome, List<IncomeOverviewModel>>
Expand All @@ -43,6 +44,20 @@ public async Task HandleAsync(IncomeCreated payload)
}
}

public async Task HandleAsync(IncomeAmountChanged payload)
{
using (ReadModelContext db = dbFactory.Create())
{
IncomeEntity entity = await db.Incomes.FindAsync(payload.AggregateKey.AsGuidKey().Guid);
if (entity != null)
{
entity.Amount = payload.NewValue.Value;
entity.Currency = payload.NewValue.Currency;
await db.SaveChangesAsync();
}
}
}

public async Task HandleAsync(IncomeDeleted payload)
{
using (ReadModelContext db = dbFactory.Create())
Expand Down
41 changes: 41 additions & 0 deletions src/Money/Commands/ChangeIncomeAmount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Neptuo;
using Neptuo.Commands;
using Neptuo.Models.Keys;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Commands
{
/// <summary>
/// Changes an <see cref="Amount"/> of the income with <see cref="IncomeKey"/>.
/// </summary>
public class ChangeIncomeAmount : Command
{
/// <summary>
/// Gets a key of the income to modify.
/// </summary>
public IKey IncomeKey { get; private set; }

/// <summary>
/// Gets a new income value.
/// </summary>
public Price Amount { get; private set; }

/// <summary>
/// Changes an <paramref name="amount"/> of the income with <paramref name="key"/>.
/// </summary>
/// <param name="incomeKey">A key of the income to modify.</param>
/// <param name="amount">A new income value.</param>
public ChangeIncomeAmount(IKey incomeKey, Price amount)
{
Ensure.Condition.NotEmptyKey(incomeKey);
Ensure.NotNull(amount, "amount");
IncomeKey = incomeKey;
Amount = amount;
}
}
}
4 changes: 3 additions & 1 deletion src/Money/Commands/Handlers/IncomeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ namespace Money.Commands.Handlers
{
public class IncomeHandler : AggregateRootCommandHandler<Income>,
ICommandHandler<Envelope<CreateIncome>>,
ICommandHandler<Envelope<DeleteIncome>>
ICommandHandler<Envelope<DeleteIncome>>,
ICommandHandler<Envelope<ChangeIncomeAmount>>
{
public IncomeHandler(IFactory<IRepository<Income, IKey>> repositoryFactory)
: base(repositoryFactory)
{ }

public Task HandleAsync(Envelope<CreateIncome> envelope) => WithCommand(envelope.Body.Key).Execute(envelope, () => new Income(envelope.Body.Amount, envelope.Body.Description, envelope.Body.When));
public Task HandleAsync(Envelope<ChangeIncomeAmount> envelope) => WithCommand(envelope.Body.Key).Execute(envelope.Body.IncomeKey, envelope, model => model.ChangeAmount(envelope.Body.Amount));
public Task HandleAsync(Envelope<DeleteIncome> envelope) => WithCommand(envelope.Body.Key).Execute(envelope.Body.IncomeKey, envelope, model => model.Delete());
}
}
31 changes: 31 additions & 0 deletions src/Money/Events/IncomeAmountChanged.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Events
{
/// <summary>
/// An event raised when an amount of income has changed.
/// </summary>
public class IncomeAmountChanged : UserEvent
{
/// <summary>
/// Gets an original value of the income.
/// </summary>
public Price OldValue { get; private set; }

/// <summary>
/// Gets a new value of the income.
/// </summary>
public Price NewValue { get; private set; }

internal IncomeAmountChanged(Price oldValue, Price newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
}
}
23 changes: 23 additions & 0 deletions src/Money/Income.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace Money
/// </summary>
public class Income : AggregateRoot,
IEventHandler<IncomeCreated>,
IEventHandler<IncomeAmountChanged>,
IEventHandler<IncomeDeleted>
{
public bool IsDeleted { get; private set; }
Expand Down Expand Up @@ -51,6 +52,20 @@ public Income(IKey key, IEnumerable<IEvent> events)
: base(key, events)
{ }

private void EnsureNotDeleted()
{
if (IsDeleted)
throw new IncomeAlreadyDeletedException();
}

public void ChangeAmount(Price amount)
{
EnsureNotDeleted();

if (Amount != amount)
Publish(new IncomeAmountChanged(Amount, amount));
}

public void Delete() => Publish(new IncomeDeleted());

Task IEventHandler<IncomeCreated>.HandleAsync(IncomeCreated payload)
Expand All @@ -63,6 +78,14 @@ Task IEventHandler<IncomeCreated>.HandleAsync(IncomeCreated payload)
});
}

Task IEventHandler<IncomeAmountChanged>.HandleAsync(IncomeAmountChanged payload)
{
return UpdateState(() =>
{
Amount = payload.NewValue;
});
}

Task IEventHandler<IncomeDeleted>.HandleAsync(IncomeDeleted payload)
{
return UpdateState(() =>
Expand Down
16 changes: 16 additions & 0 deletions src/Money/IncomeAlreadyDeletedException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Neptuo.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money
{
/// <summary>
/// An exception raised when trying to modify an income that is already deleted.
/// </summary>
public class IncomeAlreadyDeletedException : AggregateRootException
{ }
}

0 comments on commit ade679e

Please sign in to comment.