-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #180 from Brixel/feature/financial-years
Feature/financial years
- Loading branch information
Showing
44 changed files
with
2,221 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
Commands.Test/FinancialYear/When_adding_a_financial_year.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using Commands.Handlers.FinancialYear.AddFinancialYear; | ||
|
||
using Domain; | ||
using Domain.Interfaces; | ||
|
||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Options; | ||
|
||
using Moq; | ||
|
||
using Persistence; | ||
using Persistence.Repositories; | ||
|
||
using Xunit; | ||
|
||
namespace Commands.Test.FinancialYear; | ||
|
||
public class When_adding_a_financial_year | ||
{ | ||
private readonly Mock<IFinancialYearRepository> _financialYearRepositoryMock; | ||
private readonly HaSpManContext _haspmanDbContext; | ||
|
||
public When_adding_a_financial_year() | ||
{ | ||
_financialYearRepositoryMock = new Mock<IFinancialYearRepository>(); | ||
|
||
var financialYearConfigurationOptions = Options.Create(new FinancialYearConfiguration() | ||
{ | ||
StartDate = new DateTimeOffset(new DateTime(2022,9,1)), | ||
EndDate = new DateTimeOffset(new DateTime(2023,8,31)) | ||
}); | ||
|
||
_haspmanDbContext = new HaSpManContext(new DbContextOptionsBuilder<HaSpManContext>() | ||
.UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); | ||
SUT = new AddFinancialYearHandler(_financialYearRepositoryMock.Object, financialYearConfigurationOptions, | ||
_haspmanDbContext); | ||
} | ||
|
||
public AddFinancialYearHandler SUT { get; set; } | ||
|
||
|
||
|
||
|
||
public class And_no_financial_year_already_exists : When_adding_a_financial_year | ||
{ | ||
[Fact] | ||
public async Task It_should_add_a_new_financial_year() | ||
{ | ||
var startDate = new DateTimeOffset(new DateTime(DateTime.Now.Year, 9, 1)); | ||
var endDate = new DateTimeOffset(new DateTime(DateTime.Now.AddYears(1).Year, 8, 31)); | ||
_financialYearRepositoryMock | ||
.Setup(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.StartDate == startDate))) | ||
.Verifiable(); | ||
_financialYearRepositoryMock | ||
.Setup(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.EndDate == endDate))) | ||
.Verifiable(); | ||
|
||
await SUT.Handle(new AddFinancialYearCommand(), CancellationToken.None); | ||
|
||
_financialYearRepositoryMock | ||
.Verify(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.StartDate == startDate))); | ||
_financialYearRepositoryMock | ||
.Verify(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.EndDate == endDate))); | ||
|
||
} | ||
|
||
|
||
public class And_a_financial_year_already_exists : When_adding_a_financial_year | ||
{ | ||
[Fact] | ||
public async Task It_should_add_a_new_financial_year_following_the_last_year() | ||
{ | ||
|
||
var startDate = new DateTimeOffset(new DateTime(2023, 9, 1)); | ||
|
||
var endDate = new DateTimeOffset(new DateTime(2024, 8, 31)); | ||
_financialYearRepositoryMock | ||
.Setup(x => | ||
x.GetMostRecentAsync(It.IsAny<CancellationToken>())) | ||
.ReturnsAsync(new Domain.FinancialYear(new DateTimeOffset(new DateTime(2022, 9, 1)), | ||
new DateTimeOffset(new DateTime(2023,8,31)), new List<Domain.Transaction>())); | ||
|
||
_financialYearRepositoryMock | ||
.Setup(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.StartDate == startDate))) | ||
.Verifiable(); | ||
_financialYearRepositoryMock | ||
.Setup(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.EndDate == endDate))) | ||
.Verifiable(); | ||
|
||
await SUT.Handle(new AddFinancialYearCommand(), CancellationToken.None); | ||
|
||
_financialYearRepositoryMock | ||
.Verify(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.StartDate == startDate))); | ||
_financialYearRepositoryMock | ||
.Verify(x => | ||
x.Add(It.Is<Domain.FinancialYear>(financialYear => financialYear.EndDate == endDate))); | ||
|
||
} | ||
} | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
Commands.Test/FinancialYear/When_closing_a_financial_year.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Commands.Handlers.FinancialYear.CloseFinancialYear; | ||
|
||
using Domain; | ||
using Domain.Interfaces; | ||
|
||
using FluentAssertions; | ||
|
||
using Moq; | ||
|
||
using Persistence.Repositories; | ||
|
||
using Xunit; | ||
|
||
namespace Commands.Test.FinancialYear; | ||
|
||
public class When_closing_a_financial_year | ||
{ | ||
private readonly Mock<IFinancialYearRepository> _financialYearRepositoryMock; | ||
|
||
public When_closing_a_financial_year() | ||
{ | ||
_financialYearRepositoryMock = new Mock<IFinancialYearRepository>(); | ||
SUT = new CloseFinancialYearHandler(_financialYearRepositoryMock.Object); | ||
} | ||
|
||
public CloseFinancialYearHandler SUT { get; set; } | ||
|
||
[Fact] | ||
public async Task It_should_mark_the_year_as_closed() | ||
{ | ||
var startDate = DateTimeOffset.Now; | ||
var financialYear = new Domain.FinancialYear(startDate, startDate.AddYears(1).AddDays(-1), new List<Domain.Transaction>()); | ||
_financialYearRepositoryMock | ||
.Setup(x => x.GetByIdAsync(financialYear.Id, CancellationToken.None)) | ||
.ReturnsAsync(financialYear); | ||
; await SUT.Handle(new CloseFinancialYearCommand(financialYear.Id), CancellationToken.None); | ||
|
||
financialYear.IsClosed.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public async Task It_should_mark_all_related_transactions_as_as_locked() | ||
{ | ||
var startDate = DateTimeOffset.Now; | ||
var financialYear = new Domain.FinancialYear(startDate, startDate.AddYears(1).AddDays(-1), new List<Domain.Transaction>() | ||
{ | ||
new CreditTransaction("Random counter party", Guid.NewGuid(), 20,DateTimeOffset.Now, "A description", new List<TransactionAttachment>(), null, new List<TransactionTypeAmount>()) | ||
}); | ||
_financialYearRepositoryMock | ||
.Setup(x => x.GetByIdAsync(financialYear.Id, CancellationToken.None)) | ||
.ReturnsAsync(financialYear); | ||
; | ||
await SUT.Handle(new CloseFinancialYearCommand(financialYear.Id), CancellationToken.None); | ||
|
||
financialYear.IsClosed.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public async Task It_should_throw_an_exception_when_no_year_is_found() | ||
{ | ||
var newGuid = Guid.NewGuid(); | ||
var exception = await Assert.ThrowsAsync<ArgumentException>(async () => | ||
{ | ||
await SUT.Handle(new CloseFinancialYearCommand(newGuid), CancellationToken.None); | ||
}); | ||
Assert.Equal($"No financial year found by Id {newGuid} (Parameter 'Id')", exception.Message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Commands.Handlers.Transaction.EditTransaction; | ||
|
||
using Domain; | ||
using Domain.Interfaces; | ||
|
||
using FluentAssertions; | ||
|
||
using MediatR; | ||
|
||
using Moq; | ||
|
||
using Persistence.Repositories; | ||
|
||
using Xunit; | ||
|
||
using AttachmentFile = Commands.Handlers.AttachmentFile; | ||
|
||
namespace Commands.Test.Transaction; | ||
public class When_editing_a_transaction | ||
{ | ||
private readonly Mock<IFinancialYearRepository> _financialYearRepositoryMock; | ||
|
||
public When_editing_a_transaction() | ||
{ | ||
_financialYearRepositoryMock = new Mock<IFinancialYearRepository>(); | ||
var mediatorMock = new Mock<IMediator>(); | ||
SUT = new EditTransactionHandler(_financialYearRepositoryMock.Object, mediatorMock.Object); | ||
} | ||
|
||
public EditTransactionHandler SUT { get; set; } | ||
|
||
[Fact] | ||
public async Task It_should_throw_an_exception_when_locked() | ||
{ | ||
var bankAccountId = Guid.NewGuid(); | ||
|
||
var transaction = new CreditTransaction("Random counter party", bankAccountId, 20m, DateTimeOffset.Now, | ||
"A description", new List<TransactionAttachment>(), null, new List<TransactionTypeAmount>()); | ||
var financialYear = new Domain.FinancialYear(new DateTimeOffset(new DateTime(2022,9,1)), new DateTimeOffset(new DateTime(2023,8,31)), new List<Domain.Transaction>() | ||
{ | ||
transaction | ||
}); | ||
financialYear.Close(); | ||
|
||
_financialYearRepositoryMock | ||
.Setup(x => x.GetFinancialYearByTransactionId(transaction.Id, CancellationToken.None)) | ||
.ReturnsAsync(financialYear); | ||
|
||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async () => await SUT.Handle( | ||
new EditTransactionCommand(transaction.Id, "Random counter party name", null, bankAccountId, | ||
DateTimeOffset.Now, "Another description", new List<TransactionTypeAmount>(), | ||
new List<AttachmentFile>()), CancellationToken.None)); | ||
|
||
exception.Message.Should().Be("Financial year is already closed"); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Commands/Handlers/FinancialYear/AddFinancialYear/AddFinancialYearCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using FluentValidation; | ||
|
||
namespace Commands.Handlers.FinancialYear.AddFinancialYear; | ||
|
||
public record AddFinancialYearCommand() : IRequest<Domain.FinancialYear>; | ||
|
||
|
||
public class AddFinancialYearCommandValidator : AbstractValidator<AddFinancialYearCommand> | ||
{ | ||
public AddFinancialYearCommandValidator() | ||
{ | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
Commands/Handlers/FinancialYear/AddFinancialYear/AddFinancialYearHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using Domain; | ||
using Domain.Interfaces; | ||
|
||
using Microsoft.Extensions.Options; | ||
|
||
using Persistence; | ||
using Persistence.Repositories; | ||
|
||
namespace Commands.Handlers.FinancialYear.AddFinancialYear; | ||
|
||
public class AddFinancialYearHandler : IRequestHandler<AddFinancialYearCommand, Domain.FinancialYear> | ||
{ | ||
private readonly IFinancialYearRepository _financialYearRepository; | ||
private readonly FinancialYearConfiguration _financialYearOptions; | ||
|
||
private readonly HaSpManContext _haSpManContext; | ||
|
||
public AddFinancialYearHandler(IFinancialYearRepository financialYearRepository, | ||
IOptions<FinancialYearConfiguration> financialYearOptions, | ||
HaSpManContext haSpManContext) | ||
{ | ||
_financialYearRepository = financialYearRepository; | ||
_financialYearOptions = financialYearOptions.Value; | ||
_haSpManContext = haSpManContext; | ||
} | ||
public async Task<Domain.FinancialYear> Handle(AddFinancialYearCommand request, CancellationToken cancellationToken) | ||
{ | ||
|
||
var lastFinancialYear = await _financialYearRepository.GetMostRecentAsync(cancellationToken); | ||
|
||
// In case this is the first year we create, assume we want it to be this year. | ||
// Otherwise, just add a new year | ||
var year = lastFinancialYear == null ? DateTime.Now.Year : lastFinancialYear.EndDate.Year; | ||
|
||
var startDate = new DateTimeOffset(new DateTime(year, _financialYearOptions.StartDate.Month, _financialYearOptions.StartDate.Day)); | ||
|
||
var financialYear = new Domain.FinancialYear( | ||
startDate, | ||
startDate.AddYears(1).AddDays(-1), | ||
new List<Domain.Transaction>()); | ||
|
||
_financialYearRepository.Add(financialYear); | ||
await _financialYearRepository.SaveChangesAsync(cancellationToken); | ||
return financialYear; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
Commands/Handlers/FinancialYear/CloseFinancialYear/CloseFinancialYearCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using FluentValidation; | ||
|
||
namespace Commands.Handlers.FinancialYear.CloseFinancialYear; | ||
|
||
public record CloseFinancialYearCommand(Guid Id) : IRequest; | ||
|
||
public class CloseFinancialYearCommandValidator : AbstractValidator<CloseFinancialYearCommand> | ||
{ | ||
public CloseFinancialYearCommandValidator() | ||
{ | ||
RuleFor(x => x.Id).NotEmpty(); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
Commands/Handlers/FinancialYear/CloseFinancialYear/CloseFinancialYearHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using Domain.Interfaces; | ||
|
||
using Persistence.Repositories; | ||
|
||
namespace Commands.Handlers.FinancialYear.CloseFinancialYear; | ||
|
||
public class CloseFinancialYearHandler : IRequestHandler<CloseFinancialYearCommand> | ||
{ | ||
private readonly IFinancialYearRepository _financialYearRepository; | ||
|
||
public CloseFinancialYearHandler(IFinancialYearRepository financialYearRepository) | ||
{ | ||
_financialYearRepository = financialYearRepository; | ||
} | ||
public async Task Handle(CloseFinancialYearCommand request, CancellationToken cancellationToken) | ||
{ | ||
var financialYear = await _financialYearRepository.GetByIdAsync(request.Id, cancellationToken) | ||
?? throw new ArgumentException($"No financial year found by Id {request.Id}", nameof(request.Id)); | ||
financialYear.Close(); | ||
|
||
await _financialYearRepository.SaveChangesAsync(cancellationToken); | ||
|
||
} | ||
} |
Oops, something went wrong.