From d4dc227e843d5fa8ec982320e5a3ceefe74e0b07 Mon Sep 17 00:00:00 2001 From: Kevin Joy Date: Thu, 10 Oct 2024 10:35:20 +0100 Subject: [PATCH] Added GTCWales job for QTS & Inductions --- .../Dqt/Models/GeneratedCode.cs | 2065 ++++++++++++++++- .../Dqt/Models/GeneratedOptionSets.cs | 128 + ...CreateHeQualificationTransactionalQuery.cs | 17 + ...CreateInductionPeriodTransactionalQuery.cs | 10 + .../CreateInductionTransactionalQuery.cs | 10 + ...nitialTeacherTrainingTransactionalQuery.cs | 10 + .../CreateIntegrationTransactionQuery.cs | 8 + ...tionTransactionRecordTransactionalQuery.cs | 17 + ...CreateQtsRegistrationTransactionalQuery.cs | 9 + ...FindActiveOrganisationsByOrgNumberQuery.cs | 3 + ...InitialTeacherTrainingsByContactIdQuery.cs | 4 + .../GetAllActiveIttQualificationsQuery.cs | 3 + .../Queries/GetAllActiveIttSubjectsQuery.cs | 3 + .../Dqt/Queries/GetAllCountriesQuery.cs | 3 + ...UpdateInductionPeriodTransactionalQuery.cs | 9 + .../UpdateInductionTransactionalQuery.cs | 8 + ...tionTransactionRecordTransactionalQuery.cs | 17 + ...ntegrationTransactionTransactionalQuery.cs | 12 + ...eateHeQualificationTransactionalHandler.cs | 28 + ...eateInductionPeriodTransactionalHandler.cs | 24 + .../CreateInductionTransactionalHandler.cs | 23 + ...tialTeacherTrainingTransactionalHandler.cs | 23 + ...onTransactionRecordTransactionalHandler.cs | 31 + ...egrationTransactionTransactionalHandler.cs | 19 + ...eateQtsRegistrationTransactionalHandler.cs | 23 + ...tiveOrganisationsByAccountNumberHandler.cs | 32 + .../GetAllActiveIttQualificationsHandler.cs | 31 + .../GetAllActiveIttSubjectsHandler.cs | 30 + .../QueryHandlers/GetAllCountriesHandler.cs | 21 + .../GetInductionByContactIdHandler.cs | 3 +- ...itialTeacherTrainingsByContactIdHandler.cs | 29 + ...dateInductionPeriodTransactionalHandler.cs | 23 + .../UpdateInductionTransactionalHandler.cs | 22 + ...onTransactionRecordTransactionalHandler.cs | 31 + ...egrationTransactionTransactionalHandler.cs | 26 + .../Jobs/EWCWalesImport/EWCWalesImportJob.cs | 142 ++ .../EWCWalesImport/EwcWalesImportFileType.cs | 7 + .../EwcWalesInductionImportData.cs | 38 + .../EWCWalesImport/EwcWalesMatchStatus.cs | 13 + .../EwcWalesQTSFileImportData.cs | 98 + .../EWCWalesImport/InductionImportResult.cs | 4 + .../Jobs/EWCWalesImport/InductionImporter.cs | 481 ++++ .../Jobs/EWCWalesImport/QtsImportResult.cs | 3 + .../Jobs/EWCWalesImport/QtsImporter.cs | 672 ++++++ .../EwcWalesImport/EwcWalesImportFileType.cs | 7 + .../EwcWalesInductionImportData.cs | 38 + .../EwcWalesQTSFileImportData.cs | 98 + .../Jobs/EwcWalesImport/InductionImporter.cs | 481 ++++ .../Jobs/EwcWalesImport/QtsImporter.cs | 672 ++++++ .../Jobs/HostApplicationBuilderExtensions.cs | 11 + .../ReferenceDataCache.cs | 39 + .../QueryTests/CreateInductionPeriodTests.cs | 74 + .../QueryTests/CreateInductionTests.cs | 53 + .../CreateInitialTeacherTrainingTests.cs | 54 + ...CreateIntegrationTransactionRecordTests.cs | 91 + .../CreateIntegrationTransactionTests.cs | 44 + .../QueryTests/CreateQTSTests.cs | 53 + .../FindOrganisationsByOrgNumberTests.cs | 80 + .../GetAllActiveIttQualificationsTests.cs | 24 + .../GetAllActiveIttSubjectsTests.cs | 24 + .../QueryTests/UpdateInductionPeriodTests.cs | 86 + .../QueryTests/UpdateInductionTests.cs | 59 + ...UpdateIntegrationTransactionRecordTests.cs | 109 + .../UpdateIntegrationTransactionTests.cs | 66 + .../Jobs/EwcWalesImportJobTests.cs | 689 ++++++ .../Jobs/InductionImporterTests.cs | 378 +++ .../Jobs/QTSImporterTests.cs | 923 ++++++++ .../SeedCrmReferenceData.cs | 73 + .../TestData.CreateAccount.cs | 15 +- .../TestData.CreatePerson.cs | 7 +- crm_attributes.json | 44 +- tools/coretools/CrmSvcUtil.exe.config | 4 +- 72 files changed, 8409 insertions(+), 100 deletions(-) create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateHeQualificationTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionPeriodTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInitialTeacherTrainingTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionRecordTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateQtsRegistrationTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/FindActiveOrganisationsByOrgNumberQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetActiveInitialTeacherTrainingsByContactIdQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttQualificationsQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttSubjectsQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllCountriesQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionPeriodTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionRecordTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionTransactionalQuery.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateHeQualificationTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionPeriodTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInitialTeacherTrainingTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionRecordTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateQtsRegistrationTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/FindActiveOrganisationsByAccountNumberHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttQualificationsHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttSubjectsHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllCountriesHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInitialTeacherTrainingsByContactIdHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionPeriodTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionRecordTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionTransactionalHandler.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EWCWalesImportJob.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesImportFileType.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesInductionImportData.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesMatchStatus.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesQTSFileImportData.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImportResult.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImporter.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImportResult.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImporter.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesImportFileType.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesInductionImportData.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesQTSFileImportData.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/InductionImporter.cs create mode 100644 TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/QtsImporter.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionPeriodTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInitialTeacherTrainingTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionRecordTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateQTSTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/FindOrganisationsByOrgNumberTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttQualificationsTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttSubjectsTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionPeriodTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionRecordTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/EwcWalesImportJobTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/InductionImporterTests.cs create mode 100644 TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/QTSImporterTests.cs diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs index 49bca8536..bc221417e 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedCode.cs @@ -44,6 +44,7 @@ public static class Fields { public const string AccountId = "accountid"; public const string Id = "accountid"; + public const string AccountNumber = "accountnumber"; public const string dfeta_TrainingProvider = "dfeta_trainingprovider"; public const string dfeta_UKPRN = "dfeta_ukprn"; public const string Name = "name"; @@ -57,6 +58,8 @@ public static class Fields public const string dfeta_account_dfeta_document = "dfeta_account_dfeta_document"; public const string dfeta_account_dfeta_inductionperiod = "dfeta_account_dfeta_inductionperiod"; public const string dfeta_account_dfeta_initialteachertraining = "dfeta_account_dfeta_initialteachertraining"; + public const string dfeta_account_dfeta_integrationtransaction = "dfeta_account_dfeta_integrationtransaction"; + public const string dfeta_account_dfeta_integrationtransactionrecor = "dfeta_account_dfeta_integrationtransactionrecor"; public const string dfeta_account_dfeta_qualification_he = "dfeta_account_dfeta_qualification_he"; public const string incident_customer_accounts = "incident_customer_accounts"; public const string Referencedmsa_account_managingpartner = "Referencedmsa_account_managingpartner"; @@ -160,6 +163,26 @@ public override System.Guid Id } } + /// + /// User-provided account number used in correspondence about the account. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("accountnumber")] + public string AccountNumber + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("accountnumber"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("AccountNumber"); + this.SetAttributeValue("accountnumber", value); + this.OnPropertyChanged("AccountNumber"); + } + } + /// /// /// @@ -435,6 +458,46 @@ public System.Collections.Generic.IEnumerable + /// 1:N dfeta_account_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_account_dfeta_integrationtransaction")] + public System.Collections.Generic.IEnumerable dfeta_account_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_account_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_account_dfeta_integrationtransaction"); + this.SetRelatedEntities("dfeta_account_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("dfeta_account_dfeta_integrationtransaction"); + } + } + + /// + /// 1:N dfeta_account_dfeta_integrationtransactionrecor + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_account_dfeta_integrationtransactionrecor")] + public System.Collections.Generic.IEnumerable dfeta_account_dfeta_integrationtransactionrecor + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_account_dfeta_integrationtransactionrecor", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_account_dfeta_integrationtransactionrecor"); + this.SetRelatedEntities("dfeta_account_dfeta_integrationtransactionrecor", null, value); + this.OnPropertyChanged("dfeta_account_dfeta_integrationtransactionrecor"); + } + } + /// /// 1:N dfeta_account_dfeta_qualification_he /// @@ -1663,6 +1726,8 @@ public static class Fields public const string business_unit_dfeta_induction = "business_unit_dfeta_induction"; public const string business_unit_dfeta_inductionperiod = "business_unit_dfeta_inductionperiod"; public const string business_unit_dfeta_initialteachertraining = "business_unit_dfeta_initialteachertraining"; + public const string business_unit_dfeta_integrationtransaction = "business_unit_dfeta_integrationtransaction"; + public const string business_unit_dfeta_integrationtransactionrecord = "business_unit_dfeta_integrationtransactionrecord"; public const string business_unit_dfeta_previousname = "business_unit_dfeta_previousname"; public const string business_unit_dfeta_qtsregistration = "business_unit_dfeta_qtsregistration"; public const string business_unit_dfeta_qualification = "business_unit_dfeta_qualification"; @@ -1928,6 +1993,46 @@ public System.Collections.Generic.IEnumerable + /// 1:N business_unit_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("business_unit_dfeta_integrationtransaction")] + public System.Collections.Generic.IEnumerable business_unit_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("business_unit_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("business_unit_dfeta_integrationtransaction"); + this.SetRelatedEntities("business_unit_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("business_unit_dfeta_integrationtransaction"); + } + } + + /// + /// 1:N business_unit_dfeta_integrationtransactionrecord + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("business_unit_dfeta_integrationtransactionrecord")] + public System.Collections.Generic.IEnumerable business_unit_dfeta_integrationtransactionrecord + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("business_unit_dfeta_integrationtransactionrecord", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("business_unit_dfeta_integrationtransactionrecord"); + this.SetRelatedEntities("business_unit_dfeta_integrationtransactionrecord", null, value); + this.OnPropertyChanged("business_unit_dfeta_integrationtransactionrecord"); + } + } + /// /// 1:N business_unit_dfeta_previousname /// @@ -2361,6 +2466,8 @@ public static class Fields public const string dfeta_contact_dfeta_inductionperiod = "dfeta_contact_dfeta_inductionperiod"; public const string dfeta_contact_dfeta_initialteachertraining = "dfeta_contact_dfeta_initialteachertraining"; public const string dfeta_contact_dfeta_initialteachertraining1 = "dfeta_contact_dfeta_initialteachertraining1"; + public const string dfeta_contact_dfeta_integrationtransaction = "dfeta_contact_dfeta_integrationtransaction"; + public const string dfeta_contact_dfeta_integrationtransactionrecor = "dfeta_contact_dfeta_integrationtransactionrecor"; public const string dfeta_contact_dfeta_previousname = "dfeta_contact_dfeta_previousname"; public const string dfeta_contact_dfeta_qtsregistration = "dfeta_contact_dfeta_qtsregistration"; public const string dfeta_contact_dfeta_qtsregistration1 = "dfeta_contact_dfeta_qtsregistration1"; @@ -3707,6 +3814,46 @@ public System.Collections.Generic.IEnumerable + /// 1:N dfeta_contact_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_integrationtransaction")] + public System.Collections.Generic.IEnumerable dfeta_contact_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_contact_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_contact_dfeta_integrationtransaction"); + this.SetRelatedEntities("dfeta_contact_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_integrationtransaction"); + } + } + + /// + /// 1:N dfeta_contact_dfeta_integrationtransactionrecor + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_integrationtransactionrecor")] + public System.Collections.Generic.IEnumerable dfeta_contact_dfeta_integrationtransactionrecor + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_contact_dfeta_integrationtransactionrecor", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_contact_dfeta_integrationtransactionrecor"); + this.SetRelatedEntities("dfeta_contact_dfeta_integrationtransactionrecor", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_integrationtransactionrecor"); + } + } + /// /// 1:N dfeta_contact_dfeta_previousname /// @@ -6242,6 +6389,7 @@ public static class Fields public const string StateCode = "statecode"; public const string StatusCode = "statuscode"; public const string dfeta_dfeta_induction_dfeta_inductionperiod = "dfeta_dfeta_induction_dfeta_inductionperiod"; + public const string dfeta_dfeta_induction_dfeta_integrationtransact = "dfeta_dfeta_induction_dfeta_integrationtransact"; public const string dfeta_dfeta_induction_dfeta_qtsregistration = "dfeta_dfeta_induction_dfeta_qtsregistration"; public const string business_unit_dfeta_induction = "business_unit_dfeta_induction"; public const string dfeta_contact_dfeta_induction = "dfeta_contact_dfeta_induction"; @@ -6574,6 +6722,26 @@ public System.Collections.Generic.IEnumerable + /// 1:N dfeta_dfeta_induction_dfeta_integrationtransact + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_induction_dfeta_integrationtransact")] + public System.Collections.Generic.IEnumerable dfeta_dfeta_induction_dfeta_integrationtransact + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_dfeta_induction_dfeta_integrationtransact", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_induction_dfeta_integrationtransact"); + this.SetRelatedEntities("dfeta_dfeta_induction_dfeta_integrationtransact", null, value); + this.OnPropertyChanged("dfeta_dfeta_induction_dfeta_integrationtransact"); + } + } + /// /// 1:N dfeta_dfeta_induction_dfeta_qtsregistration /// @@ -6790,9 +6958,12 @@ public static class Fields public const string dfeta_AppropriateBodyId = "dfeta_appropriatebodyid"; public const string dfeta_EndDate = "dfeta_enddate"; public const string dfeta_InductionId = "dfeta_inductionid"; + public const string dfeta_inductionperiodId = "dfeta_inductionperiodid"; + public const string Id = "dfeta_inductionperiodid"; public const string dfeta_Numberofterms = "dfeta_numberofterms"; public const string dfeta_StartDate = "dfeta_startdate"; public const string StateCode = "statecode"; + public const string dfeta_dfeta_inductionperiod_dfeta_integrationtr = "dfeta_dfeta_inductionperiod_dfeta_integrationtr"; public const string business_unit_dfeta_inductionperiod = "business_unit_dfeta_inductionperiod"; public const string dfeta_account_dfeta_inductionperiod = "dfeta_account_dfeta_inductionperiod"; public const string dfeta_contact_dfeta_inductionperiod = "dfeta_contact_dfeta_inductionperiod"; @@ -6907,6 +7078,49 @@ public Microsoft.Xrm.Sdk.EntityReference dfeta_InductionId } } + /// + /// Unique identifier for entity instances + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionperiodid")] + public System.Nullable dfeta_inductionperiodId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_inductionperiodid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_inductionperiodId"); + this.SetAttributeValue("dfeta_inductionperiodid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + this.OnPropertyChanged("dfeta_inductionperiodId"); + } + } + + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionperiodid")] + public override System.Guid Id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return base.Id; + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.dfeta_inductionperiodId = value; + } + } + /// /// /// @@ -6982,6 +7196,26 @@ public System.Nullable + /// 1:N dfeta_dfeta_inductionperiod_dfeta_integrationtr + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_inductionperiod_dfeta_integrationtr")] + public System.Collections.Generic.IEnumerable dfeta_dfeta_inductionperiod_dfeta_integrationtr + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_dfeta_inductionperiod_dfeta_integrationtr", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_inductionperiod_dfeta_integrationtr"); + this.SetRelatedEntities("dfeta_dfeta_inductionperiod_dfeta_integrationtr", null, value); + this.OnPropertyChanged("dfeta_dfeta_inductionperiod_dfeta_integrationtr"); + } + } + /// /// N:1 business_unit_dfeta_inductionperiod /// @@ -7214,6 +7448,7 @@ public static class Fields public const string dfeta_Subject3Id = "dfeta_subject3id"; public const string dfeta_TraineeID = "dfeta_traineeid"; public const string StateCode = "statecode"; + public const string dfeta_dfeta_initialteachertraining_dfeta_integr = "dfeta_dfeta_initialteachertraining_dfeta_integr"; public const string business_unit_dfeta_initialteachertraining = "business_unit_dfeta_initialteachertraining"; public const string dfeta_account_dfeta_initialteachertraining = "dfeta_account_dfeta_initialteachertraining"; public const string dfeta_contact_dfeta_initialteachertraining = "dfeta_contact_dfeta_initialteachertraining"; @@ -7648,6 +7883,26 @@ public System.Nullable + /// 1:N dfeta_dfeta_initialteachertraining_dfeta_integr + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_initialteachertraining_dfeta_integr")] + public System.Collections.Generic.IEnumerable dfeta_dfeta_initialteachertraining_dfeta_integr + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_dfeta_initialteachertraining_dfeta_integr", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_initialteachertraining_dfeta_integr"); + this.SetRelatedEntities("dfeta_dfeta_initialteachertraining_dfeta_integr", null, value); + this.OnPropertyChanged("dfeta_dfeta_initialteachertraining_dfeta_integr"); + } + } + /// /// N:1 business_unit_dfeta_initialteachertraining /// @@ -7691,254 +7946,1627 @@ public TeachingRecordSystem.Core.Dqt.Models.Account dfeta_account_dfeta_initialt } /// - /// N:1 dfeta_contact_dfeta_initialteachertraining + /// N:1 dfeta_contact_dfeta_initialteachertraining + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_personid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_initialteachertraining")] + public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_initialteachertraining + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_contact_dfeta_initialteachertraining", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_contact_dfeta_initialteachertraining"); + this.SetRelatedEntity("dfeta_contact_dfeta_initialteachertraining", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_initialteachertraining"); + } + } + + /// + /// N:1 dfeta_contact_dfeta_initialteachertraining1 + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_requestedbyid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_initialteachertraining1")] + public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_initialteachertraining1 + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_contact_dfeta_initialteachertraining1", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_contact_dfeta_initialteachertraining1"); + this.SetRelatedEntity("dfeta_contact_dfeta_initialteachertraining1", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_initialteachertraining1"); + } + } + + /// + /// N:1 dfeta_dfeta_country_dfeta_initialteachertrainin + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_countryid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_country_dfeta_initialteachertrainin")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_country dfeta_dfeta_country_dfeta_initialteachertrainin + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_dfeta_country_dfeta_initialteachertrainin", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_country_dfeta_initialteachertrainin"); + this.SetRelatedEntity("dfeta_dfeta_country_dfeta_initialteachertrainin", null, value); + this.OnPropertyChanged("dfeta_dfeta_country_dfeta_initialteachertrainin"); + } + } + + /// + /// N:1 dfeta_dfeta_ittqualification_dfeta_initialteach + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_ittqualificationid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittqualification_dfeta_initialteach")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittqualification dfeta_dfeta_ittqualification_dfeta_initialteach + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_dfeta_ittqualification_dfeta_initialteach", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_ittqualification_dfeta_initialteach"); + this.SetRelatedEntity("dfeta_dfeta_ittqualification_dfeta_initialteach", null, value); + this.OnPropertyChanged("dfeta_dfeta_ittqualification_dfeta_initialteach"); + } + } + + /// + /// N:1 dfeta_dfeta_ittsubject1_dfeta_initialteachertra + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject1id")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject1_dfeta_initialteachertra")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject1_dfeta_initialteachertra + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_dfeta_ittsubject1_dfeta_initialteachertra", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_ittsubject1_dfeta_initialteachertra"); + this.SetRelatedEntity("dfeta_dfeta_ittsubject1_dfeta_initialteachertra", null, value); + this.OnPropertyChanged("dfeta_dfeta_ittsubject1_dfeta_initialteachertra"); + } + } + + /// + /// N:1 dfeta_dfeta_ittsubject2_dfeta_initialteachertra + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject2id")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject2_dfeta_initialteachertra")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject2_dfeta_initialteachertra + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_dfeta_ittsubject2_dfeta_initialteachertra", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_ittsubject2_dfeta_initialteachertra"); + this.SetRelatedEntity("dfeta_dfeta_ittsubject2_dfeta_initialteachertra", null, value); + this.OnPropertyChanged("dfeta_dfeta_ittsubject2_dfeta_initialteachertra"); + } + } + + /// + /// N:1 dfeta_dfeta_ittsubject3_dfeta_initialteachertra + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject3id")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject3_dfeta_initialteachertra")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject3_dfeta_initialteachertra + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_dfeta_ittsubject3_dfeta_initialteachertra", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_ittsubject3_dfeta_initialteachertra"); + this.SetRelatedEntity("dfeta_dfeta_ittsubject3_dfeta_initialteachertra", null, value); + this.OnPropertyChanged("dfeta_dfeta_ittsubject3_dfeta_initialteachertra"); + } + } + + /// + /// N:1 lk_dfeta_initialteachertraining_createdby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_createdby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_createdby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_initialteachertraining_createdby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_initialteachertraining_createdby"); + this.SetRelatedEntity("lk_dfeta_initialteachertraining_createdby", null, value); + this.OnPropertyChanged("lk_dfeta_initialteachertraining_createdby"); + } + } + + /// + /// N:1 lk_dfeta_initialteachertraining_createdonbehalfby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdonbehalfby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_createdonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_createdonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_initialteachertraining_createdonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_initialteachertraining_createdonbehalfby"); + this.SetRelatedEntity("lk_dfeta_initialteachertraining_createdonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_initialteachertraining_createdonbehalfby"); + } + } + + /// + /// N:1 lk_dfeta_initialteachertraining_modifiedby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_modifiedby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_modifiedby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_initialteachertraining_modifiedby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_initialteachertraining_modifiedby"); + this.SetRelatedEntity("lk_dfeta_initialteachertraining_modifiedby", null, value); + this.OnPropertyChanged("lk_dfeta_initialteachertraining_modifiedby"); + } + } + + /// + /// N:1 lk_dfeta_initialteachertraining_modifiedonbehalfby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedonbehalfby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_modifiedonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_modifiedonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_initialteachertraining_modifiedonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_initialteachertraining_modifiedonbehalfby"); + this.SetRelatedEntity("lk_dfeta_initialteachertraining_modifiedonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_initialteachertraining_modifiedonbehalfby"); + } + } + + /// + /// N:1 user_dfeta_initialteachertraining + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("owninguser")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_initialteachertraining")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser user_dfeta_initialteachertraining + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("user_dfeta_initialteachertraining", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("user_dfeta_initialteachertraining"); + this.SetRelatedEntity("user_dfeta_initialteachertraining", null, value); + this.OnPropertyChanged("user_dfeta_initialteachertraining"); + } + } + } + + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_integrationtransactionState + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + Active = 0, + + [System.Runtime.Serialization.EnumMemberAttribute()] + Inactive = 1, + } + + /// + /// + /// + [System.Runtime.Serialization.DataContractAttribute()] + [Microsoft.Xrm.Sdk.Client.EntityLogicalNameAttribute("dfeta_integrationtransaction")] + public partial class dfeta_integrationtransaction : Microsoft.Xrm.Sdk.Entity, System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged + { + + /// + /// Available fields, a the time of codegen, for the dfeta_integrationtransaction entity + /// + public static class Fields + { + public const string CreatedBy = "createdby"; + public const string CreatedOn = "createdon"; + public const string dfeta_DuplicateCount = "dfeta_duplicatecount"; + public const string dfeta_EndDate = "dfeta_enddate"; + public const string dfeta_FailureCount = "dfeta_failurecount"; + public const string dfeta_FailureMessage = "dfeta_failuremessage"; + public const string dfeta_Filename = "dfeta_filename"; + public const string dfeta_id = "dfeta_id"; + public const string dfeta_ImportOrganisation = "dfeta_importorganisation"; + public const string dfeta_integrationtransactionId = "dfeta_integrationtransactionid"; + public const string Id = "dfeta_integrationtransactionid"; + public const string dfeta_Interface = "dfeta_interface"; + public const string dfeta_StartDate = "dfeta_startdate"; + public const string dfeta_SuccessCount = "dfeta_successcount"; + public const string dfeta_TotalCount = "dfeta_totalcount"; + public const string StateCode = "statecode"; + public const string dfeta_dfeta_integrationtransaction_dfeta_integr = "dfeta_dfeta_integrationtransaction_dfeta_integr"; + public const string business_unit_dfeta_integrationtransaction = "business_unit_dfeta_integrationtransaction"; + public const string dfeta_account_dfeta_integrationtransaction = "dfeta_account_dfeta_integrationtransaction"; + public const string dfeta_contact_dfeta_integrationtransaction = "dfeta_contact_dfeta_integrationtransaction"; + public const string lk_dfeta_integrationtransaction_createdby = "lk_dfeta_integrationtransaction_createdby"; + public const string lk_dfeta_integrationtransaction_createdonbehalfby = "lk_dfeta_integrationtransaction_createdonbehalfby"; + public const string lk_dfeta_integrationtransaction_modifiedby = "lk_dfeta_integrationtransaction_modifiedby"; + public const string lk_dfeta_integrationtransaction_modifiedonbehalfby = "lk_dfeta_integrationtransaction_modifiedonbehalfby"; + public const string user_dfeta_integrationtransaction = "user_dfeta_integrationtransaction"; + } + + /// + /// Default Constructor. + /// + [System.Diagnostics.DebuggerNonUserCode()] + public dfeta_integrationtransaction() : + base(EntityLogicalName) + { + } + + public const string EntitySchemaName = "dfeta_integrationtransaction"; + + public const string PrimaryIdAttribute = "dfeta_integrationtransactionid"; + + public const string PrimaryNameAttribute = "dfeta_id"; + + public const string EntityLogicalName = "dfeta_integrationtransaction"; + + public const string EntityLogicalCollectionName = "dfeta_integrationtransactions"; + + public const string EntitySetName = "dfeta_integrationtransactions"; + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + + [System.Diagnostics.DebuggerNonUserCode()] + private void OnPropertyChanged(string propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.Diagnostics.DebuggerNonUserCode()] + private void OnPropertyChanging(string propertyName) + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// Unique identifier of the user who created the record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdby")] + public Microsoft.Xrm.Sdk.EntityReference CreatedBy + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("createdby"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("CreatedBy"); + this.SetAttributeValue("createdby", value); + this.OnPropertyChanged("CreatedBy"); + } + } + + /// + /// Date and time when the record was created. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdon")] + public System.Nullable CreatedOn + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("createdon"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("CreatedOn"); + this.SetAttributeValue("createdon", value); + this.OnPropertyChanged("CreatedOn"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_duplicatecount")] + public System.Nullable dfeta_DuplicateCount + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_duplicatecount"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_DuplicateCount"); + this.SetAttributeValue("dfeta_duplicatecount", value); + this.OnPropertyChanged("dfeta_DuplicateCount"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_enddate")] + public System.Nullable dfeta_EndDate + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_enddate"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_EndDate"); + this.SetAttributeValue("dfeta_enddate", value); + this.OnPropertyChanged("dfeta_EndDate"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_failurecount")] + public System.Nullable dfeta_FailureCount + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_failurecount"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_FailureCount"); + this.SetAttributeValue("dfeta_failurecount", value); + this.OnPropertyChanged("dfeta_FailureCount"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_failuremessage")] + public string dfeta_FailureMessage + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_failuremessage"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_FailureMessage"); + this.SetAttributeValue("dfeta_failuremessage", value); + this.OnPropertyChanged("dfeta_FailureMessage"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_filename")] + public string dfeta_Filename + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_filename"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_Filename"); + this.SetAttributeValue("dfeta_filename", value); + this.OnPropertyChanged("dfeta_Filename"); + } + } + + /// + /// The name of the custom entity. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_id")] + public string dfeta_id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_id"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_id"); + this.SetAttributeValue("dfeta_id", value); + this.OnPropertyChanged("dfeta_id"); + } + } + + /// + /// Unique identifier for Organisation associated with Integration Transaction. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_importorganisation")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_ImportOrganisation + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_importorganisation"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_ImportOrganisation"); + this.SetAttributeValue("dfeta_importorganisation", value); + this.OnPropertyChanged("dfeta_ImportOrganisation"); + } + } + + /// + /// Unique identifier for entity instances + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionid")] + public System.Nullable dfeta_integrationtransactionId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_integrationtransactionid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_integrationtransactionId"); + this.SetAttributeValue("dfeta_integrationtransactionid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + this.OnPropertyChanged("dfeta_integrationtransactionId"); + } + } + + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionid")] + public override System.Guid Id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return base.Id; + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.dfeta_integrationtransactionId = value; + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_interface")] + public virtual dfeta_IntegrationInterface? dfeta_Interface + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return ((dfeta_IntegrationInterface?)(EntityOptionSetEnum.GetEnum(this, "dfeta_interface"))); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_Interface"); + this.SetAttributeValue("dfeta_interface", value.HasValue ? new Microsoft.Xrm.Sdk.OptionSetValue((int)value) : null); + this.OnPropertyChanged("dfeta_Interface"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_startdate")] + public System.Nullable dfeta_StartDate + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_startdate"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_StartDate"); + this.SetAttributeValue("dfeta_startdate", value); + this.OnPropertyChanged("dfeta_StartDate"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_successcount")] + public System.Nullable dfeta_SuccessCount + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_successcount"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_SuccessCount"); + this.SetAttributeValue("dfeta_successcount", value); + this.OnPropertyChanged("dfeta_SuccessCount"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_totalcount")] + public System.Nullable dfeta_TotalCount + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_totalcount"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_TotalCount"); + this.SetAttributeValue("dfeta_totalcount", value); + this.OnPropertyChanged("dfeta_TotalCount"); + } + } + + /// + /// Status of the Integration Transaction + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("statecode")] + public System.Nullable StateCode + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + Microsoft.Xrm.Sdk.OptionSetValue optionSet = this.GetAttributeValue("statecode"); + if ((optionSet != null)) + { + return ((TeachingRecordSystem.Core.Dqt.Models.dfeta_integrationtransactionState)(System.Enum.ToObject(typeof(TeachingRecordSystem.Core.Dqt.Models.dfeta_integrationtransactionState), optionSet.Value))); + } + else + { + return null; + } + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("StateCode"); + if ((value == null)) + { + this.SetAttributeValue("statecode", null); + } + else + { + this.SetAttributeValue("statecode", new Microsoft.Xrm.Sdk.OptionSetValue(((int)(value)))); + } + this.OnPropertyChanged("StateCode"); + } + } + + /// + /// 1:N dfeta_dfeta_integrationtransaction_dfeta_integr + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_integrationtransaction_dfeta_integr")] + public System.Collections.Generic.IEnumerable dfeta_dfeta_integrationtransaction_dfeta_integr + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_dfeta_integrationtransaction_dfeta_integr", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_integrationtransaction_dfeta_integr"); + this.SetRelatedEntities("dfeta_dfeta_integrationtransaction_dfeta_integr", null, value); + this.OnPropertyChanged("dfeta_dfeta_integrationtransaction_dfeta_integr"); + } + } + + /// + /// N:1 business_unit_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("owningbusinessunit")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("business_unit_dfeta_integrationtransaction")] + public TeachingRecordSystem.Core.Dqt.Models.BusinessUnit business_unit_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("business_unit_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("business_unit_dfeta_integrationtransaction"); + this.SetRelatedEntity("business_unit_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("business_unit_dfeta_integrationtransaction"); + } + } + + /// + /// N:1 dfeta_account_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_importorganisation")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_account_dfeta_integrationtransaction")] + public TeachingRecordSystem.Core.Dqt.Models.Account dfeta_account_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_account_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_account_dfeta_integrationtransaction"); + this.SetRelatedEntity("dfeta_account_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("dfeta_account_dfeta_integrationtransaction"); + } + } + + /// + /// N:1 dfeta_contact_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_importuser")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_integrationtransaction")] + public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("dfeta_contact_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_contact_dfeta_integrationtransaction"); + this.SetRelatedEntity("dfeta_contact_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_integrationtransaction"); + } + } + + /// + /// N:1 lk_dfeta_integrationtransaction_createdby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_createdby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransaction_createdby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_integrationtransaction_createdby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_createdby"); + this.SetRelatedEntity("lk_dfeta_integrationtransaction_createdby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_createdby"); + } + } + + /// + /// N:1 lk_dfeta_integrationtransaction_createdonbehalfby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdonbehalfby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_createdonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransaction_createdonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_integrationtransaction_createdonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_createdonbehalfby"); + this.SetRelatedEntity("lk_dfeta_integrationtransaction_createdonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_createdonbehalfby"); + } + } + + /// + /// N:1 lk_dfeta_integrationtransaction_modifiedby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_modifiedby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransaction_modifiedby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_integrationtransaction_modifiedby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_modifiedby"); + this.SetRelatedEntity("lk_dfeta_integrationtransaction_modifiedby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_modifiedby"); + } + } + + /// + /// N:1 lk_dfeta_integrationtransaction_modifiedonbehalfby + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedonbehalfby")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_modifiedonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransaction_modifiedonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("lk_dfeta_integrationtransaction_modifiedonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_modifiedonbehalfby"); + this.SetRelatedEntity("lk_dfeta_integrationtransaction_modifiedonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_modifiedonbehalfby"); + } + } + + /// + /// N:1 user_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("owninguser")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_integrationtransaction")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser user_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("user_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("user_dfeta_integrationtransaction"); + this.SetRelatedEntity("user_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("user_dfeta_integrationtransaction"); + } + } + } + + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_integrationtransactionrecordState + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + Active = 0, + + [System.Runtime.Serialization.EnumMemberAttribute()] + Inactive = 1, + } + + /// + /// + /// + [System.Runtime.Serialization.DataContractAttribute()] + [Microsoft.Xrm.Sdk.Client.EntityLogicalNameAttribute("dfeta_integrationtransactionrecord")] + public partial class dfeta_integrationtransactionrecord : Microsoft.Xrm.Sdk.Entity, System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged + { + + /// + /// Available fields, a the time of codegen, for the dfeta_integrationtransactionrecord entity + /// + public static class Fields + { + public const string dfeta_DuplicateStatus = "dfeta_duplicatestatus"; + public const string dfeta_FailureMessage = "dfeta_failuremessage"; + public const string dfeta_Filename = "dfeta_filename"; + public const string dfeta_id = "dfeta_id"; + public const string dfeta_InductionId = "dfeta_inductionid"; + public const string dfeta_InductionPeriodId = "dfeta_inductionperiodid"; + public const string dfeta_InitialTeacherTrainingId = "dfeta_initialteachertrainingid"; + public const string dfeta_IntegrationTransactionId = "dfeta_integrationtransactionid"; + public const string dfeta_integrationtransactionrecordId = "dfeta_integrationtransactionrecordid"; + public const string Id = "dfeta_integrationtransactionrecordid"; + public const string dfeta_OrganisationId = "dfeta_organisationid"; + public const string dfeta_PersonId = "dfeta_personid"; + public const string dfeta_QualificationId = "dfeta_qualificationid"; + public const string dfeta_RowData = "dfeta_rowdata"; + public const string dfeta_TREFNO = "dfeta_trefno"; + public const string dfeta_UKPRN = "dfeta_ukprn"; + public const string StateCode = "statecode"; + public const string StatusCode = "statuscode"; + public const string business_unit_dfeta_integrationtransactionrecord = "business_unit_dfeta_integrationtransactionrecord"; + public const string dfeta_account_dfeta_integrationtransactionrecor = "dfeta_account_dfeta_integrationtransactionrecor"; + public const string dfeta_contact_dfeta_integrationtransactionrecor = "dfeta_contact_dfeta_integrationtransactionrecor"; + public const string dfeta_dfeta_induction_dfeta_integrationtransact = "dfeta_dfeta_induction_dfeta_integrationtransact"; + public const string dfeta_dfeta_inductionperiod_dfeta_integrationtr = "dfeta_dfeta_inductionperiod_dfeta_integrationtr"; + public const string dfeta_dfeta_initialteachertraining_dfeta_integr = "dfeta_dfeta_initialteachertraining_dfeta_integr"; + public const string dfeta_dfeta_integrationtransaction_dfeta_integr = "dfeta_dfeta_integrationtransaction_dfeta_integr"; + public const string dfeta_dfeta_qualification_dfeta_integrationtran = "dfeta_dfeta_qualification_dfeta_integrationtran"; + public const string lk_dfeta_integrationtransactionrecord_createdby = "lk_dfeta_integrationtransactionrecord_createdby"; + public const string lk_dfeta_integrationtransactionrecord_createdonbehalfby = "lk_dfeta_integrationtransactionrecord_createdonbehalfby"; + public const string lk_dfeta_integrationtransactionrecord_modifiedby = "lk_dfeta_integrationtransactionrecord_modifiedby"; + public const string lk_dfeta_integrationtransactionrecord_modifiedonbehalfby = "lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"; + public const string user_dfeta_integrationtransactionrecord = "user_dfeta_integrationtransactionrecord"; + } + + /// + /// Default Constructor. + /// + [System.Diagnostics.DebuggerNonUserCode()] + public dfeta_integrationtransactionrecord() : + base(EntityLogicalName) + { + } + + public const string EntitySchemaName = "dfeta_integrationtransactionrecord"; + + public const string PrimaryIdAttribute = "dfeta_integrationtransactionrecordid"; + + public const string PrimaryNameAttribute = "dfeta_id"; + + public const string EntityLogicalName = "dfeta_integrationtransactionrecord"; + + public const string EntityLogicalCollectionName = "dfeta_integrationtransactionrecords"; + + public const string EntitySetName = "dfeta_integrationtransactionrecords"; + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + + [System.Diagnostics.DebuggerNonUserCode()] + private void OnPropertyChanged(string propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.Diagnostics.DebuggerNonUserCode()] + private void OnPropertyChanging(string propertyName) + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName)); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_duplicatestatus")] + public virtual dfeta_integrationtransactionrecord_dfeta_DuplicateStatus? dfeta_DuplicateStatus + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return ((dfeta_integrationtransactionrecord_dfeta_DuplicateStatus?)(EntityOptionSetEnum.GetEnum(this, "dfeta_duplicatestatus"))); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_DuplicateStatus"); + this.SetAttributeValue("dfeta_duplicatestatus", value.HasValue ? new Microsoft.Xrm.Sdk.OptionSetValue((int)value) : null); + this.OnPropertyChanged("dfeta_DuplicateStatus"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_failuremessage")] + public string dfeta_FailureMessage + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_failuremessage"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_FailureMessage"); + this.SetAttributeValue("dfeta_failuremessage", value); + this.OnPropertyChanged("dfeta_FailureMessage"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_filename")] + public string dfeta_Filename + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_filename"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_Filename"); + this.SetAttributeValue("dfeta_filename", value); + this.OnPropertyChanged("dfeta_Filename"); + } + } + + /// + /// The name of the custom entity. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_id")] + public string dfeta_id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_id"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_id"); + this.SetAttributeValue("dfeta_id", value); + this.OnPropertyChanged("dfeta_id"); + } + } + + /// + /// Unique identifier for Induction associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_InductionId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_inductionid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_InductionId"); + this.SetAttributeValue("dfeta_inductionid", value); + this.OnPropertyChanged("dfeta_InductionId"); + } + } + + /// + /// Unique identifier for Induction Period associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionperiodid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_InductionPeriodId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_inductionperiodid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_InductionPeriodId"); + this.SetAttributeValue("dfeta_inductionperiodid", value); + this.OnPropertyChanged("dfeta_InductionPeriodId"); + } + } + + /// + /// Unique identifier for Initial Teacher Training associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_initialteachertrainingid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_InitialTeacherTrainingId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_initialteachertrainingid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_InitialTeacherTrainingId"); + this.SetAttributeValue("dfeta_initialteachertrainingid", value); + this.OnPropertyChanged("dfeta_InitialTeacherTrainingId"); + } + } + + /// + /// Unique identifier for Integration Transaction associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_IntegrationTransactionId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_integrationtransactionid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_IntegrationTransactionId"); + this.SetAttributeValue("dfeta_integrationtransactionid", value); + this.OnPropertyChanged("dfeta_IntegrationTransactionId"); + } + } + + /// + /// Unique identifier for entity instances + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionrecordid")] + public System.Nullable dfeta_integrationtransactionrecordId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue>("dfeta_integrationtransactionrecordid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_integrationtransactionrecordId"); + this.SetAttributeValue("dfeta_integrationtransactionrecordid", value); + if (value.HasValue) + { + base.Id = value.Value; + } + else + { + base.Id = System.Guid.Empty; + } + this.OnPropertyChanged("dfeta_integrationtransactionrecordId"); + } + } + + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionrecordid")] + public override System.Guid Id + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return base.Id; + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.dfeta_integrationtransactionrecordId = value; + } + } + + /// + /// Unique identifier for Organisation associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_organisationid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_OrganisationId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_organisationid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_OrganisationId"); + this.SetAttributeValue("dfeta_organisationid", value); + this.OnPropertyChanged("dfeta_OrganisationId"); + } + } + + /// + /// Unique identifier for Person associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_personid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_PersonId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_personid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_PersonId"); + this.SetAttributeValue("dfeta_personid", value); + this.OnPropertyChanged("dfeta_PersonId"); + } + } + + /// + /// Unique identifier for Qualification associated with Integration Transaction Record. + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_qualificationid")] + public Microsoft.Xrm.Sdk.EntityReference dfeta_QualificationId + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_qualificationid"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_QualificationId"); + this.SetAttributeValue("dfeta_qualificationid", value); + this.OnPropertyChanged("dfeta_QualificationId"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_rowdata")] + public string dfeta_RowData + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_rowdata"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_RowData"); + this.SetAttributeValue("dfeta_rowdata", value); + this.OnPropertyChanged("dfeta_RowData"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_trefno")] + public string dfeta_TREFNO + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_trefno"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_TREFNO"); + this.SetAttributeValue("dfeta_trefno", value); + this.OnPropertyChanged("dfeta_TREFNO"); + } + } + + /// + /// + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_ukprn")] + public string dfeta_UKPRN + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetAttributeValue("dfeta_ukprn"); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_UKPRN"); + this.SetAttributeValue("dfeta_ukprn", value); + this.OnPropertyChanged("dfeta_UKPRN"); + } + } + + /// + /// Status of the Integration Transaction Record + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("statecode")] + public System.Nullable StateCode + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + Microsoft.Xrm.Sdk.OptionSetValue optionSet = this.GetAttributeValue("statecode"); + if ((optionSet != null)) + { + return ((TeachingRecordSystem.Core.Dqt.Models.dfeta_integrationtransactionrecordState)(System.Enum.ToObject(typeof(TeachingRecordSystem.Core.Dqt.Models.dfeta_integrationtransactionrecordState), optionSet.Value))); + } + else + { + return null; + } + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("StateCode"); + if ((value == null)) + { + this.SetAttributeValue("statecode", null); + } + else + { + this.SetAttributeValue("statecode", new Microsoft.Xrm.Sdk.OptionSetValue(((int)(value)))); + } + this.OnPropertyChanged("StateCode"); + } + } + + /// + /// Reason for the status of the Integration Transaction Record + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("statuscode")] + public virtual dfeta_integrationtransactionrecord_StatusCode? StatusCode + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return ((dfeta_integrationtransactionrecord_StatusCode?)(EntityOptionSetEnum.GetEnum(this, "statuscode"))); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("StatusCode"); + this.SetAttributeValue("statuscode", value.HasValue ? new Microsoft.Xrm.Sdk.OptionSetValue((int)value) : null); + this.OnPropertyChanged("StatusCode"); + } + } + + /// + /// N:1 business_unit_dfeta_integrationtransactionrecord + /// + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("owningbusinessunit")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("business_unit_dfeta_integrationtransactionrecord")] + public TeachingRecordSystem.Core.Dqt.Models.BusinessUnit business_unit_dfeta_integrationtransactionrecord + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntity("business_unit_dfeta_integrationtransactionrecord", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("business_unit_dfeta_integrationtransactionrecord"); + this.SetRelatedEntity("business_unit_dfeta_integrationtransactionrecord", null, value); + this.OnPropertyChanged("business_unit_dfeta_integrationtransactionrecord"); + } + } + + /// + /// N:1 dfeta_account_dfeta_integrationtransactionrecor /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_personid")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_initialteachertraining")] - public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_initialteachertraining + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_organisationid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_account_dfeta_integrationtransactionrecor")] + public TeachingRecordSystem.Core.Dqt.Models.Account dfeta_account_dfeta_integrationtransactionrecor { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_contact_dfeta_initialteachertraining", null); + return this.GetRelatedEntity("dfeta_account_dfeta_integrationtransactionrecor", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_contact_dfeta_initialteachertraining"); - this.SetRelatedEntity("dfeta_contact_dfeta_initialteachertraining", null, value); - this.OnPropertyChanged("dfeta_contact_dfeta_initialteachertraining"); + this.OnPropertyChanging("dfeta_account_dfeta_integrationtransactionrecor"); + this.SetRelatedEntity("dfeta_account_dfeta_integrationtransactionrecor", null, value); + this.OnPropertyChanged("dfeta_account_dfeta_integrationtransactionrecor"); } } /// - /// N:1 dfeta_contact_dfeta_initialteachertraining1 + /// N:1 dfeta_contact_dfeta_integrationtransactionrecor /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_requestedbyid")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_initialteachertraining1")] - public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_initialteachertraining1 + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_personid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_contact_dfeta_integrationtransactionrecor")] + public TeachingRecordSystem.Core.Dqt.Models.Contact dfeta_contact_dfeta_integrationtransactionrecor { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_contact_dfeta_initialteachertraining1", null); + return this.GetRelatedEntity("dfeta_contact_dfeta_integrationtransactionrecor", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_contact_dfeta_initialteachertraining1"); - this.SetRelatedEntity("dfeta_contact_dfeta_initialteachertraining1", null, value); - this.OnPropertyChanged("dfeta_contact_dfeta_initialteachertraining1"); + this.OnPropertyChanging("dfeta_contact_dfeta_integrationtransactionrecor"); + this.SetRelatedEntity("dfeta_contact_dfeta_integrationtransactionrecor", null, value); + this.OnPropertyChanged("dfeta_contact_dfeta_integrationtransactionrecor"); } } /// - /// N:1 dfeta_dfeta_country_dfeta_initialteachertrainin + /// N:1 dfeta_dfeta_induction_dfeta_integrationtransact /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_countryid")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_country_dfeta_initialteachertrainin")] - public TeachingRecordSystem.Core.Dqt.Models.dfeta_country dfeta_dfeta_country_dfeta_initialteachertrainin + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_induction_dfeta_integrationtransact")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_induction dfeta_dfeta_induction_dfeta_integrationtransact { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_dfeta_country_dfeta_initialteachertrainin", null); + return this.GetRelatedEntity("dfeta_dfeta_induction_dfeta_integrationtransact", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_dfeta_country_dfeta_initialteachertrainin"); - this.SetRelatedEntity("dfeta_dfeta_country_dfeta_initialteachertrainin", null, value); - this.OnPropertyChanged("dfeta_dfeta_country_dfeta_initialteachertrainin"); + this.OnPropertyChanging("dfeta_dfeta_induction_dfeta_integrationtransact"); + this.SetRelatedEntity("dfeta_dfeta_induction_dfeta_integrationtransact", null, value); + this.OnPropertyChanged("dfeta_dfeta_induction_dfeta_integrationtransact"); } } /// - /// N:1 dfeta_dfeta_ittqualification_dfeta_initialteach + /// N:1 dfeta_dfeta_inductionperiod_dfeta_integrationtr /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_ittqualificationid")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittqualification_dfeta_initialteach")] - public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittqualification dfeta_dfeta_ittqualification_dfeta_initialteach + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_inductionperiodid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_inductionperiod_dfeta_integrationtr")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_inductionperiod dfeta_dfeta_inductionperiod_dfeta_integrationtr { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_dfeta_ittqualification_dfeta_initialteach", null); + return this.GetRelatedEntity("dfeta_dfeta_inductionperiod_dfeta_integrationtr", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_dfeta_ittqualification_dfeta_initialteach"); - this.SetRelatedEntity("dfeta_dfeta_ittqualification_dfeta_initialteach", null, value); - this.OnPropertyChanged("dfeta_dfeta_ittqualification_dfeta_initialteach"); + this.OnPropertyChanging("dfeta_dfeta_inductionperiod_dfeta_integrationtr"); + this.SetRelatedEntity("dfeta_dfeta_inductionperiod_dfeta_integrationtr", null, value); + this.OnPropertyChanged("dfeta_dfeta_inductionperiod_dfeta_integrationtr"); } } /// - /// N:1 dfeta_dfeta_ittsubject1_dfeta_initialteachertra + /// N:1 dfeta_dfeta_initialteachertraining_dfeta_integr /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject1id")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject1_dfeta_initialteachertra")] - public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject1_dfeta_initialteachertra + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_initialteachertrainingid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_initialteachertraining_dfeta_integr")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_initialteachertraining dfeta_dfeta_initialteachertraining_dfeta_integr { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_dfeta_ittsubject1_dfeta_initialteachertra", null); + return this.GetRelatedEntity("dfeta_dfeta_initialteachertraining_dfeta_integr", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_dfeta_ittsubject1_dfeta_initialteachertra"); - this.SetRelatedEntity("dfeta_dfeta_ittsubject1_dfeta_initialteachertra", null, value); - this.OnPropertyChanged("dfeta_dfeta_ittsubject1_dfeta_initialteachertra"); + this.OnPropertyChanging("dfeta_dfeta_initialteachertraining_dfeta_integr"); + this.SetRelatedEntity("dfeta_dfeta_initialteachertraining_dfeta_integr", null, value); + this.OnPropertyChanged("dfeta_dfeta_initialteachertraining_dfeta_integr"); } } /// - /// N:1 dfeta_dfeta_ittsubject2_dfeta_initialteachertra + /// N:1 dfeta_dfeta_integrationtransaction_dfeta_integr /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject2id")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject2_dfeta_initialteachertra")] - public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject2_dfeta_initialteachertra + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_integrationtransactionid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_integrationtransaction_dfeta_integr")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_integrationtransaction dfeta_dfeta_integrationtransaction_dfeta_integr { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_dfeta_ittsubject2_dfeta_initialteachertra", null); + return this.GetRelatedEntity("dfeta_dfeta_integrationtransaction_dfeta_integr", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_dfeta_ittsubject2_dfeta_initialteachertra"); - this.SetRelatedEntity("dfeta_dfeta_ittsubject2_dfeta_initialteachertra", null, value); - this.OnPropertyChanged("dfeta_dfeta_ittsubject2_dfeta_initialteachertra"); + this.OnPropertyChanging("dfeta_dfeta_integrationtransaction_dfeta_integr"); + this.SetRelatedEntity("dfeta_dfeta_integrationtransaction_dfeta_integr", null, value); + this.OnPropertyChanged("dfeta_dfeta_integrationtransaction_dfeta_integr"); } } /// - /// N:1 dfeta_dfeta_ittsubject3_dfeta_initialteachertra + /// N:1 dfeta_dfeta_qualification_dfeta_integrationtran /// - [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_subject3id")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_ittsubject3_dfeta_initialteachertra")] - public TeachingRecordSystem.Core.Dqt.Models.dfeta_ittsubject dfeta_dfeta_ittsubject3_dfeta_initialteachertra + [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("dfeta_qualificationid")] + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_qualification_dfeta_integrationtran")] + public TeachingRecordSystem.Core.Dqt.Models.dfeta_qualification dfeta_dfeta_qualification_dfeta_integrationtran { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("dfeta_dfeta_ittsubject3_dfeta_initialteachertra", null); + return this.GetRelatedEntity("dfeta_dfeta_qualification_dfeta_integrationtran", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("dfeta_dfeta_ittsubject3_dfeta_initialteachertra"); - this.SetRelatedEntity("dfeta_dfeta_ittsubject3_dfeta_initialteachertra", null, value); - this.OnPropertyChanged("dfeta_dfeta_ittsubject3_dfeta_initialteachertra"); + this.OnPropertyChanging("dfeta_dfeta_qualification_dfeta_integrationtran"); + this.SetRelatedEntity("dfeta_dfeta_qualification_dfeta_integrationtran", null, value); + this.OnPropertyChanged("dfeta_dfeta_qualification_dfeta_integrationtran"); } } /// - /// N:1 lk_dfeta_initialteachertraining_createdby + /// N:1 lk_dfeta_integrationtransactionrecord_createdby /// [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdby")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_createdby")] - public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_createdby + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_createdby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransactionrecord_createdby { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("lk_dfeta_initialteachertraining_createdby", null); + return this.GetRelatedEntity("lk_dfeta_integrationtransactionrecord_createdby", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("lk_dfeta_initialteachertraining_createdby"); - this.SetRelatedEntity("lk_dfeta_initialteachertraining_createdby", null, value); - this.OnPropertyChanged("lk_dfeta_initialteachertraining_createdby"); + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_createdby"); + this.SetRelatedEntity("lk_dfeta_integrationtransactionrecord_createdby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_createdby"); } } /// - /// N:1 lk_dfeta_initialteachertraining_createdonbehalfby + /// N:1 lk_dfeta_integrationtransactionrecord_createdonbehalfby /// [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("createdonbehalfby")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_createdonbehalfby")] - public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_createdonbehalfby + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_createdonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransactionrecord_createdonbehalfby { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("lk_dfeta_initialteachertraining_createdonbehalfby", null); + return this.GetRelatedEntity("lk_dfeta_integrationtransactionrecord_createdonbehalfby", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("lk_dfeta_initialteachertraining_createdonbehalfby"); - this.SetRelatedEntity("lk_dfeta_initialteachertraining_createdonbehalfby", null, value); - this.OnPropertyChanged("lk_dfeta_initialteachertraining_createdonbehalfby"); + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_createdonbehalfby"); + this.SetRelatedEntity("lk_dfeta_integrationtransactionrecord_createdonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_createdonbehalfby"); } } /// - /// N:1 lk_dfeta_initialteachertraining_modifiedby + /// N:1 lk_dfeta_integrationtransactionrecord_modifiedby /// [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedby")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_modifiedby")] - public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_modifiedby + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_modifiedby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransactionrecord_modifiedby { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("lk_dfeta_initialteachertraining_modifiedby", null); + return this.GetRelatedEntity("lk_dfeta_integrationtransactionrecord_modifiedby", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("lk_dfeta_initialteachertraining_modifiedby"); - this.SetRelatedEntity("lk_dfeta_initialteachertraining_modifiedby", null, value); - this.OnPropertyChanged("lk_dfeta_initialteachertraining_modifiedby"); + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_modifiedby"); + this.SetRelatedEntity("lk_dfeta_integrationtransactionrecord_modifiedby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_modifiedby"); } } /// - /// N:1 lk_dfeta_initialteachertraining_modifiedonbehalfby + /// N:1 lk_dfeta_integrationtransactionrecord_modifiedonbehalfby /// [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("modifiedonbehalfby")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_initialteachertraining_modifiedonbehalfby")] - public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_initialteachertraining_modifiedonbehalfby + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser lk_dfeta_integrationtransactionrecord_modifiedonbehalfby { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("lk_dfeta_initialteachertraining_modifiedonbehalfby", null); + return this.GetRelatedEntity("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("lk_dfeta_initialteachertraining_modifiedonbehalfby"); - this.SetRelatedEntity("lk_dfeta_initialteachertraining_modifiedonbehalfby", null, value); - this.OnPropertyChanged("lk_dfeta_initialteachertraining_modifiedonbehalfby"); + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"); + this.SetRelatedEntity("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"); } } /// - /// N:1 user_dfeta_initialteachertraining + /// N:1 user_dfeta_integrationtransactionrecord /// [Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("owninguser")] - [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_initialteachertraining")] - public TeachingRecordSystem.Core.Dqt.Models.SystemUser user_dfeta_initialteachertraining + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_integrationtransactionrecord")] + public TeachingRecordSystem.Core.Dqt.Models.SystemUser user_dfeta_integrationtransactionrecord { [System.Diagnostics.DebuggerNonUserCode()] get { - return this.GetRelatedEntity("user_dfeta_initialteachertraining", null); + return this.GetRelatedEntity("user_dfeta_integrationtransactionrecord", null); } [System.Diagnostics.DebuggerNonUserCode()] set { - this.OnPropertyChanging("user_dfeta_initialteachertraining"); - this.SetRelatedEntity("user_dfeta_initialteachertraining", null, value); - this.OnPropertyChanged("user_dfeta_initialteachertraining"); + this.OnPropertyChanging("user_dfeta_integrationtransactionrecord"); + this.SetRelatedEntity("user_dfeta_integrationtransactionrecord", null, value); + this.OnPropertyChanged("user_dfeta_integrationtransactionrecord"); } } } @@ -9816,6 +11444,7 @@ public static class Fields public const string ModifiedOn = "modifiedon"; public const string StateCode = "statecode"; public const string StatusCode = "statuscode"; + public const string dfeta_dfeta_qualification_dfeta_integrationtran = "dfeta_dfeta_qualification_dfeta_integrationtran"; public const string business_unit_dfeta_qualification = "business_unit_dfeta_qualification"; public const string dfeta_account_dfeta_qualification_he = "dfeta_account_dfeta_qualification_he"; public const string dfeta_contact_dfeta_qualification = "dfeta_contact_dfeta_qualification"; @@ -10774,6 +12403,26 @@ public virtual dfeta_qualification_StatusCode? StatusCode } } + /// + /// 1:N dfeta_dfeta_qualification_dfeta_integrationtran + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("dfeta_dfeta_qualification_dfeta_integrationtran")] + public System.Collections.Generic.IEnumerable dfeta_dfeta_qualification_dfeta_integrationtran + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("dfeta_dfeta_qualification_dfeta_integrationtran", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("dfeta_dfeta_qualification_dfeta_integrationtran"); + this.SetRelatedEntities("dfeta_dfeta_qualification_dfeta_integrationtran", null, value); + this.OnPropertyChanged("dfeta_dfeta_qualification_dfeta_integrationtran"); + } + } + /// /// N:1 business_unit_dfeta_qualification /// @@ -20297,6 +21946,14 @@ public static class Fields public const string lk_dfeta_initialteachertraining_createdonbehalfby = "lk_dfeta_initialteachertraining_createdonbehalfby"; public const string lk_dfeta_initialteachertraining_modifiedby = "lk_dfeta_initialteachertraining_modifiedby"; public const string lk_dfeta_initialteachertraining_modifiedonbehalfby = "lk_dfeta_initialteachertraining_modifiedonbehalfby"; + public const string lk_dfeta_integrationtransaction_createdby = "lk_dfeta_integrationtransaction_createdby"; + public const string lk_dfeta_integrationtransaction_createdonbehalfby = "lk_dfeta_integrationtransaction_createdonbehalfby"; + public const string lk_dfeta_integrationtransaction_modifiedby = "lk_dfeta_integrationtransaction_modifiedby"; + public const string lk_dfeta_integrationtransaction_modifiedonbehalfby = "lk_dfeta_integrationtransaction_modifiedonbehalfby"; + public const string lk_dfeta_integrationtransactionrecord_createdby = "lk_dfeta_integrationtransactionrecord_createdby"; + public const string lk_dfeta_integrationtransactionrecord_createdonbehalfby = "lk_dfeta_integrationtransactionrecord_createdonbehalfby"; + public const string lk_dfeta_integrationtransactionrecord_modifiedby = "lk_dfeta_integrationtransactionrecord_modifiedby"; + public const string lk_dfeta_integrationtransactionrecord_modifiedonbehalfby = "lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"; public const string lk_dfeta_ittqualification_createdby = "lk_dfeta_ittqualification_createdby"; public const string lk_dfeta_ittqualification_createdonbehalfby = "lk_dfeta_ittqualification_createdonbehalfby"; public const string lk_dfeta_ittqualification_modifiedby = "lk_dfeta_ittqualification_modifiedby"; @@ -20396,6 +22053,8 @@ public static class Fields public const string user_dfeta_induction = "user_dfeta_induction"; public const string user_dfeta_inductionperiod = "user_dfeta_inductionperiod"; public const string user_dfeta_initialteachertraining = "user_dfeta_initialteachertraining"; + public const string user_dfeta_integrationtransaction = "user_dfeta_integrationtransaction"; + public const string user_dfeta_integrationtransactionrecord = "user_dfeta_integrationtransactionrecord"; public const string user_dfeta_previousname = "user_dfeta_previousname"; public const string user_dfeta_qtsregistration = "user_dfeta_qtsregistration"; public const string user_dfeta_qualification = "user_dfeta_qualification"; @@ -21882,6 +23541,166 @@ public System.Collections.Generic.IEnumerable + /// 1:N lk_dfeta_integrationtransaction_createdby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_createdby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransaction_createdby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransaction_createdby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_createdby"); + this.SetRelatedEntities("lk_dfeta_integrationtransaction_createdby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_createdby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransaction_createdonbehalfby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_createdonbehalfby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransaction_createdonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransaction_createdonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_createdonbehalfby"); + this.SetRelatedEntities("lk_dfeta_integrationtransaction_createdonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_createdonbehalfby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransaction_modifiedby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_modifiedby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransaction_modifiedby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransaction_modifiedby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_modifiedby"); + this.SetRelatedEntities("lk_dfeta_integrationtransaction_modifiedby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_modifiedby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransaction_modifiedonbehalfby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransaction_modifiedonbehalfby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransaction_modifiedonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransaction_modifiedonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransaction_modifiedonbehalfby"); + this.SetRelatedEntities("lk_dfeta_integrationtransaction_modifiedonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransaction_modifiedonbehalfby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransactionrecord_createdby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_createdby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransactionrecord_createdby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransactionrecord_createdby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_createdby"); + this.SetRelatedEntities("lk_dfeta_integrationtransactionrecord_createdby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_createdby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransactionrecord_createdonbehalfby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_createdonbehalfby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransactionrecord_createdonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransactionrecord_createdonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_createdonbehalfby"); + this.SetRelatedEntities("lk_dfeta_integrationtransactionrecord_createdonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_createdonbehalfby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransactionrecord_modifiedby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_modifiedby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransactionrecord_modifiedby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransactionrecord_modifiedby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_modifiedby"); + this.SetRelatedEntities("lk_dfeta_integrationtransactionrecord_modifiedby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_modifiedby"); + } + } + + /// + /// 1:N lk_dfeta_integrationtransactionrecord_modifiedonbehalfby + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby")] + public System.Collections.Generic.IEnumerable lk_dfeta_integrationtransactionrecord_modifiedonbehalfby + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"); + this.SetRelatedEntities("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby", null, value); + this.OnPropertyChanged("lk_dfeta_integrationtransactionrecord_modifiedonbehalfby"); + } + } + /// /// 1:N lk_dfeta_ittqualification_createdby /// @@ -23862,6 +25681,46 @@ public System.Collections.Generic.IEnumerable + /// 1:N user_dfeta_integrationtransaction + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_integrationtransaction")] + public System.Collections.Generic.IEnumerable user_dfeta_integrationtransaction + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("user_dfeta_integrationtransaction", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("user_dfeta_integrationtransaction"); + this.SetRelatedEntities("user_dfeta_integrationtransaction", null, value); + this.OnPropertyChanged("user_dfeta_integrationtransaction"); + } + } + + /// + /// 1:N user_dfeta_integrationtransactionrecord + /// + [Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("user_dfeta_integrationtransactionrecord")] + public System.Collections.Generic.IEnumerable user_dfeta_integrationtransactionrecord + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.GetRelatedEntities("user_dfeta_integrationtransactionrecord", null); + } + [System.Diagnostics.DebuggerNonUserCode()] + set + { + this.OnPropertyChanging("user_dfeta_integrationtransactionrecord"); + this.SetRelatedEntities("user_dfeta_integrationtransactionrecord", null, value); + this.OnPropertyChanged("user_dfeta_integrationtransactionrecord"); + } + } + /// /// 1:N user_dfeta_previousname /// @@ -25164,6 +27023,30 @@ public System.Linq.IQueryable + /// Gets a binding to the set of all entities. + /// + public System.Linq.IQueryable dfeta_integrationtransactionSet + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.CreateQuery(); + } + } + + /// + /// Gets a binding to the set of all entities. + /// + public System.Linq.IQueryable dfeta_integrationtransactionrecordSet + { + [System.Diagnostics.DebuggerNonUserCode()] + get + { + return this.CreateQuery(); + } + } + /// /// Gets a binding to the set of all entities. /// diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedOptionSets.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedOptionSets.cs index a63c68c65..fa6a57921 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedOptionSets.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Models/GeneratedOptionSets.cs @@ -1988,6 +1988,134 @@ public enum dfeta_initialteachertraining_StatusCode Inactive = 2, } + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_IntegrationInterface + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Appropriate Body Import", 7)] + AppropriateBodyImport = 389040001, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Capita Export Amend", 10)] + CapitaExportAmend = 389040004, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Capita Export New", 9)] + CapitaExportNew = 389040003, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Capita Import", 8)] + CapitaImport = 389040002, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("DMS Export QTS Date", 15)] + DMSExportQTSDate = 389040009, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("DMS Export TRN", 14)] + DMSExportTRN = 389040008, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("DMS Import", 13)] + DMSImport = 389040007, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("DMS Import TTR1", 0)] + DMSImportTTR1 = 389040014, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("DMS Import TTR4\\TTR5", 1)] + DMSImportTTR4TTR5 = 389040015, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Edubase", 11)] + Edubase = 389040005, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Edubase Links", 12)] + EdubaseLinks = 389040006, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("GTC Wales Import", 4)] + GTCWalesImport = 389040011, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("HESA Export", 3)] + HESAExport = 389040012, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("HESA Import", 6)] + HESAImport = 389040000, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("ITTPUpdate", 2)] + ITTPUpdate = 389040013, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("NPQ Export", 17, "#0000ff")] + NPQExport = 389040017, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("NPQ Import", 16, "#0000ff")] + NPQImport = 389040016, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Training Provider Import", 5)] + TrainingProviderImport = 389040010, + } + + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_integrationtransaction_StatusCode + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Active", 0)] + Active = 1, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Inactive", 1)] + Inactive = 2, + } + + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_integrationtransactionrecord_dfeta_DuplicateStatus + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Duplicate", 0)] + Duplicate = 389040000, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Duplicate Resolved", 1)] + DuplicateResolved = 389040002, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Not Applicable", 3)] + NotApplicable = 389040003, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Third Party Notified", 2)] + ThirdPartyNotified = 389040001, + } + + [System.Runtime.Serialization.DataContractAttribute()] + public enum dfeta_integrationtransactionrecord_StatusCode + { + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Fail", 1)] + Fail = 389040000, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Inactive", 2)] + Inactive = 2, + + [System.Runtime.Serialization.EnumMemberAttribute()] + [OptionSetMetadataAttribute("Success", 0)] + Success = 1, + } + [System.Runtime.Serialization.DataContractAttribute()] public enum dfeta_ITTProgrammeType { diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateHeQualificationTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateHeQualificationTransactionalQuery.cs new file mode 100644 index 000000000..e328078ac --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateHeQualificationTransactionalQuery.cs @@ -0,0 +1,17 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateHeQualificationTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid Id { get; init; } + public required Guid ContactId { get; init; } + public required Guid? HECountryId { get; init; } + public required string? HECourseLength { get; init; } + public required Guid? HEEstablishmentId { get; init; } + public required Guid? HEQualificationId { get; init; } + public required dfeta_classdivision? HEClassDivision { get; init; } + public required Guid? HESubject1id { get; init; } + public required Guid? HESubject2id { get; init; } + public required Guid? HESubject3id { get; init; } + public required dfeta_qualification_dfeta_Type? Type { get; init; } +} + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionPeriodTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionPeriodTransactionalQuery.cs new file mode 100644 index 000000000..3e7e76fc0 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionPeriodTransactionalQuery.cs @@ -0,0 +1,10 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateInductionPeriodTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid Id { get; init; } + public required Guid InductionId { get; init; } + public required Guid? AppropriateBodyId { get; init; } + public required DateTime? InductionStartDate { get; init; } + public required DateTime? InductionEndDate { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionTransactionalQuery.cs new file mode 100644 index 000000000..530461c1d --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInductionTransactionalQuery.cs @@ -0,0 +1,10 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateInductionTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid Id { get; init; } + public required Guid ContactId { get; init; } + public required DateTime? StartDate { get; init; } + public required DateTime? CompletionDate { get; init; } + public required dfeta_InductionStatus InductionStatus { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInitialTeacherTrainingTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInitialTeacherTrainingTransactionalQuery.cs new file mode 100644 index 000000000..8894fcdac --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateInitialTeacherTrainingTransactionalQuery.cs @@ -0,0 +1,10 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateInitialTeacherTrainingTransactionalQuery : ICrmTransactionalQuery +{ + public Guid Id { get; set; } + public required Guid ContactId { get; init; } + public required Guid? CountryId { get; init; } + public required Guid? ITTQualificationId { get; init; } + public required dfeta_ITTResult Result { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionQuery.cs new file mode 100644 index 000000000..fc31de15e --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionQuery.cs @@ -0,0 +1,8 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateIntegrationTransactionQuery : ICrmQuery +{ + public required int TypeId { get; init; } + public required DateTime StartDate { get; init; } + public required string? FileName { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionRecordTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionRecordTransactionalQuery.cs new file mode 100644 index 000000000..c99fe77a0 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateIntegrationTransactionRecordTransactionalQuery.cs @@ -0,0 +1,17 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateIntegrationTransactionRecordTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid IntegrationTransactionId { get; init; } + public required string? Reference { get; init; } + public required Guid? ContactId { get; init; } + public required Guid? InitialTeacherTrainingId { get; init; } + public required Guid? QualificationId { get; init; } + public required Guid? InductionId { get; init; } + public required Guid? InductionPeriodId { get; init; } + public required dfeta_integrationtransactionrecord_dfeta_DuplicateStatus? DuplicateStatus { get; init; } + public required dfeta_integrationtransactionrecord_StatusCode? StatusCode { get; init; } + public required string? FailureMessage { get; init; } + public required string? RowData { get; init; } + public required string? FileName { get; set; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateQtsRegistrationTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateQtsRegistrationTransactionalQuery.cs new file mode 100644 index 000000000..ca3ce7d55 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/CreateQtsRegistrationTransactionalQuery.cs @@ -0,0 +1,9 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record CreateQtsRegistrationTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid Id { get; init; } + public required Guid ContactId { get; init; } + public required Guid TeacherStatusId { get; init; } + public required DateTime? QtsDate { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/FindActiveOrganisationsByOrgNumberQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/FindActiveOrganisationsByOrgNumberQuery.cs new file mode 100644 index 000000000..de15d227b --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/FindActiveOrganisationsByOrgNumberQuery.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record FindActiveOrganisationsByAccountNumberQuery(string AccountNumber) : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetActiveInitialTeacherTrainingsByContactIdQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetActiveInitialTeacherTrainingsByContactIdQuery.cs new file mode 100644 index 000000000..302778e38 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetActiveInitialTeacherTrainingsByContactIdQuery.cs @@ -0,0 +1,4 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetActiveInitialTeacherTrainingsByContactIdQuery(Guid ContactId) : + ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttQualificationsQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttQualificationsQuery.cs new file mode 100644 index 000000000..006745332 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttQualificationsQuery.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetAllActiveIttQualificationsQuery : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttSubjectsQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttSubjectsQuery.cs new file mode 100644 index 000000000..d1fca9c61 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllActiveIttSubjectsQuery.cs @@ -0,0 +1,3 @@ +using TeachingRecordSystem.Core.Dqt; + +public record GetAllActiveIttSubjectsQuery : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllCountriesQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllCountriesQuery.cs new file mode 100644 index 000000000..bcbfee606 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/GetAllCountriesQuery.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record GetAllCountriesQuery : ICrmQuery; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionPeriodTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionPeriodTransactionalQuery.cs new file mode 100644 index 000000000..bc3ab25cb --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionPeriodTransactionalQuery.cs @@ -0,0 +1,9 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record UpdateInductionPeriodTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid InductionPeriodId { get; init; } + public required Guid? AppropriateBodyId { get; init; } + public required DateTime? InductionStartDate { get; init; } + public required DateTime? InductionEndDate { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionTransactionalQuery.cs new file mode 100644 index 000000000..8738aa9c8 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateInductionTransactionalQuery.cs @@ -0,0 +1,8 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record UpdateInductionTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid InductionId { get; init; } + public required DateTime? CompletionDate { get; init; } + public required dfeta_InductionStatus InductionStatus { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionRecordTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionRecordTransactionalQuery.cs new file mode 100644 index 000000000..66bb714d7 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionRecordTransactionalQuery.cs @@ -0,0 +1,17 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record UpdateIntegrationTransactionRecordTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid IntegrationTransactionRecordId { get; init; } + public required Guid IntegrationTransactionId { get; init; } + public required string? Reference { get; init; } + public required Guid? PersonId { get; init; } + public required Guid? InitialTeacherTrainingId { get; init; } + public required Guid? QualificationId { get; init; } + public required Guid? InductionId { get; init; } + public required Guid? InductionPeriodId { get; init; } + public required dfeta_integrationtransactionrecord_dfeta_DuplicateStatus? DuplicateStatus { get; init; } + public required dfeta_integrationtransactionrecord_StatusCode? StatusCode { get; init; } + public required string? FailureMessage { get; init; } + public required string? RowData { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionTransactionalQuery.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionTransactionalQuery.cs new file mode 100644 index 000000000..59ad3418c --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/Queries/UpdateIntegrationTransactionTransactionalQuery.cs @@ -0,0 +1,12 @@ +namespace TeachingRecordSystem.Core.Dqt.Queries; + +public record UpdateIntegrationTransactionTransactionalQuery : ICrmTransactionalQuery +{ + public required Guid IntegrationTransactionId { get; init; } + public required DateTime? EndDate { get; init; } + public required int? TotalCount { get; init; } + public required int? SuccessCount { get; init; } + public required int? DuplicateCount { get; init; } + public required int? FailureCount { get; init; } + public required string? FailureMessage { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateHeQualificationTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateHeQualificationTransactionalHandler.cs new file mode 100644 index 000000000..8808ceabe --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateHeQualificationTransactionalHandler.cs @@ -0,0 +1,28 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateHeQualificationTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateHeQualificationTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_qualification() + { + Id = query.Id, + dfeta_HE_CountryId = query.HECountryId?.ToEntityReference(dfeta_country.EntityLogicalName), + dfeta_HE_ClassDivision = query.HEClassDivision, + dfeta_HE_HEQualificationId = query.HEQualificationId?.ToEntityReference(dfeta_hequalification.EntityLogicalName), + dfeta_Type = query.Type, + dfeta_PersonId = query.ContactId.ToEntityReference(Contact.EntityLogicalName), + dfeta_HE_EstablishmentId = query.HEEstablishmentId?.ToEntityReference(Account.EntityLogicalName), + dfeta_HE_HESubject1Id = query.HESubject1id?.ToEntityReference(dfeta_hesubject.EntityLogicalName), + dfeta_HE_HESubject2Id = query.HESubject2id?.ToEntityReference(dfeta_hesubject.EntityLogicalName), + dfeta_HE_HESubject3Id = query.HESubject3id?.ToEntityReference(dfeta_hesubject.EntityLogicalName), + } + }); + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionPeriodTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionPeriodTransactionalHandler.cs new file mode 100644 index 000000000..6dbeab6a2 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionPeriodTransactionalHandler.cs @@ -0,0 +1,24 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateInductionPeriodTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateInductionPeriodTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_inductionperiod() + { + Id = query.Id, + dfeta_InductionId = query.InductionId.ToEntityReference(dfeta_induction.EntityLogicalName), + dfeta_AppropriateBodyId = query.AppropriateBodyId?.ToEntityReference(Account.EntityLogicalName), + dfeta_StartDate = query.InductionStartDate, + dfeta_EndDate = query.InductionEndDate, + } + }); + + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionTransactionalHandler.cs new file mode 100644 index 000000000..0a418ba51 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInductionTransactionalHandler.cs @@ -0,0 +1,23 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateInductionTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateInductionTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_induction() + { + Id = query.Id, + dfeta_PersonId = query.ContactId.ToEntityReference(Contact.EntityLogicalName), + dfeta_StartDate = query.StartDate, + dfeta_CompletionDate = query.CompletionDate, + dfeta_InductionStatus = query.InductionStatus, + } + }); + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInitialTeacherTrainingTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInitialTeacherTrainingTransactionalHandler.cs new file mode 100644 index 000000000..63d69101c --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateInitialTeacherTrainingTransactionalHandler.cs @@ -0,0 +1,23 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateInitialTeacherTrainingTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateInitialTeacherTrainingTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_initialteachertraining() + { + Id = query.Id, + dfeta_PersonId = query.ContactId.ToEntityReference(Contact.EntityLogicalName), + dfeta_CountryId = query.CountryId?.ToEntityReference(dfeta_country.EntityLogicalName), + dfeta_ITTQualificationId = query.ITTQualificationId?.ToEntityReference(dfeta_qualification.EntityLogicalName), + dfeta_Result = query.Result + } + }); + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionRecordTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionRecordTransactionalHandler.cs new file mode 100644 index 000000000..6f98f9a3f --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionRecordTransactionalHandler.cs @@ -0,0 +1,31 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateIntegrationTransactionRecordTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateIntegrationTransactionRecordTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_integrationtransactionrecord() + { + dfeta_IntegrationTransactionId = query.IntegrationTransactionId.ToEntityReference(dfeta_integrationtransaction.EntityLogicalName), + dfeta_id = query.Reference, + dfeta_PersonId = query.ContactId?.ToEntityReference(Contact.EntityLogicalName), + dfeta_InitialTeacherTrainingId = query.InitialTeacherTrainingId?.ToEntityReference(dfeta_initialteachertraining.EntityLogicalName), + dfeta_QualificationId = query.QualificationId?.ToEntityReference(dfeta_qualification.EntityLogicalName), + dfeta_InductionId = query.InductionId?.ToEntityReference(dfeta_induction.EntityLogicalName), + dfeta_InductionPeriodId = query.InductionPeriodId?.ToEntityReference(dfeta_inductionperiod.EntityLogicalName), + dfeta_DuplicateStatus = query.DuplicateStatus, + StatusCode = query.StatusCode, + dfeta_FailureMessage = query.FailureMessage, + dfeta_RowData = query.RowData, + dfeta_Filename = query.FileName + } + }); + + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionTransactionalHandler.cs new file mode 100644 index 000000000..191e1a3ef --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateIntegrationTransactionTransactionalHandler.cs @@ -0,0 +1,19 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateIntegrationTransactionTransactionalHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(CreateIntegrationTransactionQuery query, IOrganizationServiceAsync organizationService) + { + var integrationTransactionId = await organizationService.CreateAsync(new dfeta_integrationtransaction() + { + Id = Guid.NewGuid(), + dfeta_Interface = dfeta_IntegrationInterface.GTCWalesImport, + dfeta_StartDate = query.StartDate, + dfeta_Filename = query.FileName + }); + return integrationTransactionId; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateQtsRegistrationTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateQtsRegistrationTransactionalHandler.cs new file mode 100644 index 000000000..0cffb489d --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/CreateQtsRegistrationTransactionalHandler.cs @@ -0,0 +1,23 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class CreateQtsRegistrationTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(CreateQtsRegistrationTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new CreateRequest() + { + Target = new dfeta_qtsregistration() + { + Id = query.Id, + dfeta_PersonId = query.ContactId.ToEntityReference(Contact.EntityLogicalName), + dfeta_TeacherStatusId = query.TeacherStatusId.ToEntityReference(dfeta_teacherstatus.EntityLogicalName), + dfeta_QTSDate = query.QtsDate + } + }); + + return () => createResponse.GetResponse().id; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/FindActiveOrganisationsByAccountNumberHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/FindActiveOrganisationsByAccountNumberHandler.cs new file mode 100644 index 000000000..8c71a6020 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/FindActiveOrganisationsByAccountNumberHandler.cs @@ -0,0 +1,32 @@ +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 FindActiveOrganisationsByAccountNumberHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(FindActiveOrganisationsByAccountNumberQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = Account.EntityLogicalName, + ColumnSet = new ColumnSet( + Account.Fields.AccountNumber, + Account.Fields.Name) + }; + + queryExpression.Criteria.AddCondition(Account.Fields.AccountNumber, ConditionOperator.Equal, query.AccountNumber); + queryExpression.Criteria.AddCondition(Account.Fields.StateCode, ConditionOperator.Equal, (int)AccountState.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/GetAllActiveIttQualificationsHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttQualificationsHandler.cs new file mode 100644 index 000000000..8cc5f4022 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttQualificationsHandler.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 GetAllActiveIttQualificationsHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(GetAllActiveIttQualificationsQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = dfeta_ittqualification.EntityLogicalName, + ColumnSet = new ColumnSet( + dfeta_ittqualification.Fields.dfeta_name, + dfeta_ittqualification.Fields.dfeta_Value) + }; + + queryExpression.Criteria.AddCondition(dfeta_ittqualification.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_ittqualificationState.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/GetAllActiveIttSubjectsHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttSubjectsHandler.cs new file mode 100644 index 000000000..f7c161eef --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllActiveIttSubjectsHandler.cs @@ -0,0 +1,30 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Messages; +using Microsoft.Xrm.Sdk.Query; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetAllActiveIttSubjectsHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(GetAllActiveIttSubjectsQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = dfeta_ittsubject.EntityLogicalName, + ColumnSet = new ColumnSet( + dfeta_hesubject.Fields.dfeta_name, + dfeta_hesubject.Fields.dfeta_Value) + }; + + queryExpression.Criteria.AddCondition(dfeta_ittsubject.Fields.StateCode, ConditionOperator.Equal, (int)dfeta_ittsubjectState.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/GetAllCountriesHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllCountriesHandler.cs new file mode 100644 index 000000000..4e136ba8a --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetAllCountriesHandler.cs @@ -0,0 +1,21 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetAllCountriesHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(GetAllCountriesQuery query, IOrganizationServiceAsync organizationService) + { + var queryExpression = new QueryExpression() + { + EntityName = dfeta_country.EntityLogicalName, + ColumnSet = new ColumnSet( + dfeta_country.Fields.dfeta_name, + dfeta_country.Fields.dfeta_Value) + }; + var response = await organizationService.RetrieveMultipleAsync(queryExpression); + return response.Entities.Select(e => e.ToEntity()).ToArray(); + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInductionByContactIdHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInductionByContactIdHandler.cs index bbbc545de..aca70f270 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInductionByContactIdHandler.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInductionByContactIdHandler.cs @@ -35,7 +35,8 @@ public async Task ExecuteAsync(GetActiveInductionByContactIdQue dfeta_inductionperiod.Fields.dfeta_StartDate, dfeta_inductionperiod.Fields.dfeta_EndDate, dfeta_inductionperiod.Fields.dfeta_Numberofterms, - dfeta_inductionperiod.Fields.dfeta_AppropriateBodyId + dfeta_inductionperiod.Fields.dfeta_AppropriateBodyId, + dfeta_inductionperiod.PrimaryIdAttribute, }); inductionPeriodLink.EntityAlias = dfeta_inductionperiod.EntityLogicalName; diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInitialTeacherTrainingsByContactIdHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInitialTeacherTrainingsByContactIdHandler.cs new file mode 100644 index 000000000..47a6f50f3 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/GetInitialTeacherTrainingsByContactIdHandler.cs @@ -0,0 +1,29 @@ +using Microsoft.PowerPlatform.Dataverse.Client; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class GetInitialTeacherTrainingsByContactIdHandler : ICrmQueryHandler +{ + public async Task ExecuteAsync(GetActiveInitialTeacherTrainingsByContactIdQuery queryItt, IOrganizationServiceAsync organizationService) + { + var filter = new FilterExpression(); + filter.AddCondition(dfeta_initialteachertraining.Fields.dfeta_PersonId, ConditionOperator.Equal, queryItt.ContactId); + filter.AddCondition(dfeta_initialteachertraining.Fields.StateCode, ConditionOperator.Equal, dfeta_initialteachertrainingState.Active); + + var query = new QueryExpression(dfeta_initialteachertraining.EntityLogicalName) + { + ColumnSet = new ColumnSet(new string[] { + dfeta_initialteachertraining.PrimaryIdAttribute, + dfeta_initialteachertraining.Fields.dfeta_Subject1Id, + dfeta_initialteachertraining.Fields.dfeta_Subject2Id, + dfeta_initialteachertraining.Fields.dfeta_Subject3Id, + }), + Criteria = filter + }; + var result = await organizationService.RetrieveMultipleAsync(query); + var itt = result.Entities.Select(entity => entity.ToEntity()); + return itt.ToArray(); + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionPeriodTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionPeriodTransactionalHandler.cs new file mode 100644 index 000000000..9126319b7 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionPeriodTransactionalHandler.cs @@ -0,0 +1,23 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class UpdateInductionPeriodTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(UpdateInductionPeriodTransactionalQuery query, RequestBuilder requestBuilder) + { + var updateResponse = requestBuilder.AddRequest(new UpdateRequest() + { + Target = new dfeta_inductionperiod() + { + Id = query.InductionPeriodId, + dfeta_AppropriateBodyId = query.AppropriateBodyId?.ToEntityReference(Account.EntityLogicalName), + dfeta_StartDate = query.InductionStartDate, + dfeta_EndDate = query.InductionEndDate, + } + }); + + return () => true; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionTransactionalHandler.cs new file mode 100644 index 000000000..2b2d992ee --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateInductionTransactionalHandler.cs @@ -0,0 +1,22 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class UpdateInductionTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(UpdateInductionTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new UpdateRequest() + { + Target = new dfeta_induction() + { + Id = query.InductionId, + dfeta_CompletionDate = query.CompletionDate, + dfeta_InductionStatus = query.InductionStatus, + } + }); + + return () => true; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionRecordTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionRecordTransactionalHandler.cs new file mode 100644 index 000000000..25016b7f6 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionRecordTransactionalHandler.cs @@ -0,0 +1,31 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class UpdateIntegrationTransactionRecordTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(UpdateIntegrationTransactionRecordTransactionalQuery query, RequestBuilder requestBuilder) + { + var createResponse = requestBuilder.AddRequest(new UpdateRequest() + { + Target = new dfeta_integrationtransactionrecord() + { + Id = query.IntegrationTransactionRecordId, + dfeta_IntegrationTransactionId = query.IntegrationTransactionId.ToEntityReference(dfeta_integrationtransaction.EntityLogicalName), + dfeta_id = query.Reference, + dfeta_PersonId = query.PersonId?.ToEntityReference(Contact.EntityLogicalName), + dfeta_InitialTeacherTrainingId = query.InitialTeacherTrainingId?.ToEntityReference(dfeta_initialteachertraining.EntityLogicalName), + dfeta_QualificationId = query.QualificationId?.ToEntityReference(dfeta_qualification.EntityLogicalName), + dfeta_InductionId = query.InductionId?.ToEntityReference(dfeta_induction.EntityLogicalName), + dfeta_InductionPeriodId = query.InductionPeriodId?.ToEntityReference(dfeta_inductionperiod.EntityLogicalName), + dfeta_DuplicateStatus = query.DuplicateStatus, + StatusCode = query.StatusCode, + dfeta_FailureMessage = query.FailureMessage, + dfeta_RowData = query.RowData + } + }); + + return () => true; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionTransactionalHandler.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionTransactionalHandler.cs new file mode 100644 index 000000000..5f2b7c92d --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Dqt/QueryHandlers/UpdateIntegrationTransactionTransactionalHandler.cs @@ -0,0 +1,26 @@ +using Microsoft.Xrm.Sdk.Messages; +using TeachingRecordSystem.Core.Dqt.Queries; + +namespace TeachingRecordSystem.Core.Dqt.QueryHandlers; + +public class UpdateIntegrationTransactionTransactionalHandler : ICrmTransactionalQueryHandler +{ + public Func AppendQuery(UpdateIntegrationTransactionTransactionalQuery query, RequestBuilder requestBuilder) + { + var updateResponse = requestBuilder.AddRequest(new UpdateRequest() + { + Target = new dfeta_integrationtransaction() + { + Id = query.IntegrationTransactionId, + dfeta_EndDate = query.EndDate, + dfeta_TotalCount = query.TotalCount, + dfeta_SuccessCount = query.SuccessCount, + dfeta_DuplicateCount = query.DuplicateCount, + dfeta_FailureCount = query.FailureCount, + dfeta_FailureMessage = query.FailureMessage, + } + }); + + return () => true; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EWCWalesImportJob.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EWCWalesImportJob.cs new file mode 100644 index 000000000..50083779f --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EWCWalesImportJob.cs @@ -0,0 +1,142 @@ +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Azure.Storage.Blobs.Specialized; +using Microsoft.Extensions.Logging; +using TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +namespace TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +public class EwcWalesImportJob(BlobServiceClient blobServiceClient, InductionImporter inductionImporter, QtsImporter qtsImporter, ILogger logger) +{ + private const string ProcessedFolder = "ewc/processed"; + private const string PickupFolder = "ewc/pickup"; + private const string StorageContainer = "dqt-integrations"; + public const string JobSchedule = "0 8 * * *"; + + private async Task GetImportFilesAsync(CancellationToken cancellationToken) + { + var blobContainerClient = blobServiceClient.GetBlobContainerClient(StorageContainer); + var fileNames = new List(); + var resultSegment = blobContainerClient.GetBlobsByHierarchyAsync(prefix: PickupFolder, delimiter: "", cancellationToken: cancellationToken).AsPages(); + + // Enumerate the blobs returned for each page. + await foreach (Azure.Page blobPage in resultSegment) + { + foreach (BlobHierarchyItem blobhierarchyItem in blobPage.Values) + { + if(blobhierarchyItem.IsBlob) + { + fileNames.Add(blobhierarchyItem.Blob.Name); + } + } + } + + return fileNames.ToArray(); + } + + private async Task GetFileNamesAsync(CancellationToken cancellationToken) + { + var blobContainerClient = blobServiceClient.GetBlobContainerClient(StorageContainer); + var fileNames = new List(); + var resultSegment = blobContainerClient.GetBlobsByHierarchyAsync(prefix: "", delimiter: PickupFolder, cancellationToken: cancellationToken).AsPages(); + + // Enumerate the blobs returned for each page. + await foreach (Azure.Page blobPage in resultSegment) + { + foreach (BlobHierarchyItem blobhierarchyItem in blobPage.Values) + { + fileNames.Add(blobhierarchyItem.Blob.Name); + } + } + + return fileNames.ToArray(); + } + + public async Task GetDownloadStreamAsync(string fileName) + { + BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(StorageContainer); + BlobClient blobClient = containerClient.GetBlobClient($"{fileName}"); + var streamingResult = await blobClient.DownloadStreamingAsync(); + return streamingResult.Value.Content; + } + + public async Task ImportAsync(string fileName, StreamReader reader) + { + var fileNameParts = fileName.Split("/"); + var fileNameWithoutFolder = fileNameParts.Last(); + + if (TryGetImportFileType(fileNameWithoutFolder, out var importType)) + { + + if (importType == EwcWalesImportFileType.Induction) + { + var result = await inductionImporter.ImportAsync(reader, fileNameWithoutFolder); + return result.IntegrationTransactionId; + } + else + { + var result = await qtsImporter.ImportAsync(reader, fileNameWithoutFolder); + return result.IntegrationTransactionId; + } + } + else + { + //file not recognised + logger.LogError("Import filename must begin with IND or QTS"); + + return null; + } + } + + public async Task ExecuteAsync(CancellationToken cancellationToken) + { + foreach (var file in await GetImportFilesAsync(cancellationToken)) + { + using (var downloadStream = await GetDownloadStreamAsync(file)) + using (var reader = new StreamReader(downloadStream)) + { + await ImportAsync(file, reader); + await ArchiveFileAsync(file, cancellationToken); + } + } + } + + public async Task ArchiveFileAsync(string fileName, CancellationToken cancellationToken) + { + var blobContainerClient = blobServiceClient.GetBlobContainerClient(StorageContainer); + var sourceBlobClient = blobContainerClient.GetBlobClient(fileName); + var fileNameParts = fileName.Split("/"); + var fileNameWithoutFolder = fileNameParts.Last(); + var targetFileName = $"{ProcessedFolder}/{fileNameWithoutFolder}"; + + // Acquire a lease to prevent another client modifying the source blob + var lease = sourceBlobClient.GetBlobLeaseClient(); + await lease.AcquireAsync(TimeSpan.FromSeconds(60), cancellationToken: cancellationToken); + + var targetBlobClient = blobContainerClient.GetBlobClient(targetFileName); + var copyOperation = await targetBlobClient.StartCopyFromUriAsync(sourceBlobClient.Uri, cancellationToken: cancellationToken); + await copyOperation.WaitForCompletionAsync(); + + // Release the lease + var sourceProperties = await sourceBlobClient.GetPropertiesAsync(cancellationToken: cancellationToken); + if (sourceProperties.Value.LeaseState == LeaseState.Leased) + { + await lease.ReleaseAsync(cancellationToken: cancellationToken); + } + + // Now remove the original blob + await sourceBlobClient.DeleteAsync(DeleteSnapshotsOption.IncludeSnapshots, cancellationToken: cancellationToken); + } + + public bool TryGetImportFileType(string fileName, out EwcWalesImportFileType? fileType) + { + fileType = fileName switch + { + var f when f.StartsWith("Ind", StringComparison.OrdinalIgnoreCase) => EwcWalesImportFileType.Induction, + var f when f.StartsWith("QTS", StringComparison.OrdinalIgnoreCase) => EwcWalesImportFileType.Qualification, + _ => null + }; + + return fileType is not null; + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesImportFileType.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesImportFileType.cs new file mode 100644 index 000000000..7597e5d6b --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesImportFileType.cs @@ -0,0 +1,7 @@ +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public enum EwcWalesImportFileType +{ + Induction = 1, + Qualification = 2 +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesInductionImportData.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesInductionImportData.cs new file mode 100644 index 000000000..b89d45201 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesInductionImportData.cs @@ -0,0 +1,38 @@ +using CsvHelper.Configuration.Attributes; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public record EwcWalesInductionImportData +{ + [Name("REFERENCE_NO")] + public required string ReferenceNumber { get; set; } + + [Name("FIRST_NAME")] + public required string FirstName { get; set; } + + [Name("LAST_NAME")] + public required string LastName { get; set; } + + [Name("DATE_OF_BIRTH")] + public required string DateOfBirth { get; set; } + + [Name("START_DATE")] + public required string StartDate { get; set; } + + [Name("PASS_DATE")] + public required string PassedDate { get; set; } + + [Name("FAIL_DATE")] + public required string FailDate { get; set; } + + [Name("EMPLOYER_NAME")] + public required string EmployerName { get; set; } + + [Name("EMPLOYER_CODE")] + public required string EmployerCode { get; set; } + + [Name("IND_STATUS_NAME")] + public required string InductionStatusName { get; set; } +} + + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesMatchStatus.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesMatchStatus.cs new file mode 100644 index 000000000..a69e1a3b0 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesMatchStatus.cs @@ -0,0 +1,13 @@ +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public enum EwcWalesMatchStatus +{ + NoMatch, + MultipleTrnMatched, + TrnAndDateOfBirthMatchFailed, + TeacherInactive, + NoAssociatedQts, + TeacherHasQts, + OneMatch, + MultipleMatchesFound, +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesQTSFileImportData.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesQTSFileImportData.cs new file mode 100644 index 000000000..ea8f896d3 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/EwcWalesQTSFileImportData.cs @@ -0,0 +1,98 @@ +using CsvHelper.Configuration.Attributes; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class EwcWalesQtsFileImportData +{ + [Name("QTS_REF_NO")] + public required string QtsRefNo { get; set; } + + [Name("FORENAME")] + public required string Forename { get; set; } + + [Name("SURNAME")] + public required string Surname { get; set; } + + [Name("DATE_OF_BIRTH")] + public required string DateOfBirth { get; set; } + + [Name("QTS_STATUS")] + public required string QtsStatus { get; set; } + + [Name("QTS_DATE")] + public required string QtsDate { get; set; } + + [Name("ITT StartMONTH")] + public required string IttStartMonth { get; set; } + + [Name("ITT START YY")] + public required string IttStartYear { get; set; } + + [Name("ITT End Date")] + public required string IttEndDate { get; set; } + + [Name("ITT Course Length")] + public required string ITTCourseLength { get; set; } + + [Name("ITT Estab LEA code")] + public required string IttEstabLeaCode { get; set; } + + [Name("ITT Estab Code")] + public required string IttEstabCode { get; set; } + + [Name("ITT Qual Code")] + public required string IttQualCode { get; set; } + + [Name("ITT Class Code")] + public required string IttClassCode { get; set; } + + [Name("ITT Subject Code 1")] + public required string IttSubjectCode1 { get; set; } + + [Name("ITT Subject Code 2")] + public required string IttSubjectCode2 { get; set; } + + [Name("ITT Min Age Range")] + public required string IttMinAgeRange { get; set; } + + [Name("ITT Max Age Range")] + public required string IttMaxAgeRange { get; set; } + + [Name("ITT Min Sp Age Range")] + public required string IttMinSpAgeRange { get; set; } + + [Name("ITT Max Sp Age Range")] + public required string IttMaxSpAgeRange { get; set; } + + [Name("ITT Course Length")] + public required string PqCourseLength { get; set; } + + [Name("PQ Year of Award")] + public required string PqYearOfAward { get; set; } + + [Name("COUNTRY")] + public required string Country { get; set; } + + [Name("PQ Estab Code")] + public required string PqEstabCode { get; set; } + + [Name("PQ Qual Code")] + public required string PqQualCode { get; set; } + + [Name("HONOURS")] + public required string Honours { get; set; } + + [Name("PQ Class Code")] + public required string PqClassCode { get; set; } + + [Name("PQ Subject Code 1")] + public required string PqSubjectCode1 { get; set; } + + [Name("PQ Subject Code 2")] + public required string PqSubjectCode2 { get; set; } + + [Name("PQ Subject Code 3")] + public required string PqSubjectCode3 { get; set; } +} + + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImportResult.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImportResult.cs new file mode 100644 index 000000000..e3e67f285 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImportResult.cs @@ -0,0 +1,4 @@ +namespace TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +public record InductionImportResult(int TotalCount, int SuccessCount, int DuplicateCount, int FailureCount, string FailureMessage, Guid IntegrationTransactionId); + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImporter.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImporter.cs new file mode 100644 index 000000000..087b625b4 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/InductionImporter.cs @@ -0,0 +1,481 @@ +using System.Globalization; +using System.Text; +using CsvHelper; +using Microsoft.Extensions.Logging; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt; +using TeachingRecordSystem.Core.Dqt.Queries; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class InductionImporter(ICrmQueryDispatcher crmQueryDispatcher, ILogger logger) +{ + private const string DATE_FORMAT = "dd/MM/yyyy"; + + public async Task ImportAsync(StreamReader csvReaderStream, string fileName) + { + using (var csv = new CsvReader(csvReaderStream, CultureInfo.InvariantCulture)) + { + var integrationJob = new CreateIntegrationTransactionQuery() + { + StartDate = DateTime.Now, + TypeId = (int)dfeta_IntegrationInterface.GTCWalesImport, + FileName = fileName + }; + var integrationId = await crmQueryDispatcher.ExecuteQueryAsync(integrationJob); + + var records = csv.GetRecords().ToList(); + var validationMessages = new List(); + + var totalRowCount = 0; + var successCount = 0; + var duplicateRowCount = 0; + var failureRowCount = 0; + var failureMessage = new StringBuilder(); + foreach (var row in records) + { + totalRowCount++; + Guid? personId = null; + Guid? inductionId = null; + Guid? inductionPeriodId = null; + Guid itrId = Guid.NewGuid(); + var itrFailureMessage = new StringBuilder(); + using var rowTransaction = crmQueryDispatcher.CreateTransactionRequestBuilder(); + + try + { + var lookupData = await GetLookupDataAsync(row); + var validationFailures = Validate(row, lookupData); + personId = lookupData.Person?.ContactId; + inductionId = lookupData.Induction?.Id; + + //append non processable errors to list of failures that will be a line in + //the IntegrationTransaction (job) failuremessage field. + if (validationFailures.Errors.Any()) + { + failureRowCount++; + foreach (var error in validationFailures.Errors) + { + failureMessage.AppendLine(error); + itrFailureMessage.AppendLine(error); + } + + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + } + else + { + // if contact does not have an associated induction - create one with the data from the imported file row + // else if there is an associated induction update status & passed date with the data from the imported file row + if (!inductionId.HasValue) + { + inductionId = Guid.NewGuid(); + var createInductionQuery = new CreateInductionTransactionalQuery() + { + Id = inductionId.Value, + ContactId = personId!.Value, + StartDate = DateTime.ParseExact(row.StartDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + CompletionDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionStatus = dfeta_InductionStatus.PassedinWales + }; + rowTransaction.AppendQuery(createInductionQuery); + } + else + { + var updateInductionQuery = new UpdateInductionTransactionalQuery() + { + InductionId = inductionId.Value, + CompletionDate = !string.IsNullOrEmpty(row.PassedDate) ? DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None) : null, + InductionStatus = dfeta_InductionStatus.PassedinWales + }; + rowTransaction.AppendQuery(updateInductionQuery); + } + + //if an induction period is not found - create one + //else if an induction period is found - update it + if (lookupData.InductionPeriod is null) + { + inductionPeriodId = Guid.NewGuid(); + var queryInductionPeriod = new CreateInductionPeriodTransactionalQuery() + { + Id = inductionPeriodId.Value, + InductionId = inductionId.Value, + AppropriateBodyId = lookupData.OrganisationId, + InductionStartDate = DateTime.ParseExact(row.StartDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionEndDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + }; + rowTransaction.AppendQuery(queryInductionPeriod); + } + else + { + inductionPeriodId = lookupData.InductionPeriod.dfeta_inductionperiodId; + var updateInduction = new UpdateInductionTransactionalQuery() + { + InductionId = inductionId!.Value, + CompletionDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionStatus = lookupData.Induction!.dfeta_InductionStatus!.Value + }; + rowTransaction.AppendQuery(updateInduction); + + var updateInductionPeriodQuery = new UpdateInductionPeriodTransactionalQuery() + { + InductionPeriodId = inductionPeriodId!.Value, + AppropriateBodyId = lookupData.OrganisationId, + InductionStartDate = lookupData.InductionPeriod.dfeta_StartDate, + InductionEndDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + }; + rowTransaction.AppendQuery(updateInductionPeriodQuery); + } + + //soft validation errors can be appended to the IntegrationTransactionRecord Failure message + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + + //increase failurecount if row is processable or if there are validation failures + //else increase success counter + if (validationFailures.ValidationFailures.Any() || validationFailures.Errors.Any()) + { + failureRowCount++; + } + else + { + successCount++; + } + } + + //create ITR row with status of import row + var createIntegrationTransactionRecord = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationId, + Reference = totalRowCount.ToString(), + ContactId = personId, + InitialTeacherTrainingId = null, + QualificationId = null, + InductionId = inductionId, + InductionPeriodId = inductionPeriodId, + DuplicateStatus = null, + FailureMessage = itrFailureMessage.ToString(), + StatusCode = string.IsNullOrEmpty(itrFailureMessage.ToString()) ? dfeta_integrationtransactionrecord_StatusCode.Success : dfeta_integrationtransactionrecord_StatusCode.Fail, + RowData = ConvertToCSVString(row), + FileName = fileName + }; + rowTransaction.AppendQuery(createIntegrationTransactionRecord); + + //update IntegrationTransaction so that it's always up to date with + //counts of rows + var updateIntegrationTransactionQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = null, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = 0, + FailureCount = failureRowCount, + FailureMessage = itrFailureMessage.ToString() + }; + rowTransaction.AppendQuery(updateIntegrationTransactionQuery); + await rowTransaction.ExecuteAsync(); + } + catch (Exception e) + { + failureRowCount++; + logger.LogError(e.ToString()); + } + } + + var updateIntTrxQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = DateTime.Now, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = duplicateRowCount, + FailureCount = failureRowCount, + FailureMessage = failureMessage.ToString() + }; + + using var txn = crmQueryDispatcher.CreateTransactionRequestBuilder(); + txn.AppendQuery(updateIntTrxQuery); + await txn.ExecuteAsync(); + + return new InductionImportResult(totalRowCount, successCount, duplicateRowCount, failureRowCount, failureMessage.ToString(), integrationId); + } + } + + public string ConvertToCSVString(EwcWalesInductionImportData row) + { + using (var writer = new StringWriter()) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecord(row); + csv.NextRecord(); + return writer.ToString(); + } + } + + public async Task GetLookupDataAsync(EwcWalesInductionImportData row) + { + var (personMatchStatus, contact) = await FindMatchingTeacherRecordAsync(row); + var (orgMatchStatus, organisationId) = await FindMatchingOrganisationsRecordAsync(row.EmployerCode); + InductionLookupResult? inductionMatchStatus = null; + dfeta_induction? induction = null; + dfeta_inductionperiod? inductionPeriod = null; + InductionPeriodLookupResult? inductionPeriodMatchStatus = null; + if (contact != null) + { + var (indStatus, ind) = await FindActiveInductionByContactAsync(contact.ContactId!.Value); + inductionMatchStatus = indStatus; + induction = ind?.Induction; + + if (ind?.InductionPeriods?.Length == 1) + { + inductionPeriodMatchStatus = InductionPeriodLookupResult.OneMatch; + inductionPeriod = ind.InductionPeriods.First(); + } + else if (ind?.InductionPeriods?.Length > 1) + { + inductionPeriodMatchStatus = InductionPeriodLookupResult.MultipleMatchesFound; + inductionPeriod = null; + } + } + + var lookupData = new InductionImportLookupData + { + Person = contact, + PersonMatchStatus = personMatchStatus, + Induction = induction, + InductionMatchStatus = inductionMatchStatus, + InductionPeriod = inductionPeriod, + InductionPeriodMatchStatus = inductionPeriodMatchStatus, + OrganisationMatchStatus = orgMatchStatus, + OrganisationId = organisationId + }; + return lookupData; + } + + public (List ValidationFailures, List Errors) Validate(EwcWalesInductionImportData row, InductionImportLookupData lookups) + { + var validationFailures = new List(); + var errors = new List(); + + //ReferenceNumber/Trn + if (String.IsNullOrEmpty(row.ReferenceNumber)) + { + errors.Add("Missing Reference No"); + } + + //Date Of birth + if (String.IsNullOrEmpty(row.DateOfBirth)) + { + errors.Add("Missing Date of Birth"); + } + else + { + if (!DateOnly.TryParseExact(row.DateOfBirth, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Date of Birth"); + } + } + + //InductionPassedDate + if (String.IsNullOrEmpty(row.StartDate)) + { + errors.Add("Missing Induction Start date"); + } + else + { + if (!DateOnly.TryParseExact(row.StartDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Induction start date"); + } + } + + //InductionPassedDate + if (String.IsNullOrEmpty(row.PassedDate)) + { + errors.Add("Missing Induction passed date"); + } + else + { + if (!DateOnly.TryParseExact(row.PassedDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Induction passed date"); + } + } + + switch (lookups.PersonMatchStatus) + { + case ContactLookupResult.NoAssociatedQts: + break; + case ContactLookupResult.NoMatch: + errors.Add($"Teacher with TRN {row.ReferenceNumber} was not found."); + break; + case ContactLookupResult.TrnAndDateOfBirthMatchFailed: + errors.Add($"For TRN {row.ReferenceNumber} Date of Birth does not match with the existing record."); + break; + case ContactLookupResult.TeacherHasQts: + errors.Add($"Teacher with TRN {row.ReferenceNumber} has QTS already."); + break; + } + + if (!string.IsNullOrEmpty(row.EmployerCode)) + { + switch (lookups.OrganisationMatchStatus) + { + case OrganisationLookupResult.NoMatch: + validationFailures.Add($"Organisation with Induction Body Code {row.EmployerCode} was not found."); + break; + case OrganisationLookupResult.MultipleMatchesFound: + validationFailures.Add($"Multiple organisations with Induction Body Code {row.EmployerCode} found."); + break; + } + } + + //if teacher is exempt via set and doesn't have an induction + if (lookups.InductionMatchStatus == InductionLookupResult.NoMatch && lookups.Person != null && lookups.Person!.dfeta_qtlsdate.HasValue) + { + errors.Add("may need to update either/both the 'TRA induction status' and 'Overall induction status"); + } + + //if teacher is exempt via set and inductionstatus is not in permitted updatabe statuses + if (lookups.InductionMatchStatus == InductionLookupResult.OneMatch && lookups.Person != null && lookups.Person!.dfeta_qtlsdate.HasValue) + { + errors.Add("may need to update either/both the 'TRA induction status' and 'Overall induction status'"); + } + + if (lookups.Induction != null) + { + switch (lookups.Induction.GetAttributeValue(dfeta_induction.Fields.dfeta_InductionStatus).Value) + { + case (int)dfeta_InductionStatus.Pass: + case (int)dfeta_InductionStatus.PassedinWales: + case (int)dfeta_InductionStatus.Exempt: + case (int)dfeta_InductionStatus.Fail: + case (int)dfeta_InductionStatus.FailedinWales: + errors.Add($"Teacher with TRN {row.ReferenceNumber} completed induction already."); + break; + } + } + + return (validationFailures, errors); + } + public async Task<(OrganisationLookupResult, Guid? OrganisationId)> FindMatchingOrganisationsRecordAsync(string OrgNumber) + { + var query = new FindActiveOrganisationsByAccountNumberQuery(OrgNumber); + var results = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (results.Length == 0) + { + return (OrganisationLookupResult.NoMatch, null); + } + + if (results.Length > 1) + { + return (OrganisationLookupResult.MultipleMatchesFound, null); + } + + var organisationId = results.First().Id; + return (OrganisationLookupResult.OneMatch, organisationId); + } + + public async Task<(InductionLookupResult, InductionRecord?)> FindActiveInductionByContactAsync(Guid personId) + { + var query = new GetActiveInductionByContactIdQuery(personId); + var result = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (result is null) + { + return (InductionLookupResult.NoMatch, null); + } + + return (InductionLookupResult.OneMatch, result); + } + + public async Task<(ContactLookupResult, Contact? contact)> FindMatchingTeacherRecordAsync(EwcWalesInductionImportData item) + { + var contact = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveContactByTrnQuery(item.ReferenceNumber, + new ColumnSet( + Contact.Fields.dfeta_TRN, + Contact.Fields.BirthDate, + Contact.Fields.dfeta_QTSDate, + Contact.Fields.dfeta_qtlsdate))); + + if (contact == null) + { + return (ContactLookupResult.NoMatch, null); + } + + if (DateOnly.TryParseExact(item.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dob) && contact!.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false) != dob) + { + return (ContactLookupResult.TrnAndDateOfBirthMatchFailed, null); + } + + var qtsRegistrations = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveQtsRegistrationsByContactIdsQuery( + new[] { contact!.ContactId!.Value }, + new ColumnSet( + dfeta_qtsregistration.Fields.dfeta_PersonId, + dfeta_qtsregistration.Fields.dfeta_QTSDate, + dfeta_qtsregistration.Fields.dfeta_TeacherStatusId) + ) + ); + + if (qtsRegistrations[contact.Id].Length > 0) + { + return (ContactLookupResult.TeacherHasQts, contact); + } + else + { + return (ContactLookupResult.NoAssociatedQts, contact); + } + } + + public class InductionImportLookupData + { + public required Contact? Person { get; set; } + public required ContactLookupResult? PersonMatchStatus { get; set; } + public required dfeta_induction? Induction { get; set; } + public required InductionLookupResult? InductionMatchStatus { get; set; } + public required dfeta_inductionperiod? InductionPeriod { get; set; } + public required InductionPeriodLookupResult? InductionPeriodMatchStatus { get; set; } + public required Guid? OrganisationId { get; set; } + public required OrganisationLookupResult? OrganisationMatchStatus { get; set; } + } +} + +public enum InductionLookupResult +{ + NoMatch, + OneMatch +} + +public enum ContactLookupResult +{ + NoMatch, + TrnAndDateOfBirthMatchFailed, + NoAssociatedQts, + TeacherHasQts +} + +public enum InductionPeriodLookupResult +{ + NoMatch, + OneMatch, + MultipleMatchesFound +} + +public enum OrganisationLookupResult +{ + NoMatch, + OneMatch, + MultipleMatchesFound +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImportResult.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImportResult.cs new file mode 100644 index 000000000..168f43101 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImportResult.cs @@ -0,0 +1,3 @@ +namespace TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +public record QtsImportResult(int TotalCount, int SuccessCount, int DuplicateCount, int FailureCount, string FailureMessage, Guid IntegrationTransactionId); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImporter.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImporter.cs new file mode 100644 index 000000000..bfde49a5d --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EWCWalesImport/QtsImporter.cs @@ -0,0 +1,672 @@ +using System.Globalization; +using System.Text; +using CsvHelper; +using Microsoft.Extensions.Logging; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt; +using TeachingRecordSystem.Core.Dqt.Queries; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class QtsImporter(ICrmQueryDispatcher crmQueryDispatcher, ReferenceDataCache cache, ILogger logger) +{ + private const string DATE_FORMAT = "dd/MM/yyyy"; + + public async Task ImportAsync(StreamReader csvReaderStream, string fileName) + { + using var csv = new CsvReader(csvReaderStream, CultureInfo.InvariantCulture); + var records = csv.GetRecords().ToList(); + var totalRowCount = 0; + var successCount = 0; + var duplicateRowCount = 0; + var failureRowCount = 0; + var failureMessage = new StringBuilder(); + + var integrationJob = new CreateIntegrationTransactionQuery() + { + StartDate = DateTime.Now, + TypeId = (int)dfeta_IntegrationInterface.GTCWalesImport, + FileName = fileName + }; + var integrationId = await crmQueryDispatcher.ExecuteQueryAsync(integrationJob); + + foreach (var row in records) + { + totalRowCount++; + var qualificationId = Guid.NewGuid(); + var ittId = Guid.NewGuid(); + var qtsRegistrationId = Guid.NewGuid(); + Guid? inductionId = null; + var itrFailureMessage = new StringBuilder(); + using var rowTransaction = crmQueryDispatcher.CreateTransactionRequestBuilder(); + + try + { + var lookupData = await GetLookupDataAsync(row); + var validationFailures = Validate(row, lookupData); + + //append non processable errors to list of failures that will be a line in + //the IntegrationTransaction (job) failuremessage field. + if (validationFailures.Errors.Any()) + { + foreach (var error in validationFailures.Errors) + { + failureMessage.AppendLine(error); + itrFailureMessage.AppendLine(error); + } + } + else + { + //Create ITT + var ittQuery = new CreateInitialTeacherTrainingTransactionalQuery() + { + Id = ittId, + ContactId = lookupData.PersonId!.Value, + ITTQualificationId = lookupData.IttQualificationId, + CountryId = lookupData.PQCountryId.HasValue ? lookupData.PQCountryId : null, + Result = dfeta_ITTResult.Pass // by definition of GTCW everybody should have passed training + }; + rowTransaction.AppendQuery(ittQuery); + + //Create Qualification + var qualificationQuery = new CreateHeQualificationTransactionalQuery() + { + Id = qualificationId, + ContactId = lookupData.PersonId.Value, + HECountryId = lookupData.PQCountryId, + HECourseLength = row.PqCourseLength, + HEEstablishmentId = lookupData.PqEstablishmentId, + HEQualificationId = lookupData.PQHEQualificationId, + HEClassDivision = lookupData.ClassDivision, + HESubject1id = lookupData.PQSubject1Id, + HESubject2id = lookupData.PQSubject2Id, + HESubject3id = lookupData.PQSubject3Id, + Type = dfeta_qualification_dfeta_Type.HigherEducation + }; + var getQualificationQueryResponse = rowTransaction.AppendQuery(qualificationQuery); + + //Qts + var qtsQuery = new CreateQtsRegistrationTransactionalQuery() + { + Id = qtsRegistrationId, + ContactId = lookupData.PersonId.Value, + TeacherStatusId = lookupData.TeacherStatusId!.Value, + QtsDate = DateTime.ParseExact(row.QtsDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None) + }; + rowTransaction.AppendQuery(qtsQuery); + + //soft validation errors can be appended to the IntegrationTransactionRecord Failure message + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + + if (row.QtsStatus == "67") + { + inductionId = Guid.NewGuid(); + var induction = new CreateInductionTransactionalQuery() + { + Id = inductionId.Value, + ContactId = lookupData.PersonId.Value, + StartDate = null, + CompletionDate = null, + InductionStatus = dfeta_InductionStatus.RequiredtoComplete + }; + rowTransaction.AppendQuery(induction); + } + } + + //create ITR row with status of import row + var createIntegrationTransactionRecord = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationId, + Reference = totalRowCount.ToString(), + ContactId = lookupData.PersonId, + InitialTeacherTrainingId = ittId, + QualificationId = qualificationId, + InductionId = inductionId, + InductionPeriodId = null, + DuplicateStatus = null, + FailureMessage = itrFailureMessage.ToString(), + StatusCode = string.IsNullOrEmpty(itrFailureMessage.ToString()) ? dfeta_integrationtransactionrecord_StatusCode.Success : dfeta_integrationtransactionrecord_StatusCode.Fail, + RowData = ConvertToCsvString(row), + FileName = fileName + }; + rowTransaction.AppendQuery(createIntegrationTransactionRecord); + + //update IntegrationTransaction so that it's always up to date with + //counts of rows + var updateIntegrationTransactionQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = null, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = 0, + FailureCount = failureRowCount, + FailureMessage = itrFailureMessage.ToString() + }; + rowTransaction.AppendQuery(updateIntegrationTransactionQuery); + + + await rowTransaction.ExecuteAsync(); + + //increase failurecount if row is processable or if there are validation failures + //else increase success counter + if (validationFailures.ValidationFailures.Any() || validationFailures.Errors.Any()) + { + failureRowCount++; + } + else + { + successCount++; + } + } + catch (Exception e) + { + failureRowCount++; + logger.LogError(e.ToString()); + } + } + + var updateIntTrxQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = DateTime.Now, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = duplicateRowCount, + FailureCount = failureRowCount, + FailureMessage = failureMessage.ToString() + }; + + using var txn = crmQueryDispatcher.CreateTransactionRequestBuilder(); + txn.AppendQuery(updateIntTrxQuery); + await txn.ExecuteAsync(); + + + return new QtsImportResult(totalRowCount, successCount, duplicateRowCount, failureRowCount, failureMessage.ToString(), integrationId); + } + + public string ConvertToCsvString(EwcWalesQtsFileImportData row) + { + using (var writer = new StringWriter()) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecord(row); + csv.NextRecord(); + return writer.ToString(); + } + } + + public async Task GetLookupDataAsync(EwcWalesQtsFileImportData row) + { + //contact + var (personMatchStatus, personId) = await FindMatchingTeacherRecordAsync(row); + var (ittEstabCodeStatus, ittEstabCodeId) = await FindMatchingOrganisationsRecordAsync(row.IttEstabCode); + var (ittQualCodeStatus, ittQualificationId) = await GetIttQualificationAsync(row.IttQualCode); + var (ittSubjectCode1MatchStatus, ittSubjectCode1Id) = await FindIttSubjectAsync(row.IttSubjectCode1); + var (ittSubjectCode2MatchStatus, ittSubjectCode2Id) = await FindIttSubjectAsync(row.IttSubjectCode2); + var (iqEstabCodeMatchStatus, iqEstaId) = await FindMatchingOrganisationsRecordAsync(row.PqEstabCode); + var (pqCountryMatchStatus, pqCountryId) = await GetMatchingCountryAsync(row.Country); + var (heQualificationMatchStatus, heQualificationId) = await GetHEQualificationAsync(row.PqQualCode); + var (pqSubjectCode1MatchStatus, pqSubjectCode1Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode1); + var (pqSubjectCode2MatchStatus, pqSubjectCode2Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode2); + var (pqSubjectCode3MatchStatus, pqSubjectCode3Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode3); + var (teacherStatusMatchStatus, teacherStatusId) = await GetTeacherStatusAsync(row.QtsStatus); + var heClassDivision = GetHEClassDivision(row.PqClassCode); + + var lookupData = new QtsImportLookupData + { + PersonId = personId, + PersonMatchStatus = personMatchStatus, + IttEstabCodeId = ittEstabCodeId, + IttEstabCodeMatchStatus = ittEstabCodeStatus, + IttQualificationId = ittQualificationId, + IttQualificationMatchStatus = ittQualCodeStatus, + IttSubject1Id = ittSubjectCode1Id, + IttSubject1MatchStatus = ittSubjectCode1MatchStatus, + IttSubject2Id = ittSubjectCode2Id, + IttSubject2MatchStatus = ittSubjectCode2MatchStatus, + PqEstablishmentId = iqEstaId, + PqEstablishmentMatchStatus = iqEstabCodeMatchStatus, + PQCountryId = pqCountryId, + PQCountryMatchStatus = pqCountryMatchStatus, + PQHEQualificationId = heQualificationId, + PQHEQualificationMatchStatus = heQualificationMatchStatus, + PQSubject1Id = pqSubjectCode1Id, + PQSubject1MatchStatus = pqSubjectCode1MatchStatus, + PQSubject2Id = pqSubjectCode2Id, + PQSubject2MatchStatus = pqSubjectCode2MatchStatus, + PQSubject3Id = pqSubjectCode3Id, + PQSubject3MatchStatus = pqSubjectCode3MatchStatus, + TeacherStatusId = teacherStatusId, + TeacherStatusMatchStatus = teacherStatusMatchStatus, + ClassDivision = heClassDivision + }; + return lookupData; + } + + public (List ValidationFailures, List Errors) Validate(EwcWalesQtsFileImportData row, QtsImportLookupData lookups) + { + var validationFailures = new List(); + var errors = new List(); + + //QTS REF + if (string.IsNullOrEmpty(row.QtsRefNo)) + { + errors.Add("Missing QTS Ref Number"); + } + + //Date Of birth + if (string.IsNullOrEmpty(row.DateOfBirth)) + { + errors.Add("Missing Date of Birth"); + } + else if (!DateOnly.TryParseExact(row.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add($"Validation Failed: Invalid Date of Birth {row.DateOfBirth}"); + } + + //QTS Date + if (string.IsNullOrEmpty(row.QtsDate)) + { + errors.Add("Misssing QTS Date"); + } + else if (!DateOnly.TryParseExact(row.QtsDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add($"Validation Failed: Invalid QTS Date {row.QtsDate}"); + } + + + switch (lookups.PersonMatchStatus) + { + case EwcWalesMatchStatus.NoAssociatedQts: + break; + case EwcWalesMatchStatus.NoMatch: + errors.Add($"Teacher with TRN {row.QtsRefNo} was not found."); + break; + case EwcWalesMatchStatus.TrnAndDateOfBirthMatchFailed: + errors.Add($"For TRN {row.QtsRefNo} Date of Birth does not match with the existing record."); //No Test + break; + case EwcWalesMatchStatus.MultipleTrnMatched: + errors.Add($"TRN {row.QtsRefNo} was matched to more than one record in the system."); + break; + case EwcWalesMatchStatus.TeacherInactive: + errors.Add($"Teacher with TRN {row.QtsRefNo} is inactive."); //No Test + break; + case EwcWalesMatchStatus.TeacherHasQts: + errors.Add($"Teacher with TRN {row.QtsRefNo} has QTS already."); + break; + } + + //IttEstabCode + if (!string.IsNullOrEmpty(row.IttEstabCode)) + { + if (lookups.IttEstabCodeMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Organisation with ITT Establishment Code {row.IttEstabCode} was not found."); + } + else if (lookups.IttEstabCodeMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple organisations with ITT Establishment Code {row.IttEstabCode} found."); + } + } + + // ITT Qualification + if (!string.IsNullOrEmpty(row.IttQualCode)) + { + if (lookups.IttQualificationMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT qualification with code {row.IttQualCode} was not found."); + } + else if (lookups.IttQualificationMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT qualifications with code {row.IttQualCode} found."); + } + } + + // IIT Subject 1 + if (!string.IsNullOrEmpty(row.IttSubjectCode1)) + { + if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT subject with code {row.IttSubjectCode1} was not found."); + } + else if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT subjects with code {row.IttSubjectCode1} found."); + } + } + + // IIT Subject 2 + if (!string.IsNullOrEmpty(row.IttSubjectCode2)) + { + if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT subject with code {row.IttSubjectCode2} was not found."); + } + else if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT subjects with code {row.IttSubjectCode2} found."); + } + } + + // PQ Establishment + if (!string.IsNullOrEmpty(row.PqEstabCode)) + { + if (lookups.PqEstablishmentMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Organisation with PQ Establishment Code {row.PqEstabCode} was not found."); + } + else if (lookups.PqEstablishmentMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple organisations with PQ Establishment Code {row.PqEstabCode} found."); + } + } + + // PQ Country + if (!string.IsNullOrEmpty(row.Country)) + { + if (lookups.PQCountryMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Country with PQ Country Code {row.Country} was not found."); + } + else if (lookups.PQCountryMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple countries with PQ Country Code {row.Country} found."); + } + } + + // PQ HE Qualification + if (!string.IsNullOrEmpty(row.PqQualCode)) + { + if (lookups.PQHEQualificationMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Qualification with PQ Qualification Code {row.PqQualCode} was not found."); + } + else if (lookups.PQHEQualificationMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple qualifications with PQ Qualification Code {row.PqQualCode} found."); + } + } + + // PQ Subject 1 + if (!string.IsNullOrEmpty(row.PqSubjectCode1)) + { + if (lookups.PQSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode1} was not found."); + } + else if (lookups.PQSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode1} found."); + } + } + + // PQ Subject 2 + if (!string.IsNullOrEmpty(row.PqSubjectCode2)) + { + if (lookups.PQSubject2MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode2} was not found."); + } + else if (lookups.PQSubject2MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode2} found."); + } + } + + // PQ Subject 3 + if (!string.IsNullOrEmpty(row.PqSubjectCode3)) + { + if (lookups.PQSubject3MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode3} was not found."); + } + else if (lookups.PQSubject3MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode3} found."); + } + } + + return (validationFailures, errors); + } + + public async Task<(EwcWalesMatchStatus, Guid? OrganisationId)> FindMatchingOrganisationsRecordAsync(string OrgNumber) + { + var query = new FindActiveOrganisationsByAccountNumberQuery(OrgNumber); + var results = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (results.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (results.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var organisationId = results.First().Id; + return (EwcWalesMatchStatus.OneMatch, organisationId); + } + + public async Task<(EwcWalesMatchStatus, Guid? HeQualificationId)> GetHEQualificationAsync(string qualificationCode) + { + var results = await cache.GetHeQualificationsAsync(); + var qualifications = results.Where(x => x.dfeta_Value == qualificationCode).ToArray(); + + if (qualifications.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (qualifications.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var subjectId = qualifications.First().Id; + return (EwcWalesMatchStatus.OneMatch, subjectId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetMatchingHESubjectAsync(string subjectCode) + { + var results = await cache.GetHeSubjectsAsync(); + var subjects = results.Where(x => x.dfeta_Value == subjectCode).ToArray(); + + if (subjects.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (subjects.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var subjectId = subjects.First().Id; + return (EwcWalesMatchStatus.OneMatch, subjectId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetTeacherStatusAsync(string qtsStatus) + { + var results = await cache.GetTeacherStatusesAsync(); + + if (qtsStatus != null && qtsStatus.Equals("67", StringComparison.InvariantCultureIgnoreCase)) + { + var status = results.Single(x => x.dfeta_Value == qtsStatus); //67 - Qualified Teacher: under the EC Directive + return (EwcWalesMatchStatus.OneMatch, status.Id); + } + else + { + var status = results.Single(x => x.dfeta_Value == "213"); //213 - Qualified Teacher: QTS awarded in Wales + return (EwcWalesMatchStatus.OneMatch, status.Id); + } + } + + public dfeta_classdivision? GetHEClassDivision(string classCode) + { + switch (classCode) + { + case "1": + case "01": + return dfeta_classdivision.Firstclasshonours; + case "2": + case "02": + return dfeta_classdivision.Uppersecondclasshonours; + case "3": + case "03": + return dfeta_classdivision.Lowersecondclasshonours; + case "4": + case "04": + return dfeta_classdivision.Undividedsecondclasshonours; + case "5": + case "05": + return dfeta_classdivision.Thirdclasshonours; + case "6": + case "06": + return dfeta_classdivision.Fourthclasshonours; + case "7": + case "07": + return dfeta_classdivision.Unclassifiedhonours; + case "8": + case "08": + return dfeta_classdivision.Aegrotat_whethertohonoursorpass; + case "9": + case "09": + return dfeta_classdivision.Passdegreeawardedwithouthonoursfollowinganhonourscourse; + case "10": + return dfeta_classdivision.Ordinary_includingdivisionsofordinaryifanydegreeawardedafterfollowinganonhonourscourse; + case "11": + return dfeta_classdivision.GeneralDegreedegreeawardedafterfollowinganonhonourscoursedegreethatwasnotavailabletobeclassified; + case "12": + return dfeta_classdivision.Distinction; + case "13": + return dfeta_classdivision.Merit; + case "14": + return dfeta_classdivision.Pass; + case "98": + return dfeta_classdivision.Notapplicable; + case "99": + return dfeta_classdivision.NotKnown; + default: + return null; + } + } + + public async Task<(EwcWalesMatchStatus, Guid? IttQualificationId)> GetIttQualificationAsync(string ittQualificationcode) + { + var results = await cache.GetIttQualificationsAsync(); + var qualifications = results.Where(x => x.dfeta_Value == ittQualificationcode).ToArray(); + + if (qualifications.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (qualifications.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var qualificationId = qualifications.First().Id; + return (EwcWalesMatchStatus.OneMatch, qualificationId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> FindIttSubjectAsync(string subjectCode) + { + var subject = await cache.GetIttSubjectBySubjectCodeAsync(subjectCode); + + if (subject is null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + return (EwcWalesMatchStatus.OneMatch, subject.Id); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetMatchingCountryAsync(string countryCode) + { + var country = await cache.GetCountryByCountryCodeAsync(countryCode); + if (country is null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + return (EwcWalesMatchStatus.OneMatch, country.Id); + } + + public async Task<(EwcWalesMatchStatus, Guid? PersonId)> FindMatchingTeacherRecordAsync(EwcWalesQtsFileImportData item) + { + var contact = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveContactByTrnQuery(item.QtsRefNo, + new ColumnSet( + Contact.Fields.dfeta_TRN, + Contact.Fields.BirthDate, + Contact.Fields.dfeta_QTSDate, + Contact.Fields.dfeta_qtlsdate))); + + if (contact == null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if ((DateOnly.TryParseExact(item.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dob)) && + contact.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false) != dob) + { + return (EwcWalesMatchStatus.TrnAndDateOfBirthMatchFailed, null); + } + + var qtsRegistrations = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveQtsRegistrationsByContactIdsQuery( + new[] { contact.ContactId!.Value }, + new ColumnSet( + dfeta_qtsregistration.Fields.dfeta_PersonId, + dfeta_qtsregistration.Fields.dfeta_QTSDate, + dfeta_qtsregistration.Fields.dfeta_TeacherStatusId) + ) + ); + + if (qtsRegistrations[contact.Id].Length > 0) + { + return (EwcWalesMatchStatus.TeacherHasQts, contact.ContactId!); + } + else + { + return (EwcWalesMatchStatus.NoAssociatedQts, contact.ContactId!); + } + } + + public class QtsImportLookupData + { + public required Guid? PersonId { get; set; } + public required EwcWalesMatchStatus? PersonMatchStatus { get; set; } + public required Guid? IttEstabCodeId { get; set; } + public required EwcWalesMatchStatus? IttEstabCodeMatchStatus { get; set; } + public required Guid? IttQualificationId { get; set; } + public required EwcWalesMatchStatus? IttQualificationMatchStatus { get; set; } + public required Guid? IttSubject1Id { get; set; } + public required EwcWalesMatchStatus? IttSubject1MatchStatus { get; set; } + public required Guid? IttSubject2Id { get; set; } + public required EwcWalesMatchStatus? IttSubject2MatchStatus { get; set; } + public required Guid? PqEstablishmentId { get; set; } + public required EwcWalesMatchStatus? PqEstablishmentMatchStatus { get; set; } + public required Guid? PQCountryId { get; set; } + public required EwcWalesMatchStatus? PQCountryMatchStatus { get; set; } + public required Guid? PQHEQualificationId { get; set; } + public required EwcWalesMatchStatus? PQHEQualificationMatchStatus { get; set; } + public required Guid? PQSubject1Id { get; set; } + public required EwcWalesMatchStatus? PQSubject1MatchStatus { get; set; } + public required Guid? PQSubject2Id { get; set; } + public required EwcWalesMatchStatus? PQSubject2MatchStatus { get; set; } + public required Guid? PQSubject3Id { get; set; } + public required EwcWalesMatchStatus? PQSubject3MatchStatus { get; set; } + public required Guid? TeacherStatusId { get; set; } + public required EwcWalesMatchStatus? TeacherStatusMatchStatus { get; set; } + public required dfeta_classdivision? ClassDivision { get; set; } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesImportFileType.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesImportFileType.cs new file mode 100644 index 000000000..7597e5d6b --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesImportFileType.cs @@ -0,0 +1,7 @@ +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public enum EwcWalesImportFileType +{ + Induction = 1, + Qualification = 2 +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesInductionImportData.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesInductionImportData.cs new file mode 100644 index 000000000..b89d45201 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesInductionImportData.cs @@ -0,0 +1,38 @@ +using CsvHelper.Configuration.Attributes; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public record EwcWalesInductionImportData +{ + [Name("REFERENCE_NO")] + public required string ReferenceNumber { get; set; } + + [Name("FIRST_NAME")] + public required string FirstName { get; set; } + + [Name("LAST_NAME")] + public required string LastName { get; set; } + + [Name("DATE_OF_BIRTH")] + public required string DateOfBirth { get; set; } + + [Name("START_DATE")] + public required string StartDate { get; set; } + + [Name("PASS_DATE")] + public required string PassedDate { get; set; } + + [Name("FAIL_DATE")] + public required string FailDate { get; set; } + + [Name("EMPLOYER_NAME")] + public required string EmployerName { get; set; } + + [Name("EMPLOYER_CODE")] + public required string EmployerCode { get; set; } + + [Name("IND_STATUS_NAME")] + public required string InductionStatusName { get; set; } +} + + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesQTSFileImportData.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesQTSFileImportData.cs new file mode 100644 index 000000000..ea8f896d3 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/EwcWalesQTSFileImportData.cs @@ -0,0 +1,98 @@ +using CsvHelper.Configuration.Attributes; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class EwcWalesQtsFileImportData +{ + [Name("QTS_REF_NO")] + public required string QtsRefNo { get; set; } + + [Name("FORENAME")] + public required string Forename { get; set; } + + [Name("SURNAME")] + public required string Surname { get; set; } + + [Name("DATE_OF_BIRTH")] + public required string DateOfBirth { get; set; } + + [Name("QTS_STATUS")] + public required string QtsStatus { get; set; } + + [Name("QTS_DATE")] + public required string QtsDate { get; set; } + + [Name("ITT StartMONTH")] + public required string IttStartMonth { get; set; } + + [Name("ITT START YY")] + public required string IttStartYear { get; set; } + + [Name("ITT End Date")] + public required string IttEndDate { get; set; } + + [Name("ITT Course Length")] + public required string ITTCourseLength { get; set; } + + [Name("ITT Estab LEA code")] + public required string IttEstabLeaCode { get; set; } + + [Name("ITT Estab Code")] + public required string IttEstabCode { get; set; } + + [Name("ITT Qual Code")] + public required string IttQualCode { get; set; } + + [Name("ITT Class Code")] + public required string IttClassCode { get; set; } + + [Name("ITT Subject Code 1")] + public required string IttSubjectCode1 { get; set; } + + [Name("ITT Subject Code 2")] + public required string IttSubjectCode2 { get; set; } + + [Name("ITT Min Age Range")] + public required string IttMinAgeRange { get; set; } + + [Name("ITT Max Age Range")] + public required string IttMaxAgeRange { get; set; } + + [Name("ITT Min Sp Age Range")] + public required string IttMinSpAgeRange { get; set; } + + [Name("ITT Max Sp Age Range")] + public required string IttMaxSpAgeRange { get; set; } + + [Name("ITT Course Length")] + public required string PqCourseLength { get; set; } + + [Name("PQ Year of Award")] + public required string PqYearOfAward { get; set; } + + [Name("COUNTRY")] + public required string Country { get; set; } + + [Name("PQ Estab Code")] + public required string PqEstabCode { get; set; } + + [Name("PQ Qual Code")] + public required string PqQualCode { get; set; } + + [Name("HONOURS")] + public required string Honours { get; set; } + + [Name("PQ Class Code")] + public required string PqClassCode { get; set; } + + [Name("PQ Subject Code 1")] + public required string PqSubjectCode1 { get; set; } + + [Name("PQ Subject Code 2")] + public required string PqSubjectCode2 { get; set; } + + [Name("PQ Subject Code 3")] + public required string PqSubjectCode3 { get; set; } +} + + diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/InductionImporter.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/InductionImporter.cs new file mode 100644 index 000000000..087b625b4 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/InductionImporter.cs @@ -0,0 +1,481 @@ +using System.Globalization; +using System.Text; +using CsvHelper; +using Microsoft.Extensions.Logging; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt; +using TeachingRecordSystem.Core.Dqt.Queries; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class InductionImporter(ICrmQueryDispatcher crmQueryDispatcher, ILogger logger) +{ + private const string DATE_FORMAT = "dd/MM/yyyy"; + + public async Task ImportAsync(StreamReader csvReaderStream, string fileName) + { + using (var csv = new CsvReader(csvReaderStream, CultureInfo.InvariantCulture)) + { + var integrationJob = new CreateIntegrationTransactionQuery() + { + StartDate = DateTime.Now, + TypeId = (int)dfeta_IntegrationInterface.GTCWalesImport, + FileName = fileName + }; + var integrationId = await crmQueryDispatcher.ExecuteQueryAsync(integrationJob); + + var records = csv.GetRecords().ToList(); + var validationMessages = new List(); + + var totalRowCount = 0; + var successCount = 0; + var duplicateRowCount = 0; + var failureRowCount = 0; + var failureMessage = new StringBuilder(); + foreach (var row in records) + { + totalRowCount++; + Guid? personId = null; + Guid? inductionId = null; + Guid? inductionPeriodId = null; + Guid itrId = Guid.NewGuid(); + var itrFailureMessage = new StringBuilder(); + using var rowTransaction = crmQueryDispatcher.CreateTransactionRequestBuilder(); + + try + { + var lookupData = await GetLookupDataAsync(row); + var validationFailures = Validate(row, lookupData); + personId = lookupData.Person?.ContactId; + inductionId = lookupData.Induction?.Id; + + //append non processable errors to list of failures that will be a line in + //the IntegrationTransaction (job) failuremessage field. + if (validationFailures.Errors.Any()) + { + failureRowCount++; + foreach (var error in validationFailures.Errors) + { + failureMessage.AppendLine(error); + itrFailureMessage.AppendLine(error); + } + + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + } + else + { + // if contact does not have an associated induction - create one with the data from the imported file row + // else if there is an associated induction update status & passed date with the data from the imported file row + if (!inductionId.HasValue) + { + inductionId = Guid.NewGuid(); + var createInductionQuery = new CreateInductionTransactionalQuery() + { + Id = inductionId.Value, + ContactId = personId!.Value, + StartDate = DateTime.ParseExact(row.StartDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + CompletionDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionStatus = dfeta_InductionStatus.PassedinWales + }; + rowTransaction.AppendQuery(createInductionQuery); + } + else + { + var updateInductionQuery = new UpdateInductionTransactionalQuery() + { + InductionId = inductionId.Value, + CompletionDate = !string.IsNullOrEmpty(row.PassedDate) ? DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None) : null, + InductionStatus = dfeta_InductionStatus.PassedinWales + }; + rowTransaction.AppendQuery(updateInductionQuery); + } + + //if an induction period is not found - create one + //else if an induction period is found - update it + if (lookupData.InductionPeriod is null) + { + inductionPeriodId = Guid.NewGuid(); + var queryInductionPeriod = new CreateInductionPeriodTransactionalQuery() + { + Id = inductionPeriodId.Value, + InductionId = inductionId.Value, + AppropriateBodyId = lookupData.OrganisationId, + InductionStartDate = DateTime.ParseExact(row.StartDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionEndDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + }; + rowTransaction.AppendQuery(queryInductionPeriod); + } + else + { + inductionPeriodId = lookupData.InductionPeriod.dfeta_inductionperiodId; + var updateInduction = new UpdateInductionTransactionalQuery() + { + InductionId = inductionId!.Value, + CompletionDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + InductionStatus = lookupData.Induction!.dfeta_InductionStatus!.Value + }; + rowTransaction.AppendQuery(updateInduction); + + var updateInductionPeriodQuery = new UpdateInductionPeriodTransactionalQuery() + { + InductionPeriodId = inductionPeriodId!.Value, + AppropriateBodyId = lookupData.OrganisationId, + InductionStartDate = lookupData.InductionPeriod.dfeta_StartDate, + InductionEndDate = DateTime.ParseExact(row.PassedDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None), + }; + rowTransaction.AppendQuery(updateInductionPeriodQuery); + } + + //soft validation errors can be appended to the IntegrationTransactionRecord Failure message + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + + //increase failurecount if row is processable or if there are validation failures + //else increase success counter + if (validationFailures.ValidationFailures.Any() || validationFailures.Errors.Any()) + { + failureRowCount++; + } + else + { + successCount++; + } + } + + //create ITR row with status of import row + var createIntegrationTransactionRecord = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationId, + Reference = totalRowCount.ToString(), + ContactId = personId, + InitialTeacherTrainingId = null, + QualificationId = null, + InductionId = inductionId, + InductionPeriodId = inductionPeriodId, + DuplicateStatus = null, + FailureMessage = itrFailureMessage.ToString(), + StatusCode = string.IsNullOrEmpty(itrFailureMessage.ToString()) ? dfeta_integrationtransactionrecord_StatusCode.Success : dfeta_integrationtransactionrecord_StatusCode.Fail, + RowData = ConvertToCSVString(row), + FileName = fileName + }; + rowTransaction.AppendQuery(createIntegrationTransactionRecord); + + //update IntegrationTransaction so that it's always up to date with + //counts of rows + var updateIntegrationTransactionQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = null, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = 0, + FailureCount = failureRowCount, + FailureMessage = itrFailureMessage.ToString() + }; + rowTransaction.AppendQuery(updateIntegrationTransactionQuery); + await rowTransaction.ExecuteAsync(); + } + catch (Exception e) + { + failureRowCount++; + logger.LogError(e.ToString()); + } + } + + var updateIntTrxQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = DateTime.Now, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = duplicateRowCount, + FailureCount = failureRowCount, + FailureMessage = failureMessage.ToString() + }; + + using var txn = crmQueryDispatcher.CreateTransactionRequestBuilder(); + txn.AppendQuery(updateIntTrxQuery); + await txn.ExecuteAsync(); + + return new InductionImportResult(totalRowCount, successCount, duplicateRowCount, failureRowCount, failureMessage.ToString(), integrationId); + } + } + + public string ConvertToCSVString(EwcWalesInductionImportData row) + { + using (var writer = new StringWriter()) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecord(row); + csv.NextRecord(); + return writer.ToString(); + } + } + + public async Task GetLookupDataAsync(EwcWalesInductionImportData row) + { + var (personMatchStatus, contact) = await FindMatchingTeacherRecordAsync(row); + var (orgMatchStatus, organisationId) = await FindMatchingOrganisationsRecordAsync(row.EmployerCode); + InductionLookupResult? inductionMatchStatus = null; + dfeta_induction? induction = null; + dfeta_inductionperiod? inductionPeriod = null; + InductionPeriodLookupResult? inductionPeriodMatchStatus = null; + if (contact != null) + { + var (indStatus, ind) = await FindActiveInductionByContactAsync(contact.ContactId!.Value); + inductionMatchStatus = indStatus; + induction = ind?.Induction; + + if (ind?.InductionPeriods?.Length == 1) + { + inductionPeriodMatchStatus = InductionPeriodLookupResult.OneMatch; + inductionPeriod = ind.InductionPeriods.First(); + } + else if (ind?.InductionPeriods?.Length > 1) + { + inductionPeriodMatchStatus = InductionPeriodLookupResult.MultipleMatchesFound; + inductionPeriod = null; + } + } + + var lookupData = new InductionImportLookupData + { + Person = contact, + PersonMatchStatus = personMatchStatus, + Induction = induction, + InductionMatchStatus = inductionMatchStatus, + InductionPeriod = inductionPeriod, + InductionPeriodMatchStatus = inductionPeriodMatchStatus, + OrganisationMatchStatus = orgMatchStatus, + OrganisationId = organisationId + }; + return lookupData; + } + + public (List ValidationFailures, List Errors) Validate(EwcWalesInductionImportData row, InductionImportLookupData lookups) + { + var validationFailures = new List(); + var errors = new List(); + + //ReferenceNumber/Trn + if (String.IsNullOrEmpty(row.ReferenceNumber)) + { + errors.Add("Missing Reference No"); + } + + //Date Of birth + if (String.IsNullOrEmpty(row.DateOfBirth)) + { + errors.Add("Missing Date of Birth"); + } + else + { + if (!DateOnly.TryParseExact(row.DateOfBirth, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Date of Birth"); + } + } + + //InductionPassedDate + if (String.IsNullOrEmpty(row.StartDate)) + { + errors.Add("Missing Induction Start date"); + } + else + { + if (!DateOnly.TryParseExact(row.StartDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Induction start date"); + } + } + + //InductionPassedDate + if (String.IsNullOrEmpty(row.PassedDate)) + { + errors.Add("Missing Induction passed date"); + } + else + { + if (!DateOnly.TryParseExact(row.PassedDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add("Validation Failed: Invalid Induction passed date"); + } + } + + switch (lookups.PersonMatchStatus) + { + case ContactLookupResult.NoAssociatedQts: + break; + case ContactLookupResult.NoMatch: + errors.Add($"Teacher with TRN {row.ReferenceNumber} was not found."); + break; + case ContactLookupResult.TrnAndDateOfBirthMatchFailed: + errors.Add($"For TRN {row.ReferenceNumber} Date of Birth does not match with the existing record."); + break; + case ContactLookupResult.TeacherHasQts: + errors.Add($"Teacher with TRN {row.ReferenceNumber} has QTS already."); + break; + } + + if (!string.IsNullOrEmpty(row.EmployerCode)) + { + switch (lookups.OrganisationMatchStatus) + { + case OrganisationLookupResult.NoMatch: + validationFailures.Add($"Organisation with Induction Body Code {row.EmployerCode} was not found."); + break; + case OrganisationLookupResult.MultipleMatchesFound: + validationFailures.Add($"Multiple organisations with Induction Body Code {row.EmployerCode} found."); + break; + } + } + + //if teacher is exempt via set and doesn't have an induction + if (lookups.InductionMatchStatus == InductionLookupResult.NoMatch && lookups.Person != null && lookups.Person!.dfeta_qtlsdate.HasValue) + { + errors.Add("may need to update either/both the 'TRA induction status' and 'Overall induction status"); + } + + //if teacher is exempt via set and inductionstatus is not in permitted updatabe statuses + if (lookups.InductionMatchStatus == InductionLookupResult.OneMatch && lookups.Person != null && lookups.Person!.dfeta_qtlsdate.HasValue) + { + errors.Add("may need to update either/both the 'TRA induction status' and 'Overall induction status'"); + } + + if (lookups.Induction != null) + { + switch (lookups.Induction.GetAttributeValue(dfeta_induction.Fields.dfeta_InductionStatus).Value) + { + case (int)dfeta_InductionStatus.Pass: + case (int)dfeta_InductionStatus.PassedinWales: + case (int)dfeta_InductionStatus.Exempt: + case (int)dfeta_InductionStatus.Fail: + case (int)dfeta_InductionStatus.FailedinWales: + errors.Add($"Teacher with TRN {row.ReferenceNumber} completed induction already."); + break; + } + } + + return (validationFailures, errors); + } + public async Task<(OrganisationLookupResult, Guid? OrganisationId)> FindMatchingOrganisationsRecordAsync(string OrgNumber) + { + var query = new FindActiveOrganisationsByAccountNumberQuery(OrgNumber); + var results = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (results.Length == 0) + { + return (OrganisationLookupResult.NoMatch, null); + } + + if (results.Length > 1) + { + return (OrganisationLookupResult.MultipleMatchesFound, null); + } + + var organisationId = results.First().Id; + return (OrganisationLookupResult.OneMatch, organisationId); + } + + public async Task<(InductionLookupResult, InductionRecord?)> FindActiveInductionByContactAsync(Guid personId) + { + var query = new GetActiveInductionByContactIdQuery(personId); + var result = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (result is null) + { + return (InductionLookupResult.NoMatch, null); + } + + return (InductionLookupResult.OneMatch, result); + } + + public async Task<(ContactLookupResult, Contact? contact)> FindMatchingTeacherRecordAsync(EwcWalesInductionImportData item) + { + var contact = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveContactByTrnQuery(item.ReferenceNumber, + new ColumnSet( + Contact.Fields.dfeta_TRN, + Contact.Fields.BirthDate, + Contact.Fields.dfeta_QTSDate, + Contact.Fields.dfeta_qtlsdate))); + + if (contact == null) + { + return (ContactLookupResult.NoMatch, null); + } + + if (DateOnly.TryParseExact(item.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dob) && contact!.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false) != dob) + { + return (ContactLookupResult.TrnAndDateOfBirthMatchFailed, null); + } + + var qtsRegistrations = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveQtsRegistrationsByContactIdsQuery( + new[] { contact!.ContactId!.Value }, + new ColumnSet( + dfeta_qtsregistration.Fields.dfeta_PersonId, + dfeta_qtsregistration.Fields.dfeta_QTSDate, + dfeta_qtsregistration.Fields.dfeta_TeacherStatusId) + ) + ); + + if (qtsRegistrations[contact.Id].Length > 0) + { + return (ContactLookupResult.TeacherHasQts, contact); + } + else + { + return (ContactLookupResult.NoAssociatedQts, contact); + } + } + + public class InductionImportLookupData + { + public required Contact? Person { get; set; } + public required ContactLookupResult? PersonMatchStatus { get; set; } + public required dfeta_induction? Induction { get; set; } + public required InductionLookupResult? InductionMatchStatus { get; set; } + public required dfeta_inductionperiod? InductionPeriod { get; set; } + public required InductionPeriodLookupResult? InductionPeriodMatchStatus { get; set; } + public required Guid? OrganisationId { get; set; } + public required OrganisationLookupResult? OrganisationMatchStatus { get; set; } + } +} + +public enum InductionLookupResult +{ + NoMatch, + OneMatch +} + +public enum ContactLookupResult +{ + NoMatch, + TrnAndDateOfBirthMatchFailed, + NoAssociatedQts, + TeacherHasQts +} + +public enum InductionPeriodLookupResult +{ + NoMatch, + OneMatch, + MultipleMatchesFound +} + +public enum OrganisationLookupResult +{ + NoMatch, + OneMatch, + MultipleMatchesFound +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/QtsImporter.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/QtsImporter.cs new file mode 100644 index 000000000..bfde49a5d --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/EwcWalesImport/QtsImporter.cs @@ -0,0 +1,672 @@ +using System.Globalization; +using System.Text; +using CsvHelper; +using Microsoft.Extensions.Logging; +using Microsoft.Xrm.Sdk.Query; +using TeachingRecordSystem.Core.Dqt; +using TeachingRecordSystem.Core.Dqt.Queries; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; + +namespace TeachingRecordSystem.Core.Jobs.EwcWalesImport; + +public class QtsImporter(ICrmQueryDispatcher crmQueryDispatcher, ReferenceDataCache cache, ILogger logger) +{ + private const string DATE_FORMAT = "dd/MM/yyyy"; + + public async Task ImportAsync(StreamReader csvReaderStream, string fileName) + { + using var csv = new CsvReader(csvReaderStream, CultureInfo.InvariantCulture); + var records = csv.GetRecords().ToList(); + var totalRowCount = 0; + var successCount = 0; + var duplicateRowCount = 0; + var failureRowCount = 0; + var failureMessage = new StringBuilder(); + + var integrationJob = new CreateIntegrationTransactionQuery() + { + StartDate = DateTime.Now, + TypeId = (int)dfeta_IntegrationInterface.GTCWalesImport, + FileName = fileName + }; + var integrationId = await crmQueryDispatcher.ExecuteQueryAsync(integrationJob); + + foreach (var row in records) + { + totalRowCount++; + var qualificationId = Guid.NewGuid(); + var ittId = Guid.NewGuid(); + var qtsRegistrationId = Guid.NewGuid(); + Guid? inductionId = null; + var itrFailureMessage = new StringBuilder(); + using var rowTransaction = crmQueryDispatcher.CreateTransactionRequestBuilder(); + + try + { + var lookupData = await GetLookupDataAsync(row); + var validationFailures = Validate(row, lookupData); + + //append non processable errors to list of failures that will be a line in + //the IntegrationTransaction (job) failuremessage field. + if (validationFailures.Errors.Any()) + { + foreach (var error in validationFailures.Errors) + { + failureMessage.AppendLine(error); + itrFailureMessage.AppendLine(error); + } + } + else + { + //Create ITT + var ittQuery = new CreateInitialTeacherTrainingTransactionalQuery() + { + Id = ittId, + ContactId = lookupData.PersonId!.Value, + ITTQualificationId = lookupData.IttQualificationId, + CountryId = lookupData.PQCountryId.HasValue ? lookupData.PQCountryId : null, + Result = dfeta_ITTResult.Pass // by definition of GTCW everybody should have passed training + }; + rowTransaction.AppendQuery(ittQuery); + + //Create Qualification + var qualificationQuery = new CreateHeQualificationTransactionalQuery() + { + Id = qualificationId, + ContactId = lookupData.PersonId.Value, + HECountryId = lookupData.PQCountryId, + HECourseLength = row.PqCourseLength, + HEEstablishmentId = lookupData.PqEstablishmentId, + HEQualificationId = lookupData.PQHEQualificationId, + HEClassDivision = lookupData.ClassDivision, + HESubject1id = lookupData.PQSubject1Id, + HESubject2id = lookupData.PQSubject2Id, + HESubject3id = lookupData.PQSubject3Id, + Type = dfeta_qualification_dfeta_Type.HigherEducation + }; + var getQualificationQueryResponse = rowTransaction.AppendQuery(qualificationQuery); + + //Qts + var qtsQuery = new CreateQtsRegistrationTransactionalQuery() + { + Id = qtsRegistrationId, + ContactId = lookupData.PersonId.Value, + TeacherStatusId = lookupData.TeacherStatusId!.Value, + QtsDate = DateTime.ParseExact(row.QtsDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None) + }; + rowTransaction.AppendQuery(qtsQuery); + + //soft validation errors can be appended to the IntegrationTransactionRecord Failure message + foreach (var validationMessage in validationFailures.ValidationFailures) + { + itrFailureMessage.AppendLine(validationMessage); + failureMessage.AppendLine(validationMessage); + } + + if (row.QtsStatus == "67") + { + inductionId = Guid.NewGuid(); + var induction = new CreateInductionTransactionalQuery() + { + Id = inductionId.Value, + ContactId = lookupData.PersonId.Value, + StartDate = null, + CompletionDate = null, + InductionStatus = dfeta_InductionStatus.RequiredtoComplete + }; + rowTransaction.AppendQuery(induction); + } + } + + //create ITR row with status of import row + var createIntegrationTransactionRecord = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationId, + Reference = totalRowCount.ToString(), + ContactId = lookupData.PersonId, + InitialTeacherTrainingId = ittId, + QualificationId = qualificationId, + InductionId = inductionId, + InductionPeriodId = null, + DuplicateStatus = null, + FailureMessage = itrFailureMessage.ToString(), + StatusCode = string.IsNullOrEmpty(itrFailureMessage.ToString()) ? dfeta_integrationtransactionrecord_StatusCode.Success : dfeta_integrationtransactionrecord_StatusCode.Fail, + RowData = ConvertToCsvString(row), + FileName = fileName + }; + rowTransaction.AppendQuery(createIntegrationTransactionRecord); + + //update IntegrationTransaction so that it's always up to date with + //counts of rows + var updateIntegrationTransactionQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = null, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = 0, + FailureCount = failureRowCount, + FailureMessage = itrFailureMessage.ToString() + }; + rowTransaction.AppendQuery(updateIntegrationTransactionQuery); + + + await rowTransaction.ExecuteAsync(); + + //increase failurecount if row is processable or if there are validation failures + //else increase success counter + if (validationFailures.ValidationFailures.Any() || validationFailures.Errors.Any()) + { + failureRowCount++; + } + else + { + successCount++; + } + } + catch (Exception e) + { + failureRowCount++; + logger.LogError(e.ToString()); + } + } + + var updateIntTrxQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = integrationId, + EndDate = DateTime.Now, + TotalCount = totalRowCount, + SuccessCount = successCount, + DuplicateCount = duplicateRowCount, + FailureCount = failureRowCount, + FailureMessage = failureMessage.ToString() + }; + + using var txn = crmQueryDispatcher.CreateTransactionRequestBuilder(); + txn.AppendQuery(updateIntTrxQuery); + await txn.ExecuteAsync(); + + + return new QtsImportResult(totalRowCount, successCount, duplicateRowCount, failureRowCount, failureMessage.ToString(), integrationId); + } + + public string ConvertToCsvString(EwcWalesQtsFileImportData row) + { + using (var writer = new StringWriter()) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecord(row); + csv.NextRecord(); + return writer.ToString(); + } + } + + public async Task GetLookupDataAsync(EwcWalesQtsFileImportData row) + { + //contact + var (personMatchStatus, personId) = await FindMatchingTeacherRecordAsync(row); + var (ittEstabCodeStatus, ittEstabCodeId) = await FindMatchingOrganisationsRecordAsync(row.IttEstabCode); + var (ittQualCodeStatus, ittQualificationId) = await GetIttQualificationAsync(row.IttQualCode); + var (ittSubjectCode1MatchStatus, ittSubjectCode1Id) = await FindIttSubjectAsync(row.IttSubjectCode1); + var (ittSubjectCode2MatchStatus, ittSubjectCode2Id) = await FindIttSubjectAsync(row.IttSubjectCode2); + var (iqEstabCodeMatchStatus, iqEstaId) = await FindMatchingOrganisationsRecordAsync(row.PqEstabCode); + var (pqCountryMatchStatus, pqCountryId) = await GetMatchingCountryAsync(row.Country); + var (heQualificationMatchStatus, heQualificationId) = await GetHEQualificationAsync(row.PqQualCode); + var (pqSubjectCode1MatchStatus, pqSubjectCode1Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode1); + var (pqSubjectCode2MatchStatus, pqSubjectCode2Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode2); + var (pqSubjectCode3MatchStatus, pqSubjectCode3Id) = await GetMatchingHESubjectAsync(row.PqSubjectCode3); + var (teacherStatusMatchStatus, teacherStatusId) = await GetTeacherStatusAsync(row.QtsStatus); + var heClassDivision = GetHEClassDivision(row.PqClassCode); + + var lookupData = new QtsImportLookupData + { + PersonId = personId, + PersonMatchStatus = personMatchStatus, + IttEstabCodeId = ittEstabCodeId, + IttEstabCodeMatchStatus = ittEstabCodeStatus, + IttQualificationId = ittQualificationId, + IttQualificationMatchStatus = ittQualCodeStatus, + IttSubject1Id = ittSubjectCode1Id, + IttSubject1MatchStatus = ittSubjectCode1MatchStatus, + IttSubject2Id = ittSubjectCode2Id, + IttSubject2MatchStatus = ittSubjectCode2MatchStatus, + PqEstablishmentId = iqEstaId, + PqEstablishmentMatchStatus = iqEstabCodeMatchStatus, + PQCountryId = pqCountryId, + PQCountryMatchStatus = pqCountryMatchStatus, + PQHEQualificationId = heQualificationId, + PQHEQualificationMatchStatus = heQualificationMatchStatus, + PQSubject1Id = pqSubjectCode1Id, + PQSubject1MatchStatus = pqSubjectCode1MatchStatus, + PQSubject2Id = pqSubjectCode2Id, + PQSubject2MatchStatus = pqSubjectCode2MatchStatus, + PQSubject3Id = pqSubjectCode3Id, + PQSubject3MatchStatus = pqSubjectCode3MatchStatus, + TeacherStatusId = teacherStatusId, + TeacherStatusMatchStatus = teacherStatusMatchStatus, + ClassDivision = heClassDivision + }; + return lookupData; + } + + public (List ValidationFailures, List Errors) Validate(EwcWalesQtsFileImportData row, QtsImportLookupData lookups) + { + var validationFailures = new List(); + var errors = new List(); + + //QTS REF + if (string.IsNullOrEmpty(row.QtsRefNo)) + { + errors.Add("Missing QTS Ref Number"); + } + + //Date Of birth + if (string.IsNullOrEmpty(row.DateOfBirth)) + { + errors.Add("Missing Date of Birth"); + } + else if (!DateOnly.TryParseExact(row.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add($"Validation Failed: Invalid Date of Birth {row.DateOfBirth}"); + } + + //QTS Date + if (string.IsNullOrEmpty(row.QtsDate)) + { + errors.Add("Misssing QTS Date"); + } + else if (!DateOnly.TryParseExact(row.QtsDate, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) + { + errors.Add($"Validation Failed: Invalid QTS Date {row.QtsDate}"); + } + + + switch (lookups.PersonMatchStatus) + { + case EwcWalesMatchStatus.NoAssociatedQts: + break; + case EwcWalesMatchStatus.NoMatch: + errors.Add($"Teacher with TRN {row.QtsRefNo} was not found."); + break; + case EwcWalesMatchStatus.TrnAndDateOfBirthMatchFailed: + errors.Add($"For TRN {row.QtsRefNo} Date of Birth does not match with the existing record."); //No Test + break; + case EwcWalesMatchStatus.MultipleTrnMatched: + errors.Add($"TRN {row.QtsRefNo} was matched to more than one record in the system."); + break; + case EwcWalesMatchStatus.TeacherInactive: + errors.Add($"Teacher with TRN {row.QtsRefNo} is inactive."); //No Test + break; + case EwcWalesMatchStatus.TeacherHasQts: + errors.Add($"Teacher with TRN {row.QtsRefNo} has QTS already."); + break; + } + + //IttEstabCode + if (!string.IsNullOrEmpty(row.IttEstabCode)) + { + if (lookups.IttEstabCodeMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Organisation with ITT Establishment Code {row.IttEstabCode} was not found."); + } + else if (lookups.IttEstabCodeMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple organisations with ITT Establishment Code {row.IttEstabCode} found."); + } + } + + // ITT Qualification + if (!string.IsNullOrEmpty(row.IttQualCode)) + { + if (lookups.IttQualificationMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT qualification with code {row.IttQualCode} was not found."); + } + else if (lookups.IttQualificationMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT qualifications with code {row.IttQualCode} found."); + } + } + + // IIT Subject 1 + if (!string.IsNullOrEmpty(row.IttSubjectCode1)) + { + if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT subject with code {row.IttSubjectCode1} was not found."); + } + else if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT subjects with code {row.IttSubjectCode1} found."); + } + } + + // IIT Subject 2 + if (!string.IsNullOrEmpty(row.IttSubjectCode2)) + { + if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"ITT subject with code {row.IttSubjectCode2} was not found."); + } + else if (lookups.IttSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple ITT subjects with code {row.IttSubjectCode2} found."); + } + } + + // PQ Establishment + if (!string.IsNullOrEmpty(row.PqEstabCode)) + { + if (lookups.PqEstablishmentMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Organisation with PQ Establishment Code {row.PqEstabCode} was not found."); + } + else if (lookups.PqEstablishmentMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple organisations with PQ Establishment Code {row.PqEstabCode} found."); + } + } + + // PQ Country + if (!string.IsNullOrEmpty(row.Country)) + { + if (lookups.PQCountryMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Country with PQ Country Code {row.Country} was not found."); + } + else if (lookups.PQCountryMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple countries with PQ Country Code {row.Country} found."); + } + } + + // PQ HE Qualification + if (!string.IsNullOrEmpty(row.PqQualCode)) + { + if (lookups.PQHEQualificationMatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Qualification with PQ Qualification Code {row.PqQualCode} was not found."); + } + else if (lookups.PQHEQualificationMatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple qualifications with PQ Qualification Code {row.PqQualCode} found."); + } + } + + // PQ Subject 1 + if (!string.IsNullOrEmpty(row.PqSubjectCode1)) + { + if (lookups.PQSubject1MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode1} was not found."); + } + else if (lookups.PQSubject1MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode1} found."); + } + } + + // PQ Subject 2 + if (!string.IsNullOrEmpty(row.PqSubjectCode2)) + { + if (lookups.PQSubject2MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode2} was not found."); + } + else if (lookups.PQSubject2MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode2} found."); + } + } + + // PQ Subject 3 + if (!string.IsNullOrEmpty(row.PqSubjectCode3)) + { + if (lookups.PQSubject3MatchStatus == EwcWalesMatchStatus.NoMatch) + { + validationFailures.Add($"Subject with PQ Subject Code {row.PqSubjectCode3} was not found."); + } + else if (lookups.PQSubject3MatchStatus == EwcWalesMatchStatus.MultipleMatchesFound) + { + validationFailures.Add($"Multiple subjects with PQ Subject Code {row.PqSubjectCode3} found."); + } + } + + return (validationFailures, errors); + } + + public async Task<(EwcWalesMatchStatus, Guid? OrganisationId)> FindMatchingOrganisationsRecordAsync(string OrgNumber) + { + var query = new FindActiveOrganisationsByAccountNumberQuery(OrgNumber); + var results = await crmQueryDispatcher.ExecuteQueryAsync(query); + + if (results.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (results.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var organisationId = results.First().Id; + return (EwcWalesMatchStatus.OneMatch, organisationId); + } + + public async Task<(EwcWalesMatchStatus, Guid? HeQualificationId)> GetHEQualificationAsync(string qualificationCode) + { + var results = await cache.GetHeQualificationsAsync(); + var qualifications = results.Where(x => x.dfeta_Value == qualificationCode).ToArray(); + + if (qualifications.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (qualifications.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var subjectId = qualifications.First().Id; + return (EwcWalesMatchStatus.OneMatch, subjectId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetMatchingHESubjectAsync(string subjectCode) + { + var results = await cache.GetHeSubjectsAsync(); + var subjects = results.Where(x => x.dfeta_Value == subjectCode).ToArray(); + + if (subjects.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (subjects.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var subjectId = subjects.First().Id; + return (EwcWalesMatchStatus.OneMatch, subjectId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetTeacherStatusAsync(string qtsStatus) + { + var results = await cache.GetTeacherStatusesAsync(); + + if (qtsStatus != null && qtsStatus.Equals("67", StringComparison.InvariantCultureIgnoreCase)) + { + var status = results.Single(x => x.dfeta_Value == qtsStatus); //67 - Qualified Teacher: under the EC Directive + return (EwcWalesMatchStatus.OneMatch, status.Id); + } + else + { + var status = results.Single(x => x.dfeta_Value == "213"); //213 - Qualified Teacher: QTS awarded in Wales + return (EwcWalesMatchStatus.OneMatch, status.Id); + } + } + + public dfeta_classdivision? GetHEClassDivision(string classCode) + { + switch (classCode) + { + case "1": + case "01": + return dfeta_classdivision.Firstclasshonours; + case "2": + case "02": + return dfeta_classdivision.Uppersecondclasshonours; + case "3": + case "03": + return dfeta_classdivision.Lowersecondclasshonours; + case "4": + case "04": + return dfeta_classdivision.Undividedsecondclasshonours; + case "5": + case "05": + return dfeta_classdivision.Thirdclasshonours; + case "6": + case "06": + return dfeta_classdivision.Fourthclasshonours; + case "7": + case "07": + return dfeta_classdivision.Unclassifiedhonours; + case "8": + case "08": + return dfeta_classdivision.Aegrotat_whethertohonoursorpass; + case "9": + case "09": + return dfeta_classdivision.Passdegreeawardedwithouthonoursfollowinganhonourscourse; + case "10": + return dfeta_classdivision.Ordinary_includingdivisionsofordinaryifanydegreeawardedafterfollowinganonhonourscourse; + case "11": + return dfeta_classdivision.GeneralDegreedegreeawardedafterfollowinganonhonourscoursedegreethatwasnotavailabletobeclassified; + case "12": + return dfeta_classdivision.Distinction; + case "13": + return dfeta_classdivision.Merit; + case "14": + return dfeta_classdivision.Pass; + case "98": + return dfeta_classdivision.Notapplicable; + case "99": + return dfeta_classdivision.NotKnown; + default: + return null; + } + } + + public async Task<(EwcWalesMatchStatus, Guid? IttQualificationId)> GetIttQualificationAsync(string ittQualificationcode) + { + var results = await cache.GetIttQualificationsAsync(); + var qualifications = results.Where(x => x.dfeta_Value == ittQualificationcode).ToArray(); + + if (qualifications.Length == 0) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if (qualifications.Length > 1) + { + return (EwcWalesMatchStatus.MultipleMatchesFound, null); + } + + var qualificationId = qualifications.First().Id; + return (EwcWalesMatchStatus.OneMatch, qualificationId); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> FindIttSubjectAsync(string subjectCode) + { + var subject = await cache.GetIttSubjectBySubjectCodeAsync(subjectCode); + + if (subject is null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + return (EwcWalesMatchStatus.OneMatch, subject.Id); + } + + public async Task<(EwcWalesMatchStatus, Guid? SubjectId)> GetMatchingCountryAsync(string countryCode) + { + var country = await cache.GetCountryByCountryCodeAsync(countryCode); + if (country is null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + return (EwcWalesMatchStatus.OneMatch, country.Id); + } + + public async Task<(EwcWalesMatchStatus, Guid? PersonId)> FindMatchingTeacherRecordAsync(EwcWalesQtsFileImportData item) + { + var contact = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveContactByTrnQuery(item.QtsRefNo, + new ColumnSet( + Contact.Fields.dfeta_TRN, + Contact.Fields.BirthDate, + Contact.Fields.dfeta_QTSDate, + Contact.Fields.dfeta_qtlsdate))); + + if (contact == null) + { + return (EwcWalesMatchStatus.NoMatch, null); + } + + if ((DateOnly.TryParseExact(item.DateOfBirth, DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dob)) && + contact.BirthDate.ToDateOnlyWithDqtBstFix(isLocalTime: false) != dob) + { + return (EwcWalesMatchStatus.TrnAndDateOfBirthMatchFailed, null); + } + + var qtsRegistrations = await crmQueryDispatcher.ExecuteQueryAsync( + new GetActiveQtsRegistrationsByContactIdsQuery( + new[] { contact.ContactId!.Value }, + new ColumnSet( + dfeta_qtsregistration.Fields.dfeta_PersonId, + dfeta_qtsregistration.Fields.dfeta_QTSDate, + dfeta_qtsregistration.Fields.dfeta_TeacherStatusId) + ) + ); + + if (qtsRegistrations[contact.Id].Length > 0) + { + return (EwcWalesMatchStatus.TeacherHasQts, contact.ContactId!); + } + else + { + return (EwcWalesMatchStatus.NoAssociatedQts, contact.ContactId!); + } + } + + public class QtsImportLookupData + { + public required Guid? PersonId { get; set; } + public required EwcWalesMatchStatus? PersonMatchStatus { get; set; } + public required Guid? IttEstabCodeId { get; set; } + public required EwcWalesMatchStatus? IttEstabCodeMatchStatus { get; set; } + public required Guid? IttQualificationId { get; set; } + public required EwcWalesMatchStatus? IttQualificationMatchStatus { get; set; } + public required Guid? IttSubject1Id { get; set; } + public required EwcWalesMatchStatus? IttSubject1MatchStatus { get; set; } + public required Guid? IttSubject2Id { get; set; } + public required EwcWalesMatchStatus? IttSubject2MatchStatus { get; set; } + public required Guid? PqEstablishmentId { get; set; } + public required EwcWalesMatchStatus? PqEstablishmentMatchStatus { get; set; } + public required Guid? PQCountryId { get; set; } + public required EwcWalesMatchStatus? PQCountryMatchStatus { get; set; } + public required Guid? PQHEQualificationId { get; set; } + public required EwcWalesMatchStatus? PQHEQualificationMatchStatus { get; set; } + public required Guid? PQSubject1Id { get; set; } + public required EwcWalesMatchStatus? PQSubject1MatchStatus { get; set; } + public required Guid? PQSubject2Id { get; set; } + public required EwcWalesMatchStatus? PQSubject2MatchStatus { get; set; } + public required Guid? PQSubject3Id { get; set; } + public required EwcWalesMatchStatus? PQSubject3MatchStatus { get; set; } + public required Guid? TeacherStatusId { get; set; } + public required EwcWalesMatchStatus? TeacherStatusMatchStatus { get; set; } + public required dfeta_classdivision? ClassDivision { get; set; } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/HostApplicationBuilderExtensions.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/HostApplicationBuilderExtensions.cs index a803bec76..aced47038 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/HostApplicationBuilderExtensions.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Jobs/HostApplicationBuilderExtensions.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using TeachingRecordSystem.Core.Jobs.EwcWalesImport; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; using TeachingRecordSystem.Core.Jobs.Scheduling; using TeachingRecordSystem.Core.Services.Establishments.Gias; @@ -76,6 +78,10 @@ public static IHostApplicationBuilder AddBackgroundJobs(this IHostApplicationBui }); } + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddStartupTask(sp => { var recurringJobManager = sp.GetRequiredService(); @@ -189,6 +195,11 @@ public static IHostApplicationBuilder AddBackgroundJobs(this IHostApplicationBui job => job.ExecuteAsync(CancellationToken.None), Cron.Never); + recurringJobManager.AddOrUpdate( + nameof(EwcWalesImportJob), + job => job.ExecuteAsync(CancellationToken.None), + EwcWalesImportJob.JobSchedule); + return Task.CompletedTask; }); } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/ReferenceDataCache.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/ReferenceDataCache.cs index b90bb841d..70729c9f6 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/ReferenceDataCache.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/ReferenceDataCache.cs @@ -18,6 +18,9 @@ public class ReferenceDataCache( private Task? _getSpecialismsTask; private Task? _getHeQualificationsTask; private Task? _getHeSubjectsTask; + private Task? _getCountriesTask; + private Task? _getIttSubjectsTask; + private Task? _getIttQualificationsTask; // TRS private Task? _alertCategoriesTask; @@ -184,6 +187,24 @@ public async Task GetAlertTypeByDqtSanctionCodeAsync(string dqtSancti return alertTypes.SingleOrDefault(at => at.DqtSanctionCode == dqtSanctionCode); } + public async Task GetCountryByCountryCodeAsync(string countryCode) + { + var countries = await EnsureCountriesAsync(); + return countries.SingleOrDefault(at => at.dfeta_Value == countryCode); + } + + public async Task GetIttSubjectBySubjectCodeAsync(string subjectCode) + { + var ittSubjects = await EnsureIttSubjectsAsync(); + return ittSubjects.SingleOrDefault(at => at.dfeta_Value == subjectCode); + } + + public async Task GetIttQualificationsAsync() + { + var ittQualifications = await EnsureIttQualificationsAsync(); + return ittQualifications.ToArray(); + } + private Task EnsureSanctionCodesAsync() => LazyInitializer.EnsureInitialized( ref _getSanctionCodesTask, @@ -242,6 +263,21 @@ private Task EnsureAlertTypesAsync() => return await dbContext.AlertTypes.AsNoTracking().Include(at => at.AlertCategory).ToArrayAsync(); }); + private Task EnsureCountriesAsync() => + LazyInitializer.EnsureInitialized( + ref _getCountriesTask, + () => crmQueryDispatcher.ExecuteQueryAsync(new GetAllCountriesQuery())); + + private Task EnsureIttSubjectsAsync() => + LazyInitializer.EnsureInitialized( + ref _getIttSubjectsTask, + () => crmQueryDispatcher.ExecuteQueryAsync(new GetAllActiveIttSubjectsQuery())); + + private Task EnsureIttQualificationsAsync() => + LazyInitializer.EnsureInitialized( + ref _getIttQualificationsTask, + () => crmQueryDispatcher.ExecuteQueryAsync(new GetAllActiveIttQualificationsQuery())); + async Task IStartupTask.ExecuteAsync() { // CRM @@ -253,6 +289,9 @@ async Task IStartupTask.ExecuteAsync() await EnsureMqEstablishmentsAsync(); await EnsureHeQualificationsAsync(); await EnsureHeSubjectsAsync(); + await EnsureCountriesAsync(); + await EnsureIttSubjectsAsync(); + await EnsureIttQualificationsAsync(); // TRS await EnsureAlertCategoriesAsync(); diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionPeriodTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionPeriodTests.cs new file mode 100644 index 000000000..7706ed56e --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionPeriodTests.cs @@ -0,0 +1,74 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateInductionPeriodTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + private readonly CrmClientFixture _fixture; + + public CreateInductionPeriodTests(CrmClientFixture crmClientFixture) + { + _fixture = crmClientFixture; + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var org = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName("Testing"); + }); + var contact = await _dataScope.TestData.CreatePersonAsync(x => + { + x.WithQts(new DateOnly(2024, 01, 01)); + }); + var startDate = new DateTime(2024, 01, 01); + var completionDate = new DateTime(2024, 02, 01); + var inductionStatus = dfeta_InductionStatus.InProgress; + var inductionStartDate = new DateTime(2024, 01, 01); + var inductionEndDate = new DateTime(2024, 02, 01); + var inductionId = Guid.NewGuid(); + var inductionPeriodId = Guid.NewGuid(); + var queryInduction = new CreateInductionTransactionalQuery() + { + Id = inductionId, + ContactId = contact.PersonId, + StartDate = startDate, + CompletionDate = completionDate, + InductionStatus = inductionStatus, + }; + var queryInductionPeriod = new CreateInductionPeriodTransactionalQuery() + { + Id = inductionPeriodId, + InductionId = inductionId, + AppropriateBodyId = org.Id, + InductionStartDate = inductionStartDate, + InductionEndDate = inductionEndDate, + }; + txn.AppendQuery(queryInduction); + txn.AppendQuery(queryInductionPeriod); + + // Act + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var induction = ctx.dfeta_inductionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == inductionId); + var inductionPeriod = ctx.dfeta_inductionperiodSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_inductionperiod.PrimaryIdAttribute) == inductionPeriodId); + Assert.NotNull(induction); + Assert.NotNull(inductionPeriod); + Assert.Equal(inductionPeriodId, inductionPeriod.Id); + Assert.Equal(inductionId, inductionPeriod.dfeta_InductionId.Id); + Assert.Equal(org.Id, inductionPeriod.dfeta_AppropriateBodyId.Id); + Assert.Equal(startDate, inductionPeriod.dfeta_StartDate); + Assert.Equal(inductionEndDate, inductionPeriod.dfeta_EndDate); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionTests.cs new file mode 100644 index 000000000..22204aae2 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInductionTests.cs @@ -0,0 +1,53 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateInductionTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + private readonly CrmClientFixture _fixture; + + public CreateInductionTests(CrmClientFixture crmClientFixture) + { + _fixture = crmClientFixture; + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var contact = await _dataScope.TestData.CreatePersonAsync(x => x.WithQts(new DateOnly(2024, 01, 01))); + var startDate = new DateTime(2024, 01, 01); + var completionDate = new DateTime(2024, 02, 01); + var inductionStatus = dfeta_InductionStatus.InProgress; + var inductionId = Guid.NewGuid(); + + var query = new CreateInductionTransactionalQuery() + { + Id = inductionId, + ContactId = contact.PersonId, + StartDate = startDate, + CompletionDate = completionDate, + InductionStatus = inductionStatus, + }; + txn.AppendQuery(query); + + // Act + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var induction = ctx.dfeta_inductionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == inductionId); + Assert.NotNull(induction); + Assert.Equal(contact.PersonId, induction.dfeta_PersonId.Id); + Assert.Equal(startDate, induction.dfeta_StartDate); + Assert.Equal(completionDate, induction.dfeta_CompletionDate); + Assert.Equal(inductionStatus, induction.dfeta_InductionStatus); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInitialTeacherTrainingTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInitialTeacherTrainingTests.cs new file mode 100644 index 000000000..80c34f720 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateInitialTeacherTrainingTests.cs @@ -0,0 +1,54 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateInitialTeacherTrainingTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + private readonly CrmClientFixture _fixture; + + public CreateInitialTeacherTrainingTests(CrmClientFixture crmClientFixture) + { + _fixture = crmClientFixture; + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var countries = await _crmQueryDispatcher.ExecuteQueryAsync(new GetAllCountriesQuery()); + var country = countries.FirstOrDefault(x => x.dfeta_Value == "XK"); + var qualificationId = Guid.NewGuid(); + var ittId = Guid.NewGuid(); + var contact = await _dataScope.TestData.CreatePersonAsync(x => + { + x.WithTrn(); + x.WithQts(new DateOnly(2024, 01, 01)); + x.WithQualification(qualificationId, dfeta_qualification_dfeta_Type.NPQH); + }); + var query = new CreateInitialTeacherTrainingTransactionalQuery() + { + Id = ittId, + ContactId = contact.PersonId, + ITTQualificationId = null, + CountryId = country!.Id, + Result = dfeta_ITTResult.Pass + }; + txn.AppendQuery(query); + + // Act + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var itt = ctx.dfeta_initialteachertrainingSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_initialteachertraining.PrimaryIdAttribute) == ittId); + Assert.NotNull(itt); + Assert.Equal(dfeta_ITTResult.Pass, itt.dfeta_Result); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionRecordTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionRecordTests.cs new file mode 100644 index 000000000..275ec93c4 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionRecordTests.cs @@ -0,0 +1,91 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateIntegrationTransactionRecordTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public CreateIntegrationTransactionRecordTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var activeNpqQualificationType = dfeta_qualification_dfeta_Type.NPQLT; + var activeNpqQualificationId = Guid.NewGuid(); + var startDate = new DateTime(2011, 01, 1); + var typeId = dfeta_IntegrationInterface.GTCWalesImport; + var reference = "1"; + var fileName = "QTS_FILE.csv"; + Guid? itrId = null; + var rowData = "SOMEROWDATA"; + var statusCode = dfeta_integrationtransactionrecord_StatusCode.Fail; + var failureMessage = "SOME FAILURE"; + + var establishment1 = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName("SomeAccountName"); + }); + var person = await _dataScope.TestData.CreatePersonAsync(b => b + .WithQts(new DateOnly(2021, 01, 1)) + .WithDqtInduction(inductionStatus: dfeta_InductionStatus.Pass, inductionExemptionReason: null, inductionPeriodStartDate: new DateOnly(2021, 01, 01), completedDate: new DateOnly(2022, 01, 01), inductionStartDate: new DateOnly(2021, 01, 01), inductionPeriodEndDate: new DateOnly(2022, 01, 01), appropriateBodyOrgId: establishment1.AccountId) + .WithQualification(activeNpqQualificationId, activeNpqQualificationType, isActive: true)); + + var query = new CreateIntegrationTransactionQuery() + { + TypeId = (int)typeId, + StartDate = startDate, + FileName = fileName + }; + var integrationTransactionId = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + var recordQuery = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationTransactionId, + Reference = reference, + ContactId = person.PersonId, + InitialTeacherTrainingId = null, + QualificationId = null, + InductionId = person.DqtInductions.First().InductionId, + InductionPeriodId = person.DqtInductionPeriods.First().InductionPeriodId, + DuplicateStatus = dfeta_integrationtransactionrecord_dfeta_DuplicateStatus.Duplicate, + FileName = fileName, + RowData = rowData, + StatusCode = statusCode, + FailureMessage = failureMessage + }; + + // Act + var itr = txn.AppendQuery(recordQuery); + await txn.ExecuteAsync(); + itrId = itr(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + + var createdIntegrationTransaction = ctx.dfeta_integrationtransactionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var createdIntegrationTransactionRecord = ctx.dfeta_integrationtransactionrecordSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.PrimaryIdAttribute) == itrId.Value); + Assert.NotNull(createdIntegrationTransaction); + Assert.NotNull(createdIntegrationTransactionRecord); + Assert.Equal(fileName, createdIntegrationTransaction.dfeta_Filename); + Assert.Equal(integrationTransactionId, createdIntegrationTransactionRecord.dfeta_IntegrationTransactionId.Id); + Assert.Equal(reference, createdIntegrationTransactionRecord.dfeta_id); + Assert.Equal(person.ContactId, createdIntegrationTransactionRecord.dfeta_PersonId.Id); + Assert.Equal(person.DqtInductions.First().InductionId, createdIntegrationTransactionRecord.dfeta_InductionId.Id); + Assert.Equal(person.DqtInductionPeriods.First().InductionPeriodId, createdIntegrationTransactionRecord.dfeta_InductionPeriodId.Id); + Assert.Equal(dfeta_integrationtransactionrecord_dfeta_DuplicateStatus.Duplicate, createdIntegrationTransactionRecord.dfeta_DuplicateStatus); + Assert.Equal(fileName, createdIntegrationTransactionRecord.dfeta_Filename); + Assert.Equal(rowData, createdIntegrationTransactionRecord.dfeta_RowData); + Assert.Equal(failureMessage, createdIntegrationTransactionRecord.dfeta_FailureMessage); + Assert.Equal(statusCode, createdIntegrationTransactionRecord.StatusCode); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionTests.cs new file mode 100644 index 000000000..d56891bf9 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateIntegrationTransactionTests.cs @@ -0,0 +1,44 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateIntegrationTransactionTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public CreateIntegrationTransactionTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var startDate = new DateTime(2011, 01, 1); + var typeId = dfeta_IntegrationInterface.GTCWalesImport; + var fileName = "QTS.csv"; + var query = new CreateIntegrationTransactionQuery() + { + TypeId = (int)typeId, + StartDate = startDate, + FileName = fileName + }; + + // Act + var id = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + + var createdIntegrationTransaction = ctx.dfeta_integrationtransactionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == id); + Assert.NotNull(createdIntegrationTransaction); + Assert.Equal(dfeta_IntegrationInterface.GTCWalesImport, createdIntegrationTransaction.dfeta_Interface); + Assert.Equal(startDate, createdIntegrationTransaction.dfeta_StartDate); + Assert.Equal(fileName, createdIntegrationTransaction.dfeta_Filename); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateQTSTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateQTSTests.cs new file mode 100644 index 000000000..4cb8eff60 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/CreateQTSTests.cs @@ -0,0 +1,53 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class CreateQTSTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public CreateQTSTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var contact = await _dataScope.TestData.CreatePersonAsync(x => + { + x.WithTrn(); + x.WithQts(); + }); + var qtsDate = new DateTime(2024, 01, 01); + var teacherStatusQualifiedTeacherTrained = "213"; + var query = new GetAllTeacherStatusesQuery(); + var result = await _crmQueryDispatcher.ExecuteQueryAsync(query); + var teacherStatusId = result.FirstOrDefault(x => x.dfeta_Value == teacherStatusQualifiedTeacherTrained); + var qtsId = Guid.NewGuid(); + var queryCreateQts = new CreateQtsRegistrationTransactionalQuery() + { + Id = qtsId, + ContactId = contact.PersonId, + TeacherStatusId = teacherStatusId!.Id, + QtsDate = qtsDate + }; + txn.AppendQuery(queryCreateQts); + + // Act + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var qts = ctx.dfeta_qtsregistrationSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_qtsregistration.PrimaryIdAttribute) == qtsId); + Assert.NotNull(qts); + Assert.Equal(qtsDate, qts.dfeta_QTSDate); + Assert.Equal(contact.PersonId, qts.dfeta_PersonId.Id); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/FindOrganisationsByOrgNumberTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/FindOrganisationsByOrgNumberTests.cs new file mode 100644 index 000000000..bb8abe63a --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/FindOrganisationsByOrgNumberTests.cs @@ -0,0 +1,80 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class FindOrganisationsByOrgNumberTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public FindOrganisationsByOrgNumberTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task FindByOrgNumber_ReturnsSingleMatch() + { + // Arrange + var accountNumber = "1234"; + var accountName = "testing"; + var account1 = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName(accountName); + x.WithAccountNumber(accountNumber); + }); + var query = new FindActiveOrganisationsByAccountNumberQuery(accountNumber); + + // Act + var results = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + // Assert + Assert.Collection( + results, + account => + { + Assert.Equal(account.Id, account1.Id); + Assert.Equal(account.Name, accountName); + Assert.Equal(account.AccountNumber, accountNumber); + }); + } + + [Fact] + public async Task FindOrganisationsByAccountNumber_ReturnsMultipleMatches() + { + // Arrange + var accountNumber = "95556"; + var accountName1 = "testing"; + var account1 = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName(accountName1); + x.WithAccountNumber(accountNumber); + }); + var accountName2 = "secondAccount"; + var account2 = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName(accountName2); + x.WithAccountNumber(accountNumber); + }); + var query = new FindActiveOrganisationsByAccountNumberQuery(accountNumber); + + // Act + var results = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + // Assert + Assert.Contains(results, account => + account.Id == account1.Id && + account.Name == accountName1 && + account.AccountNumber == accountNumber + ); + + Assert.Contains(results, account => + account.Id == account2.Id && + account.Name == accountName2 && + account.AccountNumber == accountNumber + ); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttQualificationsTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttQualificationsTests.cs new file mode 100644 index 000000000..e3dcf4aa9 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttQualificationsTests.cs @@ -0,0 +1,24 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class GetAllActiveIttQualificationsTests +{ + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public GetAllActiveIttQualificationsTests(CrmClientFixture crmClientFixture) + { + _crmQueryDispatcher = crmClientFixture.CreateQueryDispatcher(); + } + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var query = new GetAllActiveIttQualificationsQuery(); + + // Act + var result = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + // Assert + Assert.NotEmpty(result); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttSubjectsTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttSubjectsTests.cs new file mode 100644 index 000000000..39c9fce42 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/GetAllActiveIttSubjectsTests.cs @@ -0,0 +1,24 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class GetAllActiveIttSubjectsTests +{ + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public GetAllActiveIttSubjectsTests(CrmClientFixture crmClientFixture) + { + _crmQueryDispatcher = crmClientFixture.CreateQueryDispatcher(); + } + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var query = new GetAllActiveIttSubjectsQuery(); + + // Act + var result = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + // Assert + Assert.NotEmpty(result); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionPeriodTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionPeriodTests.cs new file mode 100644 index 000000000..1edfdddeb --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionPeriodTests.cs @@ -0,0 +1,86 @@ + +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class UpdateInductionPeriodTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + private readonly CrmClientFixture _fixture; + + public UpdateInductionPeriodTests(CrmClientFixture crmClientFixture) + { + _fixture = crmClientFixture; + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var inductionStartDate = new DateTime(2024, 01, 01); + var inductionEndDate = new DateTime(2024, 02, 01); + var inductionStatus = dfeta_InductionStatus.InProgress; + var inductionPeriodStartDate = new DateTime(2024, 01, 01); + var inductionPeriodEndDate = new DateTime(2024, 02, 01); + var updatedInductionPeriodStartDate = new DateTime(2024, 06, 28); + var updatedInductionPeriodEndDate = new DateTime(2024, 08, 01); + var inductionId = Guid.NewGuid(); + var inductionPeriodId = Guid.NewGuid(); + var org = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName("Testing"); + }); + var contact = await _dataScope.TestData.CreatePersonAsync(x => + { + x.WithQts(new DateOnly(2024, 01, 01)); + }); + + var createInductionQuery = new CreateInductionTransactionalQuery() + { + Id = inductionId, + ContactId = contact.PersonId, + StartDate = inductionEndDate, + CompletionDate = inductionEndDate, + InductionStatus = inductionStatus, + }; + var createInductionPeriodQuery = new CreateInductionPeriodTransactionalQuery() + { + Id = inductionPeriodId, + InductionId = inductionId, + AppropriateBodyId = org.Id, + InductionStartDate = inductionPeriodStartDate, + InductionEndDate = inductionPeriodEndDate, + }; + var updatedInductionPeriodQuery = new UpdateInductionPeriodTransactionalQuery() + { + InductionPeriodId = inductionPeriodId, + AppropriateBodyId = org.Id, + InductionStartDate = updatedInductionPeriodStartDate, + InductionEndDate = updatedInductionPeriodEndDate, + }; + txn.AppendQuery(createInductionQuery); + txn.AppendQuery(createInductionPeriodQuery); + txn.AppendQuery(updatedInductionPeriodQuery); + + // Act + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var induction = ctx.dfeta_inductionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == inductionId); + var inductionPeriod = ctx.dfeta_inductionperiodSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_inductionperiod.PrimaryIdAttribute) == inductionPeriodId); + Assert.NotNull(induction); + Assert.NotNull(inductionPeriod); + Assert.Equal(inductionPeriodId, inductionPeriod.Id); + Assert.Equal(inductionId, inductionPeriod.dfeta_InductionId.Id); + Assert.Equal(org.Id, inductionPeriod.dfeta_AppropriateBodyId.Id); + Assert.Equal(updatedInductionPeriodStartDate, inductionPeriod.dfeta_StartDate); + Assert.Equal(updatedInductionPeriodEndDate, inductionPeriod.dfeta_EndDate); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionTests.cs new file mode 100644 index 000000000..6aadd1a52 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateInductionTests.cs @@ -0,0 +1,59 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class UpdateInductionTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public UpdateInductionTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var startDate = new DateTime(2001, 05, 1); + var completionDate = new DateTime(2011, 05, 1); + var inductionStatus = dfeta_InductionStatus.Pass; + var inductionId = Guid.NewGuid(); + var contact = await _dataScope.TestData.CreatePersonAsync(x => + { + x.WithQts(new DateOnly(2024, 01, 01)); + }); + var queryInduction = new CreateInductionTransactionalQuery() + { + Id = inductionId, + ContactId = contact.PersonId, + StartDate = startDate, + CompletionDate = null, + InductionStatus = dfeta_InductionStatus.InProgress, + }; + txn.AppendQuery(queryInduction); + + // Act + var updateInductionQuery = new UpdateInductionTransactionalQuery() + { + InductionId = inductionId, + CompletionDate = completionDate, + InductionStatus = inductionStatus + }; + txn.AppendQuery(updateInductionQuery); + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var induction = ctx.dfeta_inductionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == inductionId); + Assert.NotNull(induction); + Assert.Equal(startDate, induction.dfeta_StartDate); + Assert.Equal(completionDate, induction.dfeta_CompletionDate); + Assert.Equal(inductionStatus, induction.dfeta_InductionStatus); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionRecordTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionRecordTests.cs new file mode 100644 index 000000000..566799223 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionRecordTests.cs @@ -0,0 +1,109 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class UpdateIntegrationTransactionRecordTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public UpdateIntegrationTransactionRecordTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + var activeNpqQualificationType = dfeta_qualification_dfeta_Type.NPQLT; + var activeNpqQualificationId = Guid.NewGuid(); + var startDate = new DateTime(2011, 01, 1); + var typeId = dfeta_IntegrationInterface.GTCWalesImport; + var reference = "1"; + var rowData = "SOME ROW DATA"; + var statusCode = dfeta_integrationtransactionrecord_StatusCode.Fail; + var failureMessage = "THIS IS A FAILURE MESSAGE"; + var fileName = "QTS_FAILEDFILE.csv"; + Guid? itrId = null; + + var establishment1 = await _dataScope.TestData.CreateAccountAsync(x => + { + x.WithName("SomeAccountName"); + }); + var person = await _dataScope.TestData.CreatePersonAsync(b => b + .WithQts(new DateOnly(2021, 01, 1)) + .WithDqtInduction(inductionStatus: dfeta_InductionStatus.Pass, inductionExemptionReason: null, inductionPeriodStartDate: new DateOnly(2021, 01, 01), completedDate: new DateOnly(2022, 01, 01), inductionStartDate: new DateOnly(2021, 01, 01), inductionPeriodEndDate: new DateOnly(2022, 01, 01), appropriateBodyOrgId: establishment1.AccountId) + .WithQualification(activeNpqQualificationId, activeNpqQualificationType, isActive: true)); + + var query = new CreateIntegrationTransactionQuery() + { + TypeId = (int)typeId, + StartDate = startDate, + FileName = "FILENAME.csv" + }; + var integrationTransactionId = await _crmQueryDispatcher.ExecuteQueryAsync(query); + + var recordQuery = new CreateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionId = integrationTransactionId, + Reference = reference, + ContactId = person.PersonId, + InitialTeacherTrainingId = null, + QualificationId = null, + InductionId = null, + InductionPeriodId = null, + DuplicateStatus = dfeta_integrationtransactionrecord_dfeta_DuplicateStatus.Duplicate, + FileName = fileName, + FailureMessage = "", + StatusCode = dfeta_integrationtransactionrecord_StatusCode.Fail, + RowData = "", + }; + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var itr = txn.AppendQuery(recordQuery); + await txn.ExecuteAsync(); + itrId = itr(); + + + using var txn2 = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var updateRecordQuery = new UpdateIntegrationTransactionRecordTransactionalQuery() + { + IntegrationTransactionRecordId = itrId.Value, + IntegrationTransactionId = integrationTransactionId, + Reference = reference, + PersonId = person.PersonId, + InitialTeacherTrainingId = null, + QualificationId = null, + InductionId = person.DqtInductions.First().InductionId, + InductionPeriodId = person.DqtInductionPeriods.First().InductionPeriodId, + DuplicateStatus = dfeta_integrationtransactionrecord_dfeta_DuplicateStatus.Duplicate, + FailureMessage = failureMessage, + StatusCode = statusCode, + RowData = rowData, + }; + txn2.AppendQuery(updateRecordQuery); + + // Act + await txn2.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var createdIntegrationTransaction = ctx.dfeta_integrationtransactionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var updatedIntegrationTransactionRecord = ctx.dfeta_integrationtransactionrecordSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.PrimaryIdAttribute) == itrId); + Assert.NotNull(createdIntegrationTransaction); + Assert.NotNull(updatedIntegrationTransactionRecord); + Assert.Equal(integrationTransactionId, updatedIntegrationTransactionRecord.dfeta_IntegrationTransactionId.Id); + Assert.Equal(reference, updatedIntegrationTransactionRecord.dfeta_id); + Assert.Equal(person.ContactId, updatedIntegrationTransactionRecord.dfeta_PersonId.Id); + Assert.Equal(person.DqtInductions.First().InductionId, updatedIntegrationTransactionRecord.dfeta_InductionId.Id); + Assert.Equal(person.DqtInductionPeriods.First().InductionPeriodId, updatedIntegrationTransactionRecord.dfeta_InductionPeriodId.Id); + Assert.Equal(dfeta_integrationtransactionrecord_dfeta_DuplicateStatus.Duplicate, updatedIntegrationTransactionRecord.dfeta_DuplicateStatus); + Assert.Equal(rowData, updatedIntegrationTransactionRecord.dfeta_RowData); + Assert.Equal(failureMessage, updatedIntegrationTransactionRecord.dfeta_FailureMessage); + Assert.Equal(statusCode, updatedIntegrationTransactionRecord.StatusCode); + Assert.Equal(fileName, updatedIntegrationTransactionRecord.dfeta_Filename); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionTests.cs new file mode 100644 index 000000000..5b04df54a --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Dqt.CrmIntegrationTests/QueryTests/UpdateIntegrationTransactionTests.cs @@ -0,0 +1,66 @@ +namespace TeachingRecordSystem.Core.Dqt.CrmIntegrationTests.QueryTests; + +public class UpdateIntegrationTransactionTests : IAsyncLifetime +{ + private readonly CrmClientFixture.TestDataScope _dataScope; + private readonly CrmQueryDispatcher _crmQueryDispatcher; + + public UpdateIntegrationTransactionTests(CrmClientFixture crmClientFixture) + { + _dataScope = crmClientFixture.CreateTestDataScope(); + _crmQueryDispatcher = _dataScope.CreateQueryDispatcher(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() => await _dataScope.DisposeAsync(); + + [Fact] + public async Task QueryExecutesSuccessfully() + { + // Arrange + using var txn = _crmQueryDispatcher.CreateTransactionRequestBuilder(); + var totalCount = 10; + var successCount = 5; + var duplicateCount = 1; + var failureCount = 4; + var failureMessage = "fail"; + var fileName = "fileName.csv"; + + var startDate = new DateTime(2011, 01, 1); + var endDate = new DateTime(2011, 01, 2); + var typeId = dfeta_IntegrationInterface.GTCWalesImport; + var query = new CreateIntegrationTransactionQuery() + { + TypeId = (int)typeId, + StartDate = startDate, + FileName = fileName + }; + + // Act + var id = await _crmQueryDispatcher.ExecuteQueryAsync(query); + var updateQuery = new UpdateIntegrationTransactionTransactionalQuery() + { + IntegrationTransactionId = id, + EndDate = endDate, + TotalCount = totalCount, + SuccessCount = successCount, + DuplicateCount = duplicateCount, + FailureCount = failureCount, + FailureMessage = failureMessage + }; + txn.AppendQuery(updateQuery); + await txn.ExecuteAsync(); + + // Assert + using var ctx = new DqtCrmServiceContext(_dataScope.OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == id); + Assert.Equal(totalCount, integrationTransaction!.dfeta_TotalCount); + Assert.Equal(successCount, integrationTransaction!.dfeta_SuccessCount); + Assert.Equal(duplicateCount, integrationTransaction!.dfeta_DuplicateCount); + Assert.Equal(failureCount, integrationTransaction!.dfeta_FailureCount); + Assert.Equal(failureMessage, integrationTransaction!.dfeta_FailureMessage); + Assert.Equal(endDate, integrationTransaction!.dfeta_EndDate); + Assert.Equal(fileName, integrationTransaction!.dfeta_Filename); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/EwcWalesImportJobTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/EwcWalesImportJobTests.cs new file mode 100644 index 000000000..f3238229b --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/EwcWalesImportJobTests.cs @@ -0,0 +1,689 @@ +using System.Globalization; +using System.Text; +using Azure.Storage.Blobs; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.PowerPlatform.Dataverse.Client; +using TeachingRecordSystem.Core.Dqt; +using TeachingRecordSystem.Core.Dqt.Models; +using TeachingRecordSystem.Core.Jobs.EwcWalesImport; +using TeachingRecordSystem.Core.Jobs.EWCWalesImport; +using TeachingRecordSystem.Core.Services.TrsDataSync; + +namespace TeachingRecordSystem.Core.Tests.Jobs; + +[Collection(nameof(DisableParallelization))] +public class EwcWalesImportJobTests : IClassFixture +{ + public EwcWalesImportJobTests(EwcWalesImportJobFixture fixture) + { + Fixture = fixture; + } + + private DbFixture DbFixture => Fixture.DbFixture; + + private IClock Clock => Fixture.Clock; + + private TestData TestData => Fixture.TestData; + + private EwcWalesImportJobFixture Fixture { get; } + + public IOrganizationServiceAsync2 OrganizationService => Fixture.OrganizationService; + + private EwcWalesImportJob Job => Fixture.Job; + + [Theory] + [InlineData("IND", EwcWalesImportFileType.Induction)] + [InlineData("QTS", EwcWalesImportFileType.Qualification)] + [InlineData("", null)] + public void EwcWalesImportJob_GetImportFileType_ReturnsExpected(string filename, EwcWalesImportFileType? importType) + { + Fixture.Job.TryGetImportFileType(filename, out var type); + Assert.Equal(importType, type); + } + + [Fact] + public async Task EwcWalesImportJobQts_ImportsQtsFileSuccessfully() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var fileName = "QTS.csv"; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn = person.Trn; + var csvContent = $"QTS_REF_NO,FORENAME,SURNAME,DATE_OF_BIRTH,QTS_STATUS,QTS_DATE,ITT StartMONTH,ITT START YY,ITT End Date,ITT Course Length,ITT Estab LEA code,ITT Estab Code,ITT Qual Code,ITT Class Code,ITT Subject Code 1,ITT Subject Code 2,ITT Min Age Range,ITT Max Age Range,ITT Min Sp Age Range,ITT Max Sp Age Range,ITT Course Length,PQ Year of Award,COUNTRY,PQ Estab Code,PQ Qual Code,HONOURS,PQ Class Code,PQ Subject Code 1,PQ Subject Code 2,PQ Subject Code 3\r\n{trn},firstname,lastname,{person.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync(fileName, reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var qualification = ctx.dfeta_qualificationSet.Single(i => i.GetAttributeValue(dfeta_qualification.Fields.dfeta_PersonId) == person.ContactId); + var itt = ctx.dfeta_initialteachertrainingSet.Single(i => i.GetAttributeValue(dfeta_initialteachertraining.Fields.dfeta_PersonId) == person.ContactId); + var qts = ctx.dfeta_qtsregistrationSet.Single(i => i.GetAttributeValue(dfeta_qtsregistration.Fields.dfeta_PersonId) == person.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + }); + Assert.NotNull(qualification); + Assert.NotNull(itt); + Assert.NotNull(qts); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + Assert.Equal(fileName, integrationTransaction.dfeta_Filename); + } + + [Fact] + public async Task EwcWalesImportJobQts_SingleSuccessAndFailure_ReturnsExpectedCounts() + { + // Arrange + var expectedTotalRowCount = 2; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 1; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn = person.Trn; + var expectedValueMessage = $"Teacher with TRN {trn} has QTS already."; + var csvContent = $"QTS_REF_NO,FORENAME,SURNAME,DATE_OF_BIRTH,QTS_STATUS,QTS_DATE,ITT StartMONTH,ITT START YY,ITT End Date,ITT Course Length,ITT Estab LEA code,ITT Estab Code,ITT Qual Code,ITT Class Code,ITT Subject Code 1,ITT Subject Code 2,ITT Min Age Range,ITT Max Age Range,ITT Min Sp Age Range,ITT Max Sp Age Range,ITT Course Length,PQ Year of Award,COUNTRY,PQ Estab Code,PQ Qual Code,HONOURS,PQ Class Code,PQ Subject Code 1,PQ Subject Code 2,PQ Subject Code 3\r\n{trn},firstname,lastname,{person.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n{trn},firstname,lastname,{person.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("QTS", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var qualification = ctx.dfeta_qualificationSet.Single(i => i.GetAttributeValue(dfeta_qualification.Fields.dfeta_PersonId) == person.ContactId); + var itt = ctx.dfeta_initialteachertrainingSet.Single(i => i.GetAttributeValue(dfeta_initialteachertraining.Fields.dfeta_PersonId) == person.ContactId); + var qts = ctx.dfeta_qtsregistrationSet.Single(i => i.GetAttributeValue(dfeta_qtsregistration.Fields.dfeta_PersonId) == person.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + }, + item2 => + { + Assert.Contains(expectedValueMessage, item2.dfeta_FailureMessage); + }); + Assert.NotNull(qualification); + Assert.NotNull(itt); + Assert.NotNull(qts); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.NotEmpty(integrationTransaction.dfeta_FailureMessage); + Assert.Contains(expectedValueMessage, integrationTransaction.dfeta_FailureMessage, StringComparison.InvariantCultureIgnoreCase); + } + + [Fact] + public async Task EwcWalesImportJobQts_MultipleSuccessMultipleFailure_ReturnsExpectedCounts() + { + // Arrange + var expectedTotalRowCount = 4; + var expectedSuccessCount = 2; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 2; + var person1 = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person1.Trn; + var person2 = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn2 = person2.Trn; + var expectedValueMessage1 = $"Teacher with TRN {trn1} has QTS already."; + var expectedValueMessage2 = $"Teacher with TRN {trn2} has QTS already."; + var csvContent = $"QTS_REF_NO,FORENAME,SURNAME,DATE_OF_BIRTH,QTS_STATUS,QTS_DATE,ITT StartMONTH,ITT START YY,ITT End Date,ITT Course Length,ITT Estab LEA code,ITT Estab Code,ITT Qual Code,ITT Class Code,ITT Subject Code 1,ITT Subject Code 2,ITT Min Age Range,ITT Max Age Range,ITT Min Sp Age Range,ITT Max Sp Age Range,ITT Course Length,PQ Year of Award,COUNTRY,PQ Estab Code,PQ Qual Code,HONOURS,PQ Class Code,PQ Subject Code 1,PQ Subject Code 2,PQ Subject Code 3\r\n{trn1},firstname,lastname,{person1.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n{trn1},firstname,lastname,{person1.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n{trn2},firstname,lastname,{person2.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n{trn2},firstname,lastname,{person2.DateOfBirth.ToString("dd/MM/yyyy")},49,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("QTS", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var qualificationPerson1 = ctx.dfeta_qualificationSet.Single(i => i.GetAttributeValue(dfeta_qualification.Fields.dfeta_PersonId) == person1.ContactId); + var ittPerson1 = ctx.dfeta_initialteachertrainingSet.Single(i => i.GetAttributeValue(dfeta_initialteachertraining.Fields.dfeta_PersonId) == person1.ContactId); + var qtsPerson1 = ctx.dfeta_qtsregistrationSet.Single(i => i.GetAttributeValue(dfeta_qtsregistration.Fields.dfeta_PersonId) == person1.ContactId); + var qualificationPerson2 = ctx.dfeta_qualificationSet.Single(i => i.GetAttributeValue(dfeta_qualification.Fields.dfeta_PersonId) == person2.ContactId); + var ittPerson2 = ctx.dfeta_initialteachertrainingSet.Single(i => i.GetAttributeValue(dfeta_initialteachertraining.Fields.dfeta_PersonId) == person2.ContactId); + var qtsPerson2 = ctx.dfeta_qtsregistrationSet.Single(i => i.GetAttributeValue(dfeta_qtsregistration.Fields.dfeta_PersonId) == person2.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Success, item1.StatusCode); + }, + item2 => + { + Assert.Contains(expectedValueMessage1, item2.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Fail, item2.StatusCode); + + }, + item3 => + { + Assert.Empty(item3.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Success, item3.StatusCode); + }, + item4 => + { + Assert.Contains(expectedValueMessage2, item4.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Fail, item4.StatusCode); + }); + Assert.NotNull(qualificationPerson1); + Assert.NotNull(ittPerson1); + Assert.NotNull(qtsPerson1); + Assert.NotNull(qualificationPerson2); + Assert.NotNull(ittPerson2); + Assert.NotNull(qtsPerson2); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.NotEmpty(integrationTransaction.dfeta_FailureMessage); + Assert.Contains(expectedValueMessage1, integrationTransaction.dfeta_FailureMessage, StringComparison.InvariantCultureIgnoreCase); + Assert.Contains(expectedValueMessage2, integrationTransaction.dfeta_FailureMessage, StringComparison.InvariantCultureIgnoreCase); + } + + [Fact] + public async Task EwcWalesImportJobQts_WithQualifiedTeacherQTSStatus_ReturnsSuccess() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var person1 = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person1.Trn; + var csvContent = $"QTS_REF_NO,FORENAME,SURNAME,DATE_OF_BIRTH,QTS_STATUS,QTS_DATE,ITT StartMONTH,ITT START YY,ITT End Date,ITT Course Length,ITT Estab LEA code,ITT Estab Code,ITT Qual Code,ITT Class Code,ITT Subject Code 1,ITT Subject Code 2,ITT Min Age Range,ITT Max Age Range,ITT Min Sp Age Range,ITT Max Sp Age Range,ITT Course Length,PQ Year of Award,COUNTRY,PQ Estab Code,PQ Qual Code,HONOURS,PQ Class Code,PQ Subject Code 1,PQ Subject Code 2,PQ Subject Code 3\r\n{trn1},firstname,lastname,{person1.DateOfBirth.ToString("dd/MM/yyyy")},67,04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("QTS", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var qualificationPerson1 = ctx.dfeta_qualificationSet.Single(i => i.GetAttributeValue(dfeta_qualification.Fields.dfeta_PersonId) == person1.ContactId); + var ittPerson1 = ctx.dfeta_initialteachertrainingSet.Single(i => i.GetAttributeValue(dfeta_initialteachertraining.Fields.dfeta_PersonId) == person1.ContactId); + var qtsRegistration = ctx.dfeta_qtsregistrationSet.Single(i => i.GetAttributeValue(dfeta_qtsregistration.Fields.dfeta_PersonId) == person1.ContactId); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.Fields.dfeta_PersonId) == person1.ContactId); + Assert.NotNull(integrationTransaction); + Assert.NotNull(qtsRegistration); + Assert.Collection(itrRecords, + item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Success, item1.StatusCode); + }); + Assert.NotNull(qualificationPerson1); + Assert.NotNull(ittPerson1); + Assert.NotNull(induction); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJobInduction_NoExistingInduction_CreatesInductionAndReturnsExpectedCounts() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person.Trn; + var inductionStartDate = new DateTime(2024, 05, 01); + var inductionPassDate = new DateTime(2024, 10, 07); + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{person.Trn!},Keri Louise Lyddon,Nicholas,{person.DateOfBirth.ToString("dd/MM/yyyy")},{inductionStartDate.ToString("dd/MM/yyyy")},{inductionPassDate.ToString("dd/MM/yyyy")},,Pembrokeshire Local Authority,,Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.Fields.dfeta_PersonId) == person.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Success, item1.StatusCode); + }); + Assert.NotNull(induction); + Assert.Equal(dfeta_InductionStatus.PassedinWales, induction.dfeta_InductionStatus); + Assert.Equal(inductionStartDate, induction.dfeta_StartDate); + Assert.Equal(inductionPassDate, induction.dfeta_CompletionDate); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJobInduction_DateOfBirthDoesNotMatch_FailsReturnsExpectedCounts() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var expectedTotalRowCount = 1; + var expectedSuccessCount = 0; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 1; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person.Trn; + var inductionStartDate = new DateTime(2024, 05, 01); + var inductionPassDate = new DateTime(2024, 10, 07); + var dob = "01/09/1977"; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{person.Trn!},Keri Louise Lyddon,Nicholas,{dob},{inductionStartDate.ToString()},{inductionPassDate.ToString()},,Pembrokeshire Local Authority,{account},Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.FirstOrDefault(i => i.GetAttributeValue(dfeta_induction.Fields.dfeta_PersonId) == person.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Contains($"For TRN {person.Trn!} Date of Birth does not match with the existing record.", item1.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Fail, item1.StatusCode); + }); + Assert.Null(induction); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.NotEmpty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJobInduction_ValidRow_ReturnsSuccessAndExpectedCounts() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person.Trn; + var inductionStartDate = new DateTime(2024, 05, 01); + var inductionPassDate = new DateTime(2024, 10, 07); + var fileName = "IND.csv"; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{person.Trn!},Keri Louise Lyddon,Nicholas,{person.DateOfBirth.ToString("dd/MM/yyyy")},{inductionStartDate.ToString("dd/MM/yyyy")},{inductionPassDate.ToString("dd/MM/yyyy")},,{account.AccountNumber},,Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync(fileName, reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.Fields.dfeta_PersonId) == person.ContactId); + var inductionPeriod = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_inductionperiod.Fields.dfeta_InductionId) == induction.Id); + Assert.NotNull(integrationTransaction); + Assert.NotNull(induction); + Assert.NotNull(inductionPeriod); + Assert.Collection(itrRecords, + item1 => + { + Assert.Empty(item1.dfeta_FailureMessage); + Assert.Equal(fileName, item1.dfeta_Filename); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Success, item1.StatusCode); + }); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJobInduction_WithInvalidEmployerCode_ReturnsExpectedCounts() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 0; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 1; + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn1 = person.Trn; + var inductionStartDate = new DateTime(2024, 05, 01); + var inductionPassDate = new DateTime(2024, 10, 07); + var invalidEmployeCode = "invalid"; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{person.Trn!},Keri Louise Lyddon,Nicholas,{person.DateOfBirth.ToString("dd/MM/yyyy")},{inductionStartDate.ToString("dd/MM/yyyy")},{inductionPassDate.ToString("dd/MM/yyyy")},,Pembrokeshire Local Authority,{invalidEmployeCode},Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.Fields.dfeta_PersonId) == person.ContactId); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Contains($"Organisation with Induction Body Code {invalidEmployeCode} was not found.", item1.dfeta_FailureMessage); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Fail, item1.StatusCode); + }); + Assert.NotNull(induction); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.NotEmpty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJobInduction_WithInvalidTRN_ReturnsExpectedCounts() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var expectedTotalRowCount = 1; + var expectedSuccessCount = 0; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 1; + var inductionStartDate = new DateTime(2024, 05, 01); + var inductionPassDate = new DateTime(2024, 10, 07); + var invalidTRN = "invalid"; + var expectedFailureMessage = $"Teacher with TRN {invalidTRN} was not found."; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{invalidTRN},Keri Louise Lyddon,Nicholas,01/01/2024,{inductionStartDate.ToString()},{inductionPassDate.ToString()},,{account.AccountNumber},12345,Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecords = ctx.dfeta_integrationtransactionrecordSet.Where(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + Assert.NotNull(integrationTransaction); + Assert.Collection(itrRecords, + item1 => + { + Assert.Contains(expectedFailureMessage, item1.dfeta_FailureMessage); + Assert.Null(item1.dfeta_PersonId); + Assert.Null(item1.dfeta_InductionPeriodId); + Assert.Null(item1.dfeta_InductionId); + Assert.Equal(dfeta_integrationtransactionrecord_StatusCode.Fail, item1.StatusCode); + }); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.NotEmpty(integrationTransaction.dfeta_FailureMessage); + } + + [Fact] + public async Task EwcWalesImportJob_ImportsInvalidFileType_ReturnsExpected() + { + // Arrange + var person = await TestData.CreatePersonAsync(); + var trn = person.Trn; + var csvContent = $"QTS_REF_NO,FORENAME,SURNAME,DATE_OF_BIRTH,QTS_STATUS,QTS_DATE,ITT StartMONTH,ITT START YY,ITT End Date,ITT Course Length,ITT Estab LEA code,ITT Estab Code,ITT Qual Code,ITT Class Code,ITT Subject Code 1,ITT Subject Code 2,ITT Min Age Range,ITT Max Age Range,ITT Min Sp Age Range,ITT Max Sp Age Range,ITT Course Length,PQ Year of Award,COUNTRY,PQ Estab Code,PQ Qual Code,HONOURS,PQ Class Code,PQ Subject Code 1,PQ Subject Code 2,PQ Subject Code 3\r\n{trn},firstname,lastname,{person.DateOfBirth.ToString("dd/MM/yyyy")},49, 04/04/2014,,,,,,,,,,,,,,,,,,,,,,,,\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("INVALID_FILETYPE.csv", reader); + + // Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.SingleOrDefault(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + Assert.Null(integrationTransactionId); + Assert.Null(integrationTransaction); + Fixture.Logger.Verify( + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, t) => v.ToString()!.Contains("Import filename must begin with IND or QTS")), + null, + It.IsAny>()), + Times.Once); + } + + [Fact] + public async Task EwcWalesImportJobInduction_ImportsInductionFileSuccessfully() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var accountNumber = "54321"; + var startDate = DateTime.ParseExact("17/09/2014", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var passDate = DateTime.ParseExact("28/09/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn = person.Trn; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{trn},{person.FirstName},{person.LastName},{person.DateOfBirth.ToString("dd/MM/yyyy")},{startDate.ToString("dd/MM/yyyy")},{passDate.ToString("dd/MM/yyyy")},,{account.Name},{accountNumber},Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + //Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecord = ctx.dfeta_integrationtransactionrecordSet.Single(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == itrRecord.dfeta_InductionId.Id); + var inductionPeriod = ctx.dfeta_inductionperiodSet.Single(i => i.GetAttributeValue(dfeta_inductionperiod.PrimaryIdAttribute) == itrRecord.dfeta_InductionPeriodId.Id); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + Assert.Equal(startDate, induction.dfeta_StartDate); + Assert.Equal(passDate, induction.dfeta_CompletionDate); + Assert.Equal(startDate, inductionPeriod.dfeta_StartDate); + Assert.Equal(passDate, inductionPeriod.dfeta_EndDate); + Assert.Equal(account.Id, inductionPeriod.dfeta_AppropriateBodyId.Id); + } + + [Fact] + public async Task EwcWalesImportJobInductionWithoutAppropriateBody_ImportsInductionFileSuccessfully() + { + // Arrange + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var startDate = DateTime.ParseExact("17/09/2014", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var passDate = DateTime.ParseExact("28/09/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var trn = person.Trn; + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{trn},{person.FirstName},{person.LastName},{person.DateOfBirth.ToString("dd/MM/yyyy")},{startDate.ToString("dd/MM/yyyy")},{passDate.ToString("dd/MM/yyyy")},,,,Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + //Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecord = ctx.dfeta_integrationtransactionrecordSet.Single(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == itrRecord.dfeta_InductionId.Id); + var inductionPeriod = ctx.dfeta_inductionperiodSet.Single(i => i.GetAttributeValue(dfeta_inductionperiod.PrimaryIdAttribute) == itrRecord.dfeta_InductionPeriodId.Id); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + Assert.Equal(startDate, induction.dfeta_StartDate); + Assert.Equal(passDate, induction.dfeta_CompletionDate); + Assert.Equal(startDate, inductionPeriod.dfeta_StartDate); + Assert.Equal(passDate, inductionPeriod.dfeta_EndDate); + Assert.Null(inductionPeriod.dfeta_AppropriateBodyId); + } + + [Fact] + public async Task EwcWalesImportJobInduction_UpdatesExistingInduction() + { + // Arrange + var accountNumber = "678910"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var expectedTotalRowCount = 1; + var expectedSuccessCount = 1; + var expectedDuplicateRowCount = 0; + var expectedFailureRowCount = 0; + var startDate = DateTime.ParseExact("17/09/2014", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var passDate = DateTime.ParseExact("28/09/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture); + var person = await TestData.CreatePersonAsync(x => + { + x.WithTrn(); + x.WithDqtInduction(dfeta_InductionStatus.InProgress, + null, startDate.ToDateOnlyWithDqtBstFix(isLocalTime: false), + completedDate: passDate.ToDateOnlyWithDqtBstFix(isLocalTime: false), + inductionPeriodStartDate: startDate.ToDateOnlyWithDqtBstFix(isLocalTime: false), + inductionPeriodEndDate: passDate.ToDateOnlyWithDqtBstFix(isLocalTime: false), + appropriateBodyOrgId: account.Id); + }); + var trn = person.Trn; + var updatedStartDate = DateTime.ParseExact("17/09/2019", "dd/mm/yyyy", CultureInfo.InvariantCulture); + var updatedPassDate = DateTime.ParseExact("28/09/2020", "dd/mm/yyyy", CultureInfo.InvariantCulture); + var csvContent = $"REFERENCE_NO,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,START_DATE,PASS_DATE,FAIL_DATE,EMPLOYER_NAME,EMPLOYER_CODE,IND_STATUS_NAME\r\n{trn},{person.FirstName},{person.LastName},{person.DateOfBirth.ToString("dd/MM/yyyy")},{updatedStartDate.ToString("dd/MM/yyyy")},{updatedPassDate.ToString("dd/MM/yyyy")},,,{account.AccountNumber},Pass\r\n"; + var csvBytes = Encoding.UTF8.GetBytes(csvContent); + var stream = new MemoryStream(csvBytes); + var reader = new StreamReader(stream); + + // Act + var integrationTransactionId = await Job.ImportAsync("IND", reader); + + //Assert + using var ctx = new DqtCrmServiceContext(OrganizationService); + var integrationTransaction = ctx.dfeta_integrationtransactionSet.Single(i => i.GetAttributeValue(dfeta_integrationtransaction.PrimaryIdAttribute) == integrationTransactionId); + var itrRecord = ctx.dfeta_integrationtransactionrecordSet.Single(i => i.GetAttributeValue(dfeta_integrationtransactionrecord.Fields.dfeta_IntegrationTransactionId) == integrationTransaction.Id); + var induction = ctx.dfeta_inductionSet.Single(i => i.GetAttributeValue(dfeta_induction.PrimaryIdAttribute) == itrRecord.dfeta_InductionId.Id); + var inductionPeriod = ctx.dfeta_inductionperiodSet.Single(i => i.GetAttributeValue(dfeta_inductionperiod.PrimaryIdAttribute) == itrRecord.dfeta_InductionPeriodId.Id); + Assert.Equal(expectedTotalRowCount, integrationTransaction.dfeta_TotalCount); + Assert.Equal(expectedSuccessCount, integrationTransaction.dfeta_SuccessCount); + Assert.Equal(expectedDuplicateRowCount, integrationTransaction.dfeta_DuplicateCount); + Assert.Equal(expectedFailureRowCount, integrationTransaction.dfeta_FailureCount); + Assert.Empty(integrationTransaction.dfeta_FailureMessage); + Assert.Equal(updatedPassDate, induction.dfeta_CompletionDate); + Assert.Equal(updatedPassDate, inductionPeriod.dfeta_EndDate); + Assert.Equal(account.Id, inductionPeriod.dfeta_AppropriateBodyId.Id); + } +} + +public class EwcWalesImportJobFixture : IAsyncLifetime +{ + public EwcWalesImportJobFixture( + DbFixture dbFixture, + ReferenceDataCache referenceDataCache, + FakeTrnGenerator trnGenerator, + IServiceProvider provider) + { + OrganizationService = provider.GetService()!; + DbFixture = dbFixture; + Clock = new(); + Helper = new TrsDataSyncHelper( + dbFixture.GetDataSource(), + OrganizationService, + referenceDataCache, + Clock); + + var blobServiceClient = new Mock(); + var qtsImporter = ActivatorUtilities.CreateInstance(provider); + var inductionImporter = ActivatorUtilities.CreateInstance(provider); + Logger = new Mock>(); + Job = ActivatorUtilities.CreateInstance(provider, blobServiceClient.Object, qtsImporter, inductionImporter, Logger.Object); + TestData = new TestData( + dbFixture.GetDbContextFactory(), + OrganizationService, + referenceDataCache, + Clock, + trnGenerator, + TestDataSyncConfiguration.Sync(Helper)); + } + + public DbFixture DbFixture { get; } + + public TestData TestData { get; } + + public TestableClock Clock { get; } + + public TrsDataSyncHelper Helper { get; } + + public Mock> Logger { get; } + + Task IAsyncLifetime.InitializeAsync() => DbFixture.WithDbContextAsync(dbContext => dbContext.Events.ExecuteDeleteAsync()); + + Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; + + public IOrganizationServiceAsync2 OrganizationService { get; } + + public EwcWalesImportJob Job { get; } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/InductionImporterTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/InductionImporterTests.cs new file mode 100644 index 000000000..a9540f22d --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/InductionImporterTests.cs @@ -0,0 +1,378 @@ +using Azure.Storage.Blobs; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.PowerPlatform.Dataverse.Client; +using TeachingRecordSystem.Core.Dqt.Models; +using TeachingRecordSystem.Core.Jobs.EwcWalesImport; +using TeachingRecordSystem.Core.Services.TrsDataSync; + +namespace TeachingRecordSystem.Core.Tests.Jobs; + +[Collection(nameof(DisableParallelization))] +public class InductionImporterTests : IAsyncLifetime +{ + public InductionImporterTests( + DbFixture dbFixture, + IOrganizationServiceAsync2 organizationService, + ReferenceDataCache referenceDataCache, + FakeTrnGenerator trnGenerator, + IServiceProvider provider) + { + DbFixture = dbFixture; + Clock = new(); + Helper = new TrsDataSyncHelper( + dbFixture.GetDataSource(), + organizationService, + referenceDataCache, + Clock); + + TestData = new TestData( + dbFixture.GetDbContextFactory(), + organizationService, + referenceDataCache, + Clock, + trnGenerator, + TestDataSyncConfiguration.Sync(Helper)); + var blobServiceClient = new Mock(); + Importer = ActivatorUtilities.CreateInstance(provider); + } + private DbFixture DbFixture { get; } + + private TestData TestData { get; } + + private TestableClock Clock { get; } + + public TrsDataSyncHelper Helper { get; } + + Task IAsyncLifetime.InitializeAsync() => DbFixture.WithDbContextAsync(dbContext => dbContext.Events.ExecuteDeleteAsync()); + + Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; + + public InductionImporter Importer { get; } + + [Fact] + public async Task Validate_MissingReferenceNumber_ReturnsError() + { + // Arrange + var row = GetDefaultRow(); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Missing Reference No")); + } + + [Fact] + public async Task Validate_MissingDateOfBirth_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.DateOfBirth = ""; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Missing Date of Birth")); + } + + [Fact] + public async Task Validate_InvalidDateOfBirth_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.DateOfBirth = "45/11/19990"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Validation Failed: Invalid Date of Birth")); + } + + [Fact] + public async Task Validate_MissingStartDate_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.StartDate = ""; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Missing Induction Start date")); + } + + [Fact] + public async Task Validate_InvalidStartDate_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.StartDate = "55/13/20001111"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Validation Failed: Invalid Induction start date")); + } + + [Fact] + public async Task Validate_MissinPassedDate_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.PassedDate = ""; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Missing Induction passed date")); + } + + [Fact] + public async Task Validate_InvalidPassedDate_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.PassedDate = "25/13/20001"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Validation Failed: Invalid Induction passed date")); + } + + [Fact] + public async Task Validate_ReferenceNumberNotFound_ReturnsError() + { + // Arrange + var row = GetDefaultRow(x => + { + x.ReferenceNumber = "NONE EXISTENT"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Teacher with TRN {row.ReferenceNumber} was not found.")); + } + + [Fact] + public async Task Validate_WithQtlsDateNoInduction_ReturnsError() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => + { + x.WithQtlsDate(new DateOnly(2024, 01, 01)); + }); + var row = GetDefaultRow(x => + { + x.ReferenceNumber = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy"); + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"may need to update either/both the 'TRA induction status' and 'Overall induction status")); + } + + [Theory] + [InlineData(dfeta_InductionStatus.Pass, null)] + [InlineData(dfeta_InductionStatus.PassedinWales, null)] + [InlineData(dfeta_InductionStatus.Exempt, dfeta_InductionExemptionReason.Exempt)] + [InlineData(dfeta_InductionStatus.FailedinWales, null)] + [InlineData(dfeta_InductionStatus.Fail, null)] + public async Task Validate_WithCompletedInduction_ReturnsError(dfeta_InductionStatus inductionStatus, dfeta_InductionExemptionReason? inductionExemptionReason) + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => + { + x.WithDqtInduction(inductionStatus: inductionStatus, inductionExemptionReason: inductionExemptionReason, null, null, null, null, null); + }); + var row = GetDefaultRow(x => + { + x.ReferenceNumber = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy"); + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Teacher with TRN {row.ReferenceNumber} completed induction already.")); + } + + [Fact] + public async Task GetLookupData_TrnDoesNotExist_ReturnsNoMatch() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(); + var row = GetDefaultRow(x => + { + x.ReferenceNumber = "InvalidTrn"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(ContactLookupResult.NoMatch, lookups.PersonMatchStatus); + Assert.Null(lookups.Person); + } + + [Fact] + public async Task GetLookupData_ValidTrnWithoutQTS_ReturnsNoAssociatedQTS() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.ReferenceNumber = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy"); + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(ContactLookupResult.NoAssociatedQts, lookups.PersonMatchStatus); + Assert.NotNull(lookups.Person); + Assert.Equal(person.ContactId, lookups.Person!.ContactId); + } + + [Fact] + public async Task GetLookupData_ValidTrnWithQTS_ReturnsTeacherHasQTS() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => + { + x.WithQts(); + }); + var row = GetDefaultRow(x => + { + x.ReferenceNumber = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy"); + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(ContactLookupResult.TeacherHasQts, lookups.PersonMatchStatus); + Assert.NotNull(lookups.Person); + Assert.Equal(person.ContactId, lookups.Person!.ContactId); + } + + [Fact] + public async Task GetLookupData_InvalidOrganisationCode_ReturnsError() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => + { + x.WithQts(); + }); + var row = GetDefaultRow(x => + { + x.EmployerCode = "SOMEINVALID"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(OrganisationLookupResult.NoMatch, lookups.OrganisationMatchStatus); + Assert.Null(lookups.OrganisationId); + } + + private EwcWalesInductionImportData GetDefaultRow(Func? configurator = null) + { + var row = new EwcWalesInductionImportData() + { + ReferenceNumber = "", + FirstName = Faker.Name.First(), + LastName = Faker.Name.First(), + DateOfBirth = Faker.Identification.DateOfBirth().ToString(), + StartDate = "10/10/2023", + PassedDate = "10/10/2024", + FailDate = "", + EmployerCode = "", + EmployerName = "", + InductionStatusName = "01/07/2024", + }; + var configuredRow = configurator != null ? configurator(row) : row; + return configuredRow; + } + +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/QTSImporterTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/QTSImporterTests.cs new file mode 100644 index 000000000..6c5a31185 --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Core.Tests/Jobs/QTSImporterTests.cs @@ -0,0 +1,923 @@ +using Azure.Storage.Blobs; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.PowerPlatform.Dataverse.Client; +using TeachingRecordSystem.Core.Jobs.EwcWalesImport; +using TeachingRecordSystem.Core.Services.TrsDataSync; + +namespace TeachingRecordSystem.Core.Tests.Jobs; + +[Collection(nameof(DisableParallelization))] +public class QtsImporterTests : IAsyncLifetime +{ + public QtsImporterTests( + DbFixture dbFixture, + IOrganizationServiceAsync2 organizationService, + ReferenceDataCache referenceDataCache, + FakeTrnGenerator trnGenerator, + IServiceProvider provider) + { + DbFixture = dbFixture; + Clock = new(); + Helper = new TrsDataSyncHelper( + dbFixture.GetDataSource(), + organizationService, + referenceDataCache, + Clock); + + TestData = new TestData( + dbFixture.GetDbContextFactory(), + organizationService, + referenceDataCache, + Clock, + trnGenerator, + TestDataSyncConfiguration.Sync(Helper)); + var blobServiceClient = new Mock(); + Importer = ActivatorUtilities.CreateInstance(provider); + } + + private DbFixture DbFixture { get; } + + private TestData TestData { get; } + + private TestableClock Clock { get; } + + public TrsDataSyncHelper Helper { get; } + + Task IAsyncLifetime.InitializeAsync() => DbFixture.WithDbContextAsync(dbContext => dbContext.Events.ExecuteDeleteAsync()); + + Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; + + public QtsImporter Importer { get; } + + [Fact] + public async Task Validate_NoneExistentTeacher_ReturnsErrorMessage() + { + // Arrange + var row = GetDefaultRow(x => + { + x.QtsRefNo = "InvalidTrn"; + return x; + }); + + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Teacher with TRN {row.QtsRefNo} was not found.")); + } + + [Fact] + public async Task Validate_ExistingTeacherWithQTS_ReturnsErrorMessage() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => + { + x.WithQts(); + }); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"Teacher with TRN {row.QtsRefNo} has QTS already.")); + } + + [Fact] + public async Task Validate_WithMissingMandatoryFields_ReturnsErrorMessages() + { + // Arrange + var person = await TestData.CreatePersonAsync(); + var row = GetDefaultRow(x => + { + x.QtsRefNo = ""; + x.DateOfBirth = ""; + x.QtsDate = ""; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains("Missing QTS Ref Number")); + Assert.Contains(errors, item => item.Contains("Missing Date of Birth")); + Assert.Contains(errors, item => item.Contains("Misssing QTS Date")); + } + + [Fact] + public async Task Validate_WithMalformedDateOfBirth_ReturnsErrorMessages() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = "67/13/2025"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains("Validation Failed: Invalid Date of Birth")); + } + + [Fact] + public async Task Validate_WithMalformedQTSDate_ReturnsErrorMessages() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.QtsDate = "67/13/2025"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains("Validation Failed: Invalid QTS Date")); + } + + [Fact] + public async Task Validate_ExistingTeacherDateOfBirthDoesNotMatch_ReturnsErrorMessage() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = "01/06/1999"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(errors, item => item.Contains($"For TRN {row.QtsRefNo} Date of Birth does not match with the existing record.")); + } + + [Fact] + public async Task Validate_MultipleMatchingOrganisations_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "12345"; + var account1 = await TestData.CreateAccountAsync(x => + { + x.WithName("test"); + x.WithAccountNumber(accountNumber); + }); + var account2 = await TestData.CreateAccountAsync(x => + { + x.WithName("test2"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = accountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"Multiple organisations with ITT Establishment Code {row.IttEstabCode} found.")); + } + + [Fact] + public async Task Validate_NoMatchingOrganisations_ReturnsErrorMessage() + { + // Arrange + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = "SomeInvalidOrg"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"Organisation with ITT Establishment Code {row.IttEstabCode} was not found.")); + } + + [Fact] + public async Task Validate_NoPqSubjects_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + x.PqSubjectCode1 = "3333333"; + x.PqSubjectCode2 = "5555555"; + x.PqSubjectCode3 = "6666666"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode1} was not found.")); + Assert.Contains(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode2} was not found.")); + Assert.Contains(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode3} was not found.")); + } + + [Fact] + public async Task Validate_ValidPqSubjects_DoesNotReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.DoesNotContain(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode1} was not found.")); + Assert.DoesNotContain(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode2} was not found.")); + Assert.DoesNotContain(failures, item => item.Contains($"Subject with PQ Subject Code {row.PqSubjectCode3} was not found.")); + } + + [Fact] + public async Task Validate_ValidCountry_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString()!; + x.IttEstabCode = account.AccountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.DoesNotContain(failures, item => item.Contains($"Country with PQ Country Code {row.Country} was not found.")); + } + + [Fact] + public async Task Validate_InvalidCountry_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + x.Country = "INVALID"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"Country with PQ Country Code {row.Country} was not found.")); + } + + [Fact] + public async Task Validate_ValidITTSubjetCodes_DoesNotReturnErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.DoesNotContain(failures, item => item.Contains($"ITT subject with code {row.IttSubjectCode1} was not found.")); + Assert.DoesNotContain(failures, item => item.Contains($"ITT subject with code {row.IttSubjectCode2} was not found.")); + } + + [Fact] + public async Task Validate_InvalidITTSubjetCodes_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + x.IttSubjectCode1 = "Invalid1"; + x.IttSubjectCode2 = "Invalid2"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"ITT subject with code {row.IttSubjectCode1} was not found.")); + Assert.Contains(failures, item => item.Contains($"ITT subject with code {row.IttSubjectCode2} was not found.")); + } + + [Fact] + public async Task Validate_InvalidITTQualification_ReturnsErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + x.IttQualCode = "InvalidIttQualCode"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"TT qualification with code {row.IttQualCode} was not found.")); + } + + [Fact] + public async Task Validate_ValidITTQualification_DoesNotReturnErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttEstabCode = account.AccountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.DoesNotContain(failures, item => item.Contains($"ITT qualification with code {row.IttQualCode} was not found.")); + } + + [Fact] + public async Task Validate_InvalidPqEstabCode_ReturnErrorMessage() + { + // Arrange + var accountNumber = "13571"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqEstabCode = "InvalidOrg"; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.Contains(failures, item => item.Contains($"Organisation with PQ Establishment Code {row.PqEstabCode} was not found.")); + } + + [Fact] + public async Task Validate_ValidPqEstabCode_DoesNotReturnErrorMessage() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = account.AccountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqEstabCode = account.AccountNumber; + return x; + }); + var lookups = await Importer.GetLookupDataAsync(row); + + // Act + var (failures, errors) = Importer.Validate(row, lookups); + + // Assert + Assert.DoesNotContain(failures, item => item.Contains($"Organisation with PQ Establishment Code {row.PqEstabCode} was not found.")); + } + + [Fact] + public async Task GetLookupData_TrnDoesNotExist_ReturnsNoMatch() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(); + var row = GetDefaultRow(x => + { + x.QtsRefNo = "InvalidTrn"; + x.IttEstabCode = account.AccountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqEstabCode = account.AccountNumber; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PersonMatchStatus); + Assert.Null(lookups.PersonId); + } + + [Fact] + public async Task GetLookupData_IttEstabCodeDoesNotExist_ReturnsNoMatch() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = "Invalid"; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqEstabCode = account.AccountNumber; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.IttEstabCodeMatchStatus); + Assert.Null(lookups.IttEstabCodeId); + } + + [Fact] + public async Task GetLookupData_IttEstabCodeMultipleMatching_ReturnsMultipleMatchesFound() + { + // Arrange + var accountNumber = "1357"; + var account1 = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var account2 = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName2"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.MultipleMatchesFound, lookups.IttEstabCodeMatchStatus); + Assert.Null(lookups.IttEstabCodeId); + } + + [Fact] + public async Task GetLookupData_IttQualificationDoesNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttQualCode = "InvalidQual Code"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.IttQualificationMatchStatus); + Assert.Null(lookups.IttQualificationId); + } + + [Fact] + public async Task GetLookupData_IttSubjectsDoNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.IttSubjectCode1 = "Invalid Subject1"; + x.IttSubjectCode2 = "Invalid Subject2"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.IttSubject1MatchStatus); + Assert.Null(lookups.IttSubject1Id); + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.IttSubject2MatchStatus); + Assert.Null(lookups.IttSubject2Id); + } + + [Fact] + public async Task GetLookupData_PqSubjectCodesDoNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqSubjectCode1 = "InvalidSubject1"; + x.PqSubjectCode2 = "InvalidSubject2"; + x.PqSubjectCode3 = "InvalidSubject3"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PQSubject1MatchStatus); + Assert.Null(lookups.PQSubject1Id); + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PQSubject2MatchStatus); + Assert.Null(lookups.PQSubject2Id); + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PQSubject3MatchStatus); + Assert.Null(lookups.PQSubject3Id); + } + + [Fact] + public async Task GetLookupData_PqEstablishmentIdDoesNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqEstabCode = "Invalid Org number"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PqEstablishmentMatchStatus); + Assert.Null(lookups.PqEstablishmentId); + } + + [Fact] + public async Task GetLookupData_PQCountryDoesNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.Country = "Invalid"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PQCountryMatchStatus); + Assert.Null(lookups.PQCountryId); + } + + [Fact] + public async Task GetLookupData_PQHEQualificationNotExist_ReturnsNotFound() + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.PqQualCode = "Invalid Qualification Code"; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.Equal(EwcWalesMatchStatus.NoMatch, lookups.PQHEQualificationMatchStatus); + Assert.Null(lookups.PQHEQualificationId); + } + + [Theory] + [InlineData("63")] + [InlineData("")] + public async Task GetLookupData_TeacherStatusIsNotNull(string qtsStatus) + { + // Arrange + var accountNumber = "1357"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithTrn()); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.IttEstabCode = accountNumber; + x.DateOfBirth = person.DateOfBirth.ToString("dd/MM/yyyy")!; + x.QtsStatus = qtsStatus; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.NotNull(lookups.TeacherStatusId); + } + + [Fact] + public async Task GetLookupData_ConvertToCSVString_ReturnsExpectedCSV() + { + // Arrange + var accountNumber = "135711"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithQts(new DateOnly(2024, 01, 01))); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.PqEstabCode = account.AccountNumber; + x.IttEstabCode = account.AccountNumber; + return x; + }); + var expectedJson = $"{row.QtsRefNo},{row.Forename},{row.Surname},{row.DateOfBirth},{row.QtsStatus},{row.QtsDate},{row.IttStartMonth},{row.IttStartYear},{row.IttEndDate},{row.ITTCourseLength},{row.IttEstabLeaCode},{row.IttEstabCode},{row.IttQualCode},{row.IttClassCode},{row.IttSubjectCode1},{row.IttSubjectCode2},{row.IttMinAgeRange},{row.IttMaxAgeRange},{row.IttMinSpAgeRange},{row.IttMaxSpAgeRange},{row.PqCourseLength},{row.PqYearOfAward},{row.Country},{row.PqEstabCode},{row.PqQualCode},{row.Honours},{row.PqClassCode},{row.PqSubjectCode1},{row.PqSubjectCode2},{row.PqSubjectCode3}\r\n"; + + // Act + var json = Importer.ConvertToCsvString(row); + + // Assert + Assert.Equal(json, expectedJson); + } + + [Fact] + public async Task GetLookupData_ValidRow_PopulatesLookupDate() + { + // Arrange + var accountNumber = "1357111"; + var account = await TestData.CreateAccountAsync(x => + { + x.WithName("SomeName"); + x.WithAccountNumber(accountNumber); + }); + var person = await TestData.CreatePersonAsync(x => x.WithQts(new DateOnly(2024, 01, 01))); + var row = GetDefaultRow(x => + { + x.QtsRefNo = person.Trn!; + x.PqEstabCode = account.AccountNumber; + x.IttEstabCode = account.AccountNumber; + return x; + }); + + // Act + var lookups = await Importer.GetLookupDataAsync(row); + + // Assert + Assert.NotNull(lookups.PersonId); + Assert.Equal(EwcWalesMatchStatus.TeacherHasQts, lookups.PersonMatchStatus); + Assert.NotNull(lookups.IttEstabCodeId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.IttEstabCodeMatchStatus); + Assert.NotNull(lookups.IttQualificationId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.IttQualificationMatchStatus); + Assert.NotNull(lookups.IttSubject1Id); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.IttSubject1MatchStatus); + Assert.NotNull(lookups.IttSubject2Id); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.IttSubject2MatchStatus); + Assert.NotNull(lookups.PqEstablishmentId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PqEstablishmentMatchStatus); + Assert.NotNull(lookups.PQCountryId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PQCountryMatchStatus); + Assert.NotNull(lookups.PQHEQualificationId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PQHEQualificationMatchStatus); + Assert.NotNull(lookups.PQSubject1Id); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PQSubject1MatchStatus); + Assert.NotNull(lookups.PQSubject2Id); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PQSubject2MatchStatus); + Assert.NotNull(lookups.PQSubject3Id); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.PQSubject3MatchStatus); + Assert.NotNull(lookups.TeacherStatusId); + Assert.Equal(EwcWalesMatchStatus.OneMatch, lookups.TeacherStatusMatchStatus); + Assert.NotNull(lookups.ClassDivision); + } + + private EwcWalesQtsFileImportData GetDefaultRow(Func? configurator = null) + { + var row = new EwcWalesQtsFileImportData() + { + QtsRefNo = "", + Forename = Faker.Name.First(), + Surname = Faker.Name.First(), + DateOfBirth = Faker.Identification.DateOfBirth().ToString(), + QtsStatus = "63", + QtsDate = "01/04/2024", + IttStartMonth = "07", + IttStartYear = "2023", + IttEndDate = "01/07/2024", + ITTCourseLength = "1", + IttEstabLeaCode = "", + IttEstabCode = "", + IttQualCode = "400", //degree + IttClassCode = "", + IttSubjectCode1 = "100078", //business and management + IttSubjectCode2 = "100300", //classical studies + IttMinAgeRange = "", + IttMaxAgeRange = "", + IttMinSpAgeRange = "", + IttMaxSpAgeRange = "", + PqCourseLength = "", + PqYearOfAward = "", + Country = "XK", //United Kingdom + PqEstabCode = "", + PqQualCode = "001", //bED + Honours = "", + PqClassCode = "01", + PqSubjectCode1 = "002", //English + PqSubjectCode2 = "003", //Science + PqSubjectCode3 = "004" //Art + }; + var configuredRow = configurator != null ? configurator(row) : row; + return configuredRow; + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs index 42f68ec70..891f84cd0 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/SeedCrmReferenceData.cs @@ -22,6 +22,9 @@ public Task ExecuteAsync() AddSpecialisms(); AddHeQualifications(); AddHeSubjects(); + AddCountries(); + AddITTSubjects(); + AddITTQualifications(); return Task.CompletedTask; } @@ -408,4 +411,74 @@ private void AddHeSubjects() dfeta_Value = "007" }); } + + private void AddCountries() + { + _xrmFakedContext.CreateEntity(new dfeta_country() + { + dfeta_name = "United Kingdom", + dfeta_Value = "XK" + }); + + + _xrmFakedContext.CreateEntity(new dfeta_country() + { + dfeta_name = "Wales", + dfeta_Value = "WA" + }); + } + + private void AddITTSubjects() + { + _xrmFakedContext.CreateEntity(new dfeta_ittsubject() + { + dfeta_name = "business and management", + dfeta_Value = "100078" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittsubject() + { + dfeta_name = "business studies", + dfeta_Value = "100079" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittsubject() + { + dfeta_name = "applied biology", + dfeta_Value = "100343" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittsubject() + { + dfeta_name = "classical studies", + dfeta_Value = "100300" + }); + } + + private void AddITTQualifications() + { + _xrmFakedContext.CreateEntity(new dfeta_ittqualification() + { + dfeta_name = "BA (Hons)", + dfeta_Value = "008" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittqualification() + { + dfeta_name = "BSc", + dfeta_Value = "003" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittqualification() + { + dfeta_name = "BTech/Education", + dfeta_Value = "005" + }); + + _xrmFakedContext.CreateEntity(new dfeta_ittqualification() + { + dfeta_name = "Degree", + dfeta_Value = "400" + }); + } } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateAccount.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateAccount.cs index 146ceadef..d7a895527 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateAccount.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateAccount.cs @@ -15,6 +15,7 @@ public Task CreateAccountAsync(Action? configure) public class CreateAccountBuilder { private string? _name = null; + private string? _accountnumber = null; public CreateAccountBuilder WithName(string name) { @@ -27,6 +28,17 @@ public CreateAccountBuilder WithName(string name) return this; } + public CreateAccountBuilder WithAccountNumber(string accountnumber) + { + if (_accountnumber is not null && _accountnumber != accountnumber) + { + throw new InvalidOperationException("WithAccountNumber cannot be changed after it's set."); + } + + _accountnumber = accountnumber; + return this; + } + public async Task ExecuteAsync(TestData testData) { var name = _name ?? Faker.Company.Name(); @@ -34,7 +46,8 @@ public async Task ExecuteAsync(TestData testData) var account = new Account() { Id = accountId, - Name = name + Name = name, + AccountNumber = _accountnumber }; await testData.OrganizationService.ExecuteAsync(new CreateRequest() { diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs index 732a3f83a..23060d202 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreatePerson.cs @@ -103,6 +103,7 @@ public CreatePersonBuilder WithDqtInduction( EnsureTrn(); var inductionId = Guid.NewGuid(); + var inductionPeriodId = Guid.NewGuid(); if (inductionStatus == dfeta_InductionStatus.Exempt && inductionExemptionReason == null) { throw new InvalidOperationException("WithInduction must provide InductionExemptionReason if InductionStatus is Exempt"); @@ -116,7 +117,7 @@ public CreatePersonBuilder WithDqtInduction( } if (appropriateBodyOrgId.HasValue) { - _dqtInductionPeriods.Add(new DqtInductionPeriod(inductionId, inductionPeriodStartDate, inductionPeriodEndDate, appropriateBodyOrgId!.Value, numberOfTerms)); + _dqtInductionPeriods.Add(new DqtInductionPeriod(inductionPeriodId, inductionId, inductionPeriodStartDate, inductionPeriodEndDate, appropriateBodyOrgId!.Value, numberOfTerms)); } return this; } @@ -533,7 +534,7 @@ internal async Task ExecuteAsync(TestData testData) { Target = new dfeta_inductionperiod() { - Id = Guid.NewGuid(), + Id = inductionperiod!.InductionPeriodId, dfeta_InductionId = inductionperiod!.InductionId.ToEntityReference(dfeta_induction.EntityLogicalName), dfeta_StartDate = inductionperiod.startDate.ToDateTimeWithDqtBstFix(isLocalTime: false), dfeta_EndDate = inductionperiod.endDate.ToDateTimeWithDqtBstFix(isLocalTime: false), @@ -1246,7 +1247,7 @@ public record CreatePersonResult public record DqtInduction(Guid InductionId, dfeta_InductionStatus inductionStatus, dfeta_InductionExemptionReason? inductionExemptionReason, DateOnly? StartDate, DateOnly? CompletetionDate); - public record DqtInductionPeriod(Guid InductionId, DateOnly? startDate, DateOnly? endDate, Guid AppropriateBodyOrgId, int? NumberOfTerms); + public record DqtInductionPeriod(Guid InductionPeriodId, Guid InductionId, DateOnly? startDate, DateOnly? endDate, Guid AppropriateBodyOrgId, int? NumberOfTerms); public record QtsRegistration(DateOnly? QtsDate, string? TeacherStatusValue, DateTime? CreatedOn, DateOnly? EytsDate, string? EytsStatusValue); diff --git a/crm_attributes.json b/crm_attributes.json index f25ebce59..37ebfc3ad 100644 --- a/crm_attributes.json +++ b/crm_attributes.json @@ -4,7 +4,8 @@ "dfeta_trainingprovider", "dfeta_ukprn", "name", - "statecode" + "statecode", + "accountnumber" ], "annotation": [ "annotationid", @@ -135,11 +136,13 @@ "modifiedon" ], "dfeta_inductionperiod": [ + "dfeta_inductionperiodid", "dfeta_startdate", "dfeta_enddate", "dfeta_inductionid", "dfeta_numberofterms", "dfeta_appropriatebodyid", + "dfeta_inductionStatus", "statecode" ], "dfeta_initialteachertraining": [ @@ -241,7 +244,8 @@ "dfeta_trsevent", "CreatedOn", "CreatedBy", - "ModifiedOn" + "ModifiedOn", + "dfeta_HECourseLength" ], "dfeta_specialism": [ "dfeta_specialismid", @@ -352,6 +356,42 @@ "subject", "dfeta_EmailAddress" ], + "dfeta_integrationtransaction": [ + "createdby", + "createdon", + "dfeta_enddate", + "dfeta_failurecount", + "dfeta_failuremessage", + "dfeta_filename", + "dfeta_id", + "dfeta_interface", + "dfeta_startdate", + "dfeta_successcount", + "dfeta_duplicatecount", + "dfeta_importorganisation", + "dfeta_integrationtransactionid", + "dfeta_totalcount", + "statecode" + ], + "dfeta_integrationtransactionrecord" : [ + "dfeta_id", + "dfeta_filename", + "dfeta_personid", + "dfeta_organisationid", + "dfeta_inductionperiodid", + "dfeta_inductionid", + "dfeta_initialteachertrainingid", + "dfeta_duplicatestatus", + "dfeta_trefno", + "dfeta_failuremessage", + "dfeta_integrationtransactionrecordid", + "dfeta_integrationtransactionid", + "dfeta_qualificationid", + "dfeta_rowdata", + "dfeta_ukprn", + "statecode", + "statuscode" + ], "dfeta_trsoutboxmessage": [ "dfeta_trsoutboxmessageid", "dfeta_messagename", diff --git a/tools/coretools/CrmSvcUtil.exe.config b/tools/coretools/CrmSvcUtil.exe.config index d5ebba9e7..67db2cb97 100644 --- a/tools/coretools/CrmSvcUtil.exe.config +++ b/tools/coretools/CrmSvcUtil.exe.config @@ -19,8 +19,8 @@ - - + +