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
Expand Up @@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Shared.EventStore" Version="2025.10.3" />
<PackageReference Include="Shared.EventStore" Version="2025.11.1" />
<PackageReference Include="Shouldly" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="13.1.0" />
<PackageReference Include="Shared" Version="2025.10.3" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.10.3" />
<PackageReference Include="Shared.EventStore" Version="2025.10.3" />
<PackageReference Include="Shared" Version="2025.11.1" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.11.1" />
<PackageReference Include="Shared.EventStore" Version="2025.11.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CallbackHandler.CallbackMessageAggregate\CallbackHandler.CallbackMessageAggregate.csproj" />
Expand Down
30 changes: 2 additions & 28 deletions CallbackHandler.BusinessLogic/Services/CallbackDomainService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using Shared.Results;
using Shared.EventStore.Helpers;
using SimpleResults;

namespace CallbackHandler.BusinessLogic.Services;

using CallbackHandler.BusinessLogic.Requests;
using CallbackHandlers.Models;
using CallbackMessageAggregate;
using Shared.DomainDrivenDesign.EventSourcing;
using Shared.EventStore.Aggregate;
Expand All @@ -27,7 +26,7 @@ public async Task<Result> RecordCallback(CallbackCommands.RecordCallbackCommand
String[] referenceData = command.Reference?.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
// TODO: Validate the reference data has the correct number of elements
if (referenceData.Length == 0) {
return Result.Failure("Reference cannot be empty.");
return Result.Invalid("Reference cannot be empty.");
}

// Element 0 is estate reference, Element 1 is merchant reference
Expand All @@ -47,29 +46,4 @@ public async Task<Result> RecordCallback(CallbackCommands.RecordCallbackCommand
return stateResult;
return await this.AggregateRepository.SaveChanges(aggregate, cancellationToken);
}
}

public static class DomainServiceHelper
{
public static Result<T> HandleGetAggregateResult<T>(Result<T> result, Guid aggregateId, bool isNotFoundError = true)
where T : Aggregate, new() // Constraint: T is a subclass of Aggregate and has a parameterless constructor
{
if (result.IsFailed && result.Status != ResultStatus.NotFound)
{
return ResultHelpers.CreateFailure(result);
}

if (result.Status == ResultStatus.NotFound && isNotFoundError)
{
return ResultHelpers.CreateFailure(result);
}

T aggregate = result.Status switch
{
ResultStatus.NotFound => new T { AggregateId = aggregateId }, // Set AggregateId when creating a new instance
_ => result.Data
};

return Result.Success(aggregate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<DebugType>None</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Shared" Version="2025.10.3" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.10.3" />
<PackageReference Include="Shared" Version="2025.11.1" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.11.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="Shared.EventStore" Version="2025.10.3" />
<PackageReference Include="Shared.EventStore" Version="2025.11.1" />
<PackageReference Include="Shouldly" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.Net.Client" Version="2.71.0" />
<PackageReference Include="Shared" Version="2025.10.3" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.10.3" />
<PackageReference Include="Shared.EventStore" Version="2025.10.3" />
<PackageReference Include="Shared" Version="2025.11.1" />
<PackageReference Include="Shared.DomainDrivenDesign" Version="2025.11.1" />
<PackageReference Include="Shared.EventStore" Version="2025.11.1" />
</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions CallbackHandler.DataTransferObjects/CallbackMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace CallbackHandler.DataTransferObjects
{
Expand All @@ -16,4 +17,11 @@ public class CallbackMessage

public String Reference { get; set; }
}

public class CallbackResponse {
[JsonProperty("callback_id")]
public Guid CallbackId { get; set; }
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="5.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="Shared" Version="2025.10.3" />
<PackageReference Include="Shared.IntegrationTesting" Version="2025.10.3" />
<PackageReference Include="Shared" Version="2025.11.1" />
<PackageReference Include="Shared.IntegrationTesting" Version="2025.11.1" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 7 additions & 7 deletions CallbackHandler.IntegrationTests/Shared/SharedSteps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}

[Given(@"I have the following Bank Deposit Callbacks")]
public async Task GivenIHaveTheFollowingBankDepositCallbacks(DataTable table)

Check warning on line 34 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 34 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
List<Deposit> requests = table.Rows.ToDepositRequests();
this.TestingContext.Deposits = requests;
Expand All @@ -53,10 +53,10 @@
var response = await client.SendAsync(msg);
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var content = await response.Content.ReadAsStringAsync();
ResponseData<Guid> responseData =
JsonConvert.DeserializeObject<ResponseData<Guid>>(content);
CallbackResponse responseData =
JsonConvert.DeserializeObject<CallbackResponse>(content);

Check warning on line 57 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

Converting null literal or possible null value to non-nullable type.

Check warning on line 57 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

Converting null literal or possible null value to non-nullable type.

this.TestingContext.SentCallbacks.Add(responseData.Data, payload);
this.TestingContext.SentCallbacks.Add(responseData.CallbackId, payload);
}
}

Expand All @@ -75,12 +75,12 @@
var originalDeposit = JsonConvert.DeserializeObject<Deposit>(sentCallback.Value);

var content = await response.Content.ReadAsStringAsync();
ResponseData<CallbackMessage> responseData =
JsonConvert.DeserializeObject<ResponseData<CallbackMessage>>(content);
CallbackMessage responseData =
JsonConvert.DeserializeObject<CallbackMessage>(content);


responseData.Data.Reference.ShouldBe(originalDeposit.Reference);
var callbackDeposit = JsonConvert.DeserializeObject<Deposit>(responseData.Data.Message);
responseData.Reference.ShouldBe(originalDeposit.Reference);
var callbackDeposit = JsonConvert.DeserializeObject<Deposit>(responseData.Message);
callbackDeposit.AccountNumber.ShouldBe(originalDeposit.AccountNumber);
}
}
Expand Down Expand Up @@ -112,6 +112,6 @@

internal class ResponseData<T>
{
public T Data { get; set; }

Check warning on line 115 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

Non-nullable property 'Data' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 115 in CallbackHandler.IntegrationTests/Shared/SharedSteps.cs

View workflow job for this annotation

GitHub Actions / Build and Test Pull Requests

Non-nullable property 'Data' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
}
}
3 changes: 2 additions & 1 deletion CallbackHandler/CallbackHandler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
<PackageReference Include="MediatR" Version="13.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="Shared" Version="2025.10.3" />
<PackageReference Include="Shared" Version="2025.11.1" />
<PackageReference Include="Shared.Results.Web" Version="2025.11.1" />
<PackageReference Include="SimpleResults.AspNetCore" Version="4.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="9.0.6" />
Expand Down
9 changes: 6 additions & 3 deletions CallbackHandler/Endpoints/CallbackEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Microsoft.AspNetCore.Builder;
using CallbackHandler.DataTransferObjects;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using SimpleResults;
using System;
using Shared.Extensions;
using Shared.Middleware;

namespace CallbackHandler.Endpoints
{
Expand All @@ -18,12 +21,12 @@
group.MapPost("/", Handlers.CallbackHandlers.RecordCallback)
.WithName("RecordCallback")
.WithSummary("Records a deposit callback")
.Produces<Result<Guid>>(StatusCodes.Status200OK);
.WithStandardProduces<CallbackResponse, ErrorResponse>(); ;

Check notice on line 24 in CallbackHandler/Endpoints/CallbackEndpoints.cs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

CallbackHandler/Endpoints/CallbackEndpoints.cs#L24

Remove this empty statement.

group.MapGet("/{callbackId:guid}", Handlers.CallbackHandlers.GetCallback)
.WithName("GetCallback")
.WithSummary("Gets a callback by ID")
.Produces<Result<DataTransferObjects.CallbackMessage>>(StatusCodes.Status200OK);
.WithStandardProduces<DataTransferObjects.CallbackMessage, ErrorResponse>();

return endpoints;
}
Expand Down
51 changes: 25 additions & 26 deletions CallbackHandler/Handlers/CallbackHandlers.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using CallbackHandler.BusinessLogic.Requests;
using CallbackHandler.BusinessLogic.Requests;
using CallbackHandler.DataTransferObjects;
using CallbackHandlers.Models;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Shared.Results;
using SimpleResults;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.HttpResults;
using Shared.Results.Web;

namespace CallbackHandler.Handlers;

public static class CallbackHandlers
{
public static async Task<Result<Guid>> RecordCallback(Deposit depositCallback,
IMediator mediator,
CancellationToken cancellationToken)
public static async Task<IResult> RecordCallback(Deposit depositCallback,
IMediator mediator,
CancellationToken cancellationToken)
{
Guid callbackId = Guid.NewGuid();

Expand All @@ -29,31 +36,23 @@ public static async Task<Result<Guid>> RecordCallback(Deposit depositCallback,

Result result = await mediator.Send(request, cancellationToken);

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

return Result.Success(callbackId);
return ResponseFactory.FromResult<CallbackResponse>(result, (r) => new CallbackResponse {
CallbackId = callbackId
});
}

public static async Task<Result<DataTransferObjects.CallbackMessage>> GetCallback(Guid callbackId,
IMediator mediator,
CancellationToken cancellationToken)
public static async Task<IResult> GetCallback(Guid callbackId,
IMediator mediator,
CancellationToken cancellationToken)
{
CallbackQueries.GetCallbackQuery query = new(callbackId);
Result<global::CallbackHandlers.Models.CallbackMessage> getResult = await mediator.Send(query, cancellationToken);
Result<global::CallbackHandlers.Models.CallbackMessage> result = await mediator.Send(query, cancellationToken);

if (getResult.IsFailed) {
return ResultHelpers.CreateFailure(getResult);
}

Result<DataTransferObjects.CallbackMessage> result = Result.Success(new DataTransferObjects.CallbackMessage
return ResponseFactory.FromResult(result, (r) => new DataTransferObjects.CallbackMessage
{
Reference = getResult.Data.Reference,
TypeString = getResult.Data.TypeString,
Message = getResult.Data.Message
Reference = r.Reference,
TypeString = r.TypeString,
Message = r.Message
});

return result;
}
}
Loading