diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ExcludeFromSchemaAttribute.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ExcludeFromSchemaAttribute.cs new file mode 100644 index 000000000..6686a4cf2 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ExcludeFromSchemaAttribute.cs @@ -0,0 +1,6 @@ +namespace TeachingRecordSystem.Api.Infrastructure.OpenApi; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] +public sealed class ExcludeFromSchemaAttribute : Attribute +{ +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/RemoveExcludedEnumOptionsSchemaProcessor.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/RemoveExcludedEnumOptionsSchemaProcessor.cs new file mode 100644 index 000000000..c81e97c67 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/RemoveExcludedEnumOptionsSchemaProcessor.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using NJsonSchema.Generation; + +namespace TeachingRecordSystem.Api.Infrastructure.OpenApi; + +public class RemoveExcludedEnumOptionsSchemaProcessor : ISchemaProcessor +{ + public void Process(SchemaProcessorContext context) + { + var type = context.ContextualType.Type; + + if (!type.IsEnum) + { + return; + } + + foreach (var memberName in Enum.GetNames(type)) + { + var member = type.GetField(memberName)!; + if (member.GetCustomAttribute() is not null) + { + context.Schema.Enumeration.Remove(memberName); + context.Schema.EnumerationNames.Remove(memberName); + } + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ServiceCollectionExtensions.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ServiceCollectionExtensions.cs index d077a9677..1dee59527 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ServiceCollectionExtensions.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/Infrastructure/OpenApi/ServiceCollectionExtensions.cs @@ -22,6 +22,7 @@ public static IServiceCollection AddOpenApi(this IServiceCollection services, IC settings.DocumentProcessors.Add(new PopulateResponseDescriptionOperationProcessor()); settings.SchemaProcessors.Add(new RemoveCompositeValuesFromFlagsEnumSchemaProcessor()); + settings.SchemaProcessors.Add(new RemoveExcludedEnumOptionsSchemaProcessor()); settings.OperationProcessors.Add(new ResponseContentTypeOperationProcessor()); settings.OperationProcessors.Add(new PopulateResponseDescriptionOperationProcessor()); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/ApiModels/AlertInfo.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/ApiModels/AlertInfo.cs index ea99231f9..e1db08a71 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/ApiModels/AlertInfo.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/ApiModels/AlertInfo.cs @@ -4,4 +4,6 @@ public record AlertInfo { public required AlertType AlertType { get; init; } public required string DqtSanctionCode { get; init; } + public required DateOnly? StartDate { get; init; } + public required DateOnly? EndDate { get; init; } } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs index 0f06422cb..74e6cbb88 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs @@ -45,7 +45,8 @@ public GetTeacherHandler( Contact.Fields.dfeta_NINumber, Contact.Fields.dfeta_QTSDate, Contact.Fields.dfeta_EYTSDate, - Contact.Fields.EMailAddress1))); + Contact.Fields.EMailAddress1, + Contact.Fields.dfeta_AllowIDSignInWithProhibitions))); if (contactDetail is null) { @@ -201,7 +202,10 @@ public GetTeacherHandler( var getSanctionsQuery = new GetSanctionsByContactIdsQuery( new[] { teacher.Id }, ActiveOnly: true, - ColumnSet: new(dfeta_sanction.Fields.dfeta_StartDate)); + ColumnSet: new( + dfeta_sanction.Fields.dfeta_StartDate, + dfeta_sanction.Fields.dfeta_EndDate, + dfeta_sanction.Fields.dfeta_Spent)); sanctions = (await _crmQueryDispatcher.ExecuteQuery(getSanctionsQuery))[teacher.Id]; } @@ -275,6 +279,10 @@ public GetTeacherHandler( var qtsAwardedInWales = qtsRegistrations.Any(qts => qts.dfeta_QTSDate is not null && qts.dfeta_TeacherStatusId.Id == qtsAwardedInWalesStatus.Id); + var allowIdSignInWithProhibitions = request.Include.HasFlag(GetTeacherRequestIncludes._AllowIdSignInWithProhibitions) ? + Option.Some(teacher.dfeta_AllowIDSignInWithProhibitions == true) : + default; + return new GetTeacherResponse() { Trn = request.Trn, @@ -317,6 +325,7 @@ public GetTeacherHandler( Sanctions = request.Include.HasFlag(GetTeacherRequestIncludes.Sanctions) ? Option.Some(sanctions! .Where(s => Constants.ExposableSanctionCodes.Contains(s.SanctionCode)) + .Where(s => s.Sanction.dfeta_EndDate is null && s.Sanction.dfeta_Spent != true) .Select(s => new SanctionInfo() { Code = s.SanctionCode, @@ -329,12 +338,15 @@ public GetTeacherHandler( .Select(s => new AlertInfo() { AlertType = AlertType.Prohibition, - DqtSanctionCode = s.SanctionCode + DqtSanctionCode = s.SanctionCode, + StartDate = s.Sanction.dfeta_StartDate?.ToDateOnlyWithDqtBstFix(isLocalTime: true), + EndDate = s.Sanction.dfeta_EndDate?.ToDateOnlyWithDqtBstFix(isLocalTime: true) })) : default, PreviousNames = request.Include.HasFlag(GetTeacherRequestIncludes.PreviousNames) ? Option.Some(previousNames!.Select(n => n)) : - default + default, + AllowIdSignInWithProhibitions = allowIdSignInWithProhibitions }; } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Requests/GetTeacherRequest.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Requests/GetTeacherRequest.cs index 822fa6d11..9111a3337 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Requests/GetTeacherRequest.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Requests/GetTeacherRequest.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using MediatR; +using TeachingRecordSystem.Api.Infrastructure.OpenApi; using TeachingRecordSystem.Api.V3.Responses; namespace TeachingRecordSystem.Api.V3.Requests; @@ -27,5 +28,8 @@ public enum GetTeacherRequestIncludes Alerts = 1 << 7, PreviousNames = 1 << 8, + [ExcludeFromSchema] + _AllowIdSignInWithProhibitions = 1 << 9, + All = Induction | InitialTeacherTraining | NpqQualifications | MandatoryQualifications | PendingDetailChanges | HigherEducationQualifications | Sanctions | Alerts | PreviousNames } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Responses/GetTeacherResponse.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Responses/GetTeacherResponse.cs index 78e6511a6..d689f3441 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Responses/GetTeacherResponse.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Responses/GetTeacherResponse.cs @@ -25,6 +25,7 @@ public record GetTeacherResponse public required Option> Sanctions { get; init; } public required Option> Alerts { get; init; } public required Option> PreviousNames { get; init; } + public required Option AllowIdSignInWithProhibitions { get; init; } } public record GetTeacherResponseQts diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs index a096e139e..3f73c6b14 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs @@ -1293,6 +1293,7 @@ public static class Fields public const string Id = "contactid"; public const string CreatedOn = "createdon"; public const string dfeta_ActiveSanctions = "dfeta_activesanctions"; + public const string dfeta_AllowIDSignInWithProhibitions = "dfeta_allowidsigninwithprohibitions"; public const string dfeta_AllowPiiUpdatesFromRegister = "dfeta_allowpiiupdatesfromregister"; public const string dfeta_EYTSDate = "dfeta_eytsdate"; public const string dfeta_HUSID = "dfeta_husid"; @@ -1626,6 +1627,26 @@ public System.Nullable dfeta_ActiveSanctions } } + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_allowidsigninwithprohibitions")] + public System.Nullable dfeta_AllowIDSignInWithProhibitions + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_allowidsigninwithprohibitions"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_AllowIDSignInWithProhibitions"); + this.SetAttributeValue("dfeta_allowidsigninwithprohibitions", value); + this.OnPropertyChanged("dfeta_AllowIDSignInWithProhibitions"); + } + } + /// /// /// diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetSanctionsByContactIdsHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetSanctionsByContactIdsHandler.cs index ed548056c..4ff47b426 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetSanctionsByContactIdsHandler.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetSanctionsByContactIdsHandler.cs @@ -29,11 +29,9 @@ public async Task> Execute( if (query.ActiveOnly) { - queryExpression.Criteria.AddCondition(dfeta_sanction.Fields.dfeta_Spent, ConditionOperator.Equal, false); - queryExpression.Criteria.AddCondition(dfeta_sanction.Fields.dfeta_EndDate, ConditionOperator.Null); + queryExpression.Criteria.AddCondition(dfeta_sanction.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_sanctionState.Active); } - queryExpression.Criteria.AddCondition(dfeta_sanction.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_sanctionState.Active); queryExpression.Criteria.AddCondition(dfeta_sanction.Fields.dfeta_PersonId, ConditionOperator.In, contactIdsArray.Cast().ToArray()); // https://community.dynamics.com/crm/b/crmbusiness/posts/crm-2011-odd-error-with-query-expression-and-conditionoperator-in var sanctionCodeLink = queryExpression.AddLink( diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/GetTeacherTestBase.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/GetTeacherTestBase.cs index cf62d6331..f123497ad 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/GetTeacherTestBase.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/GetTeacherTestBase.cs @@ -568,12 +568,16 @@ protected async Task ValidRequestWithAlerts_ReturnsExpectedSanctionsContent( new { alertType = "Prohibition", - dqtSanctionCode = sanctions[0].SanctionCode + dqtSanctionCode = sanctions[0].SanctionCode, + startDate = sanctions[0].StartDate, + endDate = (DateOnly?)null }, new { alertType = "Prohibition", - dqtSanctionCode = sanctions[1].SanctionCode + dqtSanctionCode = sanctions[1].SanctionCode, + startDate = sanctions[1].StartDate, + endDate = (DateOnly?)null } }, responseAlerts); diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.Tests/QueryTests/GetSanctionsByContactIdsTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.Tests/QueryTests/GetSanctionsByContactIdsTests.cs index b8b36e481..797b06c8e 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.Tests/QueryTests/GetSanctionsByContactIdsTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.Tests/QueryTests/GetSanctionsByContactIdsTests.cs @@ -39,57 +39,4 @@ public async Task ReturnsSanctionsForEachContactIdSpecified() Assert.Collection(sanctionCodesByContactId[person2.ContactId], c => Assert.Equal(person2Sanction2Code, c.SanctionCode), c => Assert.Equal(person2Sanction1Code, c.SanctionCode)); Assert.Empty(sanctionCodesByContactId[person3.ContactId]); } - - [Theory] - [InlineData(true, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, true)] - [InlineData(false, false, true)] - public async Task SpentSanctionIsReturnedAsExpected(bool spent, bool activeOnly, bool expectSanctionReturned) - { - // Arrange - var sanctionCode = "G1"; - var person = await _dataScope.TestData.CreatePerson(x => x.WithSanction(sanctionCode, spent: spent)); - - // Act - var sanctionCodesByContactId = await _crmQueryDispatcher.ExecuteQuery( - new GetSanctionsByContactIdsQuery(new[] { person.ContactId }, ActiveOnly: activeOnly, new ColumnSet())); - - // Assert - if (expectSanctionReturned) - { - Assert.Collection(sanctionCodesByContactId[person.ContactId], c => Assert.Equal("G1", sanctionCode)); - } - else - { - Assert.Empty(sanctionCodesByContactId[person.ContactId]); - } - } - - [Theory] - [InlineData(true, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, true)] - [InlineData(false, false, true)] - public async Task EndedSanctionIsReturnedAsExpected(bool ended, bool activeOnly, bool expectSanctionReturned) - { - // Arrange - var sanctionCode = "G1"; - var person = await _dataScope.TestData.CreatePerson( - x => x.WithSanction(sanctionCode, spent: false, endDate: ended ? DateOnly.FromDateTime(DateTime.Today.AddDays(-1)) : null)); - - // Act - var sanctionCodesByContactId = await _crmQueryDispatcher.ExecuteQuery( - new GetSanctionsByContactIdsQuery(new[] { person.ContactId }, ActiveOnly: activeOnly, new ColumnSet())); - - // Assert - if (expectSanctionReturned) - { - Assert.Collection(sanctionCodesByContactId[person.ContactId], c => Assert.Equal(sanctionCode, c.SanctionCode)); - } - else - { - Assert.Empty(sanctionCodesByContactId[person.ContactId]); - } - } } diff --git a/crm_attributes.json b/crm_attributes.json index 0b7223e2e..4a3111312 100644 --- a/crm_attributes.json +++ b/crm_attributes.json @@ -59,7 +59,8 @@ "telephone1", "dfeta_slugid", "dfeta_allowpiiupdatesfromregister", - "dfeta_previouslastname" + "dfeta_previouslastname", + "dfeta_AllowIDSignInWithProhibitions" ], "dfeta_businesseventaudit":[ "createdon", diff --git a/tools/coretools/CrmSvcUtil.exe.config b/tools/coretools/CrmSvcUtil.exe.config index fe178e606..a49c145e3 100644 --- a/tools/coretools/CrmSvcUtil.exe.config +++ b/tools/coretools/CrmSvcUtil.exe.config @@ -20,7 +20,13 @@ +<<<<<<< HEAD +||||||| parent of 89cf2325 (Add AllowIdSignInWithProhibitions member to v3 teacher response) + +======= + +>>>>>>> 89cf2325 (Add AllowIdSignInWithProhibitions member to v3 teacher response)