Skip to content

Commit

Permalink
Added qtlsstatus to vnext getperson
Browse files Browse the repository at this point in the history
  • Loading branch information
MrKevJoy committed Dec 19, 2024
1 parent 4556756 commit dab37f0
Show file tree
Hide file tree
Showing 11 changed files with 505 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.ComponentModel;

namespace TeachingRecordSystem.Api.V3.Implementation.Dtos;

public enum QtlsStatus
{
[Description("None")]
None = 0,

[Description("Expired")]
Expired = 1,

[Description("Active")]
Active = 2,
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,59 @@ public record QtsInfo
public required string CertificateUrl { get; init; }
public required string StatusDescription { get; init; }

public static async Task<QtsInfo?> CreateAsync(dfeta_qtsregistration? qtsRegistration, ReferenceDataCache referenceDataCache)
public static async Task<QtsInfo?> CreateAsync(dfeta_qtsregistration? qtsRegistration, ReferenceDataCache referenceDataCache, DateTime? qtlsDate)
{
if (qtsRegistration is null)
var qtsDates = new List<DateTime?>() { qtsRegistration?.dfeta_QTSDate, qtlsDate };
var earliestDate = qtsDates.Where(x => x != null).OrderBy(date => date).FirstOrDefault();
if (earliestDate is null && qtsRegistration is null)
{
return null;
}

var awardedDate = qtsRegistration.dfeta_QTSDate.ToDateOnlyWithDqtBstFix(isLocalTime: true);
if (awardedDate is null)
{
return null;
}

var teacherStatus = await referenceDataCache.GetTeacherStatusByIdAsync(qtsRegistration.dfeta_TeacherStatusId.Id);
var statusDescription = GetStatusDescription(teacherStatus);
var teacherStatus = qtsRegistration != null ? await referenceDataCache.GetTeacherStatusByIdAsync(qtsRegistration.dfeta_TeacherStatusId.Id) : null;
var statusDescription = GetStatusDescription(teacherStatus, qtsRegistration?.dfeta_QTSDate, qtlsDate);

return new()
{
Awarded = awardedDate!.Value,
Awarded = earliestDate!.Value.ToDateOnlyWithDqtBstFix(isLocalTime: true),
CertificateUrl = "/v3/certificates/qts",
StatusDescription = statusDescription,
};
}

private static string GetStatusDescription(dfeta_teacherstatus teacherStatus) => teacherStatus.dfeta_Value switch
private static string GetStatusDescription(dfeta_teacherstatus? teacherStatus, DateTime? qtsDate = null, DateTime? qtlsDate = null)
{
"28" => "Qualified",
"50" => "Qualified",
"67" => "Qualified",
"68" => "Qualified",
"69" => "Qualified",
"71" => "Qualified",
"87" => "Qualified",
"90" => "Qualified",
"100" => "Qualified",
"103" => "Qualified",
"104" => "Qualified",
"206" => "Qualified",
"211" => "Trainee teacher",
"212" => "Assessment only route candidate",
"213" => "Qualified",
"214" => "Partial qualified teacher status",
"223" => "Qualified",
_ when teacherStatus.dfeta_name.StartsWith("Qualified teacher", StringComparison.OrdinalIgnoreCase) => "Qualified",
_ => throw new ArgumentException($"Unregonized QTS status: '{teacherStatus.dfeta_Value}'.", nameof(teacherStatus))
};
return (qtsDate, qtlsDate) switch
{
(null, null) => GetStatusDescriptionForTeacherStatus(teacherStatus),
(var qts, var qtls) when qtls.ToDateOnlyWithDqtBstFix(isLocalTime: true) <= qts.ToDateOnlyWithDqtBstFix(isLocalTime: true) => "Qualified Teacher Learning and Skills status",
(null, var qtls) => "Qualified Teacher Learning and Skills status",
_ => GetStatusDescriptionForTeacherStatus(teacherStatus),
};

string GetStatusDescriptionForTeacherStatus(dfeta_teacherstatus? teacherStatus) =>
teacherStatus!.dfeta_Value switch
{
"28" => "Qualified",
"50" => "Qualified",
"67" => "Qualified",
"68" => "Qualified",
"69" => "Qualified",
"71" => "Qualified",
"87" => "Qualified",
"90" => "Qualified",
"100" => "Qualified",
"103" => "Qualified",
"104" => "Qualified",
"206" => "Qualified",
"211" => "Trainee teacher",
"212" => "Assessment only route candidate",
"213" => "Qualified",
"214" => "Partial qualified teacher status",
"223" => "Qualified",
_ when teacherStatus.dfeta_name.StartsWith("Qualified teacher", StringComparison.OrdinalIgnoreCase) => "Qualified",
_ => throw new ArgumentException($"Unrecognized QTS status: '{teacherStatus.dfeta_Value}'.", nameof(teacherStatus))
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public record FindPersonsResultItem
public required DqtInductionStatusInfo? DqtInductionStatus { get; init; }
public required QtsInfo? Qts { get; init; }
public required EytsInfo? Eyts { get; init; }
public required QtlsStatus QtlsStatus { get; init; }
}

public abstract class FindPersonsHandlerBase(
Expand All @@ -45,7 +46,20 @@ public abstract class FindPersonsHandlerBase(
Contact.Fields.dfeta_StatedFirstName,
Contact.Fields.dfeta_StatedMiddleName,
Contact.Fields.dfeta_StatedLastName,
Contact.Fields.dfeta_InductionStatus);
Contact.Fields.dfeta_InductionStatus,
Contact.Fields.dfeta_qtlsdate,
Contact.Fields.dfeta_QtlsDateHasBeenSet);

private static QtlsStatus MapQtlsStatus(DateTime? qtlsDate, bool? qtlsDateHasBeenSet)
{
return (qtlsDate, qtlsDateHasBeenSet) switch
{
(not null, _) => QtlsStatus.Active,
(null, true) => QtlsStatus.Expired,
(null, false) => QtlsStatus.None,
(_, _) => QtlsStatus.None,
};
}

protected async Task<FindPersonsResult> CreateResultAsync(IEnumerable<Contact> matched)
{
Expand Down Expand Up @@ -81,6 +95,7 @@ protected async Task<FindPersonsResult> CreateResultAsync(IEnumerable<Contact> m
.ToAsyncEnumerable()
.SelectAwait(async r => new FindPersonsResultItem()
{
QtlsStatus = MapQtlsStatus(r.dfeta_qtlsdate, r.dfeta_QtlsDateHasBeenSet),
Trn = r.dfeta_TRN,
DateOfBirth = r.BirthDate!.Value.ToDateOnlyWithDqtBstFix(isLocalTime: false),
FirstName = r.ResolveFirstName(),
Expand All @@ -95,26 +110,26 @@ protected async Task<FindPersonsResult> CreateResultAsync(IEnumerable<Contact> m
})
.AsReadOnly(),
Alerts = alerts.GetValueOrDefault(r.Id, [])
.Where(a => !a.AlertType.InternalOnly)
.Select(a => new Alert()
{
AlertId = a.AlertId,
AlertType = new()
.Where(a => !a.AlertType.InternalOnly)
.Select(a => new Alert()
{
AlertTypeId = a.AlertType.AlertTypeId,
AlertCategory = new()
AlertId = a.AlertId,
AlertType = new()
{
AlertCategoryId = a.AlertType.AlertCategory.AlertCategoryId,
Name = a.AlertType.AlertCategory.Name
AlertTypeId = a.AlertType.AlertTypeId,
AlertCategory = new()
{
AlertCategoryId = a.AlertType.AlertCategory.AlertCategoryId,
Name = a.AlertType.AlertCategory.Name
},
Name = a.AlertType.Name,
DqtSanctionCode = a.AlertType.DqtSanctionCode!
},
Name = a.AlertType.Name,
DqtSanctionCode = a.AlertType.DqtSanctionCode!
},
Details = a.Details,
StartDate = a.StartDate,
EndDate = a.EndDate
})
.AsReadOnly(),
Details = a.Details,
StartDate = a.StartDate,
EndDate = a.EndDate
})
.AsReadOnly(),
PreviousNames = previousNameHelper.GetFullPreviousNames(previousNames[r.Id], contactsById[r.Id])
.Select(name => new NameInfo()
{
Expand All @@ -131,7 +146,7 @@ protected async Task<FindPersonsResult> CreateResultAsync(IEnumerable<Contact> m
StatusDescription = inductionStatus.GetDescription()
} :
null,
Qts = await QtsInfo.CreateAsync(qtsRegistrations[r.Id].OrderBy(qr => qr.CreatedOn).FirstOrDefault(s => s.dfeta_QTSDate is not null), referenceDataCache),
Qts = await QtsInfo.CreateAsync(qtsRegistrations[r.Id].OrderBy(qr => qr.CreatedOn).FirstOrDefault(s => s.dfeta_QTSDate is not null), referenceDataCache, r.dfeta_qtlsdate),
Eyts = await EytsInfo.CreateAsync(qtsRegistrations[r.Id].OrderBy(qr => qr.CreatedOn).FirstOrDefault(s => s.dfeta_EYTSDate is not null), referenceDataCache),
})
.OrderBy(c => c.Trn)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public record GetPersonResult
public required Option<IReadOnlyCollection<Alert>> Alerts { get; init; }
public required Option<IReadOnlyCollection<NameInfo>> PreviousNames { get; init; }
public required Option<bool> AllowIdSignInWithProhibitions { get; init; }
public required QtlsStatus QtlsStatus { get; set; }
}

public record GetPersonResultInduction : InductionInfo
Expand Down Expand Up @@ -193,7 +194,9 @@ public async Task<ApiResult<GetPersonResult>> HandleAsync(GetPersonCommand comma
Contact.Fields.dfeta_EYTSDate,
Contact.Fields.EMailAddress1,
Contact.Fields.dfeta_AllowIDSignInWithProhibitions,
Contact.Fields.dfeta_InductionStatus)));
Contact.Fields.dfeta_InductionStatus,
Contact.Fields.dfeta_QtlsDateHasBeenSet,
Contact.Fields.dfeta_qtlsdate)));

if (contactDetail is null)
{
Expand Down Expand Up @@ -386,6 +389,8 @@ async Task<T> WithTrsDbLockAsync<T>(Func<Task<T>> action)
induction = Option.Some(mappedInduction.Induction);
}

var qtlsStatus = MapQtlsStatus(contact.dfeta_qtlsdate, contact.dfeta_QtlsDateHasBeenSet);

return new GetPersonResult()
{
Trn = command.Trn,
Expand All @@ -396,7 +401,8 @@ async Task<T> WithTrsDbLockAsync<T>(Func<Task<T>> action)
NationalInsuranceNumber = contact.dfeta_NINumber,
PendingNameChange = command.Include.HasFlag(GetPersonCommandIncludes.PendingDetailChanges) ? Option.Some((await getPendingDetailChangesTask!).PendingNameRequest) : default,
PendingDateOfBirthChange = command.Include.HasFlag(GetPersonCommandIncludes.PendingDetailChanges) ? Option.Some((await getPendingDetailChangesTask!).PendingDateOfBirthRequest) : default,
Qts = await QtsInfo.CreateAsync(qts, referenceDataCache),
Qts = await QtsInfo.CreateAsync(qts, referenceDataCache, contact.dfeta_qtlsdate),
QtlsStatus = qtlsStatus,
Eyts = await EytsInfo.CreateAsync(eyts, referenceDataCache),
EmailAddress = contact.EMailAddress1,
Induction = induction,
Expand Down Expand Up @@ -462,6 +468,17 @@ async Task<T> WithTrsDbLockAsync<T>(Func<Task<T>> action)
};
}

private static QtlsStatus MapQtlsStatus(DateTime? qtlsDate, bool? qtlsDateHasBeenSet)
{
return (qtlsDate, qtlsDateHasBeenSet) switch
{
(not null, _) => QtlsStatus.Active,
(null, true) => QtlsStatus.Expired,
(null, false) => QtlsStatus.None,
(_, _) => QtlsStatus.None,
};
}

private static (GetPersonResultDqtInduction? DqtInduction, GetPersonResultInduction Induction) MapInduction(
dfeta_induction? induction,
IEnumerable<dfeta_inductionperiod>? inductionPeriods,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using TeachingRecordSystem.Api.V3.Implementation.Dtos;
using TeachingRecordSystem.Api.V3.Implementation.Operations;
using InductionStatus = TeachingRecordSystem.Core.ApiSchema.V3.VNext.Dtos.InductionStatus;

Expand All @@ -14,4 +15,5 @@ public partial record FindPersonResponse
public partial record FindPersonResponseResult
{
public required InductionStatus InductionStatus { get; init; }
public required QtlsStatus QtlsStatus { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AutoMapper.Configuration.Annotations;
using TeachingRecordSystem.Api.V3.Implementation.Dtos;
using TeachingRecordSystem.Api.V3.Implementation.Operations;
using InductionStatus = TeachingRecordSystem.Core.ApiSchema.V3.VNext.Dtos.InductionStatus;

Expand All @@ -17,4 +18,5 @@ public partial record FindPersonsResponse
public partial record FindPersonsResponseResult
{
public required InductionStatus InductionStatus { get; init; }
public required QtlsStatus QtlsStatus { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Optional;
using TeachingRecordSystem.Api.V3.Implementation.Dtos;
using TeachingRecordSystem.Api.V3.Implementation.Operations;
using TeachingRecordSystem.Core.ApiSchema.V3.VNext.Dtos;

namespace TeachingRecordSystem.Api.V3.VNext.Responses;

Expand All @@ -9,6 +9,7 @@ namespace TeachingRecordSystem.Api.V3.VNext.Responses;
public partial record GetPersonResponse
{
public required Option<GetPersonResponseInduction> Induction { get; init; }
public required QtlsStatus QtlsStatus { get; set; }
}

[AutoMap(typeof(GetPersonResultInduction))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using TeachingRecordSystem.Api.V3.Implementation.Dtos;

namespace TeachingRecordSystem.Api.Tests.V3.VNext;

[Collection(nameof(DisableParallelization))]
Expand Down Expand Up @@ -67,4 +69,86 @@ public async Task Get_PersonHasNonNullDqtInductionStatus_ReturnsExpectedStatus()
var responseInduction = jsonResponse.RootElement.GetProperty("results").EnumerateArray().Single().GetProperty("inductionStatus").GetString();
Assert.Equal(inductionStatus.ToString(), responseInduction);
}

[Fact]
public async Task Get_WithExpiredQtlsDate_ReturnsExpiredQtlsStatus()
{
// Arrange
var lastName = "Smith";
var dateOfBirth = new DateOnly(1990, 1, 1);
var qtlsDate = new DateOnly(2020, 01, 01);

var person = await TestData.CreatePersonAsync(p => p
.WithTrn()
.WithLastName(lastName)
.WithQtlsDate(qtlsDate)
.WithDateOfBirth(dateOfBirth));

var entity = new Microsoft.Xrm.Sdk.Entity() { Id = person.PersonId, LogicalName = Contact.EntityLogicalName };
entity[Contact.Fields.dfeta_qtlsdate] = null;
await TestData.OrganizationService.UpdateAsync(entity);

var request = new HttpRequestMessage(
HttpMethod.Get,
$"/v3/persons?findBy=LastNameAndDateOfBirth&lastName={lastName}&dateOfBirth={dateOfBirth:yyyy-MM-dd}");

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

// Assert
var jsonResponse = await AssertEx.JsonResponseAsync(response);
var qtlsStatus = jsonResponse.RootElement.GetProperty("results").EnumerateArray().Single().GetProperty("qtlsStatus").GetString();
Assert.Equal(QtlsStatus.Expired.ToString(), qtlsStatus!);
}

[Fact]
public async Task Get_WithQtlsDate_ReturnsActiveQtlsStatus()
{
// Arrange
var lastName = "Smith";
var dateOfBirth = new DateOnly(1990, 1, 1);
var qtlsDate = new DateOnly(2020, 01, 01);

var person = await TestData.CreatePersonAsync(p => p
.WithTrn()
.WithLastName(lastName)
.WithQtlsDate(qtlsDate)
.WithDateOfBirth(dateOfBirth));

var request = new HttpRequestMessage(
HttpMethod.Get,
$"/v3/persons?findBy=LastNameAndDateOfBirth&lastName={lastName}&dateOfBirth={dateOfBirth:yyyy-MM-dd}");

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

// Assert
var jsonResponse = await AssertEx.JsonResponseAsync(response);
var qtlsStatus = jsonResponse.RootElement.GetProperty("results").EnumerateArray().Single().GetProperty("qtlsStatus").GetString();
Assert.Equal(QtlsStatus.Active.ToString(), qtlsStatus!);
}

[Fact]
public async Task Get_WithoutQtlsDate_ReturnsNoneQtlsStatus()
{
// Arrange
var lastName = "Smith";
var dateOfBirth = new DateOnly(1990, 1, 1);
var person = await TestData.CreatePersonAsync(p => p
.WithTrn()
.WithLastName(lastName)
.WithDateOfBirth(dateOfBirth));

var request = new HttpRequestMessage(
HttpMethod.Get,
$"/v3/persons?findBy=LastNameAndDateOfBirth&lastName={lastName}&dateOfBirth={dateOfBirth:yyyy-MM-dd}");

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

// Assert
var jsonResponse = await AssertEx.JsonResponseAsync(response);
var qtlsStatus = jsonResponse.RootElement.GetProperty("results").EnumerateArray().Single().GetProperty("qtlsStatus").GetString();
Assert.Equal(QtlsStatus.None.ToString(), qtlsStatus!);
}
}
Loading

0 comments on commit dab37f0

Please sign in to comment.