From c970f68d529cb40e86b297e293a0ca57800052d1 Mon Sep 17 00:00:00 2001 From: Andrew Horth Date: Thu, 21 Mar 2024 17:58:37 +0000 Subject: [PATCH] Allow HE quals with no link to dfeta_hequalification table Amended to only return HE quals with at least one subject + added tests Removed commented out code Removed unnecessary code Removed commented out code --- .../V3/Handlers/GetTeacherHandler.cs | 45 ++---- .../V3/Responses/GetTeacherResponse.cs | 2 +- .../Dqt/Models/GeneratedCode.cs | 45 ++++++ .../Queries/GetAllHeQualificationsQuery.cs | 3 + .../Dqt/Queries/GetAllHeSubjectsQuery.cs | 3 + .../GetQualificationsByContactIdQuery.cs | 5 + .../GetAllHeQualificationsHandler.cs | 31 ++++ .../QueryHandlers/GetAllHeSubjectsHandler.cs | 31 ++++ .../GetQualificationsByContactIdHandler.cs | 77 ++++++++++ .../Dqt/ReferenceDataCache.cs | 40 +++++ .../V3/V20240101/GetTeacherByTrnTests.cs | 25 ++- .../V3/V20240101/GetTeacherTestBase.cs | 145 +++++++----------- .../V3/V20240101/GetTeacherTests.cs | 25 ++- .../QueryTests/GetAllHeQualificationsTests.cs | 24 +++ .../QueryTests/GetAllHeSubjectsTests.cs | 24 +++ .../GetQualificationsByContactIdTests.cs | 107 +++++++++++++ .../SeedCrmReferenceData.cs | 98 ++++++++++++ .../TestData.CreatePerson.cs | 80 ++++++++++ crm_attributes.json | 1 + tools/coretools/CrmSvcUtil.exe.config | 2 +- 20 files changed, 677 insertions(+), 136 deletions(-) create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeQualificationsQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeSubjectsQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetQualificationsByContactIdQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeQualificationsHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeSubjectsHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetQualificationsByContactIdHandler.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeQualificationsTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeSubjectsTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetQualificationsByContactIdTests.cs diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs index 161fc6311..6e838dc79 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Handlers/GetTeacherHandler.cs @@ -128,37 +128,15 @@ public class GetTeacherHandler( if ((request.Include & (GetTeacherRequestIncludes.NpqQualifications | GetTeacherRequestIncludes.HigherEducationQualifications)) != 0) { - string[]? columnNames = new[] - { - dfeta_qualification.Fields.dfeta_CompletionorAwardDate, - dfeta_qualification.Fields.dfeta_Type, - dfeta_qualification.Fields.StateCode - }; - - string[]? heQualificationColumnNames = null; - string[]? heSubjectColumnNames = null; - - if (request.Include.HasFlag(GetTeacherRequestIncludes.HigherEducationQualifications)) - { - heQualificationColumnNames = new[] - { - dfeta_hequalification.PrimaryIdAttribute, - dfeta_hequalification.Fields.dfeta_name - }; - - heSubjectColumnNames = new[] - { - dfeta_hesubject.PrimaryIdAttribute, - dfeta_hesubject.Fields.dfeta_name, - dfeta_hesubject.Fields.dfeta_Value - }; - } - - qualifications = await dataverseAdapter.GetQualificationsForTeacher( - teacher.Id, - columnNames, - heQualificationColumnNames, - heSubjectColumnNames); + qualifications = await crmQueryDispatcher.ExecuteQuery( + new GetQualificationsByContactIdQuery( + teacher.Id, + new ColumnSet( + dfeta_qualification.PrimaryIdAttribute, + dfeta_qualification.Fields.dfeta_CompletionorAwardDate, + dfeta_qualification.Fields.dfeta_Type, + dfeta_qualification.Fields.StateCode), + IncludeHigherEducationDetails: request.Include.HasFlag(GetTeacherRequestIncludes.HigherEducationQualifications))); } bool pendingNameChange = default, pendingDateOfBirthChange = default; @@ -514,8 +492,7 @@ private static IReadOnlyCollection q.dfeta_Type.HasValue && q.dfeta_Type.Value == dfeta_qualification_dfeta_Type.HigherEducation && - q.StateCode == dfeta_qualificationState.Active && - q.Extract() is not null) + q.StateCode == dfeta_qualificationState.Active) ?.Select(q => { var heQualification = q.Extract(); @@ -555,7 +532,7 @@ private static IReadOnlyCollection Subjects { get; init; } } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs index 2265d0b41..e67a05331 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs @@ -5670,6 +5670,8 @@ public partial class dfeta_hesubject : Microsoft.Xrm.Sdk.Entity, System.Componen /// public static class Fields { + public const string dfeta_hesubjectId = "dfeta_hesubjectid"; + public const string Id = "dfeta_hesubjectid"; public const string dfeta_name = "dfeta_name"; public const string dfeta_Value = "dfeta_value"; public const string StateCode = "statecode"; @@ -5725,6 +5727,49 @@ private void OnPropertyChanging(string propertyName) } } + /// + /// Unique identifier for entity instances + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_hesubjectid")] + public System.Nullable dfeta_hesubjectId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_hesubjectid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_hesubjectId"); + this.SetAttributeValue("dfeta_hesubjectid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + this.OnPropertyChanged("dfeta_hesubjectId"); + } + } + + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_hesubjectid")] + public override System.Guid Id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return base.Id; + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.dfeta_hesubjectId = value; + } + } + /// /// The name of the custom entity. /// diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeQualificationsQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeQualificationsQuery.cs new file mode 100644 index 000000000..5ebad83d2 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeQualificationsQuery.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetAllHeQualificationsQuery : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeSubjectsQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeSubjectsQuery.cs new file mode 100644 index 000000000..8289a94e5 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllHeSubjectsQuery.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetAllHeSubjectsQuery : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetQualificationsByContactIdQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetQualificationsByContactIdQuery.cs new file mode 100644 index 000000000..36a7649a8 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetQualificationsByContactIdQuery.cs @@ -0,0 +1,5 @@ +using Microsoft.Xrm.Sdk.Query; + +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetQualificationsByContactIdQuery(Guid ContactId, ColumnSet ColumnSet, bool IncludeHigherEducationDetails = false) : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeQualificationsHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeQualificationsHandler.cs new file mode 100644 index 000000000..9b7002fc2 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeQualificationsHandler.cs @@ -0,0 +1,31 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Messages; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetAllHeQualificationsHandler : ICrmQueryHandler +{ + public async Task Execute(GetAllHeQualificationsQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = dfeta_hequalification.EntityLogicalName, + ColumnSet = new ColumnSet( + dfeta_hequalification.Fields.dfeta_name, + dfeta_hequalification.Fields.dfeta_Value) + }; + + queryExpression.Criteria.AddCondition(dfeta_hequalification.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_hequalificationState.Active); + + var request = new RetrieveMultipleRequest() + { + Query = queryExpression + }; + + var response = await organizationService.RetrieveMultipleAsync(queryExpression); + + return response.Entities.Select(e => e.ToEntity()).ToArray(); + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeSubjectsHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeSubjectsHandler.cs new file mode 100644 index 000000000..c9e8210be --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllHeSubjectsHandler.cs @@ -0,0 +1,31 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Messages; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetAllHeSubjectsHandler : ICrmQueryHandler +{ + public async Task Execute(GetAllHeSubjectsQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = dfeta_hesubject.EntityLogicalName, + ColumnSet = new ColumnSet( + dfeta_hesubject.Fields.dfeta_name, + dfeta_hesubject.Fields.dfeta_Value) + }; + + queryExpression.Criteria.AddCondition(dfeta_hesubject.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_hesubjectState.Active); + + var request = new RetrieveMultipleRequest() + { + Query = queryExpression + }; + + var response = await organizationService.RetrieveMultipleAsync(queryExpression); + + return response.Entities.Select(e => e.ToEntity()).ToArray(); + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetQualificationsByContactIdHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetQualificationsByContactIdHandler.cs new file mode 100644 index 000000000..f6289a6e4 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetQualificationsByContactIdHandler.cs @@ -0,0 +1,77 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetQualificationsByContactIdHandler : ICrmQueryHandler +{ + public async Task Execute(GetQualificationsByContactIdQuery query, IOrganizationServiceAsync organizationService) + { + var filter = new FilterExpression(); + filter.AddCondition(dfeta_qualification.Fields.dfeta_PersonId, ConditionOperator.Equal, query.ContactId); + filter.AddCondition(dfeta_qualification.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_qualificationState.Active); + + var qualificationTypeFilter = new FilterExpression(LogicalOperator.Or); + qualificationTypeFilter.AddCondition(dfeta_qualification.Fields.dfeta_Type, ConditionOperator.NotEqual, (int)dfeta_qualification_dfeta_Type.HigherEducation); + + var heFilter = new FilterExpression(LogicalOperator.And); + heFilter.AddCondition(dfeta_qualification.Fields.dfeta_Type, ConditionOperator.Equal, (int)dfeta_qualification_dfeta_Type.HigherEducation); + + var heSubjectFilter = new FilterExpression(LogicalOperator.Or); + heSubjectFilter.AddCondition(dfeta_qualification.Fields.dfeta_HE_HESubject1Id, ConditionOperator.NotNull); + heSubjectFilter.AddCondition(dfeta_qualification.Fields.dfeta_HE_HESubject2Id, ConditionOperator.NotNull); + heSubjectFilter.AddCondition(dfeta_qualification.Fields.dfeta_HE_HESubject3Id, ConditionOperator.NotNull); + heFilter.AddFilter(heSubjectFilter); + + qualificationTypeFilter.AddFilter(heFilter); + filter.AddFilter(qualificationTypeFilter); + + var queryExpression = new QueryExpression(dfeta_qualification.EntityLogicalName) + { + ColumnSet = query.ColumnSet, + Criteria = filter, + Orders = + { + new OrderExpression(dfeta_qualification.Fields.CreatedOn, OrderType.Ascending) + } + }; + + if (query.IncludeHigherEducationDetails) + { + var heLink = queryExpression.AddLink( + dfeta_hequalification.EntityLogicalName, + dfeta_qualification.Fields.dfeta_HE_HEQualificationId, + dfeta_hequalification.Fields.Id, + JoinOperator.LeftOuter); + + heLink.Columns = new ColumnSet( + dfeta_hequalification.PrimaryIdAttribute, + dfeta_hequalification.Fields.dfeta_name); + heLink.EntityAlias = dfeta_hequalification.EntityLogicalName; + + AddHeSubjectLink(queryExpression, dfeta_qualification.Fields.dfeta_HE_HESubject1Id, $"{dfeta_hesubject.EntityLogicalName}1"); + AddHeSubjectLink(queryExpression, dfeta_qualification.Fields.dfeta_HE_HESubject2Id, $"{dfeta_hesubject.EntityLogicalName}2"); + AddHeSubjectLink(queryExpression, dfeta_qualification.Fields.dfeta_HE_HESubject3Id, $"{dfeta_hesubject.EntityLogicalName}3"); + } + + var result = await organizationService.RetrieveMultipleAsync(queryExpression); + + return result.Entities.Select(entity => entity.ToEntity()).ToArray(); + + void AddHeSubjectLink(QueryExpression query, string subjectIdField, string alias) + { + var heSubjectLink = query.AddLink( + dfeta_hesubject.EntityLogicalName, + subjectIdField, + dfeta_hesubject.PrimaryIdAttribute, + JoinOperator.LeftOuter); + + heSubjectLink.Columns = new ColumnSet( + dfeta_hesubject.PrimaryIdAttribute, + dfeta_hesubject.Fields.dfeta_name, + dfeta_hesubject.Fields.dfeta_Value); + heSubjectLink.EntityAlias = alias; + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/ReferenceDataCache.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/ReferenceDataCache.cs index 949b9c8ef..64edbd65d 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/ReferenceDataCache.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/ReferenceDataCache.cs @@ -11,6 +11,8 @@ public class ReferenceDataCache : IStartupTask private Task? _getTeacherStatusesTask; private Task? _getEarlyYearsStatusesTask; private Task? _getSpecialismsTask; + private Task? _getHeQualificationsTask; + private Task? _getHeSubjectsTask; public ReferenceDataCache(ICrmQueryDispatcher crmQueryDispatcher) { @@ -104,6 +106,32 @@ public async Task GetMqEstablishmentById(Guid mqEstablish return mqEstablishments.Single(s => s.dfeta_mqestablishmentId == mqEstablishmentId, $"Could not find MQ establishment with ID: '{mqEstablishmentId}'."); } + public async Task GetHeQualifications() + { + var heQualifications = await EnsureHeQualifications(); + return heQualifications.ToArray(); + } + + public async Task GetHeQualificationByValue(string value) + { + var heQualifications = await EnsureHeQualifications(); + // build environment has some duplicate HE Qualifications, which prevent us using Single() here + return heQualifications.First(s => s.dfeta_Value == value, $"Could not find HE qualification with value: '{value}'."); + } + + public async Task GetHeSubjects() + { + var heSubjects = await EnsureHeSubjects(); + return heSubjects.ToArray(); + } + + public async Task GetHeSubjectByValue(string value) + { + var heSubjects = await EnsureHeSubjects(); + // build environment has some duplicate HE Subjects, which prevent us using Single() here + return heSubjects.First(s => s.dfeta_Value == value, $"Could not find HE subject with value: '{value}'."); + } + private Task EnsureSanctionCodes() => LazyInitializer.EnsureInitialized( ref _getSanctionCodesTask, @@ -134,6 +162,16 @@ private Task EnsureMqEstablishments() => ref _mqEstablishmentsTask, () => _crmQueryDispatcher.ExecuteQuery(new GetAllMqEstablishmentsQuery())); + private Task EnsureHeQualifications() => + LazyInitializer.EnsureInitialized( + ref _getHeQualificationsTask, + () => _crmQueryDispatcher.ExecuteQuery(new GetAllHeQualificationsQuery())); + + private Task EnsureHeSubjects() => + LazyInitializer.EnsureInitialized( + ref _getHeSubjectsTask, + () => _crmQueryDispatcher.ExecuteQuery(new GetAllHeSubjectsQuery())); + async Task IStartupTask.Execute() { await EnsureSanctionCodes(); @@ -142,5 +180,7 @@ async Task IStartupTask.Execute() await EnsureEarlyYearsStatuses(); await EnsureSpecialisms(); await EnsureMqEstablishments(); + await EnsureHeQualifications(); + await EnsureHeSubjects(); } } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherByTrnTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherByTrnTests.cs index 52103f3e1..c7f02315e 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherByTrnTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherByTrnTests.cs @@ -110,10 +110,17 @@ public async Task Get_ValidRequestWithInitialTeacherTraining_ReturnsExpectedInit [Fact] public async Task Get_ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent() { - var contact = await CreateContact(); + var qualifications = new[] +{ + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQLL, null, IsActive:true), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQSL, new DateOnly(2022, 5, 6), IsActive:false), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQEYL, new DateOnly(2022, 3, 4), IsActive:true) + }; + + var contact = await CreateContact(qualifications: qualifications); var baseUrl = $"/v3/teachers/{contact.dfeta_TRN}"; - await ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent(GetHttpClientWithApiKey(), baseUrl, contact, expectCertificateUrls: false); + await ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent(GetHttpClientWithApiKey(), baseUrl, contact, qualifications, expectCertificateUrls: false); } [Fact] @@ -158,10 +165,20 @@ public async Task Get_ValidRequestWithMandatoryQualifications_ReturnsExpectedMan [Fact] public async Task Get_ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent() { - var contact = await CreateContact(); + var qualifications = new[] + { + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 6), true, "001", "001", "002", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 2), true, "002", "002"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, null, true, "001", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 8), false, "001", "001", "002", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, null, true, null, "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 8), true), + }; + + var contact = await CreateContact(qualifications: qualifications); var baseUrl = $"/v3/teachers/{contact.dfeta_TRN}"; - await ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent(GetHttpClientWithApiKey(), baseUrl, contact); + await ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent(GetHttpClientWithApiKey(), baseUrl, contact, qualifications); } [Fact] diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTestBase.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTestBase.cs index 12eb38c87..0e13fcad2 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTestBase.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTestBase.cs @@ -275,21 +275,13 @@ protected async Task ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualifi HttpClient httpClient, string baseUrl, Contact contact, + Qualification[] qualifications, bool expectCertificateUrls) { // Arrange - var npqQualificationNoAwardDate = CreateQualification(dfeta_qualification_dfeta_Type.NPQLL, null, dfeta_qualificationState.Active, null); - var npqQualificationInactive = CreateQualification(dfeta_qualification_dfeta_Type.NPQSL, new DateTime(2022, 5, 6), dfeta_qualificationState.Inactive, null); - var npqQualificationValid = CreateQualification(dfeta_qualification_dfeta_Type.NPQEYL, new DateTime(2022, 3, 4), dfeta_qualificationState.Active, null); + var npqQualificationValid = qualifications[2]; - var qualifications = new dfeta_qualification[] - { - npqQualificationNoAwardDate, - npqQualificationInactive, - npqQualificationValid - }; - - await ConfigureMocks(contact, qualifications: qualifications); + await ConfigureMocks(contact); var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}?include=NpqQualifications"); @@ -301,13 +293,13 @@ protected async Task ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualifi { new { - awarded = npqQualificationValid.dfeta_CompletionorAwardDate?.ToString("yyyy-MM-dd"), + awarded = npqQualificationValid.CompletionOrAwardDate?.ToString("yyyy-MM-dd"), type = new { - code = npqQualificationValid.dfeta_Type.ToString(), - name = npqQualificationValid.dfeta_Type?.GetName() + code = npqQualificationValid.Type.ToString(), + name = npqQualificationValid.Type.GetName() }, - certificateUrl = $"/v3/certificates/npq/{npqQualificationValid.Id}", + certificateUrl = $"/v3/certificates/npq/{npqQualificationValid.QualificationId}", } })!; @@ -325,70 +317,11 @@ protected async Task ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualifi protected async Task ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent( HttpClient httpClient, string baseUrl, - Contact contact) + Contact contact, + Qualification[] qualifications) { // Arrange - var qualification1AwardDate = new DateTime(2022, 4, 6); - var qualification1Name = "My HE Qual 1"; - var qualification1Subject1 = (Code: "Qualification1Subject1", Name: "Qualification 1 Subject 1"); - var qualification1Subject2 = (Code: "Qualification1Subject2", Name: "Qualification 1 Subject 2"); - var qualification1Subject3 = (Code: "Qualification1Subject3", Name: "Qualification 1 Subject 3"); - - var qualification2AwardDate = new DateTime(2022, 4, 2); - var qualification2Name = "My HE Qual 2"; - var qualification2Subject1 = (Code: "Qualification2Subject1", Name: "Qualification 2 Subject 1"); - - var qualification3Name = "My HE Qual 3"; - var qualification3Subject1 = (Code: "Qualification3Subject1", Name: "Qualification 3 Subject 1"); - - var qualification4AwardDate = new DateTime(2022, 4, 8); - var qualification4Name = "My HE Qual 4"; - var qualification4Subject1 = (Code: "Qualification4Subject1", Name: "Qualification 4 Subject 1"); - var qualification4Subject2 = (Code: "Qualification4Subject2", Name: "Qualification 4 Subject 2"); - var qualification4Subject3 = (Code: "Qualification4Subject3", Name: "Qualification 4 Subject 3"); - - var heQualificationWith3Subjects = CreateQualification( - dfeta_qualification_dfeta_Type.HigherEducation, - qualification1AwardDate, - dfeta_qualificationState.Active, - null, - qualification1Name, - qualification1Subject1, - qualification1Subject2, - qualification1Subject3); - var heQualificationWith1Subject = CreateQualification( - dfeta_qualification_dfeta_Type.HigherEducation, - qualification2AwardDate, - dfeta_qualificationState.Active, - null, - qualification2Name, - qualification2Subject1); - var heQualificationWithNoAwardDate = CreateQualification( - dfeta_qualification_dfeta_Type.HigherEducation, - null, - dfeta_qualificationState.Active, - null, - qualification3Name, - qualification3Subject1); - var heQualificationInactive = CreateQualification( - dfeta_qualification_dfeta_Type.HigherEducation, - qualification4AwardDate, - dfeta_qualificationState.Inactive, - null, - qualification4Name, - qualification4Subject1, - qualification4Subject2, - qualification4Subject3); - - var qualifications = new dfeta_qualification[] - { - heQualificationWith3Subjects, - heQualificationWith1Subject, - heQualificationWithNoAwardDate, - heQualificationInactive - }; - - await ConfigureMocks(contact, qualifications: qualifications); + await ConfigureMocks(contact); var request = new HttpRequestMessage(HttpMethod.Get, $"{baseUrl}?include=HigherEducationQualifications"); @@ -399,36 +332,55 @@ protected async Task ValidRequestWithHigherEducationQualifications_ReturnsExpect var jsonResponse = await AssertEx.JsonResponse(response); var responseHigherEducationQualifications = jsonResponse.RootElement.GetProperty("higherEducationQualifications"); + var heQualification1 = await TestData.ReferenceDataCache.GetHeQualificationByValue(qualifications[0].HeQualificationValue!); + var heQualification1Subject1 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[0].HeSubject1Value!); + var heQualification1Subject2 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[0].HeSubject2Value!); + var heQualification1Subject3 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[0].HeSubject3Value!); + var heQualification2 = await TestData.ReferenceDataCache.GetHeQualificationByValue(qualifications[1].HeQualificationValue!); + var heQualification2Subject1 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[1].HeSubject1Value!); + var heQualification3 = await TestData.ReferenceDataCache.GetHeQualificationByValue(qualifications[2].HeQualificationValue!); + var heQualification3Subject1 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[2].HeSubject1Value!); + var heQualification5Subject1 = await TestData.ReferenceDataCache.GetHeSubjectByValue(qualifications[4].HeSubject1Value!); + AssertEx.JsonObjectEquals( new[] { new { - name = qualification1Name, - awarded = (string?)qualification1AwardDate.ToString("yyyy-MM-dd"), - subjects = new[] + name = (string?)heQualification1.dfeta_name, + awarded = (string?)qualifications[0].CompletionOrAwardDate?.ToString("yyyy-MM-dd"), + subjects = (object[])new[] { - new { code = qualification1Subject1.Code, name = qualification1Subject1.Name }, - new { code = qualification1Subject2.Code, name = qualification1Subject2.Name }, - new { code = qualification1Subject3.Code, name = qualification1Subject3.Name } + new { code = heQualification1Subject1.dfeta_Value, name = heQualification1Subject1.dfeta_name }, + new { code = heQualification1Subject2.dfeta_Value, name = heQualification1Subject2.dfeta_name }, + new { code = heQualification1Subject3.dfeta_Value, name = heQualification1Subject3.dfeta_name }, } }, new { - name = qualification2Name, - awarded = (string?)qualification2AwardDate.ToString("yyyy-MM-dd"), - subjects = new[] + name = (string?)heQualification2.dfeta_name, + awarded = (string?)qualifications[1].CompletionOrAwardDate?.ToString("yyyy-MM-dd"), + subjects = (object[])new[] { - new { code = qualification2Subject1.Code, name = qualification2Subject1.Name } + new { code = heQualification2Subject1.dfeta_Value, name = heQualification2Subject1.dfeta_name }, } }, new { - name = qualification3Name, + name = (string?)heQualification3.dfeta_name, awarded = (string?)null, - subjects = new[] + subjects = (object[])new[] { - new { code = qualification3Subject1.Code, name = qualification3Subject1.Name } + new { code = heQualification3Subject1.dfeta_Value, name = heQualification3Subject1.dfeta_name }, + } + }, + new + { + name = (string?)null, + awarded = (string?)null, + subjects = (object[])new[] + { + new { code = heQualification5Subject1.dfeta_Value, name = heQualification5Subject1.dfeta_name }, } } }, @@ -624,6 +576,7 @@ protected async Task ValidRequestWithPreviousNames_ReturnsExpectedPreviousNamesC protected async Task CreateContact( QtsRegistration[]? qtsRegistrations = null, + Qualification[]? qualifications = null, bool hasMultiWordFirstName = false) { var firstName = hasMultiWordFirstName ? $"{Faker.Name.First()} {Faker.Name.First()}" : Faker.Name.First(); @@ -637,6 +590,11 @@ protected async Task CreateContact( { b.WithQtsRegistration(item!.QtsDate, item!.TeacherStatusValue, item.CreatedOn, item!.EytsDate, item!.EytsStatusValue); } + + foreach (var item in qualifications ?? Array.Empty()) + { + b.WithQualification(item.QualificationId, item.Type, item.CompletionOrAwardDate, item.IsActive, item.HeQualificationValue, item.HeSubject1Value, item.HeSubject2Value, item.HeSubject3Value); + } }); return person.Contact; @@ -884,8 +842,11 @@ private static dfeta_qualification CreateQualification( if (type == dfeta_qualification_dfeta_Type.HigherEducation) { - qualification.Attributes.Add($"{nameof(dfeta_hequalification)}.{dfeta_hequalification.PrimaryIdAttribute}", new AliasedValue(dfeta_hequalification.EntityLogicalName, dfeta_hequalification.PrimaryIdAttribute, Guid.NewGuid())); - qualification.Attributes.Add($"{nameof(dfeta_hequalification)}.{dfeta_hequalification.Fields.dfeta_name}", new AliasedValue(dfeta_hequalification.EntityLogicalName, dfeta_hequalification.Fields.dfeta_name, heName)); + if (heName is not null) + { + qualification.Attributes.Add($"{nameof(dfeta_hequalification)}.{dfeta_hequalification.PrimaryIdAttribute}", new AliasedValue(dfeta_hequalification.EntityLogicalName, dfeta_hequalification.PrimaryIdAttribute, Guid.NewGuid())); + qualification.Attributes.Add($"{nameof(dfeta_hequalification)}.{dfeta_hequalification.Fields.dfeta_name}", new AliasedValue(dfeta_hequalification.EntityLogicalName, dfeta_hequalification.Fields.dfeta_name, heName)); + } if (heSubject1 != null) { diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTests.cs index 0e9a9b0ec..319074b4d 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/V20240101/GetTeacherTests.cs @@ -193,11 +193,18 @@ public async Task Get_ValidRequestWithInitialTeacherTraining_ReturnsExpectedInit [Fact] public async Task Get_ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent() { - var contact = await CreateContact(); + var qualifications = new[] +{ + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQLL, null, IsActive:true), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQSL, new DateOnly(2022, 5, 6), IsActive:false), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.NPQEYL, new DateOnly(2022, 3, 4), IsActive:true) + }; + + var contact = await CreateContact(qualifications: qualifications); var httpClient = GetHttpClientWithIdentityAccessToken(contact.dfeta_TRN); var baseUrl = "/v3/teacher"; - await ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent(httpClient, baseUrl, contact, expectCertificateUrls: true); + await ValidRequestWithNpqQualifications_ReturnsExpectedNpqQualificationsContent(httpClient, baseUrl, contact, qualifications, expectCertificateUrls: true); } [Fact] @@ -242,11 +249,21 @@ public async Task Get_ValidRequestWithMandatoryQualifications_ReturnsExpectedMan [Fact] public async Task Get_ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent() { - var contact = await CreateContact(); + var qualifications = new[] + { + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 6), true, "001", "001", "002", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 2), true, "002", "002"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, null, true, "001", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 8), false, "001", "001", "002", "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, null, true, null, "003"), + new Qualification(Guid.NewGuid(), dfeta_qualification_dfeta_Type.HigherEducation, new DateOnly(2022, 4, 8), true), + }; + + var contact = await CreateContact(qualifications: qualifications); var httpClient = GetHttpClientWithIdentityAccessToken(contact.dfeta_TRN); var baseUrl = "/v3/teacher"; - await ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent(httpClient, baseUrl, contact); + await ValidRequestWithHigherEducationQualifications_ReturnsExpectedHigherEducationQualificationsContent(httpClient, baseUrl, contact, qualifications); } [Fact] diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeQualificationsTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeQualificationsTests.cs new file mode 100644 index 000000000..9b7228c39 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeQualificationsTests.cs @@ -0,0 +1,24 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class GetAllHeQualificationsTests +{ + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public GetAllHeQualificationsTests(CrmClientFixture crmClientFixture) + { + _crmQueryDispatcher = crmClientFixture.CreateQueryDispatcher(); + } + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var query = new GetAllHeQualificationsQuery(); + + // Act + var result = await _crmQueryDispatcher.ExecuteQuery(query); + + // Assert + Assert.NotEmpty(result); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeSubjectsTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeSubjectsTests.cs new file mode 100644 index 000000000..8becafd1f --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllHeSubjectsTests.cs @@ -0,0 +1,24 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class GetAllHeSubjectsTests +{ + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public GetAllHeSubjectsTests(CrmClientFixture crmClientFixture) + { + _crmQueryDispatcher = crmClientFixture.CreateQueryDispatcher(); + } + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var query = new GetAllHeSubjectsQuery(); + + // Act + var result = await _crmQueryDispatcher.ExecuteQuery(query); + + // Assert + Assert.NotEmpty(result); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetQualificationsByContactIdTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetQualificationsByContactIdTests.cs new file mode 100644 index 000000000..ddb83cf9e --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetQualificationsByContactIdTests.cs @@ -0,0 +1,107 @@ +using Microsoft.Xrm.Sdk.Query; + +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class GetQualificationsByContactIdTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public GetQualificationsByContactIdTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = crmClientFixture.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task WhenCalled_ForContactWithoutQualifications_ReturnsEmptyArray() + { + // Arrange + var person = await _dataScope.TestData.CreatePerson(); + + // Act + var qualifications = await _crmQueryDispatcher.ExecuteQuery(new GetQualificationsByContactIdQuery(person.ContactId, new ColumnSet())); + + // Assert + Assert.Empty(qualifications); + } + + [Fact] + public async Task WhenCalled_ForContactWithQualifications_ReturnsQualificationsAsExpected() + { + // Arrange + var activeNpqQualificationId = Guid.NewGuid(); + var activeNpqQualificationType = dfeta_qualification_dfeta_Type.NPQLT; + var inActiveNpqQualificationId = Guid.NewGuid(); + var inActiveNpqQualificationType = dfeta_qualification_dfeta_Type.NPQH; + var activeHeQualificationId = Guid.NewGuid(); + var inActiveHeQualificationId = Guid.NewGuid(); + var activeHeQualificationWithNoSubjectsId = Guid.NewGuid(); + + var person = await _dataScope.TestData.CreatePerson( + x => x.WithQualification(activeNpqQualificationId, activeNpqQualificationType, isActive: true) + .WithQualification(inActiveNpqQualificationId, inActiveNpqQualificationType, isActive: false) + .WithQualification(activeHeQualificationId, dfeta_qualification_dfeta_Type.HigherEducation, isActive: true, heSubject1Value: "100035") + .WithQualification(inActiveHeQualificationId, dfeta_qualification_dfeta_Type.HigherEducation, isActive: false, heSubject1Value: "100037") + .WithQualification(activeHeQualificationWithNoSubjectsId, dfeta_qualification_dfeta_Type.HigherEducation, isActive: true)); + + // Act + var qualifications = await _crmQueryDispatcher.ExecuteQuery(new GetQualificationsByContactIdQuery(person.ContactId, new ColumnSet())); + + // Assert + Assert.Equal(2, qualifications.Length); + Assert.Contains(activeNpqQualificationId, qualifications.Select(q => q.Id)); + Assert.Contains(activeHeQualificationId, qualifications.Select(q => q.Id)); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task WhenCalledWithIncludeHigherEducationDetails_ForContactWithHeQualifications_ReturnsHeQualificationDetailsAsExpected(bool includeHeEducationDetails) + { + // Arrange + var activeHeQualificationId = Guid.NewGuid(); + var activeHeQualificationWithNoSubjectsId = Guid.NewGuid(); + + var person = await _dataScope.TestData.CreatePerson( + x => x.WithQualification( + activeHeQualificationId, + dfeta_qualification_dfeta_Type.HigherEducation, + isActive: true, + heQualificationValue: "215", + heSubject1Value: "100035", + heSubject2Value: "100036", + heSubject3Value: "100037")); + + // Act + var qualifications = await _crmQueryDispatcher.ExecuteQuery( + new GetQualificationsByContactIdQuery(person.ContactId, new ColumnSet(), IncludeHigherEducationDetails: includeHeEducationDetails)); + + // Assert + Assert.Single(qualifications); + Assert.Contains(activeHeQualificationId, qualifications.Select(q => q.Id)); + var heQualification = qualifications[0].Extract(); + var heSubject1 = qualifications[0].Extract($"{nameof(dfeta_hesubject)}1", dfeta_hesubject.PrimaryIdAttribute); + var heSubject2 = qualifications[0].Extract($"{nameof(dfeta_hesubject)}2", dfeta_hesubject.PrimaryIdAttribute); + var heSubject3 = qualifications[0].Extract($"{nameof(dfeta_hesubject)}3", dfeta_hesubject.PrimaryIdAttribute); + + if (includeHeEducationDetails) + { + Assert.NotNull(heQualification); + Assert.NotNull(heSubject1); + Assert.NotNull(heSubject2); + Assert.NotNull(heSubject3); + } + else + { + Assert.Null(heQualification); + Assert.Null(heSubject1); + Assert.Null(heSubject2); + Assert.Null(heSubject3); + } + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs index e9d960f87..689f04775 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs @@ -20,6 +20,8 @@ public Task Execute() AddEarlyYearsStatuses(); AddMqEstablishments(); AddSpecialisms(); + AddHeQualifications(); + AddHeSubjects(); return Task.CompletedTask; } @@ -264,4 +266,100 @@ private void AddSpecialisms() }); } } + + private void AddHeQualifications() + { + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BEd", + dfeta_Value = "001" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BEd (Hons)", + dfeta_Value = "002" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BSc/Education", + dfeta_Value = "003" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BSc Hons /Education", + dfeta_Value = "004" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BTech/Education", + dfeta_Value = "005" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BTech (Hons) /Education", + dfeta_Value = "006" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BA/Education", + dfeta_Value = "007" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hequalification() + { + dfeta_name = "BA (Hons) /Education", + dfeta_Value = "008" + }); + } + + private void AddHeSubjects() + { + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "Mathematics", + dfeta_Value = "001" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "English", + dfeta_Value = "002" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "Science", + dfeta_Value = "003" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "Art", + dfeta_Value = "004" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "Physical Education", + dfeta_Value = "005" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "Geography", + dfeta_Value = "006" + }); + + _xrmFakedContext.CreateEntity(new dfeta_hesubject() + { + dfeta_name = "History", + dfeta_Value = "007" + }); + } } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs index 5da2e0003..36addd5f9 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs @@ -32,6 +32,7 @@ public class CreatePersonBuilder private Contact_GenderCode? _gender; private bool? _hasNationalInsuranceNumber; private string? _nationalInsuranceNumber; + private readonly List _qualifications = new(); private readonly List _mandatoryQualifications = new(); private readonly List _qtsRegistrations = new(); private readonly List _sanctions = []; @@ -125,6 +126,20 @@ public CreatePersonBuilder WithSanction( return this; } + public CreatePersonBuilder WithQualification( + Guid? qualificationId, + dfeta_qualification_dfeta_Type type, + DateOnly? completionOrAwardDate = null, + bool? isActive = true, + string? heQualificationValue = null, + string? heSubject1Value = null, + string? heSubject2Value = null, + string? heSubject3Value = null) + { + _qualifications.Add(new(qualificationId ?? Guid.NewGuid(), type, completionOrAwardDate, isActive!.Value, heQualificationValue, heSubject1Value, heSubject2Value, heSubject3Value)); + return this; + } + public CreatePersonBuilder WithMandatoryQualification(Action? configure = null) { var mqBuilder = new CreatePersonMandatoryQualificationBuilder(); @@ -329,6 +344,61 @@ internal async Task Execute(TestData testData) }); } + foreach (var qualification in _qualifications) + { + var crmQualification = new dfeta_qualification() + { + Id = qualification.QualificationId, + dfeta_PersonId = PersonId.ToEntityReference(Contact.EntityLogicalName), + dfeta_Type = qualification.Type, + dfeta_CompletionorAwardDate = qualification.CompletionOrAwardDate?.ToDateTimeWithDqtBstFix(isLocalTime: true) + }; + + if (qualification.Type == dfeta_qualification_dfeta_Type.HigherEducation) + { + if (qualification.HeQualificationValue is not null) + { + var heQualification = await testData.ReferenceDataCache.GetHeQualificationByValue(qualification.HeQualificationValue!); + crmQualification.dfeta_HE_HEQualificationId = heQualification.Id.ToEntityReference(dfeta_hequalification.EntityLogicalName); + } + + if (qualification.HeSubject1Value is not null) + { + var heSubject1 = await testData.ReferenceDataCache.GetHeSubjectByValue(qualification.HeSubject1Value!); + crmQualification.dfeta_HE_HESubject1Id = heSubject1.Id.ToEntityReference(dfeta_hesubject.EntityLogicalName); + } + + if (qualification.HeSubject2Value is not null) + { + var heSubject2 = await testData.ReferenceDataCache.GetHeSubjectByValue(qualification.HeSubject2Value!); + crmQualification.dfeta_HE_HESubject2Id = heSubject2.Id.ToEntityReference(dfeta_hesubject.EntityLogicalName); + } + + if (qualification.HeSubject3Value is not null) + { + var heSubject3 = await testData.ReferenceDataCache.GetHeSubjectByValue(qualification.HeSubject3Value!); + crmQualification.dfeta_HE_HESubject3Id = heSubject3.Id.ToEntityReference(dfeta_hesubject.EntityLogicalName); + } + } + + txnRequestBuilder.AddRequest(new CreateRequest() + { + Target = crmQualification + }); + + if (!qualification.IsActive) + { + txnRequestBuilder.AddRequest(new UpdateRequest() + { + Target = new dfeta_qualification() + { + Id = qualification.QualificationId, + StateCode = dfeta_qualificationState.Inactive + } + }); + } + } + foreach (var sanction in _sanctions) { var sanctionCode = await testData.ReferenceDataCache.GetSanctionCodeByValue(sanction.SanctionCode); @@ -650,4 +720,14 @@ public record MandatoryQualificationInfo( DateOnly? EndDate); public record QtsRegistration(DateOnly? QtsDate, string? TeacherStatusValue, DateTime? CreatedOn, DateOnly? EytsDate, string? EytsStatusValue); + + public record Qualification( + Guid QualificationId, + dfeta_qualification_dfeta_Type Type, + DateOnly? CompletionOrAwardDate = null, + bool IsActive = true, + string? HeQualificationValue = null, + string? HeSubject1Value = null, + string? HeSubject2Value = null, + string? HeSubject3Value = null); } diff --git a/crm_attributes.json b/crm_attributes.json index 4234f47f6..1e2100cf9 100644 --- a/crm_attributes.json +++ b/crm_attributes.json @@ -109,6 +109,7 @@ "statecode" ], "dfeta_hesubject": [ + "dfeta_hesubjectid", "dfeta_name", "dfeta_value", "statecode" diff --git a/tools/coretools/CrmSvcUtil.exe.config b/tools/coretools/CrmSvcUtil.exe.config index 9276a9e53..d2c5058d1 100644 --- a/tools/coretools/CrmSvcUtil.exe.config +++ b/tools/coretools/CrmSvcUtil.exe.config @@ -20,7 +20,7 @@ - +