-
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.
- Loading branch information
0 parents
commit fdf2f26
Showing
130 changed files
with
11,533 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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,70 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.0.31903.59 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "src\Domain\Domain.csproj", "{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "src\Application\Application.csproj", "{34C0FACD-F3D9-400C-8945-554DD6B0819A}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{664D406C-2F83-48F0-BFC3-408D5CB53C65}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}" | ||
ProjectSection(SolutionItems) = preProject | ||
.editorconfig = .editorconfig | ||
.gitignore = .gitignore | ||
Directory.Build.props = Directory.Build.props | ||
Directory.Packages.props = Directory.Packages.props | ||
global.json = global.json | ||
README.md = README.md | ||
EndProjectSection | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.FunctionalTests", "tests\Application.FunctionalTests\Application.FunctionalTests.csproj", "{EA6127A5-94C9-4C31-AD11-E6811B92B520}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(NestedProjects) = preSolution | ||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} | ||
{34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} | ||
{117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} | ||
{4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} | ||
{EA6127A5-94C9-4C31-AD11-E6811B92B520} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430} | ||
EndGlobalSection | ||
EndGlobal |
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,10 @@ | ||
<!-- See https://aka.ms/dotnet/msbuild/customize for more details on customizing your build --> | ||
<Project> | ||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<!-- <ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath> --> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
</Project> |
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,44 @@ | ||
<!-- For more info on central package management go to https://devblogs.microsoft.com/nuget/introducing-central-package-management/ --> | ||
<Project> | ||
<PropertyGroup> | ||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageVersion Include="Ardalis.GuardClauses" Version="4.2.0" /> | ||
<PackageVersion Include="AutoMapper" Version="13.0.1" /> | ||
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" /> | ||
<PackageVersion Include="Azure.Identity" Version="1.10.4" /> | ||
<PackageVersion Include="coverlet.collector" Version="6.0.0" /> | ||
<PackageVersion Include="FluentAssertions" Version="6.12.0" /> | ||
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" /> | ||
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.8.1" /> | ||
<PackageVersion Include="MediatR" Version="12.2.0" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.AspNetCore.SpaProxy" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> | ||
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" /> | ||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.2" /> | ||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> | ||
<PackageVersion Include="Moq" Version="4.20.69" /> | ||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> | ||
<PackageVersion Include="NSwag.AspNetCore" Version="14.0.7" /> | ||
<PackageVersion Include="NSwag.MSBuild" Version="14.0.3" /> | ||
<PackageVersion Include="nunit" Version="3.14.0" /> | ||
<PackageVersion Include="NUnit.Analyzers" Version="3.9.0" /> | ||
<PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" /> | ||
<PackageVersion Include="Respawn" Version="6.1.0" /> | ||
<PackageVersion Include="Testcontainers.MsSql" Version="3.6.0" /> | ||
<PackageVersion Include="Microsoft.Playwright" Version="1.40.0" /> | ||
<PackageVersion Include="SpecFlow.Plus.LivingDocPlugin" Version="3.9.57" /> | ||
<PackageVersion Include="SpecFlow.NUnit" Version="3.9.74" /> | ||
</ItemGroup> | ||
</Project> |
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 @@ | ||
https://localhost:5001/api |
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,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<RootNamespace>AML.Application</RootNamespace> | ||
<AssemblyName>AML.Application</AssemblyName> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Ardalis.GuardClauses" /> | ||
<PackageReference Include="AutoMapper" /> | ||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore" /> | ||
<PackageReference Include="Newtonsoft.Json" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Domain\Domain.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
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,35 @@ | ||
using ValidationException = AML.Application.Common.Exceptions.ValidationException; | ||
|
||
namespace AML.Application.Common.Behaviours; | ||
|
||
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> | ||
where TRequest : notnull | ||
{ | ||
private readonly IEnumerable<IValidator<TRequest>> _validators; | ||
|
||
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators) | ||
{ | ||
_validators = validators; | ||
} | ||
|
||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) | ||
{ | ||
if (_validators.Any()) | ||
{ | ||
var context = new ValidationContext<TRequest>(request); | ||
|
||
var validationResults = await Task.WhenAll( | ||
_validators.Select(v => | ||
v.ValidateAsync(context, cancellationToken))); | ||
|
||
var failures = validationResults | ||
.Where(r => r.Errors.Any()) | ||
.SelectMany(r => r.Errors) | ||
.ToList(); | ||
|
||
if (failures.Any()) | ||
throw new ValidationException(failures); | ||
} | ||
return await next(); | ||
} | ||
} |
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,22 @@ | ||
using FluentValidation.Results; | ||
|
||
namespace AML.Application.Common.Exceptions; | ||
|
||
public class ValidationException : Exception | ||
{ | ||
public ValidationException() | ||
: base("One or more validation failures have occurred.") | ||
{ | ||
Errors = new Dictionary<string, string[]>(); | ||
} | ||
|
||
public ValidationException(IEnumerable<ValidationFailure> failures) | ||
: this() | ||
{ | ||
Errors = failures | ||
.GroupBy(e => e.PropertyName, e => e.ErrorMessage) | ||
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); | ||
} | ||
|
||
public IDictionary<string, string[]> Errors { get; } | ||
} |
20 changes: 20 additions & 0 deletions
20
src/Application/Common/Interfaces/IApplicationDbContext.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,20 @@ | ||
using AML.Domain.Entities; | ||
|
||
namespace AML.Application.Common.Interfaces; | ||
|
||
public interface IApplicationDbContext | ||
{ | ||
|
||
|
||
DbSet<Transaction> Transactions { get; } | ||
|
||
DbSet<Address> Addresses { get; } | ||
|
||
DbSet<Customer> Customers { get; } | ||
|
||
DbSet<TransactionLimit> TransactionLimits { get; } | ||
DbSet<LimitChangeHistory> LimitChangesHistory { get; } | ||
DbSet<CustomerBalance> CustomerBalances { get; } | ||
|
||
Task<int> SaveChangesAsync(CancellationToken cancellationToken); | ||
} |
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,12 @@ | ||
using AML.Application.Common.Models; | ||
|
||
namespace AML.Application.Common.Mappings; | ||
|
||
public static class MappingExtensions | ||
{ | ||
public static Task<PaginatedList<TDestination>> PaginatedListAsync<TDestination>(this IQueryable<TDestination> queryable, int pageNumber, int pageSize) where TDestination : class | ||
=> PaginatedList<TDestination>.CreateAsync(queryable.AsNoTracking(), pageNumber, pageSize); | ||
|
||
public static Task<List<TDestination>> ProjectToListAsync<TDestination>(this IQueryable queryable, IConfigurationProvider configuration) where TDestination : class | ||
=> queryable.ProjectTo<TDestination>(configuration).AsNoTracking().ToListAsync(); | ||
} |
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,29 @@ | ||
namespace AML.Application.Common.Models; | ||
|
||
public class PaginatedList<T> | ||
{ | ||
public IReadOnlyCollection<T> Items { get; } | ||
public int PageNumber { get; } | ||
public int TotalPages { get; } | ||
public int TotalCount { get; } | ||
|
||
public PaginatedList(IReadOnlyCollection<T> items, int count, int pageNumber, int pageSize) | ||
{ | ||
PageNumber = pageNumber; | ||
TotalPages = (int)Math.Ceiling(count / (double)pageSize); | ||
TotalCount = count; | ||
Items = items; | ||
} | ||
|
||
public bool HasPreviousPage => PageNumber > 1; | ||
|
||
public bool HasNextPage => PageNumber < TotalPages; | ||
|
||
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageNumber, int pageSize) | ||
{ | ||
var count = await source.CountAsync(); | ||
var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync(); | ||
|
||
return new PaginatedList<T>(items, count, pageNumber, pageSize); | ||
} | ||
} |
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 @@ | ||
namespace AML.Application.Common.Models; | ||
|
||
public class Result | ||
{ | ||
internal Result(bool succeeded, IEnumerable<string> errors) | ||
{ | ||
Succeeded = succeeded; | ||
Errors = errors.ToArray(); | ||
} | ||
|
||
public bool Succeeded { get; init; } | ||
|
||
public string[] Errors { get; init; } | ||
|
||
public static Result Success() | ||
{ | ||
return new Result(true, Array.Empty<string>()); | ||
} | ||
|
||
public static Result Failure(IEnumerable<string> errors) | ||
{ | ||
return new Result(false, errors); | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
src/Application/Customers/Commands/CreateCustomer/CreateCustomerCommand.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,81 @@ | ||
using System.Text.Json.Serialization; | ||
using AML.Application.Common.Interfaces; | ||
using AML.Domain.Entities; | ||
using AML.Domain.Enums; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; | ||
|
||
namespace AML.Application.Customers.Commands.CreateCustomer; | ||
|
||
public record CreateCustomerCommand : IRequest<int> | ||
{ | ||
public string? FirstName { get; set; } | ||
public string? LastName { get; set; } | ||
public DateTime DateOfBirth { get; set; } | ||
public string? Street { get; set; } | ||
public string? City { get; set; } | ||
public string? ZipCode { get; set; } | ||
public string? Country { get; set; } | ||
public ICollection<CustomerBalanceDto>? Balances { get; init; } | ||
|
||
} | ||
|
||
public record CustomerBalanceDto | ||
{ | ||
public CurrencyType Currency { get; set; } | ||
public decimal Balance { get; set; } | ||
} | ||
|
||
public class CreateCustomerCommandHandler(IApplicationDbContext context) : IRequestHandler<CreateCustomerCommand, int> | ||
{ | ||
|
||
|
||
public async Task<int> Handle(CreateCustomerCommand command, CancellationToken cancellationToken) | ||
{ | ||
var customer = await CreateCustomerAsync(command, cancellationToken); | ||
await AddCustomerBalancesAsync(command, customer.Id, cancellationToken); | ||
return customer.Id; | ||
|
||
} | ||
private async Task<Customer> CreateCustomerAsync(CreateCustomerCommand command, CancellationToken cancellationToken) | ||
{ | ||
var customer = new Customer | ||
{ | ||
CustomerIdentifier= Guid.NewGuid(), | ||
FirstName = command.FirstName, | ||
LastName = command.LastName, | ||
DateOfBirth = command.DateOfBirth, | ||
Address = new Address | ||
{ | ||
Street = command.Street, | ||
City = command.City, | ||
ZipCode = command.ZipCode, | ||
Country = command.Country | ||
} | ||
}; | ||
|
||
context.Customers.Add(customer); | ||
await context.SaveChangesAsync(cancellationToken); | ||
return customer; | ||
} | ||
|
||
private async Task AddCustomerBalancesAsync(CreateCustomerCommand command, int customerId, CancellationToken cancellationToken) | ||
{ | ||
if (command.Balances != null) | ||
{ | ||
foreach (var balanceDto in command.Balances) | ||
{ | ||
var customerBalance = new CustomerBalance | ||
{ | ||
CustomerId = customerId, | ||
Currency = balanceDto.Currency, | ||
Balance = balanceDto.Balance | ||
}; | ||
|
||
context.CustomerBalances.Add(customerBalance); | ||
} | ||
|
||
await context.SaveChangesAsync(cancellationToken); | ||
} | ||
} | ||
} |
Oops, something went wrong.