Skip to content

Commit

Permalink
Merge branch 'main' into update-tech-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
aje54 authored Dec 10, 2024
2 parents 49f08bb + b0f90bb commit e655aa6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 158 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using TeachingRecordSystem.UiCommon.FormFlow;

namespace TeachingRecordSystem.AuthorizeAccess.Pages.RequestTrn;

[Journey(RequestTrnJourneyState.JourneyName), ActivatesJourney, RequireJourneyInstance]
public class IndexModel : PageModel
public class IndexModel(IConfiguration configuration) : PageModel
{
public JourneyInstance<RequestTrnJourneyState>? JourneyInstance { get; set; }

[FromQuery]
public string? AccessToken { get; set; }

public ActionResult OnGet()
{
var whitelistedAccessToken = configuration.GetRequiredValue("RequestTrnAccessToken");
if (!whitelistedAccessToken.Equals(AccessToken, StringComparison.Ordinal))
{
return NotFound();
}
return Page();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"Microsoft.AspNetCore": "Fatal"
}
}
}
},
"RequestTrnAccessToken": "n8hhN5MSrNXxCzRo"
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ public void SetInductionStatus(
DateTime now,
out PersonInductionUpdatedEvent? @event)
{
// FUTURE When we have QTS in TRS - assert person has QTS
AssertInductionChangeIsValid(status, startDate, completedDate, exemptionReasons);
// N.B. We allow missing data fields as some migrated data has missing fields
// and we want to be able to test such scenarios.

var changes = PersonInductionUpdatedEventChanges.None |
(InductionStatus != status ? PersonInductionUpdatedEventChanges.InductionStatus : 0) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,32 @@ public class IndexTests(HostFixture hostFixture) : TestBase(hostFixture)
public async Task Get_ValidRequest_RendersExpectedContent()
{
// Arrange
var accessToken = HostFixture.Services.GetRequiredService<IConfiguration>().GetValue<string>("RequestTrnAccessToken");
var state = CreateNewState();
var journeyInstance = await CreateJourneyInstance(state);

var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn?{journeyInstance.GetUniqueIdQueryParameter()}");
var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn?{journeyInstance.GetUniqueIdQueryParameter()}&AccessToken={accessToken}");

// Act
var response = await HttpClient.SendAsync(request);

// Assert
await AssertEx.HtmlResponseAsync(response);
}

[Fact]
public async Task Get_MissingAccessToken_ReturnsBadRequest()
{
// Arrange
var state = CreateNewState();
var journeyInstance = await CreateJourneyInstance(state);

var request = new HttpRequestMessage(HttpMethod.Get, $"/request-trn?{journeyInstance.GetUniqueIdQueryParameter()}&AccessToken=");

// Act
var response = await HttpClient.SendAsync(request);

// Assert
Assert.Equal(StatusCodes.Status404NotFound, (int)response.StatusCode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class CreatePersonBuilder
private string? _trnToken;
private string? _slugId;
private int? _loginFailedCounter;
private CreatePersonMandatoryQualificationBuilder.CreatePersonInductionBuilder? _inductionBuilder;
private CreatePersonInductionBuilder? _inductionBuilder;

public Guid PersonId { get; } = Guid.NewGuid();

Expand Down Expand Up @@ -291,13 +291,30 @@ public CreatePersonBuilder WithLoginFailedCounter(int? loginFailedCounter)
}

public CreatePersonBuilder WithInductionStatus(InductionStatus status) =>
WithInductionStatus(i => i.WithStatus(status));
WithInductionStatus(i =>
{
var qtsDate = GetQtsDate();
var startDate = CreatePersonInductionBuilder.GetDefaultStartDate(status, qtsDate);
var completedDate = CreatePersonInductionBuilder.GetDefaultCompletedDate(status, startDate);
var exemptionReasons = CreatePersonInductionBuilder.GetDefaultExemptionReasons(status);

if (!Person.ValidateInductionData(status, startDate, completedDate, exemptionReasons, out var error))
{
throw new InvalidOperationException(error);
}

i
.WithStatus(status)
.WithStartDate(startDate)
.WithCompletedDate(completedDate)
.WithExemptionReasons(exemptionReasons);
});

public CreatePersonBuilder WithInductionStatus(Action<CreatePersonMandatoryQualificationBuilder.CreatePersonInductionBuilder> configure)
public CreatePersonBuilder WithInductionStatus(Action<CreatePersonInductionBuilder> configure)
{
EnsureTrn();

_inductionBuilder ??= new(this);
_inductionBuilder ??= new();
configure(_inductionBuilder);

return this;
Expand Down Expand Up @@ -1042,178 +1059,100 @@ await dbContext.MandatoryQualificationProviders.SingleAsync(p => p.MandatoryQual

return (QualificationId, events);
}
}

public class CreatePersonInductionBuilder(CreatePersonBuilder createPersonBuilder)
{
private Option<InductionStatus> _status;
private Option<DateOnly?> _startDate;
private Option<DateOnly?> _completedDate;
private Option<InductionExemptionReasons> _exemptionReasons;
public class CreatePersonInductionBuilder
{
private Option<InductionStatus> _status;
private Option<DateOnly?> _startDate;
private Option<DateOnly?> _completedDate;
private Option<InductionExemptionReasons> _exemptionReasons;

public bool HasStatusRequiringQts => _status.HasValue && _status.ValueOrFailure() != InductionStatus.None;
public bool HasStatusRequiringQts => _status.HasValue && _status.ValueOrFailure() != InductionStatus.None;

public CreatePersonInductionBuilder WithStatus(InductionStatus status)
public CreatePersonInductionBuilder WithStatus(InductionStatus status)
{
if (_status.HasValue && _status.ValueOrFailure() != status)
{
if (_status.HasValue && _status.ValueOrFailure() != status)
{
throw new InvalidOperationException("Status has already been set.");
}

var qtsDate = createPersonBuilder.GetQtsDate();

if (status != InductionStatus.None && !qtsDate.HasValue)
{
throw new InvalidOperationException("Person requires QTS.");
}
else if (status == InductionStatus.None && qtsDate.HasValue)
{
throw new InvalidOperationException($"Status cannot be '{status}' when person has QTS.");
}

_status = Option.Some(status);
return this;
throw new InvalidOperationException("Status has already been set.");
}

public CreatePersonInductionBuilder WithStartDate(DateOnly? startDate)
{
if (_startDate.HasValue)
{
throw new InvalidOperationException("Start date has already been set.");
}

if (!_status.HasValue)
{
throw new InvalidOperationException("Status must be specified before the start date.");
}

var status = _status.ValueOrFailure();

if (!Person.ValidateInductionData(
status,
startDate,
GetDefaultCompletedDate(status, startDate),
GetDefaultExemptionReasons(status),
out var error))
{
throw new InvalidOperationException(error);
}

_startDate = Option.Some(startDate);
return this;
}
_status = Option.Some(status);
return this;
}

public CreatePersonInductionBuilder WithCompletedDate(DateOnly? completedDate)
public CreatePersonInductionBuilder WithStartDate(DateOnly? startDate)
{
if (_startDate.HasValue)
{
if (_completedDate.HasValue)
{
throw new InvalidOperationException("Completed date has already been set.");
}

if (!_status.HasValue)
{
throw new InvalidOperationException("Status must be specified before the start date.");
}

if (!_startDate.HasValue)
{
throw new InvalidOperationException("Start date must be specified before the completed date.");
}

var status = _status.ValueOrFailure();
var startDate = _startDate.ValueOrFailure();
throw new InvalidOperationException("Start date has already been set.");
}

if (!Person.ValidateInductionData(
status,
startDate,
completedDate,
GetDefaultExemptionReasons(status),
out var error))
{
throw new InvalidOperationException(error);
}
_startDate = Option.Some(startDate);
return this;
}

_completedDate = Option.Some(completedDate);
return this;
public CreatePersonInductionBuilder WithCompletedDate(DateOnly? completedDate)
{
if (_completedDate.HasValue)
{
throw new InvalidOperationException("Completed date has already been set.");
}

public CreatePersonInductionBuilder WithExemptionReasons(InductionExemptionReasons exemptionReasons)
{
if (_exemptionReasons.HasValue)
{
throw new InvalidOperationException("Exemption reasons have already been set.");
}
_completedDate = Option.Some(completedDate);
return this;
}

if (!_status.HasValue)
{
throw new InvalidOperationException("Status must be specified before the exemption reasons.");
}
public CreatePersonInductionBuilder WithExemptionReasons(InductionExemptionReasons exemptionReasons)
{
if (_exemptionReasons.HasValue)
{
throw new InvalidOperationException("Exemption reasons have already been set.");
}

var status = _status.ValueOrFailure();
_exemptionReasons = Option.Some(exemptionReasons);
return this;
}

if (status is not InductionStatus.Exempt && exemptionReasons != InductionExemptionReasons.None)
{
throw new InvalidOperationException($"Exemption reasons cannot be specified unless the status is {InductionStatus.Exempt}.");
}
internal IReadOnlyCollection<EventBase> Execute(
Person person,
CreatePersonBuilder createPersonBuilder,
TestData testData,
TrsDbContext dbContext)
{
var qtsDate = createPersonBuilder.GetQtsDate();

if (status is InductionStatus.Exempt && exemptionReasons == InductionExemptionReasons.None)
{
throw new InvalidOperationException($"Exemption reasons cannot be {InductionExemptionReasons.None} when the status is {InductionStatus.Exempt}.");
}
var status = _status.ValueOr(qtsDate.HasValue ? InductionStatus.RequiredToComplete : InductionStatus.None);
var startDate = _startDate.ValueOrDefault();
var completedDate = _completedDate.ValueOrDefault();
var exemptionReasons = _exemptionReasons.ValueOr(InductionExemptionReasons.None);

_exemptionReasons = Option.Some(exemptionReasons);
return this;
}
person.SetInductionStatus(
status,
startDate,
completedDate,
exemptionReasons,
updatedBy: SystemUser.SystemUserId,
testData.Clock.UtcNow,
out var @event);

internal IReadOnlyCollection<EventBase> Execute(
Person person,
CreatePersonBuilder createPersonBuilder,
TestData testData,
TrsDbContext dbContext)
if (@event is not null)
{
var qtsDate = createPersonBuilder.GetQtsDate();

var status = _status.ValueOr(qtsDate.HasValue ? InductionStatus.RequiredToComplete : InductionStatus.None);
var startDate = _startDate.ValueOr(GetDefaultStartDate(status, qtsDate));
var completedDate = _completedDate.ValueOr(GetDefaultCompletedDate(status, startDate));
var exemptionReasons = _exemptionReasons.ValueOr(GetDefaultExemptionReasons(status));

if (!Person.ValidateInductionData(
status,
startDate,
completedDate,
exemptionReasons,
out var error))
{
throw new InvalidOperationException(error);
}

person.SetInductionStatus(
status,
startDate,
completedDate,
exemptionReasons,
updatedBy: SystemUser.SystemUserId,
testData.Clock.UtcNow,
out var @event);

if (@event is not null)
{
dbContext.AddEvent(@event);
return [@event];
}

return [];
dbContext.AddEvent(@event);
return [@event];
}

private static DateOnly? GetDefaultStartDate(InductionStatus status, DateOnly? qtsDate) =>
status.RequiresStartDate() ? qtsDate!.Value.AddMonths(6) : null;
return [];
}

private static DateOnly? GetDefaultCompletedDate(InductionStatus status, DateOnly? startDate) =>
status.RequiresCompletedDate() ? startDate!.Value.AddMonths(12) : null;
internal static DateOnly? GetDefaultStartDate(InductionStatus status, DateOnly? qtsDate) =>
status.RequiresStartDate() ? qtsDate!.Value.AddMonths(6) : null;

private static InductionExemptionReasons GetDefaultExemptionReasons(InductionStatus status) =>
status is InductionStatus.Exempt ? (InductionExemptionReasons)1 : InductionExemptionReasons.None;
}
internal static DateOnly? GetDefaultCompletedDate(InductionStatus status, DateOnly? startDate) =>
status.RequiresCompletedDate() ? startDate!.Value.AddMonths(12) : null;

internal static InductionExemptionReasons GetDefaultExemptionReasons(InductionStatus status) =>
status is InductionStatus.Exempt ? (InductionExemptionReasons)1 : InductionExemptionReasons.None;
}

public record CreatePersonResult
Expand Down

0 comments on commit e655aa6

Please sign in to comment.