Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using System.Threading;
using System.Threading.Tasks;
using SimpleResults;
using System;
using TransactionProcessor.BusinessLogic.Requests;
using TransactionProcessor.BusinessLogic.Services;

namespace TransactionProcessor.BusinessLogic.Tests.Mediator;

public class DummyEstateDomainService : IEstateDomainService
{
public async Task<Result> CreateEstate(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken) => Result.Success();
public async Task<Result<Guid>> CreateEstate(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken) => Result.Success(Guid.NewGuid());

public async Task<Result> AddOperatorToEstate(EstateCommands.AddOperatorToEstateCommand command, CancellationToken cancellationToken) => Result.Success();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public async Task EstateDomainService_CreateEstate_EstateIsCreated() {
.Save(Arg<EstateAggregate>.Any(), Arg<CancellationToken>.Any())
.ReturnsAsync(SimpleResults.Result.Success());

Result result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
Result<Guid> result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
result.IsSuccess.ShouldBeTrue();
result.Data.ShouldNotBe(Guid.Empty);
}


Expand Down Expand Up @@ -274,7 +275,7 @@ public async Task EstateDomainService_CreateEstate_GetEstateFailed_ResultIsFaile
this.AggregateService.GetLatest<EstateAggregate>(Arg<Guid>.Any(), Arg<CancellationToken>.Any())
.ReturnsAsync(Result.Failure());

Result result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
Result<Guid> result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
result.IsFailed.ShouldBeTrue();
}

Expand All @@ -285,9 +286,9 @@ public async Task EstateDomainService_CreateEstate_EstateNameEmpty_ResultIsFaile
.ReturnsAsync(SimpleResults.Result.Success(new EstateAggregate()));

EstateCommands.CreateEstateCommand emptyNameCommand = new EstateCommands.CreateEstateCommand(
new CreateEstateRequest { EstateId = TestData.EstateId, EstateName = String.Empty });
new CreateEstateRequest { EstateName = String.Empty });

Result result = await this.DomainService.CreateEstate(emptyNameCommand, TestContext.Current.CancellationToken);
Result<Guid> result = await this.DomainService.CreateEstate(emptyNameCommand, TestContext.Current.CancellationToken);
result.IsFailed.ShouldBeTrue();
}

Expand All @@ -300,7 +301,7 @@ public async Task EstateDomainService_CreateEstate_SaveFailed_ResultIsFailed()
.Save(Arg<EstateAggregate>.Any(), Arg<CancellationToken>.Any())
.ReturnsAsync(Result.Failure());

Result result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
Result<Guid> result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
result.IsFailed.ShouldBeTrue();
}

Expand Down Expand Up @@ -402,7 +403,7 @@ public async Task EstateDomainService_CreateEstate_ExceptionThrown_ResultIsFaile
this.AggregateService.GetLatest<EstateAggregate>(Arg<Guid>.Any(), Arg<CancellationToken>.Any())
.ThrowsAsync(new Exception());

Result result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
Result<Guid> result = await this.DomainService.CreateEstate(TestData.Commands.CreateEstateCommand, TestContext.Current.CancellationToken);
result.IsFailed.ShouldBeTrue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
using System.Threading.Tasks;
using MediatR;
using SimpleResults;
using System;
using TransactionProcessor.BusinessLogic.Manager;
using TransactionProcessor.BusinessLogic.Requests;
using TransactionProcessor.BusinessLogic.Services;

namespace TransactionProcessor.BusinessLogic.RequestHandlers
{
public class EstateRequestHandler : IRequestHandler<EstateCommands.CreateEstateCommand, Result>,
public class EstateRequestHandler : IRequestHandler<EstateCommands.CreateEstateCommand, Result<Guid>>,
IRequestHandler<EstateCommands.AddOperatorToEstateCommand, Result>,
IRequestHandler<EstateCommands.RemoveOperatorFromEstateCommand, Result>,
IRequestHandler<EstateCommands.CreateEstateUserCommand, Result>,
Expand All @@ -35,7 +36,7 @@ public EstateRequestHandler(IEstateDomainService estateDomainService, ITransacti

#region Methods

public async Task<Result> Handle(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken)
public async Task<Result<Guid>> Handle(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken)
{
return await this.EstateDomainService.CreateEstate(command, cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace TransactionProcessor.BusinessLogic.Requests
[ExcludeFromCodeCoverage]
public class EstateCommands
{
public record CreateEstateCommand(CreateEstateRequest RequestDto) : IRequest<Result>;
public record CreateEstateCommand(CreateEstateRequest RequestDto) : IRequest<Result<Guid>>;

public record CreateEstateUserCommand(Guid EstateId, CreateEstateUserRequest RequestDto) : IRequest<Result>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Threading.Tasks;
using SecurityService.Client;
using SecurityService.DataTransferObjects;
using Shared.DomainDrivenDesign.EventSourcing;
using Shared.EventStore.Aggregate;
using Shared.Exceptions;
using Shared.Results;
Expand All @@ -20,7 +19,7 @@ public interface IEstateDomainService
{
#region Methods

Task<Result> CreateEstate(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken);
Task<Result<Guid>> CreateEstate(EstateCommands.CreateEstateCommand command, CancellationToken cancellationToken);

Task<Result> AddOperatorToEstate(EstateCommands.AddOperatorToEstateCommand command, CancellationToken cancellationToken);

Expand Down Expand Up @@ -54,10 +53,13 @@ public EstateDomainService(Func<IAggregateService> aggregateService,

#region Methods

public async Task<Result> CreateEstate(EstateCommands.CreateEstateCommand command,
public async Task<Result<Guid>> CreateEstate(EstateCommands.CreateEstateCommand command,
CancellationToken cancellationToken) {
try {
Result<EstateAggregate> estateResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest<EstateAggregate>(command.RequestDto.EstateId, ct), command.RequestDto.EstateId, cancellationToken, false);

Guid estateId = IdGenerationService.GenerateEstateId(command.RequestDto.EstateName);

Result<EstateAggregate> estateResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest<EstateAggregate>(estateId, ct), estateId, cancellationToken, false);
if (estateResult.IsFailed)
return ResultHelpers.CreateFailure(estateResult);

Expand All @@ -71,7 +73,7 @@ public async Task<Result> CreateEstate(EstateCommands.CreateEstateCommand comman
if (saveResult.IsFailed)
return ResultHelpers.CreateFailure(saveResult);

return Result.Success();
return Result.Success<Guid>(estateId);
}
catch (Exception ex) {
return Result.Failure(ex.GetExceptionMessages());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,15 @@ public static Guid GenerateMerchantScheduleAggregateId(Guid estateId, Guid merch
});

public static Guid GenerateContractId(Guid estateId, Guid operatorId, String contractName) {

String normalisedContractName = contractName.ToLower().Replace(" ", String.Empty);

return IdGenerationService.GenerateUniqueId(new { estateId, operatorId, normalisedContractName });
}

public static Guid GenerateEstateId(String estateName) {
String normalisedEstateName = estateName.ToLowerInvariant().Replace(" ", String.Empty);

return IdGenerationService.GenerateUniqueId(new { normalisedEstateName });
}
}
}
2 changes: 1 addition & 1 deletion TransactionProcessor.Client/ITransactionProcessorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Task<Result<List<EstateResponse>>> GetEstates(String accessToken,
Guid estateId,
CancellationToken cancellationToken);

Task<Result> CreateEstate(String accessToken,
Task<Result<Guid>> CreateEstate(String accessToken,
CreateEstateRequest createEstateRequest,
CancellationToken cancellationToken);

Expand Down
6 changes: 3 additions & 3 deletions TransactionProcessor.Client/TransactionProcessorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,18 @@
}
}

public async Task<Result> CreateEstate(String accessToken,
public async Task<Result<Guid>> CreateEstate(String accessToken,
CreateEstateRequest createEstateRequest,
CancellationToken cancellationToken) {
String requestUri = this.BuildRequestUrl("/api/estates/");

try {
var result = await this.Post(requestUri, createEstateRequest, accessToken, cancellationToken);
Result<Guid> result = await this.Post<CreateEstateRequest, Guid>(requestUri, createEstateRequest, accessToken, cancellationToken);

if (result.IsFailed)
return ResultHelpers.CreateFailure(result);

return Result.Success();
return Result.Success<Guid>(result.Data);
}
catch (Exception ex) {
// An exception has occurred, add some additional information to the message
Expand Down Expand Up @@ -1032,7 +1032,7 @@

return result;
}
catch (Exception ex) {

Check warning on line 1035 in TransactionProcessor.Client/TransactionProcessorClient.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

The variable 'ex' is declared but never used
// An exception has occurred, add some additional information to the message
Exception exception = new($"Error getting settlement id {settlementId} for estate [{estateId}]");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace TransactionProcessor.DataTransferObjects.Requests.Estate
{
/// <summary>
/// Estate identifier and display name used to create an estate.
/// Display name used to create an estate. The estate identifier is generated by the service.
/// </summary>
/// <example>{"estateId":"00000000-0000-0000-0000-000000000023","estateName":"Example Name"}</example>
/// <example>{"estateName":"Example Name"}</example>
public class CreateEstateRequest
{
/// <summary>
/// Estate that owns or scopes this operation.
/// </summary>
public Guid EstateId { get; set; }

/// <summary>
/// Display name for the estate.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,6 @@ public static List<CreateEstateRequest> ToCreateEstateRequests(this DataTableRow
{
CreateEstateRequest createEstateRequest = new CreateEstateRequest
{
EstateId = Guid.NewGuid(),
EstateName = ReqnrollTableHelper.GetStringRowValue(tableRow, "EstateName")
};
requests.Add(createEstateRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,24 +719,26 @@ await this.TransactionProcessorClient.GetSettlementByDate(accessToken,
}
}

public async Task<List<EstateResponse>> WhenICreateTheFollowingEstatesX(String accessToken, List<CreateEstateRequest> requests)
{
public async Task<List<EstateResponse>> WhenICreateTheFollowingEstatesX(String accessToken, List<CreateEstateRequest> requests) {
Dictionary<Guid, CreateEstateRequest> createdEstates = new();

foreach (CreateEstateRequest createEstateRequest in requests)
{
Result? result = await this.TransactionProcessorClient
.CreateEstate(accessToken, createEstateRequest, CancellationToken.None)
.ConfigureAwait(false);
Result<Guid> result = await this.TransactionProcessorClient
.CreateEstate(accessToken, createEstateRequest, CancellationToken.None)
.ConfigureAwait(false);

result.IsSuccess.ShouldBeTrue(result.Message);
createdEstates.Add(result.Data, createEstateRequest);
}

List<EstateResponse> results = new List<EstateResponse>();
foreach (CreateEstateRequest createEstateRequest in requests)
foreach (KeyValuePair<Guid, CreateEstateRequest> createEstateRequest in createdEstates)
{
EstateResponse estate = null;
await Retry.For(async () => {
Result<List<EstateResponse>>? getEstatesResult = await this.TransactionProcessorClient
.GetEstates(accessToken, createEstateRequest.EstateId, CancellationToken.None).ConfigureAwait(false);
.GetEstates(accessToken, createEstateRequest.Key, CancellationToken.None).ConfigureAwait(false);

List<EstateResponse>? estates = getEstatesResult.Data;
try
Expand All @@ -745,13 +747,13 @@ await Retry.For(async () => {
estates.ShouldNotBeNull();
estates.Count.ShouldBe(1);
estate = estates.Single();
estate.EstateName.ShouldBe(createEstateRequest.EstateName);
estate.EstateName.ShouldBe(createEstateRequest.Value.EstateName);
estate.EstateReference.ShouldNotBeNullOrWhiteSpace();
}
catch
{
StringBuilder snapshot = new StringBuilder();
snapshot.Append($"estateId={createEstateRequest.EstateId}, expectedName={createEstateRequest.EstateName}, ");
snapshot.Append($"estateId={createEstateRequest.Key}, expectedName={createEstateRequest.Value.EstateName}, ");
snapshot.Append($"isSuccess={getEstatesResult.IsSuccess}, ");
snapshot.Append($"rows={(estates == null ? "null" : estates.Count.ToString())}");

Expand Down
8 changes: 3 additions & 5 deletions TransactionProcessor.Testing/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1791,11 +1791,9 @@ public static VoucherAggregate GetVoucherAggregateWithRecipientMobile()
public static Guid SecurityUserId = Guid.Parse("45B74A2E-BF92-44E9-A300-08E5CDEACFE3");

public static CreateEstateRequest CreateEstateRequest =>
new CreateEstateRequest
{
EstateId = TestData.EstateId,
EstateName = TestData.EstateName,
};
new() {
EstateName = TestData.EstateName,
};
public static CreateEstateUserRequest CreateEstateUserRequest =>
new CreateEstateUserRequest
{
Expand Down
4 changes: 1 addition & 3 deletions TransactionProcessor.Tests/HandlerTests/WebHandlersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,16 +251,14 @@ public static IEnumerable<object[]> EstateCases()
{
yield return Case(
"CreateEstate",
SetupSuccess<EstateCommands.CreateEstateCommand>(command =>
SetupSuccess<EstateCommands.CreateEstateCommand, Guid>(EstateId, command =>
{
command.RequestDto.EstateId.ShouldBe(EstateId);
command.RequestDto.EstateName.ShouldBe("Estate");
}),
mediator => EstateHandlers.CreateEstate(mediator,
new DefaultHttpContext(),
new CreateEstateRequest
{
EstateId = EstateId,
EstateName = "Estate"
},
CancellationToken.None));
Expand Down
4 changes: 3 additions & 1 deletion TransactionProcessor/Endpoints/EstateEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Routing;
using Shared.Authorisation;
using Shared.General;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims;
using TransactionProcessor.Handlers;
Expand All @@ -27,7 +28,8 @@ public static IEndpointRouteBuilder MapEstateEndpoints(this IEndpointRouteBuilde

estateGroup.MapPost("/", EstateHandlers.CreateEstate)
.WithName("CreateEstate").WithSummary("Create an estate")
.WithDescription("Creates an estate using the supplied estate ID and display name.");
.WithDescription("Creates an estate from the supplied display name. The service generates and returns the estate ID.")
.Produces<Guid>();

estateGroup.MapGet("/{estateId:guid}", EstateHandlers.GetEstate)
.WithName("GetEstate").WithSummary("Get an estate")
Expand Down
4 changes: 2 additions & 2 deletions TransactionProcessor/Handlers/EstateHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public static class EstateHandlers
public static async Task<IResult> CreateEstate(IMediator mediator, HttpContext context, CreateEstateRequest createEstateRequest, CancellationToken cancellationToken)
{
EstateCommands.CreateEstateCommand command = new(createEstateRequest);
Result result = await mediator.Send(command, cancellationToken);
Result<Guid> result = await mediator.Send(command, cancellationToken);

return ResponseFactory.FromResult(result);
return ResponseFactory.FromResult<Guid>(result, (estateId) => result.Data);
}

public static async Task<IResult> GetEstate(IMediator mediator, HttpContext context, Guid estateId, CancellationToken cancellationToken)
Expand Down
4 changes: 2 additions & 2 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This reference covers the routes currently registered by `TransactionProcessor`

| Method | Path | Query | Request body | Success response |
|---|---|---|---|---|
| POST | `/api/estates/` | — | `CreateEstateRequest` | Result envelope/body from command result. |
| POST | `/api/estates/` | — | `CreateEstateRequest` (`EstateName: string`) | Generated estate ID (`Guid`). |
| GET | `/api/estates/{estateId}` | — | — | `EstateResponse` |
| GET | `/api/estates/{estateId}/all` | — | — | `EstateResponse[]` |
| PATCH | `/api/estates/{estateId}/users` | — | `CreateEstateUserRequest` | Result envelope/body from command result. |
Expand Down Expand Up @@ -133,7 +133,7 @@ Fields below are the declared DTO properties. Requiredness is not inferred from

| DTO | Fields |
|---|---|
| `CreateEstateRequest` | `EstateId: Guid`, `EstateName: string` |
| `CreateEstateRequest` | `EstateName: string` (the service generates `EstateId` from the request data) |
| `CreateEstateUserRequest` / `CreateMerchantUserRequest` | `EmailAddress: string`, `Password: string`, `GivenName: string`, `MiddleName: string`, `FamilyName: string` |
| `Estate.AssignOperatorRequest` | `OperatorId: Guid` |
| `CreateContractRequest` | `OperatorId: Guid`, `Description: string` |
Expand Down
Loading