Skip to content

Commit

Permalink
Scaffold bulk person find endpoint (#1457)
Browse files Browse the repository at this point in the history
  • Loading branch information
gunndabad authored Aug 8, 2024
1 parent 7d837d7 commit 3deed24
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

namespace TeachingRecordSystem.Api.V3.Core.Operations;

public record FindPersonsCommand(string LastName, DateOnly? DateOfBirth);
public record FindPersonByLastNameAndDateOfBirthCommand(string LastName, DateOnly? DateOfBirth);

public record FindPersonsResult(int Total, IReadOnlyCollection<FindPersonsResultItem> Items);
public record FindPersonByLastNameAndDateOfBirthResult(int Total, IReadOnlyCollection<FindPersonByLastNameAndDateOfBirthResultItem> Items);

public record FindPersonsResultItem
public record FindPersonByLastNameAndDateOfBirthResultItem
{
public required string Trn { get; init; }
public required DateOnly DateOfBirth { get; init; }
Expand All @@ -22,11 +22,11 @@ public record FindPersonsResultItem
public required IReadOnlyCollection<NameInfo> PreviousNames { get; init; }
}

public class FindPersonsHandler(ICrmQueryDispatcher crmQueryDispatcher, IConfiguration configuration)
public class FindPersonByLastNameAndDateOfBirthHandler(ICrmQueryDispatcher crmQueryDispatcher, IConfiguration configuration)
{
private readonly TimeSpan _concurrentNameChangeWindow = TimeSpan.FromSeconds(configuration.GetValue("ConcurrentNameChangeWindowSeconds", 5));

public async Task<FindPersonsResult> Handle(FindPersonsCommand command)
public async Task<FindPersonByLastNameAndDateOfBirthResult> Handle(FindPersonByLastNameAndDateOfBirthCommand command)
{
var contacts = await crmQueryDispatcher.ExecuteQuery(
new GetActiveContactsByLastNameAndDateOfBirthQuery(
Expand Down Expand Up @@ -55,9 +55,9 @@ public async Task<FindPersonsResult> Handle(FindPersonsCommand command)
kvp => kvp.Key,
kvp => PreviousNameHelper.GetFullPreviousNames(kvp.Value, contactsById[kvp.Key], _concurrentNameChangeWindow));

return new FindPersonsResult(
return new FindPersonByLastNameAndDateOfBirthResult(
Total: contacts.Length,
Items: contacts.Select(r => new FindPersonsResultItem()
Items: contacts.Select(r => new FindPersonByLastNameAndDateOfBirthResultItem()
{
Trn = r.dfeta_TRN,
DateOfBirth = r.BirthDate!.Value.ToDateOnlyWithDqtBstFix(isLocalTime: false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ public async Task<IActionResult> CreateDateOfBirthChange(
[Authorize(Policy = AuthorizationPolicies.GetPerson)]
public async Task<IActionResult> FindTeachers(
FindTeachersRequest request,
[FromServices] FindPersonsHandler handler)
[FromServices] FindPersonByLastNameAndDateOfBirthHandler handler)
{
var command = new FindPersonsCommand(request.LastName!, request.DateOfBirth!.Value);
var command = new FindPersonByLastNameAndDateOfBirthCommand(request.LastName!, request.DateOfBirth!.Value);
var result = await handler.Handle(command);

var response = new FindTeachersResponse()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

namespace TeachingRecordSystem.Api.V3.V20240101.Responses;

[AutoMap(typeof(FindPersonsResult))]
[AutoMap(typeof(FindPersonByLastNameAndDateOfBirthResult))]
public record FindTeachersResponse
{
public required int Total { get; init; }
public required FindTeachersRequest Query { get; init; }
public required IReadOnlyCollection<FindTeachersResponseResult> Results { get; init; }
}

[AutoMap(typeof(FindPersonsResultItem))]
[AutoMap(typeof(FindPersonByLastNameAndDateOfBirthResultItem))]
public record FindTeachersResponseResult
{
public required string Trn { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ public async Task<IActionResult> Get(

[HttpGet("")]
[SwaggerOperation(
OperationId = "FindPersons",
Summary = "Find persons",
Description = "Finds persons with a TRN matching the specified criteria.")]
[ProducesResponseType(typeof(FindPersonsResponse), StatusCodes.Status200OK)]
OperationId = "FindPerson",
Summary = "Find person",
Description = "Finds a person matching the specified criteria.")]
[ProducesResponseType(typeof(FindPersonResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[Authorize(Policy = AuthorizationPolicies.GetPerson)]
public async Task<IActionResult> FindTeachers(
FindPersonsRequest request,
[FromServices] FindPersonsHandler handler)
FindPersonRequest request,
[FromServices] FindPersonByLastNameAndDateOfBirthHandler handler)
{
var command = new FindPersonsCommand(request.LastName!, request.DateOfBirth!.Value);
var command = new FindPersonByLastNameAndDateOfBirthCommand(request.LastName!, request.DateOfBirth!.Value);
var result = await handler.Handle(command);

var response = new FindPersonsResponse()
var response = new FindPersonResponse()
{
Total = result.Total,
Query = request,
Results = result.Items.Select(mapper.Map<FindPersonsResponseResult>).AsReadOnly()
Results = result.Items.Select(mapper.Map<FindPersonResponseResult>).AsReadOnly()
};

return Ok(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

namespace TeachingRecordSystem.Api.V3.V20240606.Requests;

public record FindPersonsRequest
public record FindPersonRequest
{
[FromQuery(Name = "findBy")]
public FindPersonsFindBy FindBy { get; init; }
public FindPersonFindBy FindBy { get; init; }
[FromQuery(Name = "lastName")]
public string? LastName { get; init; }
[FromQuery(Name = "dateOfBirth")]
public DateOnly? DateOfBirth { get; init; }
}

public enum FindPersonsFindBy
public enum FindPersonFindBy
{
LastNameAndDateOfBirth = 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using TeachingRecordSystem.Api.V3.Core.Operations;
using TeachingRecordSystem.Api.V3.V20240101.ApiModels;
using TeachingRecordSystem.Api.V3.V20240606.Requests;

namespace TeachingRecordSystem.Api.V3.V20240606.Responses;

[AutoMap(typeof(FindPersonByLastNameAndDateOfBirthResult))]
public record FindPersonResponse
{
public required int Total { get; init; }
public required FindPersonRequest Query { get; init; }
public required IReadOnlyCollection<FindPersonResponseResult> Results { get; init; }
}

[AutoMap(typeof(FindPersonByLastNameAndDateOfBirthResultItem))]
public record FindPersonResponseResult
{
public required string Trn { get; init; }
public required DateOnly DateOfBirth { get; init; }
public required string FirstName { get; init; }
public required string MiddleName { get; init; }
public required string LastName { get; init; }
public required IReadOnlyCollection<SanctionInfo> Sanctions { get; init; }
public required IReadOnlyCollection<NameInfo> PreviousNames { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace TeachingRecordSystem.Api.V3.V20240606.Validators;

public class FindTeachersRequestValidator : AbstractValidator<FindPersonsRequest>
public class FindTeachersRequestValidator : AbstractValidator<FindPersonRequest>
{
public FindTeachersRequestValidator()
{
Expand All @@ -13,12 +13,12 @@ public FindTeachersRequestValidator()

RuleFor(r => r.DateOfBirth)
.NotNull()
.When(r => r.FindBy == FindPersonsFindBy.LastNameAndDateOfBirth)
.WithMessage($"A value is required when findBy is '{nameof(FindPersonsFindBy.LastNameAndDateOfBirth)}'.");
.When(r => r.FindBy == FindPersonFindBy.LastNameAndDateOfBirth)
.WithMessage($"A value is required when findBy is '{nameof(FindPersonFindBy.LastNameAndDateOfBirth)}'.");

RuleFor(r => r.LastName)
.NotEmpty()
.When(r => r.FindBy == FindPersonsFindBy.LastNameAndDateOfBirth)
.WithMessage($"A value is required when findBy is '{nameof(FindPersonsFindBy.LastNameAndDateOfBirth)}'.");
.When(r => r.FindBy == FindPersonFindBy.LastNameAndDateOfBirth)
.WithMessage($"A value is required when findBy is '{nameof(FindPersonFindBy.LastNameAndDateOfBirth)}'.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using TeachingRecordSystem.Api.V3.Core.Operations;
using TeachingRecordSystem.Api.V3.VNext.ApiModels;
using TeachingRecordSystem.Api.V3.VNext.Requests;
using TeachingRecordSystem.Api.V3.VNext.Responses;

namespace TeachingRecordSystem.Api.V3.VNext.Controllers;

Expand All @@ -13,14 +14,14 @@ public class PersonsController(IMapper mapper) : ControllerBase
{
[HttpPut("{trn}/qtls")]
[SwaggerOperation(
OperationId = "PutQtls",
OperationId = "SetQtls",
Summary = "Set QTLS status for a teacher",
Description = "Sets the QTLS status for the teacher with the given TRN.")]
[ProducesResponseType(typeof(QtlsInfo), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(void), StatusCodes.Status202Accepted)]
[MapError(10001, statusCode: StatusCodes.Status404NotFound)]
[Authorize(Policy = AuthorizationPolicies.AssignQtls)]
public async Task<IActionResult> Put(
public async Task<IActionResult> PutQtls(
[FromRoute] string trn,
[FromBody] SetQtlsRequest request,
[FromServices] SetQtlsHandler handler)
Expand All @@ -37,7 +38,7 @@ public async Task<IActionResult> Put(
Description = "Gets the QTLS status for the teacher with the given TRN.")]
[ProducesResponseType(typeof(QtlsInfo), StatusCodes.Status200OK)]
[Authorize(Policy = AuthorizationPolicies.AssignQtls)]
public async Task<IActionResult> Get(
public async Task<IActionResult> GetQtls(
[FromRoute] string trn,
[FromServices] GetQtlsHandler handler)
{
Expand All @@ -46,4 +47,17 @@ public async Task<IActionResult> Get(
var response = mapper.Map<QtlsInfo?>(result);
return response is not null ? Ok(response) : NotFound();
}

[HttpPost("find")]
[SwaggerOperation(
OperationId = "FindPersons",
Summary = "Find persons",
Description = "Finds persons matching the specified criteria.")]
[ProducesResponseType(typeof(FindPersonsResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[Authorize(Policy = AuthorizationPolicies.GetPerson)]
public Task<IActionResult> FindTeachers([FromBody] FindPersonsRequest request)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace TeachingRecordSystem.Api.V3.VNext.Requests;

public record FindPersonsRequest
{
public required IReadOnlyCollection<FindPersonsRequestPerson> Persons { get; init; }
}

public record FindPersonsRequestPerson
{
public required string Trn { get; init; }
public required DateOnly DateOfBirth { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
using TeachingRecordSystem.Api.V3.Core.Operations;
using TeachingRecordSystem.Api.V3.V20240101.ApiModels;
using TeachingRecordSystem.Api.V3.V20240606.Requests;

namespace TeachingRecordSystem.Api.V3.V20240606.Responses;
namespace TeachingRecordSystem.Api.V3.VNext.Responses;

[AutoMap(typeof(FindPersonsResult))]
public record FindPersonsResponse
{
public required int Total { get; init; }
public required FindPersonsRequest Query { get; init; }
public required IReadOnlyCollection<FindPersonsResponseResult> Results { get; init; }
}

[AutoMap(typeof(FindPersonsResultItem))]
public record FindPersonsResponseResult
{
public required string Trn { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace TeachingRecordSystem.Api.Tests.V3.V20240606;

[Collection(nameof(DisableParallelization))]
public class FindTeachersTests : TestBase
public class FindPersonByLastNameAndDateOfBirthTests : TestBase
{
public FindTeachersTests(HostFixture hostFixture)
public FindPersonByLastNameAndDateOfBirthTests(HostFixture hostFixture)
: base(hostFixture)
{
XrmFakedContext.DeleteAllEntities<Contact>();
Expand Down

0 comments on commit 3deed24

Please sign in to comment.