diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/TrnRequestHelper.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/TrnRequestHelper.cs index 36b33e3d1..3bfe9c4b0 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/TrnRequestHelper.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/TrnRequestHelper.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using TeachingRecordSystem.Core.DataStore.Postgres; using TeachingRecordSystem.Core.DataStore.Postgres.Models; using TeachingRecordSystem.Core.Dqt; @@ -6,7 +7,7 @@ namespace TeachingRecordSystem.Api; -public class TrnRequestHelper(TrsDbContext dbContext, ICrmQueryDispatcher crmQueryDispatcher) +public class TrnRequestHelper(TrsDbContext dbContext, ICrmQueryDispatcher crmQueryDispatcher, IClock clock) { public async Task GetTrnRequestInfo(Guid currentApplicationUserId, string requestId) { @@ -16,14 +17,20 @@ public class TrnRequestHelper(TrsDbContext dbContext, ICrmQueryDispatcher crmQue var getContactByTrnRequestIdTask = crmQueryDispatcher.ExecuteQuery( new GetContactByTrnRequestIdQuery(crmTrnRequestId, new Microsoft.Xrm.Sdk.Query.ColumnSet(Contact.Fields.ContactId, Contact.Fields.dfeta_TrnToken))); + // We can't have this running in parallel with getDbTrnRequestTask since they share a connection so make it continuation + var metadata = await getDbTrnRequestTask + .ContinueWith(_ => dbContext.TrnRequestMetadata + .SingleOrDefaultAsync(m => m.ApplicationUserId == currentApplicationUserId && m.RequestId == requestId)) + .Unwrap(); + if (await getDbTrnRequestTask is TrnRequest dbTrnRequest) { - return new(dbTrnRequest.TeacherId, dbTrnRequest.TrnToken); + return new(dbTrnRequest.TeacherId, dbTrnRequest.TrnToken, metadata, currentApplicationUserId); } if (await getContactByTrnRequestIdTask is Contact contact) { - return new(contact.ContactId!.Value, contact.dfeta_TrnToken); + return new(contact.ContactId!.Value, contact.dfeta_TrnToken, metadata, currentApplicationUserId); } return null; @@ -31,6 +38,45 @@ public class TrnRequestHelper(TrsDbContext dbContext, ICrmQueryDispatcher crmQue public static string GetCrmTrnRequestId(Guid currentApplicationUserId, string requestId) => $"{currentApplicationUserId}::{requestId}"; + + public async Task EnsureOneLoginUserIsConnected(GetTrnRequestResult trnRequest, Contact contact) + { + if (trnRequest.Metadata?.VerifiedOneLoginUserSubject is not string oneLoginUserSubject) + { + return; + } + + if (await dbContext.OneLoginUsers.AnyAsync(u => u.Subject == oneLoginUserSubject)) + { + return; + } + + Debug.Assert(contact.dfeta_TRN is not null); + + var oneLoginUser = new OneLoginUser() { Subject = oneLoginUserSubject }; + + var verifiedName = new string[] + { + contact.HasStatedNames() ? contact.dfeta_StatedFirstName : contact.FirstName, + contact.HasStatedNames() ? contact.dfeta_StatedMiddleName : contact.MiddleName, + contact.HasStatedNames() ? contact.dfeta_StatedLastName : contact.LastName + }; + + var verifiedDateOfBirth = contact.BirthDate!.Value.ToDateOnlyWithDqtBstFix(isLocalTime: false); + + oneLoginUser.SetVerified( + verifiedOn: clock.UtcNow, + OneLoginUserVerificationRoute.External, + verifiedByApplicationUserId: trnRequest.ApplicationUserId, + verifiedNames: [[.. verifiedName]], + verifiedDatesOfBirth: [verifiedDateOfBirth]); + + oneLoginUser.SetMatched(contact.Id, OneLoginUserMatchRoute.TrnAllocation, matchedAttributes: null); + + dbContext.OneLoginUsers.Add(oneLoginUser); + + await dbContext.SaveChangesAsync(); + } } -public record GetTrnRequestResult(Guid ContactId, string? TrnToken); +public record GetTrnRequestResult(Guid ContactId, string? TrnToken, TrnRequestMetadata? Metadata, Guid ApplicationUserId); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Core/Operations/GetTrnRequest.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Core/Operations/GetTrnRequest.cs index 4b1e66e18..bdf5e5d18 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Core/Operations/GetTrnRequest.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Api/V3/Core/Operations/GetTrnRequest.cs @@ -32,6 +32,9 @@ public class GetTrnRequestHandler( Contact.Fields.FirstName, Contact.Fields.MiddleName, Contact.Fields.LastName, + Contact.Fields.dfeta_StatedFirstName, + Contact.Fields.dfeta_StatedMiddleName, + Contact.Fields.dfeta_StatedLastName, Contact.Fields.EMailAddress1, Contact.Fields.dfeta_NINumber, Contact.Fields.BirthDate, @@ -40,6 +43,13 @@ public class GetTrnRequestHandler( var status = !string.IsNullOrEmpty(contact.dfeta_TRN) ? TrnRequestStatus.Completed : TrnRequestStatus.Pending; + // If we have metadata for the One Login user, ensure they're added to the OneLoginUsers table. + // FUTURE: when TRN requests are handled exclusively in TRS this should be done at the point the task is resolved instead of here. + if (status == TrnRequestStatus.Completed) + { + await trnRequestHelper.EnsureOneLoginUserIsConnected(trnRequest, contact); + } + return new TrnRequestInfo() { RequestId = command.RequestId.ToString(), diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Controllers/OAuth2Controller.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Controllers/OAuth2Controller.cs index ac1c69a6a..8ef5f7553 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Controllers/OAuth2Controller.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Controllers/OAuth2Controller.cs @@ -157,7 +157,7 @@ public async Task UserInfo() if (User.HasScope(Scopes.Email)) { - claims.Add(ClaimTypes.Email, oneLoginUser.Email); + claims.Add(ClaimTypes.Email, oneLoginUser.Email!); } if (oneLoginUser.VerificationRoute == OneLoginUserVerificationRoute.OneLogin) diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/DebugIdentity.cshtml.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/DebugIdentity.cshtml.cs index ef58640d1..3473f5208 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/DebugIdentity.cshtml.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/Pages/DebugIdentity.cshtml.cs @@ -116,7 +116,7 @@ public async Task OnPost() if (_oneLoginUser!.PersonId is not null && DetachPerson) { - _oneLoginUser.PersonId = null; + _oneLoginUser.ClearMatchedPerson(); } if (IdentityVerified) @@ -125,10 +125,7 @@ public async Task OnPost() } else { - _oneLoginUser!.VerifiedOn = null; - _oneLoginUser.VerificationRoute = null; - _oneLoginUser.VerifiedNames = null; - _oneLoginUser.VerifiedDatesOfBirth = null; + _oneLoginUser.ClearVerifiedInfo(); await JourneyInstance!.UpdateStateAsync(state => state.ClearVerified()); } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/SignInJourneyHelper.cs b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/SignInJourneyHelper.cs index 8e00ec114..2e0e70b40 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/SignInJourneyHelper.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.AuthorizeAccess/SignInJourneyHelper.cs @@ -92,14 +92,16 @@ public async Task OnUserAuthenticated(JourneyInstance journe } else { + oneLoginUser.FirstOneLoginSignIn ??= clock.UtcNow; oneLoginUser.LastOneLoginSignIn = clock.UtcNow; - // Email may have changed since the last sign in - ensure we update it. + // Email may have changed since the last sign in or we may have never had it (e.g. if we got the user ID over our API). // TODO Should we emit an event if it has changed? oneLoginUser.Email = email; if (oneLoginUser.PersonId is not null) { + oneLoginUser.FirstSignIn ??= clock.UtcNow; oneLoginUser.LastSignIn = clock.UtcNow; } } @@ -149,10 +151,7 @@ public async Task OnUserVerifiedCore( var sub = journeyInstance.State.OneLoginAuthenticationTicket!.Principal.FindFirstValue("sub") ?? throw new InvalidOperationException("No sub claim."); var oneLoginUser = await dbContext.OneLoginUsers.SingleAsync(u => u.Subject == sub); - oneLoginUser.VerifiedOn = clock.UtcNow; - oneLoginUser.VerificationRoute = OneLoginUserVerificationRoute.OneLogin; - oneLoginUser.VerifiedNames = verifiedNames; - oneLoginUser.VerifiedDatesOfBirth = verifiedDatesOfBirth; + oneLoginUser.SetVerified(clock.UtcNow, OneLoginUserVerificationRoute.OneLogin, verifiedByApplicationUserId: null, verifiedNames, verifiedDatesOfBirth); oneLoginUser.LastCoreIdentityVc = coreIdentityClaimVc; string? trn = null; @@ -167,11 +166,9 @@ public async Task OnUserVerifiedCore( if (result.MatchRoute is not null) { - oneLoginUser.PersonId = result.PersonId; oneLoginUser.FirstSignIn = clock.UtcNow; oneLoginUser.LastSignIn = clock.UtcNow; - oneLoginUser.MatchRoute = result.MatchRoute.Value; - oneLoginUser.MatchedAttributes = result.MatchedAttributes!.ToArray(); + oneLoginUser.SetMatched(result.PersonId, result.MatchRoute.Value, result.MatchedAttributes!.ToArray()); trn = result.Trn; } } @@ -319,11 +316,9 @@ public async Task TryMatchToTeachingRecord(JourneyInstance o.Subject == subject); - oneLoginUser.PersonId = matchedPersonId; oneLoginUser.FirstSignIn = clock.UtcNow; oneLoginUser.LastSignIn = clock.UtcNow; - oneLoginUser.MatchRoute = OneLoginUserMatchRoute.Interactive; - oneLoginUser.MatchedAttributes = matchedAttributes.ToArray(); + oneLoginUser.SetMatched(matchedPersonId, OneLoginUserMatchRoute.Interactive, matchedAttributes.ToArray()); await dbContext.SaveChangesAsync(); await journeyInstance.UpdateStateAsync(state => Complete(state, matchedTrn)); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/OneLoginUserMapping.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/OneLoginUserMapping.cs index c143fd420..5ccac393f 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/OneLoginUserMapping.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/OneLoginUserMapping.cs @@ -33,6 +33,7 @@ public void Configure(EntityTypeBuilder builder) new ValueComparer[]>( (a, b) => a == b, // Reference equality is fine here; we'll always replace the entire collection v => v.GetHashCode())); + builder.HasOne().WithMany().HasForeignKey(o => o.VerifiedByApplicationUserId); } } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/TrnRequestMetadataMapping.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/TrnRequestMetadataMapping.cs new file mode 100644 index 000000000..4e07a7666 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Mappings/TrnRequestMetadataMapping.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using TeachingRecordSystem.Core.DataStore.Postgres.Models; + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Mappings; + +public class TrnRequestMetadataMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(r => new { r.ApplicationUserId, r.RequestId }); + builder.Property(r => r.RequestId).IsRequired().HasMaxLength(TrnRequest.RequestIdMaxLength); + builder.Property(o => o.VerifiedOneLoginUserSubject).HasMaxLength(255); + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.Designer.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.Designer.cs new file mode 100644 index 000000000..7618b3774 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.Designer.cs @@ -0,0 +1,3306 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TeachingRecordSystem.Core.DataStore.Postgres; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + [DbContext(typeof(TrsDbContext))] + [Migration("20241107113402_TrnRequestMetadata")] + partial class TrnRequestMetadata + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("application_type"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("text") + .HasColumnName("client_secret"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_type"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("consent_type"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("JsonWebKeySet") + .HasColumnType("text") + .HasColumnName("json_web_key_set"); + + b.Property("Permissions") + .HasColumnType("text") + .HasColumnName("permissions"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text") + .HasColumnName("post_logout_redirect_uris"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedirectUris") + .HasColumnType("text") + .HasColumnName("redirect_uris"); + + b.Property("Requirements") + .HasColumnType("text") + .HasColumnName("requirements"); + + b.Property("Settings") + .HasColumnType("text") + .HasColumnName("settings"); + + b.HasKey("Id") + .HasName("pk_oidc_applications"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_oidc_applications_client_id"); + + b.ToTable("oidc_applications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Scopes") + .HasColumnType("text") + .HasColumnName("scopes"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_authorizations"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_authorizations_application_id_status_subject_type"); + + b.ToTable("oidc_authorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Descriptions") + .HasColumnType("text") + .HasColumnName("descriptions"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Resources") + .HasColumnType("text") + .HasColumnName("resources"); + + b.HasKey("Id") + .HasName("pk_oidc_scopes"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_oidc_scopes_name"); + + b.ToTable("oidc_scopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("AuthorizationId") + .HasColumnType("uuid") + .HasColumnName("authorization_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.Property("Payload") + .HasColumnType("text") + .HasColumnName("payload"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("redemption_date"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("reference_id"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_tokens"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasDatabaseName("ix_oidc_tokens_reference_id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_tokens_application_id_status_subject_type"); + + b.ToTable("oidc_tokens", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.Property("AlertId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("AlertTypeId") + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("Details") + .HasColumnType("text") + .HasColumnName("details"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtSanctionId") + .HasColumnType("uuid") + .HasColumnName("dqt_sanction_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ExternalLink") + .HasColumnType("text") + .HasColumnName("external_link"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("AlertId") + .HasName("pk_alerts"); + + b.HasIndex("AlertTypeId") + .HasDatabaseName("ix_alerts_alert_type_id"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_alerts_person_id"); + + b.ToTable("alerts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Property("AlertCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("AlertCategoryId") + .HasName("pk_alert_categories"); + + b.HasIndex("DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_categories_display_order"); + + b.ToTable("alert_categories", (string)null); + + b.HasData( + new + { + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + Name = "EEA Decision" + }, + new + { + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 2, + Name = "Failed induction" + }, + new + { + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 3, + Name = "Flag" + }, + new + { + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DisplayOrder = 4, + Name = "GTC Decision" + }, + new + { + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DisplayOrder = 5, + Name = "GTC Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DisplayOrder = 6, + Name = "GTC Restriction" + }, + new + { + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 7, + Name = "Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 8, + Name = "Restricted/DBS" + }, + new + { + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DisplayOrder = 9, + Name = "Restriction" + }, + new + { + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 10, + Name = "Section 128 (SoS)" + }, + new + { + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 12, + Name = "TRA Decision (SoS)" + }, + new + { + AlertCategoryId = new Guid("e4057fc2-a010-42a9-8cb2-7dcc5c9b5fa7"), + DisplayOrder = 11, + Name = "SoS Restriction" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.Property("AlertTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("AlertCategoryId") + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("DqtSanctionCode") + .HasMaxLength(5) + .HasColumnType("character varying(5)") + .HasColumnName("dqt_sanction_code") + .UseCollation("case_insensitive"); + + b.Property("InternalOnly") + .HasColumnType("boolean") + .HasColumnName("internal_only"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("ProhibitionLevel") + .HasColumnType("integer") + .HasColumnName("prohibition_level"); + + b.HasKey("AlertTypeId") + .HasName("pk_alert_types"); + + b.HasIndex("AlertCategoryId") + .HasDatabaseName("ix_alert_types_alert_category_id"); + + b.HasIndex("AlertCategoryId", "DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_types_display_order") + .HasFilter("display_order is not null and is_active = true"); + + b.ToTable("alert_types", (string)null); + + b.HasData( + new + { + AlertTypeId = new Guid("2ca98658-1d5b-49d5-b05f-cc08c8b8502c"), + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + DqtSanctionCode = "T8", + InternalOnly = true, + IsActive = true, + Name = "Teacher sanctioned in other EEA member state", + ProhibitionLevel = 3 + }, + new + { + AlertTypeId = new Guid("9fafaa80-f9f8-44a0-b7b3-cffedcbe0298"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 1, + DqtSanctionCode = "C2", + InternalOnly = false, + IsActive = true, + Name = "Failed induction", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("651e1f56-3135-4961-bd7e-3f7b2c75cb04"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C1", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by the Secretary of State - failed probation", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5ea8bb68-4774-4ad8-b635-213a0cdda4c3"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C3", + InternalOnly = false, + IsActive = false, + Name = "Restricted by the Secretary of State - failed probation - permitted to carry out specified work for a period equal in length to a statutory induction period only", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ae3e385d-03f8-4f12-9ce2-006afe827d23"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 1, + DqtSanctionCode = "T9", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL INFORMATION ONLY - see alert details", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("12435c00-88cb-406b-b2b8-7400c1ced7b8"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 2, + DqtSanctionCode = "T10", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL USER ONLY – known duplicate record", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("a6fc9f2e-8923-4163-978e-93bd901d146f"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A18", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - conviction of a relevant offence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1ebd1620-293d-4169-ba78-0b41a6413ad9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A7", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - serious professional incompetence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3499860a-a0fb-43e3-878e-c226d14150b0"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A3", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - unacceptable professional conduct", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("552ee226-a3a9-4dc3-8d04-0b7e4f641b51"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A15", + InternalOnly = true, + IsActive = false, + Name = "For internal information only - historic GTC finding of unsuitable for registration", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("33e00e46-6513-4136-adfd-1352cf34d8ec"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A22", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - breach of condition(s)", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0740f9eb-ece3-4394-a230-453da224d337"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A16", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - conviction for a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("b6c8d8f1-723e-49a5-9551-25805e3e29b9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A12", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("78f88de2-9ec1-41b8-948a-33bdff223206"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A11", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("fcff87d6-88f5-4fc5-ac81-5350b4fdd9e1"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A17", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - conviction of a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("3f7de5fd-05a8-404f-a97c-428f54e81322"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A8", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0ae8d4b6-ec9b-47ca-9338-6dae9192afe5"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A4", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("72e48b6a-e781-4bf3-910b-91f2d28f2eaa"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("950d3eed-bef5-448a-b0f0-bf9c54f2103b"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("cac68337-3f95-4475-97cf-1381e6b74700"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("c02bdc3a-7a19-4034-aa23-3a23c54e1d34"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("e3658a61-bee2-4df1-9a26-e010681ee310"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("fa6bd220-61b0-41fc-9066-421b3b9d7885"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("d372fcfa-1c4a-4fed-84c8-4c7885575681"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A20", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("af65c236-47a6-427b-8e4b-930de6d256f0"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A19", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("50508749-7a6b-4175-8538-9a1e55692efd"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A14", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("a6f51ccc-a19c-4dc2-ba80-ffb7a95ff2ee"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A6", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1a2b06ae-7e9f-4761-b95d-397ca5da4b13"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A13", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("872d7700-aa6f-435e-b5f9-821fb087962a"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A2", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("17b4fe26-7468-4702-92e5-785b861cf0fa"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A24", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - with conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3c5fc83b-10e1-4a15-83e6-794fce3e0b45"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A23", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - without conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("eab8b66d-68d0-4cb9-8e4d-bbd245648fb6"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B1", + InternalOnly = true, + IsActive = false, + Name = "Barring by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("2c496e3f-00d3-4f0d-81f3-21458fe707b3"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "G2", + InternalOnly = true, + IsActive = false, + Name = "Formerly barred by the Independent Safeguarding Authority", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("993daa42-96cb-4621-bd9e-d4b195076bbe"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B6", + InternalOnly = true, + IsActive = false, + Name = "Formerly on List 99", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a414283f-7d5b-4587-83bf-f6da8c05b8d5"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 1, + DqtSanctionCode = "T2", + InternalOnly = false, + IsActive = true, + Name = "Interim prohibition by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ed0cd700-3fb2-4db0-9403-ba57126090ed"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 2, + DqtSanctionCode = "T1", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - misconduct", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("8ef92c14-4b1f-4530-9189-779ad9f3cefd"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B3", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by an Independent Schools Tribunal or Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("50feafbc-5124-4189-b06c-6463c7ebb8a8"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 3, + DqtSanctionCode = "T3", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - deregistered by GTC Scotland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5aa21b8f-2069-43c9-8afd-05b34b02505f"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 4, + DqtSanctionCode = "T5", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to GTC Northern Ireland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a5bd4352-2cec-4417-87a1-4b6b79d033c2"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 5, + DqtSanctionCode = "T4", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to the Education Workforce Council, Wales", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("40794ea8-eda2-40a8-a26a-5f447aae6c99"), + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 1, + DqtSanctionCode = "G1", + InternalOnly = true, + IsActive = true, + Name = "A possible matching record was found. Please contact the DBS before employing this person", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("38db7946-2dbf-408e-bc48-1625829e7dfe"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2B", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Not Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("18e04dcb-fb86-4b05-8d5d-ff9c5da738dd"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2A", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("241eeb78-fac7-4c77-8059-c12e93dc2fae"), + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 1, + DqtSanctionCode = "T7", + InternalOnly = false, + IsActive = true, + Name = "Section 128 barring direction", + ProhibitionLevel = 4 + }, + new + { + AlertTypeId = new Guid("7924fe90-483c-49f8-84fc-674feddba848"), + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 1, + DqtSanctionCode = "T6", + InternalOnly = false, + IsActive = true, + Name = "Secretary of State decision - no prohibition", + ProhibitionLevel = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.Property("ApiKeyId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("api_key_id"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Expires") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("key"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("ApiKeyId") + .HasName("pk_api_keys"); + + b.HasIndex("ApplicationUserId") + .HasDatabaseName("ix_api_keys_application_user_id"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_api_keys_key"); + + b.ToTable("api_keys", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", b => + { + b.Property("CountryId") + .HasMaxLength(4) + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("CountryId") + .HasName("pk_countries"); + + b.ToTable("countries", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EntityChangesJournal", b => + { + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("EntityLogicalName") + .HasColumnType("text") + .HasColumnName("entity_logical_name"); + + b.Property("DataToken") + .HasColumnType("text") + .HasColumnName("data_token"); + + b.Property("LastUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_updated"); + + b.Property("LastUpdatedBy") + .HasColumnType("text") + .HasColumnName("last_updated_by"); + + b.Property("NextQueryPageNumber") + .HasColumnType("integer") + .HasColumnName("next_query_page_number"); + + b.Property("NextQueryPageSize") + .HasColumnType("integer") + .HasColumnName("next_query_page_size"); + + b.Property("NextQueryPagingCookie") + .HasColumnType("text") + .HasColumnName("next_query_paging_cookie"); + + b.HasKey("Key", "EntityLogicalName") + .HasName("pk_entity_changes_journals"); + + b.ToTable("entity_changes_journals", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.Property("EstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Address3") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("address3") + .UseCollation("case_insensitive"); + + b.Property("County") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("county") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentName") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("establishment_name") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(1) + .HasColumnName("establishment_source_id"); + + b.Property("EstablishmentStatusCode") + .HasColumnType("integer") + .HasColumnName("establishment_status_code"); + + b.Property("EstablishmentStatusName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_status_name"); + + b.Property("EstablishmentTypeCode") + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasColumnName("establishment_type_code"); + + b.Property("EstablishmentTypeGroupCode") + .HasColumnType("integer") + .HasColumnName("establishment_type_group_code"); + + b.Property("EstablishmentTypeGroupName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_type_group_name"); + + b.Property("EstablishmentTypeName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("establishment_type_name") + .UseCollation("case_insensitive"); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("LaName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("la_name") + .UseCollation("case_insensitive"); + + b.Property("Locality") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("locality") + .UseCollation("case_insensitive"); + + b.Property("Postcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("postcode") + .UseCollation("case_insensitive"); + + b.Property("Street") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("street") + .UseCollation("case_insensitive"); + + b.Property("Town") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("town") + .UseCollation("case_insensitive"); + + b.Property("Urn") + .HasMaxLength(6) + .HasColumnType("integer") + .HasColumnName("urn") + .IsFixedLength(); + + b.HasKey("EstablishmentId") + .HasName("pk_establishments"); + + b.HasIndex("EstablishmentSourceId") + .HasDatabaseName("ix_establishment_establishment_source_id"); + + b.HasIndex("Urn") + .HasDatabaseName("ix_establishment_urn"); + + b.HasIndex("LaCode", "EstablishmentNumber") + .HasDatabaseName("ix_establishment_la_code_establishment_number"); + + b.ToTable("establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", b => + { + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("establishment_source_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EstablishmentSourceId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("EstablishmentSourceId") + .HasName("pk_establishment_sources"); + + b.ToTable("establishment_sources", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Event", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("event_id"); + + b.Property("AlertId") + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("event_name"); + + b.Property("Inserted") + .HasColumnType("timestamp with time zone") + .HasColumnName("inserted"); + + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("key"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Published") + .HasColumnType("boolean") + .HasColumnName("published"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.HasKey("EventId") + .HasName("pk_events"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_events_key") + .HasFilter("key is not null"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_events_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.HasIndex("AlertId", "EventName") + .HasDatabaseName("ix_events_alert_id_event_name") + .HasFilter("alert_id is not null"); + + b.HasIndex("PersonId", "EventName") + .HasDatabaseName("ix_events_person_id_event_name") + .HasFilter("person_id is not null"); + + b.HasIndex("QualificationId", "EventName") + .HasDatabaseName("ix_events_qualification_id_event_name") + .HasFilter("qualification_id is not null"); + + b.ToTable("events", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Property("EytsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("EytsAwardedEmailsJobId") + .HasName("pk_eyts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_eyts_awarded_emails_jobs_executed_utc"); + + b.ToTable("eyts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.Property("EytsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("EytsAwardedEmailsJobId", "PersonId") + .HasName("pk_eyts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_eyts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("eyts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Property("InductionCompletedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InductionCompletedEmailsJobId") + .HasName("pk_induction_completed_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_induction_completed_emails_jobs_executed_utc"); + + b.ToTable("induction_completed_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.Property("InductionCompletedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InductionCompletedEmailsJobId", "PersonId") + .HasName("pk_induction_completed_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_induction_completed_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("induction_completed_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InternationalQtsAwardedEmailsJobId") + .HasName("pk_international_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_international_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("international_qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InternationalQtsAwardedEmailsJobId", "PersonId") + .HasName("pk_international_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_international_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("international_qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.JourneyState", b => + { + b.Property("InstanceId") + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("instance_id"); + + b.Property("Completed") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("State") + .IsRequired() + .HasColumnType("text") + .HasColumnName("state"); + + b.Property("Updated") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("user_id"); + + b.HasKey("InstanceId") + .HasName("pk_journey_states"); + + b.ToTable("journey_states", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", b => + { + b.Property("MandatoryQualificationProviderId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("mandatory_qualification_provider_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("MandatoryQualificationProviderId") + .HasName("pk_mandatory_qualification_providers"); + + b.ToTable("mandatory_qualification_providers", (string)null); + + b.HasData( + new + { + MandatoryQualificationProviderId = new Guid("e28ea41d-408d-4c89-90cc-8b9b04ac68f5"), + Name = "University of Birmingham" + }, + new + { + MandatoryQualificationProviderId = new Guid("89f9a1aa-3d68-4985-a4ce-403b6044c18c"), + Name = "University of Leeds" + }, + new + { + MandatoryQualificationProviderId = new Guid("aa5c300e-3b7c-456c-8183-3520b3d55dca"), + Name = "University of Manchester" + }, + new + { + MandatoryQualificationProviderId = new Guid("f417e73e-e2ad-40eb-85e3-55865be7f6be"), + Name = "Mary Hare School / University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("fbf22e04-b274-4c80-aba8-79fb6a7a32ce"), + Name = "University of Edinburgh" + }, + new + { + MandatoryQualificationProviderId = new Guid("26204149-349c-4ad6-9466-bb9b83723eae"), + Name = "Liverpool John Moores University" + }, + new + { + MandatoryQualificationProviderId = new Guid("0c30f666-647c-4ea8-8883-0fc6010b56be"), + Name = "University of Oxford/Oxford Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d0e6d54c-5e90-438a-945d-f97388c2b352"), + Name = "University of Cambridge" + }, + new + { + MandatoryQualificationProviderId = new Guid("aec32252-ef25-452e-a358-34a04e03369c"), + Name = "University of Newcastle-upon-Tyne" + }, + new + { + MandatoryQualificationProviderId = new Guid("d9ee7054-7fde-4cfd-9a5e-4b99511d1b3d"), + Name = "University of Plymouth" + }, + new + { + MandatoryQualificationProviderId = new Guid("707d58ca-1953-413b-9a46-41e9b0be885e"), + Name = "University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("3fc648a7-18e4-49e7-8a4b-1612616b72d5"), + Name = "University of London" + }, + new + { + MandatoryQualificationProviderId = new Guid("374dceb8-8224-45b8-b7dc-a6b0282b1065"), + Name = "Bristol Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d4fc958b-21de-47ec-9f03-36ae237a1b11"), + Name = "University College, Swansea" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.NameSynonyms", b => + { + b.Property("NameSynonymsId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("name_synonyms_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NameSynonymsId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("Synonyms") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("synonyms") + .UseCollation("case_insensitive"); + + b.HasKey("NameSynonymsId") + .HasName("pk_name_synonyms"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_name_synonyms_name"); + + b.ToTable("name_synonyms", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.Property("Subject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("subject"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email"); + + b.Property("FirstOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_one_login_sign_in"); + + b.Property("FirstSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_sign_in"); + + b.Property("LastCoreIdentityVc") + .HasColumnType("jsonb") + .HasColumnName("last_core_identity_vc"); + + b.Property("LastOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_one_login_sign_in"); + + b.Property("LastSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_sign_in"); + + b.Property("MatchRoute") + .HasColumnType("integer") + .HasColumnName("match_route"); + + b.Property("MatchedAttributes") + .HasColumnType("jsonb") + .HasColumnName("matched_attributes"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("VerificationRoute") + .HasColumnType("integer") + .HasColumnName("verification_route"); + + b.Property("VerifiedDatesOfBirth") + .HasColumnType("jsonb") + .HasColumnName("verified_dates_of_birth"); + + b.Property("VerifiedNames") + .HasColumnType("jsonb") + .HasColumnName("verified_names"); + + b.Property("VerifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_on"); + + b.HasKey("Subject") + .HasName("pk_one_login_users"); + + b.ToTable("one_login_users", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Property("PersonId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtContactId") + .HasColumnType("uuid") + .HasColumnName("dqt_contact_id"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_first_name") + .UseCollation("case_insensitive"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_last_name") + .UseCollation("case_insensitive"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtMiddleName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_middle_name") + .UseCollation("case_insensitive"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EmailAddress") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("email_address") + .UseCollation("case_insensitive"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("first_name") + .UseCollation("case_insensitive"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("last_name") + .UseCollation("case_insensitive"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("middle_name") + .UseCollation("case_insensitive"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Trn") + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("PersonId") + .HasName("pk_persons"); + + b.HasIndex("DqtContactId") + .IsUnique() + .HasDatabaseName("ix_persons_dqt_contact_id") + .HasFilter("dqt_contact_id is not null"); + + b.HasIndex("Trn") + .IsUnique() + .HasDatabaseName("ix_persons_trn") + .HasFilter("trn is not null"); + + b.ToTable("persons", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.PersonSearchAttribute", b => + { + b.Property("PersonSearchAttributeId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("person_search_attribute_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersonSearchAttributeId")); + + b.Property("AttributeKey") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_key") + .UseCollation("case_insensitive"); + + b.Property("AttributeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_type") + .UseCollation("case_insensitive"); + + b.Property("AttributeValue") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("attribute_value") + .UseCollation("case_insensitive"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("tags"); + + b.HasKey("PersonSearchAttributeId") + .HasName("pk_person_search_attributes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_person_search_attributes_person_id"); + + b.HasIndex("AttributeType", "AttributeValue") + .HasDatabaseName("ix_person_search_attributes_attribute_type_and_value"); + + b.ToTable("person_search_attributes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Property("QtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("QtsAwardedEmailsJobId") + .HasName("pk_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.Property("QtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("QtsAwardedEmailsJobId", "PersonId") + .HasName("pk_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Property("QualificationId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtQualificationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qualification_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("QualificationId") + .HasName("pk_qualifications"); + + b.HasIndex("DqtQualificationId") + .IsUnique() + .HasDatabaseName("ix_qualifications_dqt_qualification_id") + .HasFilter("dqt_qualification_id is not null"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_qualifications_person_id"); + + b.ToTable("qualifications", (string)null); + + b.HasDiscriminator("QualificationType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.Property("RouteId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("route_id"); + + b.Property("AgeRangeFrom") + .HasColumnType("integer") + .HasColumnName("age_range_from"); + + b.Property("AgeRangeTo") + .HasColumnType("integer") + .HasColumnName("age_range_to"); + + b.Property("CountryId") + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("ExternalReference") + .HasColumnType("text") + .HasColumnName("external_reference"); + + b.Property("InductionExemptionReason") + .HasColumnType("integer") + .HasColumnName("induction_exemption_reason"); + + b.Property("IttProviderId") + .HasColumnType("uuid") + .HasColumnName("itt_provider_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("ProgrammeEndDate") + .HasColumnType("date") + .HasColumnName("programme_end_date"); + + b.Property("ProgrammeStartDate") + .HasColumnType("date") + .HasColumnName("programme_start_date"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("RouteStatus") + .HasColumnType("integer") + .HasColumnName("route_status"); + + b.Property("RouteType") + .HasColumnType("integer") + .HasColumnName("route_type"); + + b.Property>("Subjects") + .IsRequired() + .HasColumnType("uuid[]") + .HasColumnName("subjects"); + + b.HasKey("RouteId") + .HasName("pk_routes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_routes_person_id"); + + b.ToTable("routes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.Property("SupportTaskReference") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("support_task_reference"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("OneLoginUserSubject") + .HasColumnType("character varying(255)") + .HasColumnName("one_login_user_subject"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("SupportTaskType") + .HasColumnType("integer") + .HasColumnName("support_task_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("_data") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.HasKey("SupportTaskReference") + .HasName("pk_support_tasks"); + + b.HasIndex("OneLoginUserSubject") + .HasDatabaseName("ix_support_tasks_one_login_user_subject"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_support_tasks_person_id"); + + b.ToTable("support_tasks", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", b => + { + b.Property("TpsCsvExtractId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Filename") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("filename"); + + b.HasKey("TpsCsvExtractId") + .HasName("pk_tps_csv_extracts"); + + b.ToTable("tps_csv_extracts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.Property("TpsCsvExtractItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasColumnType("date") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasColumnType("date") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasColumnType("date") + .HasColumnName("employment_start_date"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasColumnType("date") + .HasColumnName("extract_date"); + + b.Property("Gender") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("gender"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LocalAuthorityCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("local_authority_code") + .IsFixedLength(); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasColumnType("integer") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Result") + .HasColumnType("integer") + .HasColumnName("result"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("TpsCsvExtractLoadItemId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("WithdrawalIndicator") + .HasMaxLength(1) + .HasColumnType("character(1)") + .HasColumnName("withdrawal_indicator") + .IsFixedLength(); + + b.HasKey("TpsCsvExtractItemId") + .HasName("pk_tps_csv_extract_items"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_csv_extract_items_key"); + + b.HasIndex("TpsCsvExtractId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasIndex("TpsCsvExtractLoadItemId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_load_item_id"); + + b.HasIndex("Trn") + .HasDatabaseName("ix_tps_csv_extract_items_trn"); + + b.HasIndex("LocalAuthorityCode", "EstablishmentNumber") + .HasDatabaseName("ix_tps_csv_extract_items_la_code_establishment_number"); + + b.ToTable("tps_csv_extract_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.Property("TpsCsvExtractLoadItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_start_date"); + + b.Property("Errors") + .HasColumnType("integer") + .HasColumnName("errors"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_number"); + + b.Property("EstablishmentPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("extract_date"); + + b.Property("FullOrPartTimeIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("full_or_part_time_indicator"); + + b.Property("Gender") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("gender"); + + b.Property("LocalAuthorityCode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("local_authority_code"); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("national_insurance_number"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("Trn") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("trn"); + + b.Property("WithdrawalIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("withdrawal_indicator"); + + b.HasKey("TpsCsvExtractLoadItemId") + .HasName("pk_tps_csv_extract_load_items"); + + b.ToTable("tps_csv_extract_load_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.Property("TpsEmploymentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_employment_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("EstablishmentId") + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LastExtractDate") + .HasColumnType("date") + .HasColumnName("last_extract_date"); + + b.Property("LastKnownTpsEmployedDate") + .HasColumnType("date") + .HasColumnName("last_known_tps_employed_date"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("PersonPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("person_postcode"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("WithdrawalConfirmed") + .HasColumnType("boolean") + .HasColumnName("withdrawal_confirmed"); + + b.HasKey("TpsEmploymentId") + .HasName("pk_tps_employments"); + + b.HasIndex("EstablishmentId") + .HasDatabaseName("ix_tps_employments_establishment_id"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_employments_key"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_tps_employments_person_id"); + + b.ToTable("tps_employments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishment", b => + { + b.Property("TpsEstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_establishment_id"); + + b.Property("EmployersName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employers_name"); + + b.Property("EstablishmentCode") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_code") + .IsFixedLength(); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("SchoolClosedDate") + .HasColumnType("date") + .HasColumnName("school_closed_date"); + + b.Property("SchoolGiasName") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("school_gias_name"); + + b.HasKey("TpsEstablishmentId") + .HasName("pk_tps_establishments"); + + b.HasIndex("LaCode", "EstablishmentCode") + .HasDatabaseName("ix_tps_establishments_la_code_establishment_number"); + + b.ToTable("tps_establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishmentType", b => + { + b.Property("TpsEstablishmentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("tps_establishment_type_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TpsEstablishmentTypeId")); + + b.Property("Description") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("description"); + + b.Property("EstablishmentRangeFrom") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_from") + .IsFixedLength(); + + b.Property("EstablishmentRangeTo") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_to") + .IsFixedLength(); + + b.Property("ShortDescription") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("short_description"); + + b.HasKey("TpsEstablishmentTypeId") + .HasName("pk_tps_establishment_types"); + + b.ToTable("tps_establishment_types", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequest", b => + { + b.Property("TrnRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("trn_request_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrnRequestId")); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("IdentityUserId") + .HasColumnType("uuid") + .HasColumnName("identity_user_id"); + + b.Property("LinkedToIdentity") + .HasColumnType("boolean") + .HasColumnName("linked_to_identity"); + + b.Property("RequestId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("TeacherId") + .HasColumnType("uuid") + .HasColumnName("teacher_id"); + + b.Property("TrnToken") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("trn_token"); + + b.HasKey("TrnRequestId") + .HasName("pk_trn_requests"); + + b.HasIndex("ClientId", "RequestId") + .IsUnique() + .HasDatabaseName("ix_trn_requests_client_id_request_id"); + + b.ToTable("trn_requests", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequestMetadata", b => + { + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("RequestId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("VerifiedOneLoginUserSubject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("verified_one_login_user_subject"); + + b.HasKey("ApplicationUserId", "RequestId") + .HasName("pk_trn_request_metadata"); + + b.ToTable("trn_request_metadata", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Active") + .HasColumnType("boolean") + .HasColumnName("active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("UserType") + .HasColumnType("integer") + .HasColumnName("user_type"); + + b.HasKey("UserId") + .HasName("pk_users"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator("UserType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.Property("WebhookEndpointId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("address"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property>("CloudEventTypes") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("cloud_event_types"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.HasKey("WebhookEndpointId") + .HasName("pk_webhook_endpoints"); + + b.ToTable("webhook_endpoints", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.Property("WebhookMessageId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_message_id"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("CloudEventId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("cloud_event_id"); + + b.Property("CloudEventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("cloud_event_type"); + + b.Property("Data") + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone") + .HasColumnName("delivered"); + + b.Property>("DeliveryAttempts") + .IsRequired() + .HasColumnType("timestamp with time zone[]") + .HasColumnName("delivery_attempts"); + + b.Property>("DeliveryErrors") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("delivery_errors"); + + b.Property("NextDeliveryAttempt") + .HasColumnType("timestamp with time zone") + .HasColumnName("next_delivery_attempt"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("WebhookEndpointId") + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.HasKey("WebhookMessageId") + .HasName("pk_webhook_messages"); + + b.ToTable("webhook_messages", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EarlyYearsTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("DqtMqEstablishmentId") + .HasColumnType("uuid") + .HasColumnName("dqt_mq_establishment_id"); + + b.Property("DqtSpecialismId") + .HasColumnType("uuid") + .HasColumnName("dqt_specialism_id"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("mq_provider_id"); + + b.Property("Specialism") + .HasColumnType("integer") + .HasColumnName("mq_specialism"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("mq_status"); + + b.HasDiscriminator().HasValue(0); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QualifiedTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("ApiRoles") + .HasColumnType("varchar[]") + .HasColumnName("api_roles"); + + b.Property("ClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("client_secret"); + + b.Property("IsOidcClient") + .HasColumnType("boolean") + .HasColumnName("is_oidc_client"); + + b.Property("OneLoginAuthenticationSchemeName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_authentication_scheme_name"); + + b.Property("OneLoginClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_client_id"); + + b.Property("OneLoginPostLogoutRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_post_logout_redirect_uri_path"); + + b.Property("OneLoginPrivateKeyPem") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("one_login_private_key_pem"); + + b.Property("OneLoginRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_redirect_uri_path"); + + b.Property>("PostLogoutRedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("post_logout_redirect_uris"); + + b.Property>("RedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("redirect_uris"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_users_client_id") + .HasFilter("client_id is not null"); + + b.HasIndex("OneLoginAuthenticationSchemeName") + .IsUnique() + .HasDatabaseName("ix_users_one_login_authentication_scheme_name") + .HasFilter("one_login_authentication_scheme_name is not null"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SystemUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator().HasValue(3); + + b.HasData( + new + { + UserId = new Guid("a81394d1-a498-46d8-af3e-e077596ab303"), + Active = true, + Name = "System", + UserType = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.User", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("AzureAdUserId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("azure_ad_user_id"); + + b.Property("DqtUserId") + .HasColumnType("uuid") + .HasColumnName("dqt_user_id"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email") + .UseCollation("case_insensitive"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("varchar[]") + .HasColumnName("roles"); + + b.HasIndex("AzureAdUserId") + .IsUnique() + .HasDatabaseName("ix_users_azure_ad_user_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_authorizations_oidc_applications_application_id"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_tokens_oidc_applications_application_id"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId") + .HasConstraintName("fk_oidc_tokens_oidc_authorizations_authorization_id"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", "AlertType") + .WithMany() + .HasForeignKey("AlertTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_alert_type"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Alerts") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_person"); + + b.Navigation("AlertType"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", "AlertCategory") + .WithMany("AlertTypes") + .HasForeignKey("AlertCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alert_types_alert_category"); + + b.Navigation("AlertCategory"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", "ApplicationUser") + .WithMany("ApiKeys") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_key_application_user"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", null) + .WithMany() + .HasForeignKey("EstablishmentSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_establishments_establishment_source_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", "EytsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("EytsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_eyts_awarded_emails_job_items_eyts_awarded_emails_jobs_eyts"); + + b.Navigation("EytsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", "InductionCompletedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InductionCompletedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_induction_completed_emails_job_items_induction_completed_em"); + + b.Navigation("InductionCompletedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", "InternationalQtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InternationalQtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_international_qts_awarded_emails_job_items_international_qt"); + + b.Navigation("InternationalQtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithOne() + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", "PersonId") + .HasConstraintName("fk_one_login_users_persons_person_id"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", "QtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("QtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qts_awarded_emails_job_items_qts_awarded_emails_jobs_qts_aw"); + + b.Navigation("QtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Qualifications") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qualifications_person"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", null) + .WithMany() + .HasForeignKey("CountryId") + .HasConstraintName("fk_routes_countries_country_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany("Routes") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_routes_persons_person_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", "Qualification") + .WithOne("Route") + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", "QualificationId") + .HasConstraintName("fk_routes_qualifications_qualification_id"); + + b.Navigation("Qualification"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", null) + .WithMany() + .HasForeignKey("OneLoginUserSubject") + .HasConstraintName("fk_support_tasks_one_login_user"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .HasConstraintName("fk_support_tasks_person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", null) + .WithMany() + .HasForeignKey("TpsCsvExtractLoadItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_load_item_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_load_items_tps_csv_extract_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", null) + .WithMany() + .HasForeignKey("EstablishmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_establishment_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_person_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_endpoints_application_users_application_user_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", "WebhookEndpoint") + .WithMany() + .HasForeignKey("WebhookEndpointId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_messages_webhook_endpoints_webhook_endpoint_id"); + + b.Navigation("WebhookEndpoint"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .HasConstraintName("fk_qualifications_mandatory_qualification_provider"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Navigation("AlertTypes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Navigation("Alerts"); + + b.Navigation("Qualifications"); + + b.Navigation("Routes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Navigation("Route"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.Navigation("ApiKeys"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.cs new file mode 100644 index 000000000..605db23f8 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107113402_TrnRequestMetadata.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + /// + public partial class TrnRequestMetadata : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "trn_request_metadata", + columns: table => new + { + application_user_id = table.Column(type: "uuid", nullable: false), + request_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + verified_one_login_user_subject = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_trn_request_metadata", x => new { x.application_user_id, x.request_id }); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "trn_request_metadata"); + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.Designer.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.Designer.cs new file mode 100644 index 000000000..f946cff1b --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.Designer.cs @@ -0,0 +1,3305 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TeachingRecordSystem.Core.DataStore.Postgres; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + [DbContext(typeof(TrsDbContext))] + [Migration("20241107123546_NullableOneLoginUserFields")] + partial class NullableOneLoginUserFields + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("application_type"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("text") + .HasColumnName("client_secret"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_type"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("consent_type"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("JsonWebKeySet") + .HasColumnType("text") + .HasColumnName("json_web_key_set"); + + b.Property("Permissions") + .HasColumnType("text") + .HasColumnName("permissions"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text") + .HasColumnName("post_logout_redirect_uris"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedirectUris") + .HasColumnType("text") + .HasColumnName("redirect_uris"); + + b.Property("Requirements") + .HasColumnType("text") + .HasColumnName("requirements"); + + b.Property("Settings") + .HasColumnType("text") + .HasColumnName("settings"); + + b.HasKey("Id") + .HasName("pk_oidc_applications"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_oidc_applications_client_id"); + + b.ToTable("oidc_applications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Scopes") + .HasColumnType("text") + .HasColumnName("scopes"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_authorizations"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_authorizations_application_id_status_subject_type"); + + b.ToTable("oidc_authorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Descriptions") + .HasColumnType("text") + .HasColumnName("descriptions"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Resources") + .HasColumnType("text") + .HasColumnName("resources"); + + b.HasKey("Id") + .HasName("pk_oidc_scopes"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_oidc_scopes_name"); + + b.ToTable("oidc_scopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("AuthorizationId") + .HasColumnType("uuid") + .HasColumnName("authorization_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.Property("Payload") + .HasColumnType("text") + .HasColumnName("payload"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("redemption_date"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("reference_id"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_tokens"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasDatabaseName("ix_oidc_tokens_reference_id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_tokens_application_id_status_subject_type"); + + b.ToTable("oidc_tokens", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.Property("AlertId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("AlertTypeId") + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("Details") + .HasColumnType("text") + .HasColumnName("details"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtSanctionId") + .HasColumnType("uuid") + .HasColumnName("dqt_sanction_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ExternalLink") + .HasColumnType("text") + .HasColumnName("external_link"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("AlertId") + .HasName("pk_alerts"); + + b.HasIndex("AlertTypeId") + .HasDatabaseName("ix_alerts_alert_type_id"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_alerts_person_id"); + + b.ToTable("alerts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Property("AlertCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("AlertCategoryId") + .HasName("pk_alert_categories"); + + b.HasIndex("DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_categories_display_order"); + + b.ToTable("alert_categories", (string)null); + + b.HasData( + new + { + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + Name = "EEA Decision" + }, + new + { + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 2, + Name = "Failed induction" + }, + new + { + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 3, + Name = "Flag" + }, + new + { + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DisplayOrder = 4, + Name = "GTC Decision" + }, + new + { + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DisplayOrder = 5, + Name = "GTC Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DisplayOrder = 6, + Name = "GTC Restriction" + }, + new + { + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 7, + Name = "Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 8, + Name = "Restricted/DBS" + }, + new + { + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DisplayOrder = 9, + Name = "Restriction" + }, + new + { + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 10, + Name = "Section 128 (SoS)" + }, + new + { + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 12, + Name = "TRA Decision (SoS)" + }, + new + { + AlertCategoryId = new Guid("e4057fc2-a010-42a9-8cb2-7dcc5c9b5fa7"), + DisplayOrder = 11, + Name = "SoS Restriction" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.Property("AlertTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("AlertCategoryId") + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("DqtSanctionCode") + .HasMaxLength(5) + .HasColumnType("character varying(5)") + .HasColumnName("dqt_sanction_code") + .UseCollation("case_insensitive"); + + b.Property("InternalOnly") + .HasColumnType("boolean") + .HasColumnName("internal_only"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("ProhibitionLevel") + .HasColumnType("integer") + .HasColumnName("prohibition_level"); + + b.HasKey("AlertTypeId") + .HasName("pk_alert_types"); + + b.HasIndex("AlertCategoryId") + .HasDatabaseName("ix_alert_types_alert_category_id"); + + b.HasIndex("AlertCategoryId", "DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_types_display_order") + .HasFilter("display_order is not null and is_active = true"); + + b.ToTable("alert_types", (string)null); + + b.HasData( + new + { + AlertTypeId = new Guid("2ca98658-1d5b-49d5-b05f-cc08c8b8502c"), + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + DqtSanctionCode = "T8", + InternalOnly = true, + IsActive = true, + Name = "Teacher sanctioned in other EEA member state", + ProhibitionLevel = 3 + }, + new + { + AlertTypeId = new Guid("9fafaa80-f9f8-44a0-b7b3-cffedcbe0298"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 1, + DqtSanctionCode = "C2", + InternalOnly = false, + IsActive = true, + Name = "Failed induction", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("651e1f56-3135-4961-bd7e-3f7b2c75cb04"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C1", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by the Secretary of State - failed probation", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5ea8bb68-4774-4ad8-b635-213a0cdda4c3"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C3", + InternalOnly = false, + IsActive = false, + Name = "Restricted by the Secretary of State - failed probation - permitted to carry out specified work for a period equal in length to a statutory induction period only", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ae3e385d-03f8-4f12-9ce2-006afe827d23"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 1, + DqtSanctionCode = "T9", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL INFORMATION ONLY - see alert details", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("12435c00-88cb-406b-b2b8-7400c1ced7b8"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 2, + DqtSanctionCode = "T10", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL USER ONLY – known duplicate record", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("a6fc9f2e-8923-4163-978e-93bd901d146f"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A18", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - conviction of a relevant offence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1ebd1620-293d-4169-ba78-0b41a6413ad9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A7", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - serious professional incompetence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3499860a-a0fb-43e3-878e-c226d14150b0"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A3", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - unacceptable professional conduct", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("552ee226-a3a9-4dc3-8d04-0b7e4f641b51"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A15", + InternalOnly = true, + IsActive = false, + Name = "For internal information only - historic GTC finding of unsuitable for registration", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("33e00e46-6513-4136-adfd-1352cf34d8ec"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A22", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - breach of condition(s)", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0740f9eb-ece3-4394-a230-453da224d337"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A16", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - conviction for a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("b6c8d8f1-723e-49a5-9551-25805e3e29b9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A12", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("78f88de2-9ec1-41b8-948a-33bdff223206"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A11", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("fcff87d6-88f5-4fc5-ac81-5350b4fdd9e1"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A17", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - conviction of a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("3f7de5fd-05a8-404f-a97c-428f54e81322"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A8", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0ae8d4b6-ec9b-47ca-9338-6dae9192afe5"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A4", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("72e48b6a-e781-4bf3-910b-91f2d28f2eaa"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("950d3eed-bef5-448a-b0f0-bf9c54f2103b"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("cac68337-3f95-4475-97cf-1381e6b74700"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("c02bdc3a-7a19-4034-aa23-3a23c54e1d34"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("e3658a61-bee2-4df1-9a26-e010681ee310"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("fa6bd220-61b0-41fc-9066-421b3b9d7885"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("d372fcfa-1c4a-4fed-84c8-4c7885575681"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A20", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("af65c236-47a6-427b-8e4b-930de6d256f0"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A19", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("50508749-7a6b-4175-8538-9a1e55692efd"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A14", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("a6f51ccc-a19c-4dc2-ba80-ffb7a95ff2ee"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A6", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1a2b06ae-7e9f-4761-b95d-397ca5da4b13"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A13", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("872d7700-aa6f-435e-b5f9-821fb087962a"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A2", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("17b4fe26-7468-4702-92e5-785b861cf0fa"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A24", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - with conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3c5fc83b-10e1-4a15-83e6-794fce3e0b45"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A23", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - without conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("eab8b66d-68d0-4cb9-8e4d-bbd245648fb6"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B1", + InternalOnly = true, + IsActive = false, + Name = "Barring by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("2c496e3f-00d3-4f0d-81f3-21458fe707b3"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "G2", + InternalOnly = true, + IsActive = false, + Name = "Formerly barred by the Independent Safeguarding Authority", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("993daa42-96cb-4621-bd9e-d4b195076bbe"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B6", + InternalOnly = true, + IsActive = false, + Name = "Formerly on List 99", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a414283f-7d5b-4587-83bf-f6da8c05b8d5"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 1, + DqtSanctionCode = "T2", + InternalOnly = false, + IsActive = true, + Name = "Interim prohibition by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ed0cd700-3fb2-4db0-9403-ba57126090ed"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 2, + DqtSanctionCode = "T1", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - misconduct", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("8ef92c14-4b1f-4530-9189-779ad9f3cefd"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B3", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by an Independent Schools Tribunal or Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("50feafbc-5124-4189-b06c-6463c7ebb8a8"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 3, + DqtSanctionCode = "T3", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - deregistered by GTC Scotland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5aa21b8f-2069-43c9-8afd-05b34b02505f"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 4, + DqtSanctionCode = "T5", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to GTC Northern Ireland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a5bd4352-2cec-4417-87a1-4b6b79d033c2"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 5, + DqtSanctionCode = "T4", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to the Education Workforce Council, Wales", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("40794ea8-eda2-40a8-a26a-5f447aae6c99"), + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 1, + DqtSanctionCode = "G1", + InternalOnly = true, + IsActive = true, + Name = "A possible matching record was found. Please contact the DBS before employing this person", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("38db7946-2dbf-408e-bc48-1625829e7dfe"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2B", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Not Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("18e04dcb-fb86-4b05-8d5d-ff9c5da738dd"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2A", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("241eeb78-fac7-4c77-8059-c12e93dc2fae"), + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 1, + DqtSanctionCode = "T7", + InternalOnly = false, + IsActive = true, + Name = "Section 128 barring direction", + ProhibitionLevel = 4 + }, + new + { + AlertTypeId = new Guid("7924fe90-483c-49f8-84fc-674feddba848"), + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 1, + DqtSanctionCode = "T6", + InternalOnly = false, + IsActive = true, + Name = "Secretary of State decision - no prohibition", + ProhibitionLevel = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.Property("ApiKeyId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("api_key_id"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Expires") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("key"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("ApiKeyId") + .HasName("pk_api_keys"); + + b.HasIndex("ApplicationUserId") + .HasDatabaseName("ix_api_keys_application_user_id"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_api_keys_key"); + + b.ToTable("api_keys", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", b => + { + b.Property("CountryId") + .HasMaxLength(4) + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("CountryId") + .HasName("pk_countries"); + + b.ToTable("countries", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EntityChangesJournal", b => + { + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("EntityLogicalName") + .HasColumnType("text") + .HasColumnName("entity_logical_name"); + + b.Property("DataToken") + .HasColumnType("text") + .HasColumnName("data_token"); + + b.Property("LastUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_updated"); + + b.Property("LastUpdatedBy") + .HasColumnType("text") + .HasColumnName("last_updated_by"); + + b.Property("NextQueryPageNumber") + .HasColumnType("integer") + .HasColumnName("next_query_page_number"); + + b.Property("NextQueryPageSize") + .HasColumnType("integer") + .HasColumnName("next_query_page_size"); + + b.Property("NextQueryPagingCookie") + .HasColumnType("text") + .HasColumnName("next_query_paging_cookie"); + + b.HasKey("Key", "EntityLogicalName") + .HasName("pk_entity_changes_journals"); + + b.ToTable("entity_changes_journals", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.Property("EstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Address3") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("address3") + .UseCollation("case_insensitive"); + + b.Property("County") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("county") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentName") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("establishment_name") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(1) + .HasColumnName("establishment_source_id"); + + b.Property("EstablishmentStatusCode") + .HasColumnType("integer") + .HasColumnName("establishment_status_code"); + + b.Property("EstablishmentStatusName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_status_name"); + + b.Property("EstablishmentTypeCode") + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasColumnName("establishment_type_code"); + + b.Property("EstablishmentTypeGroupCode") + .HasColumnType("integer") + .HasColumnName("establishment_type_group_code"); + + b.Property("EstablishmentTypeGroupName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_type_group_name"); + + b.Property("EstablishmentTypeName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("establishment_type_name") + .UseCollation("case_insensitive"); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("LaName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("la_name") + .UseCollation("case_insensitive"); + + b.Property("Locality") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("locality") + .UseCollation("case_insensitive"); + + b.Property("Postcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("postcode") + .UseCollation("case_insensitive"); + + b.Property("Street") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("street") + .UseCollation("case_insensitive"); + + b.Property("Town") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("town") + .UseCollation("case_insensitive"); + + b.Property("Urn") + .HasMaxLength(6) + .HasColumnType("integer") + .HasColumnName("urn") + .IsFixedLength(); + + b.HasKey("EstablishmentId") + .HasName("pk_establishments"); + + b.HasIndex("EstablishmentSourceId") + .HasDatabaseName("ix_establishment_establishment_source_id"); + + b.HasIndex("Urn") + .HasDatabaseName("ix_establishment_urn"); + + b.HasIndex("LaCode", "EstablishmentNumber") + .HasDatabaseName("ix_establishment_la_code_establishment_number"); + + b.ToTable("establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", b => + { + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("establishment_source_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EstablishmentSourceId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("EstablishmentSourceId") + .HasName("pk_establishment_sources"); + + b.ToTable("establishment_sources", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Event", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("event_id"); + + b.Property("AlertId") + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("event_name"); + + b.Property("Inserted") + .HasColumnType("timestamp with time zone") + .HasColumnName("inserted"); + + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("key"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Published") + .HasColumnType("boolean") + .HasColumnName("published"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.HasKey("EventId") + .HasName("pk_events"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_events_key") + .HasFilter("key is not null"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_events_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.HasIndex("AlertId", "EventName") + .HasDatabaseName("ix_events_alert_id_event_name") + .HasFilter("alert_id is not null"); + + b.HasIndex("PersonId", "EventName") + .HasDatabaseName("ix_events_person_id_event_name") + .HasFilter("person_id is not null"); + + b.HasIndex("QualificationId", "EventName") + .HasDatabaseName("ix_events_qualification_id_event_name") + .HasFilter("qualification_id is not null"); + + b.ToTable("events", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Property("EytsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("EytsAwardedEmailsJobId") + .HasName("pk_eyts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_eyts_awarded_emails_jobs_executed_utc"); + + b.ToTable("eyts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.Property("EytsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("EytsAwardedEmailsJobId", "PersonId") + .HasName("pk_eyts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_eyts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("eyts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Property("InductionCompletedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InductionCompletedEmailsJobId") + .HasName("pk_induction_completed_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_induction_completed_emails_jobs_executed_utc"); + + b.ToTable("induction_completed_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.Property("InductionCompletedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InductionCompletedEmailsJobId", "PersonId") + .HasName("pk_induction_completed_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_induction_completed_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("induction_completed_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InternationalQtsAwardedEmailsJobId") + .HasName("pk_international_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_international_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("international_qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InternationalQtsAwardedEmailsJobId", "PersonId") + .HasName("pk_international_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_international_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("international_qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.JourneyState", b => + { + b.Property("InstanceId") + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("instance_id"); + + b.Property("Completed") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("State") + .IsRequired() + .HasColumnType("text") + .HasColumnName("state"); + + b.Property("Updated") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("user_id"); + + b.HasKey("InstanceId") + .HasName("pk_journey_states"); + + b.ToTable("journey_states", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", b => + { + b.Property("MandatoryQualificationProviderId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("mandatory_qualification_provider_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("MandatoryQualificationProviderId") + .HasName("pk_mandatory_qualification_providers"); + + b.ToTable("mandatory_qualification_providers", (string)null); + + b.HasData( + new + { + MandatoryQualificationProviderId = new Guid("e28ea41d-408d-4c89-90cc-8b9b04ac68f5"), + Name = "University of Birmingham" + }, + new + { + MandatoryQualificationProviderId = new Guid("89f9a1aa-3d68-4985-a4ce-403b6044c18c"), + Name = "University of Leeds" + }, + new + { + MandatoryQualificationProviderId = new Guid("aa5c300e-3b7c-456c-8183-3520b3d55dca"), + Name = "University of Manchester" + }, + new + { + MandatoryQualificationProviderId = new Guid("f417e73e-e2ad-40eb-85e3-55865be7f6be"), + Name = "Mary Hare School / University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("fbf22e04-b274-4c80-aba8-79fb6a7a32ce"), + Name = "University of Edinburgh" + }, + new + { + MandatoryQualificationProviderId = new Guid("26204149-349c-4ad6-9466-bb9b83723eae"), + Name = "Liverpool John Moores University" + }, + new + { + MandatoryQualificationProviderId = new Guid("0c30f666-647c-4ea8-8883-0fc6010b56be"), + Name = "University of Oxford/Oxford Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d0e6d54c-5e90-438a-945d-f97388c2b352"), + Name = "University of Cambridge" + }, + new + { + MandatoryQualificationProviderId = new Guid("aec32252-ef25-452e-a358-34a04e03369c"), + Name = "University of Newcastle-upon-Tyne" + }, + new + { + MandatoryQualificationProviderId = new Guid("d9ee7054-7fde-4cfd-9a5e-4b99511d1b3d"), + Name = "University of Plymouth" + }, + new + { + MandatoryQualificationProviderId = new Guid("707d58ca-1953-413b-9a46-41e9b0be885e"), + Name = "University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("3fc648a7-18e4-49e7-8a4b-1612616b72d5"), + Name = "University of London" + }, + new + { + MandatoryQualificationProviderId = new Guid("374dceb8-8224-45b8-b7dc-a6b0282b1065"), + Name = "Bristol Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d4fc958b-21de-47ec-9f03-36ae237a1b11"), + Name = "University College, Swansea" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.NameSynonyms", b => + { + b.Property("NameSynonymsId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("name_synonyms_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NameSynonymsId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("Synonyms") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("synonyms") + .UseCollation("case_insensitive"); + + b.HasKey("NameSynonymsId") + .HasName("pk_name_synonyms"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_name_synonyms_name"); + + b.ToTable("name_synonyms", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.Property("Subject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("subject"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email"); + + b.Property("FirstOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_one_login_sign_in"); + + b.Property("FirstSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_sign_in"); + + b.Property("LastCoreIdentityVc") + .HasColumnType("jsonb") + .HasColumnName("last_core_identity_vc"); + + b.Property("LastOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_one_login_sign_in"); + + b.Property("LastSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_sign_in"); + + b.Property("MatchRoute") + .HasColumnType("integer") + .HasColumnName("match_route"); + + b.Property("MatchedAttributes") + .HasColumnType("jsonb") + .HasColumnName("matched_attributes"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("VerificationRoute") + .HasColumnType("integer") + .HasColumnName("verification_route"); + + b.Property("VerifiedDatesOfBirth") + .HasColumnType("jsonb") + .HasColumnName("verified_dates_of_birth"); + + b.Property("VerifiedNames") + .HasColumnType("jsonb") + .HasColumnName("verified_names"); + + b.Property("VerifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_on"); + + b.HasKey("Subject") + .HasName("pk_one_login_users"); + + b.ToTable("one_login_users", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Property("PersonId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtContactId") + .HasColumnType("uuid") + .HasColumnName("dqt_contact_id"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_first_name") + .UseCollation("case_insensitive"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_last_name") + .UseCollation("case_insensitive"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtMiddleName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_middle_name") + .UseCollation("case_insensitive"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EmailAddress") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("email_address") + .UseCollation("case_insensitive"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("first_name") + .UseCollation("case_insensitive"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("last_name") + .UseCollation("case_insensitive"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("middle_name") + .UseCollation("case_insensitive"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Trn") + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("PersonId") + .HasName("pk_persons"); + + b.HasIndex("DqtContactId") + .IsUnique() + .HasDatabaseName("ix_persons_dqt_contact_id") + .HasFilter("dqt_contact_id is not null"); + + b.HasIndex("Trn") + .IsUnique() + .HasDatabaseName("ix_persons_trn") + .HasFilter("trn is not null"); + + b.ToTable("persons", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.PersonSearchAttribute", b => + { + b.Property("PersonSearchAttributeId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("person_search_attribute_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersonSearchAttributeId")); + + b.Property("AttributeKey") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_key") + .UseCollation("case_insensitive"); + + b.Property("AttributeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_type") + .UseCollation("case_insensitive"); + + b.Property("AttributeValue") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("attribute_value") + .UseCollation("case_insensitive"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("tags"); + + b.HasKey("PersonSearchAttributeId") + .HasName("pk_person_search_attributes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_person_search_attributes_person_id"); + + b.HasIndex("AttributeType", "AttributeValue") + .HasDatabaseName("ix_person_search_attributes_attribute_type_and_value"); + + b.ToTable("person_search_attributes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Property("QtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("QtsAwardedEmailsJobId") + .HasName("pk_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.Property("QtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("QtsAwardedEmailsJobId", "PersonId") + .HasName("pk_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Property("QualificationId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtQualificationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qualification_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("QualificationId") + .HasName("pk_qualifications"); + + b.HasIndex("DqtQualificationId") + .IsUnique() + .HasDatabaseName("ix_qualifications_dqt_qualification_id") + .HasFilter("dqt_qualification_id is not null"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_qualifications_person_id"); + + b.ToTable("qualifications", (string)null); + + b.HasDiscriminator("QualificationType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.Property("RouteId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("route_id"); + + b.Property("AgeRangeFrom") + .HasColumnType("integer") + .HasColumnName("age_range_from"); + + b.Property("AgeRangeTo") + .HasColumnType("integer") + .HasColumnName("age_range_to"); + + b.Property("CountryId") + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("ExternalReference") + .HasColumnType("text") + .HasColumnName("external_reference"); + + b.Property("InductionExemptionReason") + .HasColumnType("integer") + .HasColumnName("induction_exemption_reason"); + + b.Property("IttProviderId") + .HasColumnType("uuid") + .HasColumnName("itt_provider_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("ProgrammeEndDate") + .HasColumnType("date") + .HasColumnName("programme_end_date"); + + b.Property("ProgrammeStartDate") + .HasColumnType("date") + .HasColumnName("programme_start_date"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("RouteStatus") + .HasColumnType("integer") + .HasColumnName("route_status"); + + b.Property("RouteType") + .HasColumnType("integer") + .HasColumnName("route_type"); + + b.Property>("Subjects") + .IsRequired() + .HasColumnType("uuid[]") + .HasColumnName("subjects"); + + b.HasKey("RouteId") + .HasName("pk_routes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_routes_person_id"); + + b.ToTable("routes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.Property("SupportTaskReference") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("support_task_reference"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("OneLoginUserSubject") + .HasColumnType("character varying(255)") + .HasColumnName("one_login_user_subject"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("SupportTaskType") + .HasColumnType("integer") + .HasColumnName("support_task_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("_data") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.HasKey("SupportTaskReference") + .HasName("pk_support_tasks"); + + b.HasIndex("OneLoginUserSubject") + .HasDatabaseName("ix_support_tasks_one_login_user_subject"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_support_tasks_person_id"); + + b.ToTable("support_tasks", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", b => + { + b.Property("TpsCsvExtractId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Filename") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("filename"); + + b.HasKey("TpsCsvExtractId") + .HasName("pk_tps_csv_extracts"); + + b.ToTable("tps_csv_extracts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.Property("TpsCsvExtractItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasColumnType("date") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasColumnType("date") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasColumnType("date") + .HasColumnName("employment_start_date"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasColumnType("date") + .HasColumnName("extract_date"); + + b.Property("Gender") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("gender"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LocalAuthorityCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("local_authority_code") + .IsFixedLength(); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasColumnType("integer") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Result") + .HasColumnType("integer") + .HasColumnName("result"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("TpsCsvExtractLoadItemId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("WithdrawalIndicator") + .HasMaxLength(1) + .HasColumnType("character(1)") + .HasColumnName("withdrawal_indicator") + .IsFixedLength(); + + b.HasKey("TpsCsvExtractItemId") + .HasName("pk_tps_csv_extract_items"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_csv_extract_items_key"); + + b.HasIndex("TpsCsvExtractId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasIndex("TpsCsvExtractLoadItemId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_load_item_id"); + + b.HasIndex("Trn") + .HasDatabaseName("ix_tps_csv_extract_items_trn"); + + b.HasIndex("LocalAuthorityCode", "EstablishmentNumber") + .HasDatabaseName("ix_tps_csv_extract_items_la_code_establishment_number"); + + b.ToTable("tps_csv_extract_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.Property("TpsCsvExtractLoadItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_start_date"); + + b.Property("Errors") + .HasColumnType("integer") + .HasColumnName("errors"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_number"); + + b.Property("EstablishmentPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("extract_date"); + + b.Property("FullOrPartTimeIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("full_or_part_time_indicator"); + + b.Property("Gender") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("gender"); + + b.Property("LocalAuthorityCode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("local_authority_code"); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("national_insurance_number"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("Trn") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("trn"); + + b.Property("WithdrawalIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("withdrawal_indicator"); + + b.HasKey("TpsCsvExtractLoadItemId") + .HasName("pk_tps_csv_extract_load_items"); + + b.ToTable("tps_csv_extract_load_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.Property("TpsEmploymentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_employment_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("EstablishmentId") + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LastExtractDate") + .HasColumnType("date") + .HasColumnName("last_extract_date"); + + b.Property("LastKnownTpsEmployedDate") + .HasColumnType("date") + .HasColumnName("last_known_tps_employed_date"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("PersonPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("person_postcode"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("WithdrawalConfirmed") + .HasColumnType("boolean") + .HasColumnName("withdrawal_confirmed"); + + b.HasKey("TpsEmploymentId") + .HasName("pk_tps_employments"); + + b.HasIndex("EstablishmentId") + .HasDatabaseName("ix_tps_employments_establishment_id"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_employments_key"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_tps_employments_person_id"); + + b.ToTable("tps_employments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishment", b => + { + b.Property("TpsEstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_establishment_id"); + + b.Property("EmployersName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employers_name"); + + b.Property("EstablishmentCode") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_code") + .IsFixedLength(); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("SchoolClosedDate") + .HasColumnType("date") + .HasColumnName("school_closed_date"); + + b.Property("SchoolGiasName") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("school_gias_name"); + + b.HasKey("TpsEstablishmentId") + .HasName("pk_tps_establishments"); + + b.HasIndex("LaCode", "EstablishmentCode") + .HasDatabaseName("ix_tps_establishments_la_code_establishment_number"); + + b.ToTable("tps_establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishmentType", b => + { + b.Property("TpsEstablishmentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("tps_establishment_type_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TpsEstablishmentTypeId")); + + b.Property("Description") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("description"); + + b.Property("EstablishmentRangeFrom") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_from") + .IsFixedLength(); + + b.Property("EstablishmentRangeTo") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_to") + .IsFixedLength(); + + b.Property("ShortDescription") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("short_description"); + + b.HasKey("TpsEstablishmentTypeId") + .HasName("pk_tps_establishment_types"); + + b.ToTable("tps_establishment_types", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequest", b => + { + b.Property("TrnRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("trn_request_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrnRequestId")); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("IdentityUserId") + .HasColumnType("uuid") + .HasColumnName("identity_user_id"); + + b.Property("LinkedToIdentity") + .HasColumnType("boolean") + .HasColumnName("linked_to_identity"); + + b.Property("RequestId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("TeacherId") + .HasColumnType("uuid") + .HasColumnName("teacher_id"); + + b.Property("TrnToken") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("trn_token"); + + b.HasKey("TrnRequestId") + .HasName("pk_trn_requests"); + + b.HasIndex("ClientId", "RequestId") + .IsUnique() + .HasDatabaseName("ix_trn_requests_client_id_request_id"); + + b.ToTable("trn_requests", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequestMetadata", b => + { + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("RequestId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("VerifiedOneLoginUserSubject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("verified_one_login_user_subject"); + + b.HasKey("ApplicationUserId", "RequestId") + .HasName("pk_trn_request_metadata"); + + b.ToTable("trn_request_metadata", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Active") + .HasColumnType("boolean") + .HasColumnName("active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("UserType") + .HasColumnType("integer") + .HasColumnName("user_type"); + + b.HasKey("UserId") + .HasName("pk_users"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator("UserType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.Property("WebhookEndpointId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("address"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property>("CloudEventTypes") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("cloud_event_types"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.HasKey("WebhookEndpointId") + .HasName("pk_webhook_endpoints"); + + b.ToTable("webhook_endpoints", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.Property("WebhookMessageId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_message_id"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("CloudEventId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("cloud_event_id"); + + b.Property("CloudEventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("cloud_event_type"); + + b.Property("Data") + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone") + .HasColumnName("delivered"); + + b.Property>("DeliveryAttempts") + .IsRequired() + .HasColumnType("timestamp with time zone[]") + .HasColumnName("delivery_attempts"); + + b.Property>("DeliveryErrors") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("delivery_errors"); + + b.Property("NextDeliveryAttempt") + .HasColumnType("timestamp with time zone") + .HasColumnName("next_delivery_attempt"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("WebhookEndpointId") + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.HasKey("WebhookMessageId") + .HasName("pk_webhook_messages"); + + b.ToTable("webhook_messages", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EarlyYearsTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("DqtMqEstablishmentId") + .HasColumnType("uuid") + .HasColumnName("dqt_mq_establishment_id"); + + b.Property("DqtSpecialismId") + .HasColumnType("uuid") + .HasColumnName("dqt_specialism_id"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("mq_provider_id"); + + b.Property("Specialism") + .HasColumnType("integer") + .HasColumnName("mq_specialism"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("mq_status"); + + b.HasDiscriminator().HasValue(0); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QualifiedTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("ApiRoles") + .HasColumnType("varchar[]") + .HasColumnName("api_roles"); + + b.Property("ClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("client_secret"); + + b.Property("IsOidcClient") + .HasColumnType("boolean") + .HasColumnName("is_oidc_client"); + + b.Property("OneLoginAuthenticationSchemeName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_authentication_scheme_name"); + + b.Property("OneLoginClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_client_id"); + + b.Property("OneLoginPostLogoutRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_post_logout_redirect_uri_path"); + + b.Property("OneLoginPrivateKeyPem") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("one_login_private_key_pem"); + + b.Property("OneLoginRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_redirect_uri_path"); + + b.Property>("PostLogoutRedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("post_logout_redirect_uris"); + + b.Property>("RedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("redirect_uris"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_users_client_id") + .HasFilter("client_id is not null"); + + b.HasIndex("OneLoginAuthenticationSchemeName") + .IsUnique() + .HasDatabaseName("ix_users_one_login_authentication_scheme_name") + .HasFilter("one_login_authentication_scheme_name is not null"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SystemUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator().HasValue(3); + + b.HasData( + new + { + UserId = new Guid("a81394d1-a498-46d8-af3e-e077596ab303"), + Active = true, + Name = "System", + UserType = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.User", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("AzureAdUserId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("azure_ad_user_id"); + + b.Property("DqtUserId") + .HasColumnType("uuid") + .HasColumnName("dqt_user_id"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email") + .UseCollation("case_insensitive"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("varchar[]") + .HasColumnName("roles"); + + b.HasIndex("AzureAdUserId") + .IsUnique() + .HasDatabaseName("ix_users_azure_ad_user_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_authorizations_oidc_applications_application_id"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_tokens_oidc_applications_application_id"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId") + .HasConstraintName("fk_oidc_tokens_oidc_authorizations_authorization_id"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", "AlertType") + .WithMany() + .HasForeignKey("AlertTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_alert_type"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Alerts") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_person"); + + b.Navigation("AlertType"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", "AlertCategory") + .WithMany("AlertTypes") + .HasForeignKey("AlertCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alert_types_alert_category"); + + b.Navigation("AlertCategory"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", "ApplicationUser") + .WithMany("ApiKeys") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_key_application_user"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", null) + .WithMany() + .HasForeignKey("EstablishmentSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_establishments_establishment_source_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", "EytsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("EytsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_eyts_awarded_emails_job_items_eyts_awarded_emails_jobs_eyts"); + + b.Navigation("EytsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", "InductionCompletedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InductionCompletedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_induction_completed_emails_job_items_induction_completed_em"); + + b.Navigation("InductionCompletedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", "InternationalQtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InternationalQtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_international_qts_awarded_emails_job_items_international_qt"); + + b.Navigation("InternationalQtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithOne() + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", "PersonId") + .HasConstraintName("fk_one_login_users_persons_person_id"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", "QtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("QtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qts_awarded_emails_job_items_qts_awarded_emails_jobs_qts_aw"); + + b.Navigation("QtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Qualifications") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qualifications_person"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", null) + .WithMany() + .HasForeignKey("CountryId") + .HasConstraintName("fk_routes_countries_country_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany("Routes") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_routes_persons_person_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", "Qualification") + .WithOne("Route") + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", "QualificationId") + .HasConstraintName("fk_routes_qualifications_qualification_id"); + + b.Navigation("Qualification"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", null) + .WithMany() + .HasForeignKey("OneLoginUserSubject") + .HasConstraintName("fk_support_tasks_one_login_user"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .HasConstraintName("fk_support_tasks_person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", null) + .WithMany() + .HasForeignKey("TpsCsvExtractLoadItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_load_item_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_load_items_tps_csv_extract_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", null) + .WithMany() + .HasForeignKey("EstablishmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_establishment_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_person_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_endpoints_application_users_application_user_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", "WebhookEndpoint") + .WithMany() + .HasForeignKey("WebhookEndpointId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_messages_webhook_endpoints_webhook_endpoint_id"); + + b.Navigation("WebhookEndpoint"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .HasConstraintName("fk_qualifications_mandatory_qualification_provider"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Navigation("AlertTypes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Navigation("Alerts"); + + b.Navigation("Qualifications"); + + b.Navigation("Routes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Navigation("Route"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.Navigation("ApiKeys"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.cs new file mode 100644 index 000000000..4d6714bbc --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107123546_NullableOneLoginUserFields.cs @@ -0,0 +1,95 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + /// + public partial class NullableOneLoginUserFields : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "match_route", + table: "one_login_users", + type: "integer", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AlterColumn( + name: "last_one_login_sign_in", + table: "one_login_users", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "first_one_login_sign_in", + table: "one_login_users", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "email", + table: "one_login_users", + type: "character varying(200)", + maxLength: 200, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(200)", + oldMaxLength: 200); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "match_route", + table: "one_login_users", + type: "integer", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "integer", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "last_one_login_sign_in", + table: "one_login_users", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "first_one_login_sign_in", + table: "one_login_users", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "email", + table: "one_login_users", + type: "character varying(200)", + maxLength: 200, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(200)", + oldMaxLength: 200, + oldNullable: true); + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.Designer.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.Designer.cs new file mode 100644 index 000000000..01803d4fa --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.Designer.cs @@ -0,0 +1,3314 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TeachingRecordSystem.Core.DataStore.Postgres; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + [DbContext(typeof(TrsDbContext))] + [Migration("20241107134330_OneLoginUserVerifiedByApplicationUserId")] + partial class OneLoginUserVerifiedByApplicationUserId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("application_type"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("text") + .HasColumnName("client_secret"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_type"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("consent_type"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("JsonWebKeySet") + .HasColumnType("text") + .HasColumnName("json_web_key_set"); + + b.Property("Permissions") + .HasColumnType("text") + .HasColumnName("permissions"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text") + .HasColumnName("post_logout_redirect_uris"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedirectUris") + .HasColumnType("text") + .HasColumnName("redirect_uris"); + + b.Property("Requirements") + .HasColumnType("text") + .HasColumnName("requirements"); + + b.Property("Settings") + .HasColumnType("text") + .HasColumnName("settings"); + + b.HasKey("Id") + .HasName("pk_oidc_applications"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_oidc_applications_client_id"); + + b.ToTable("oidc_applications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Scopes") + .HasColumnType("text") + .HasColumnName("scopes"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_authorizations"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_authorizations_application_id_status_subject_type"); + + b.ToTable("oidc_authorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Descriptions") + .HasColumnType("text") + .HasColumnName("descriptions"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Resources") + .HasColumnType("text") + .HasColumnName("resources"); + + b.HasKey("Id") + .HasName("pk_oidc_scopes"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_oidc_scopes_name"); + + b.ToTable("oidc_scopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("uuid") + .HasColumnName("application_id"); + + b.Property("AuthorizationId") + .HasColumnType("uuid") + .HasColumnName("authorization_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.Property("Payload") + .HasColumnType("text") + .HasColumnName("payload"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("redemption_date"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("reference_id"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_oidc_tokens"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasDatabaseName("ix_oidc_tokens_reference_id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_oidc_tokens_application_id_status_subject_type"); + + b.ToTable("oidc_tokens", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.Property("AlertId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("AlertTypeId") + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("Details") + .HasColumnType("text") + .HasColumnName("details"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtSanctionId") + .HasColumnType("uuid") + .HasColumnName("dqt_sanction_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ExternalLink") + .HasColumnType("text") + .HasColumnName("external_link"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("AlertId") + .HasName("pk_alerts"); + + b.HasIndex("AlertTypeId") + .HasDatabaseName("ix_alerts_alert_type_id"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_alerts_person_id"); + + b.ToTable("alerts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Property("AlertCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("AlertCategoryId") + .HasName("pk_alert_categories"); + + b.HasIndex("DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_categories_display_order"); + + b.ToTable("alert_categories", (string)null); + + b.HasData( + new + { + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + Name = "EEA Decision" + }, + new + { + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 2, + Name = "Failed induction" + }, + new + { + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 3, + Name = "Flag" + }, + new + { + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DisplayOrder = 4, + Name = "GTC Decision" + }, + new + { + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DisplayOrder = 5, + Name = "GTC Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DisplayOrder = 6, + Name = "GTC Restriction" + }, + new + { + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 7, + Name = "Prohibition from teaching" + }, + new + { + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 8, + Name = "Restricted/DBS" + }, + new + { + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DisplayOrder = 9, + Name = "Restriction" + }, + new + { + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 10, + Name = "Section 128 (SoS)" + }, + new + { + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 12, + Name = "TRA Decision (SoS)" + }, + new + { + AlertCategoryId = new Guid("e4057fc2-a010-42a9-8cb2-7dcc5c9b5fa7"), + DisplayOrder = 11, + Name = "SoS Restriction" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.Property("AlertTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("alert_type_id"); + + b.Property("AlertCategoryId") + .HasColumnType("uuid") + .HasColumnName("alert_category_id"); + + b.Property("DisplayOrder") + .HasColumnType("integer") + .HasColumnName("display_order"); + + b.Property("DqtSanctionCode") + .HasMaxLength(5) + .HasColumnType("character varying(5)") + .HasColumnName("dqt_sanction_code") + .UseCollation("case_insensitive"); + + b.Property("InternalOnly") + .HasColumnType("boolean") + .HasColumnName("internal_only"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("ProhibitionLevel") + .HasColumnType("integer") + .HasColumnName("prohibition_level"); + + b.HasKey("AlertTypeId") + .HasName("pk_alert_types"); + + b.HasIndex("AlertCategoryId") + .HasDatabaseName("ix_alert_types_alert_category_id"); + + b.HasIndex("AlertCategoryId", "DisplayOrder") + .IsUnique() + .HasDatabaseName("ix_alert_types_display_order") + .HasFilter("display_order is not null and is_active = true"); + + b.ToTable("alert_types", (string)null); + + b.HasData( + new + { + AlertTypeId = new Guid("2ca98658-1d5b-49d5-b05f-cc08c8b8502c"), + AlertCategoryId = new Guid("ee78d44d-abf8-44a9-b22b-87a821f8d3c9"), + DisplayOrder = 1, + DqtSanctionCode = "T8", + InternalOnly = true, + IsActive = true, + Name = "Teacher sanctioned in other EEA member state", + ProhibitionLevel = 3 + }, + new + { + AlertTypeId = new Guid("9fafaa80-f9f8-44a0-b7b3-cffedcbe0298"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DisplayOrder = 1, + DqtSanctionCode = "C2", + InternalOnly = false, + IsActive = true, + Name = "Failed induction", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("651e1f56-3135-4961-bd7e-3f7b2c75cb04"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C1", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by the Secretary of State - failed probation", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5ea8bb68-4774-4ad8-b635-213a0cdda4c3"), + AlertCategoryId = new Guid("0ae0707b-1503-477d-bc0f-1505ed95dbdf"), + DqtSanctionCode = "C3", + InternalOnly = false, + IsActive = false, + Name = "Restricted by the Secretary of State - failed probation - permitted to carry out specified work for a period equal in length to a statutory induction period only", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ae3e385d-03f8-4f12-9ce2-006afe827d23"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 1, + DqtSanctionCode = "T9", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL INFORMATION ONLY - see alert details", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("12435c00-88cb-406b-b2b8-7400c1ced7b8"), + AlertCategoryId = new Guid("768c9eb4-355b-4491-bb20-67eb59a97579"), + DisplayOrder = 2, + DqtSanctionCode = "T10", + InternalOnly = true, + IsActive = true, + Name = "FOR INTERNAL USER ONLY – known duplicate record", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("a6fc9f2e-8923-4163-978e-93bd901d146f"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A18", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - conviction of a relevant offence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1ebd1620-293d-4169-ba78-0b41a6413ad9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A7", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - serious professional incompetence", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3499860a-a0fb-43e3-878e-c226d14150b0"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A3", + InternalOnly = false, + IsActive = false, + Name = "Conditional Registration Order - unacceptable professional conduct", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("552ee226-a3a9-4dc3-8d04-0b7e4f641b51"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A15", + InternalOnly = true, + IsActive = false, + Name = "For internal information only - historic GTC finding of unsuitable for registration", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("33e00e46-6513-4136-adfd-1352cf34d8ec"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A22", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - breach of condition(s)", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0740f9eb-ece3-4394-a230-453da224d337"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A16", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - conviction for a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("b6c8d8f1-723e-49a5-9551-25805e3e29b9"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A12", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("78f88de2-9ec1-41b8-948a-33bdff223206"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A11", + InternalOnly = true, + IsActive = false, + Name = "No Sanction - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("fcff87d6-88f5-4fc5-ac81-5350b4fdd9e1"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A17", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - conviction of a relevant offence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("3f7de5fd-05a8-404f-a97c-428f54e81322"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A8", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - serious professional incompetence", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("0ae8d4b6-ec9b-47ca-9338-6dae9192afe5"), + AlertCategoryId = new Guid("06d98708-b52d-496a-aaa7-c1d7d2ca8b24"), + DqtSanctionCode = "A4", + InternalOnly = true, + IsActive = false, + Name = "Reprimand - unacceptable professional conduct", + ProhibitionLevel = 0 + }, + new + { + AlertTypeId = new Guid("72e48b6a-e781-4bf3-910b-91f2d28f2eaa"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("950d3eed-bef5-448a-b0f0-bf9c54f2103b"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A21A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - conviction of a relevant offence - ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("cac68337-3f95-4475-97cf-1381e6b74700"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("c02bdc3a-7a19-4034-aa23-3a23c54e1d34"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A5A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - serious professional incompetence - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("e3658a61-bee2-4df1-9a26-e010681ee310"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1B", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Eligible to reapply after specified time", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("fa6bd220-61b0-41fc-9066-421b3b9d7885"), + AlertCategoryId = new Guid("70b7d473-2ec8-4643-bfd4-d4ab9a9a0988"), + DqtSanctionCode = "A1A", + InternalOnly = false, + IsActive = false, + Name = "Prohibition Order - unacceptable professional conduct - Ineligible to reapply", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("d372fcfa-1c4a-4fed-84c8-4c7885575681"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A20", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("af65c236-47a6-427b-8e4b-930de6d256f0"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A19", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - conviction of a relevant offence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("50508749-7a6b-4175-8538-9a1e55692efd"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A14", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("a6f51ccc-a19c-4dc2-ba80-ffb7a95ff2ee"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A6", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - serious professional incompetence - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("1a2b06ae-7e9f-4761-b95d-397ca5da4b13"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A13", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - with conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("872d7700-aa6f-435e-b5f9-821fb087962a"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A2", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - unacceptable professional conduct - without conditions", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("17b4fe26-7468-4702-92e5-785b861cf0fa"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A24", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - with conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("3c5fc83b-10e1-4a15-83e6-794fce3e0b45"), + AlertCategoryId = new Guid("790410c1-b884-4cdd-8db9-64a042ab54ae"), + DqtSanctionCode = "A23", + InternalOnly = false, + IsActive = false, + Name = "Suspension order - without conditions - (arising from breach of previous condition(s))", + ProhibitionLevel = 2 + }, + new + { + AlertTypeId = new Guid("eab8b66d-68d0-4cb9-8e4d-bbd245648fb6"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B1", + InternalOnly = true, + IsActive = false, + Name = "Barring by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("2c496e3f-00d3-4f0d-81f3-21458fe707b3"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "G2", + InternalOnly = true, + IsActive = false, + Name = "Formerly barred by the Independent Safeguarding Authority", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("993daa42-96cb-4621-bd9e-d4b195076bbe"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B6", + InternalOnly = true, + IsActive = false, + Name = "Formerly on List 99", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a414283f-7d5b-4587-83bf-f6da8c05b8d5"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 1, + DqtSanctionCode = "T2", + InternalOnly = false, + IsActive = true, + Name = "Interim prohibition by the Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("ed0cd700-3fb2-4db0-9403-ba57126090ed"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 2, + DqtSanctionCode = "T1", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - misconduct", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("8ef92c14-4b1f-4530-9189-779ad9f3cefd"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DqtSanctionCode = "B3", + InternalOnly = false, + IsActive = false, + Name = "Prohibited by an Independent Schools Tribunal or Secretary of State", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("50feafbc-5124-4189-b06c-6463c7ebb8a8"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 3, + DqtSanctionCode = "T3", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - deregistered by GTC Scotland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("5aa21b8f-2069-43c9-8afd-05b34b02505f"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 4, + DqtSanctionCode = "T5", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to GTC Northern Ireland", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("a5bd4352-2cec-4417-87a1-4b6b79d033c2"), + AlertCategoryId = new Guid("b2b19019-b165-47a3-8745-3297ff152581"), + DisplayOrder = 5, + DqtSanctionCode = "T4", + InternalOnly = false, + IsActive = true, + Name = "Prohibition by the Secretary of State - refer to the Education Workforce Council, Wales", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("40794ea8-eda2-40a8-a26a-5f447aae6c99"), + AlertCategoryId = new Guid("e8a9ee91-bf7f-4f70-bc66-a644d522384e"), + DisplayOrder = 1, + DqtSanctionCode = "G1", + InternalOnly = true, + IsActive = true, + Name = "A possible matching record was found. Please contact the DBS before employing this person", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("38db7946-2dbf-408e-bc48-1625829e7dfe"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2B", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Not Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("18e04dcb-fb86-4b05-8d5d-ff9c5da738dd"), + AlertCategoryId = new Guid("cbf7633f-3904-407d-8371-42a473fa641f"), + DqtSanctionCode = "B2A", + InternalOnly = true, + IsActive = false, + Name = "Restricted by the Secretary of State - Permitted to work as teacher", + ProhibitionLevel = 1 + }, + new + { + AlertTypeId = new Guid("241eeb78-fac7-4c77-8059-c12e93dc2fae"), + AlertCategoryId = new Guid("38df5a00-94ab-486f-8905-d5b2eac04000"), + DisplayOrder = 1, + DqtSanctionCode = "T7", + InternalOnly = false, + IsActive = true, + Name = "Section 128 barring direction", + ProhibitionLevel = 4 + }, + new + { + AlertTypeId = new Guid("7924fe90-483c-49f8-84fc-674feddba848"), + AlertCategoryId = new Guid("227b75e5-bb98-496c-8860-1baea37aa5c6"), + DisplayOrder = 1, + DqtSanctionCode = "T6", + InternalOnly = false, + IsActive = true, + Name = "Secretary of State decision - no prohibition", + ProhibitionLevel = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.Property("ApiKeyId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("api_key_id"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Expires") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("key"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("ApiKeyId") + .HasName("pk_api_keys"); + + b.HasIndex("ApplicationUserId") + .HasDatabaseName("ix_api_keys_application_user_id"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_api_keys_key"); + + b.ToTable("api_keys", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", b => + { + b.Property("CountryId") + .HasMaxLength(4) + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("CountryId") + .HasName("pk_countries"); + + b.ToTable("countries", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EntityChangesJournal", b => + { + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("EntityLogicalName") + .HasColumnType("text") + .HasColumnName("entity_logical_name"); + + b.Property("DataToken") + .HasColumnType("text") + .HasColumnName("data_token"); + + b.Property("LastUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_updated"); + + b.Property("LastUpdatedBy") + .HasColumnType("text") + .HasColumnName("last_updated_by"); + + b.Property("NextQueryPageNumber") + .HasColumnType("integer") + .HasColumnName("next_query_page_number"); + + b.Property("NextQueryPageSize") + .HasColumnType("integer") + .HasColumnName("next_query_page_size"); + + b.Property("NextQueryPagingCookie") + .HasColumnType("text") + .HasColumnName("next_query_paging_cookie"); + + b.HasKey("Key", "EntityLogicalName") + .HasName("pk_entity_changes_journals"); + + b.ToTable("entity_changes_journals", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.Property("EstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Address3") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("address3") + .UseCollation("case_insensitive"); + + b.Property("County") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("county") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentName") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("establishment_name") + .UseCollation("case_insensitive"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(1) + .HasColumnName("establishment_source_id"); + + b.Property("EstablishmentStatusCode") + .HasColumnType("integer") + .HasColumnName("establishment_status_code"); + + b.Property("EstablishmentStatusName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_status_name"); + + b.Property("EstablishmentTypeCode") + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasColumnName("establishment_type_code"); + + b.Property("EstablishmentTypeGroupCode") + .HasColumnType("integer") + .HasColumnName("establishment_type_group_code"); + + b.Property("EstablishmentTypeGroupName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("establishment_type_group_name"); + + b.Property("EstablishmentTypeName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("establishment_type_name") + .UseCollation("case_insensitive"); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("LaName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("la_name") + .UseCollation("case_insensitive"); + + b.Property("Locality") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("locality") + .UseCollation("case_insensitive"); + + b.Property("Postcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("postcode") + .UseCollation("case_insensitive"); + + b.Property("Street") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("street") + .UseCollation("case_insensitive"); + + b.Property("Town") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("town") + .UseCollation("case_insensitive"); + + b.Property("Urn") + .HasMaxLength(6) + .HasColumnType("integer") + .HasColumnName("urn") + .IsFixedLength(); + + b.HasKey("EstablishmentId") + .HasName("pk_establishments"); + + b.HasIndex("EstablishmentSourceId") + .HasDatabaseName("ix_establishment_establishment_source_id"); + + b.HasIndex("Urn") + .HasDatabaseName("ix_establishment_urn"); + + b.HasIndex("LaCode", "EstablishmentNumber") + .HasDatabaseName("ix_establishment_la_code_establishment_number"); + + b.ToTable("establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", b => + { + b.Property("EstablishmentSourceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("establishment_source_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EstablishmentSourceId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.HasKey("EstablishmentSourceId") + .HasName("pk_establishment_sources"); + + b.ToTable("establishment_sources", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Event", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("event_id"); + + b.Property("AlertId") + .HasColumnType("uuid") + .HasColumnName("alert_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("event_name"); + + b.Property("Inserted") + .HasColumnType("timestamp with time zone") + .HasColumnName("inserted"); + + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("key"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Published") + .HasColumnType("boolean") + .HasColumnName("published"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.HasKey("EventId") + .HasName("pk_events"); + + b.HasIndex("Key") + .IsUnique() + .HasDatabaseName("ix_events_key") + .HasFilter("key is not null"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_events_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.HasIndex("AlertId", "EventName") + .HasDatabaseName("ix_events_alert_id_event_name") + .HasFilter("alert_id is not null"); + + b.HasIndex("PersonId", "EventName") + .HasDatabaseName("ix_events_person_id_event_name") + .HasFilter("person_id is not null"); + + b.HasIndex("QualificationId", "EventName") + .HasDatabaseName("ix_events_qualification_id_event_name") + .HasFilter("qualification_id is not null"); + + b.ToTable("events", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Property("EytsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("EytsAwardedEmailsJobId") + .HasName("pk_eyts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_eyts_awarded_emails_jobs_executed_utc"); + + b.ToTable("eyts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.Property("EytsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("eyts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("EytsAwardedEmailsJobId", "PersonId") + .HasName("pk_eyts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_eyts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("eyts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Property("InductionCompletedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InductionCompletedEmailsJobId") + .HasName("pk_induction_completed_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_induction_completed_emails_jobs_executed_utc"); + + b.ToTable("induction_completed_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.Property("InductionCompletedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("induction_completed_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InductionCompletedEmailsJobId", "PersonId") + .HasName("pk_induction_completed_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_induction_completed_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("induction_completed_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("InternationalQtsAwardedEmailsJobId") + .HasName("pk_international_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_international_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("international_qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.Property("InternationalQtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("international_qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("InternationalQtsAwardedEmailsJobId", "PersonId") + .HasName("pk_international_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_international_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("international_qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.JourneyState", b => + { + b.Property("InstanceId") + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("instance_id"); + + b.Property("Completed") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("State") + .IsRequired() + .HasColumnType("text") + .HasColumnName("state"); + + b.Property("Updated") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("user_id"); + + b.HasKey("InstanceId") + .HasName("pk_journey_states"); + + b.ToTable("journey_states", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", b => + { + b.Property("MandatoryQualificationProviderId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("mandatory_qualification_provider_id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.HasKey("MandatoryQualificationProviderId") + .HasName("pk_mandatory_qualification_providers"); + + b.ToTable("mandatory_qualification_providers", (string)null); + + b.HasData( + new + { + MandatoryQualificationProviderId = new Guid("e28ea41d-408d-4c89-90cc-8b9b04ac68f5"), + Name = "University of Birmingham" + }, + new + { + MandatoryQualificationProviderId = new Guid("89f9a1aa-3d68-4985-a4ce-403b6044c18c"), + Name = "University of Leeds" + }, + new + { + MandatoryQualificationProviderId = new Guid("aa5c300e-3b7c-456c-8183-3520b3d55dca"), + Name = "University of Manchester" + }, + new + { + MandatoryQualificationProviderId = new Guid("f417e73e-e2ad-40eb-85e3-55865be7f6be"), + Name = "Mary Hare School / University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("fbf22e04-b274-4c80-aba8-79fb6a7a32ce"), + Name = "University of Edinburgh" + }, + new + { + MandatoryQualificationProviderId = new Guid("26204149-349c-4ad6-9466-bb9b83723eae"), + Name = "Liverpool John Moores University" + }, + new + { + MandatoryQualificationProviderId = new Guid("0c30f666-647c-4ea8-8883-0fc6010b56be"), + Name = "University of Oxford/Oxford Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d0e6d54c-5e90-438a-945d-f97388c2b352"), + Name = "University of Cambridge" + }, + new + { + MandatoryQualificationProviderId = new Guid("aec32252-ef25-452e-a358-34a04e03369c"), + Name = "University of Newcastle-upon-Tyne" + }, + new + { + MandatoryQualificationProviderId = new Guid("d9ee7054-7fde-4cfd-9a5e-4b99511d1b3d"), + Name = "University of Plymouth" + }, + new + { + MandatoryQualificationProviderId = new Guid("707d58ca-1953-413b-9a46-41e9b0be885e"), + Name = "University of Hertfordshire" + }, + new + { + MandatoryQualificationProviderId = new Guid("3fc648a7-18e4-49e7-8a4b-1612616b72d5"), + Name = "University of London" + }, + new + { + MandatoryQualificationProviderId = new Guid("374dceb8-8224-45b8-b7dc-a6b0282b1065"), + Name = "Bristol Polytechnic" + }, + new + { + MandatoryQualificationProviderId = new Guid("d4fc958b-21de-47ec-9f03-36ae237a1b11"), + Name = "University College, Swansea" + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.NameSynonyms", b => + { + b.Property("NameSynonymsId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("name_synonyms_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NameSynonymsId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name") + .UseCollation("case_insensitive"); + + b.Property("Synonyms") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("synonyms") + .UseCollation("case_insensitive"); + + b.HasKey("NameSynonymsId") + .HasName("pk_name_synonyms"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_name_synonyms_name"); + + b.ToTable("name_synonyms", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.Property("Subject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("subject"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email"); + + b.Property("FirstOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_one_login_sign_in"); + + b.Property("FirstSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_sign_in"); + + b.Property("LastCoreIdentityVc") + .HasColumnType("jsonb") + .HasColumnName("last_core_identity_vc"); + + b.Property("LastOneLoginSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_one_login_sign_in"); + + b.Property("LastSignIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_sign_in"); + + b.Property("MatchRoute") + .HasColumnType("integer") + .HasColumnName("match_route"); + + b.Property("MatchedAttributes") + .HasColumnType("jsonb") + .HasColumnName("matched_attributes"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("VerificationRoute") + .HasColumnType("integer") + .HasColumnName("verification_route"); + + b.Property("VerifiedByApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("verified_by_application_user_id"); + + b.Property("VerifiedDatesOfBirth") + .HasColumnType("jsonb") + .HasColumnName("verified_dates_of_birth"); + + b.Property("VerifiedNames") + .HasColumnType("jsonb") + .HasColumnName("verified_names"); + + b.Property("VerifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_on"); + + b.HasKey("Subject") + .HasName("pk_one_login_users"); + + b.ToTable("one_login_users", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Property("PersonId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtContactId") + .HasColumnType("uuid") + .HasColumnName("dqt_contact_id"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_first_name") + .UseCollation("case_insensitive"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_last_name") + .UseCollation("case_insensitive"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtMiddleName") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("dqt_middle_name") + .UseCollation("case_insensitive"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("EmailAddress") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("email_address") + .UseCollation("case_insensitive"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("first_name") + .UseCollation("case_insensitive"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("last_name") + .UseCollation("case_insensitive"); + + b.Property("MiddleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("middle_name") + .UseCollation("case_insensitive"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Trn") + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("PersonId") + .HasName("pk_persons"); + + b.HasIndex("DqtContactId") + .IsUnique() + .HasDatabaseName("ix_persons_dqt_contact_id") + .HasFilter("dqt_contact_id is not null"); + + b.HasIndex("Trn") + .IsUnique() + .HasDatabaseName("ix_persons_trn") + .HasFilter("trn is not null"); + + b.ToTable("persons", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.PersonSearchAttribute", b => + { + b.Property("PersonSearchAttributeId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("person_search_attribute_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersonSearchAttributeId")); + + b.Property("AttributeKey") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_key") + .UseCollation("case_insensitive"); + + b.Property("AttributeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("attribute_type") + .UseCollation("case_insensitive"); + + b.Property("AttributeValue") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("attribute_value") + .UseCollation("case_insensitive"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("tags"); + + b.HasKey("PersonSearchAttributeId") + .HasName("pk_person_search_attributes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_person_search_attributes_person_id"); + + b.HasIndex("AttributeType", "AttributeValue") + .HasDatabaseName("ix_person_search_attributes_attribute_type_and_value"); + + b.ToTable("person_search_attributes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Property("QtsAwardedEmailsJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("AwardedToUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("awarded_to_utc"); + + b.Property("ExecutedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("executed_utc"); + + b.HasKey("QtsAwardedEmailsJobId") + .HasName("pk_qts_awarded_emails_jobs"); + + b.HasIndex("ExecutedUtc") + .HasDatabaseName("ix_qts_awarded_emails_jobs_executed_utc"); + + b.ToTable("qts_awarded_emails_jobs", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.Property("QtsAwardedEmailsJobId") + .HasColumnType("uuid") + .HasColumnName("qts_awarded_emails_job_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address"); + + b.Property("EmailSent") + .HasColumnType("boolean") + .HasColumnName("email_sent"); + + b.Property("Personalization") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("personalization"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.HasKey("QtsAwardedEmailsJobId", "PersonId") + .HasName("pk_qts_awarded_emails_job_items"); + + b.HasIndex("Personalization") + .HasDatabaseName("ix_qts_awarded_emails_job_items_personalization"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Personalization"), "gin"); + + b.ToTable("qts_awarded_emails_job_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Property("QualificationId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("DeletedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_on"); + + b.Property("DqtCreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_created_on"); + + b.Property("DqtFirstSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_first_sync"); + + b.Property("DqtLastSync") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_last_sync"); + + b.Property("DqtModifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("dqt_modified_on"); + + b.Property("DqtQualificationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qualification_id"); + + b.Property("DqtState") + .HasColumnType("integer") + .HasColumnName("dqt_state"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.HasKey("QualificationId") + .HasName("pk_qualifications"); + + b.HasIndex("DqtQualificationId") + .IsUnique() + .HasDatabaseName("ix_qualifications_dqt_qualification_id") + .HasFilter("dqt_qualification_id is not null"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_qualifications_person_id"); + + b.ToTable("qualifications", (string)null); + + b.HasDiscriminator("QualificationType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.Property("RouteId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("route_id"); + + b.Property("AgeRangeFrom") + .HasColumnType("integer") + .HasColumnName("age_range_from"); + + b.Property("AgeRangeTo") + .HasColumnType("integer") + .HasColumnName("age_range_to"); + + b.Property("CountryId") + .HasColumnType("character varying(4)") + .HasColumnName("country_id"); + + b.Property("ExternalReference") + .HasColumnType("text") + .HasColumnName("external_reference"); + + b.Property("InductionExemptionReason") + .HasColumnType("integer") + .HasColumnName("induction_exemption_reason"); + + b.Property("IttProviderId") + .HasColumnType("uuid") + .HasColumnName("itt_provider_id"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("ProgrammeEndDate") + .HasColumnType("date") + .HasColumnName("programme_end_date"); + + b.Property("ProgrammeStartDate") + .HasColumnType("date") + .HasColumnName("programme_start_date"); + + b.Property("QualificationId") + .HasColumnType("uuid") + .HasColumnName("qualification_id"); + + b.Property("QualificationType") + .HasColumnType("integer") + .HasColumnName("qualification_type"); + + b.Property("RouteStatus") + .HasColumnType("integer") + .HasColumnName("route_status"); + + b.Property("RouteType") + .HasColumnType("integer") + .HasColumnName("route_type"); + + b.Property>("Subjects") + .IsRequired() + .HasColumnType("uuid[]") + .HasColumnName("subjects"); + + b.HasKey("RouteId") + .HasName("pk_routes"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_routes_person_id"); + + b.ToTable("routes", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.Property("SupportTaskReference") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("support_task_reference"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("OneLoginUserSubject") + .HasColumnType("character varying(255)") + .HasColumnName("one_login_user_subject"); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("SupportTaskType") + .HasColumnType("integer") + .HasColumnName("support_task_type"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("_data") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.HasKey("SupportTaskReference") + .HasName("pk_support_tasks"); + + b.HasIndex("OneLoginUserSubject") + .HasDatabaseName("ix_support_tasks_one_login_user_subject"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_support_tasks_person_id"); + + b.ToTable("support_tasks", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", b => + { + b.Property("TpsCsvExtractId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("Filename") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("filename"); + + b.HasKey("TpsCsvExtractId") + .HasName("pk_tps_csv_extracts"); + + b.ToTable("tps_csv_extracts", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.Property("TpsCsvExtractItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasColumnType("date") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasColumnType("date") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasColumnType("date") + .HasColumnName("employment_start_date"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_number") + .IsFixedLength(); + + b.Property("EstablishmentPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasColumnType("date") + .HasColumnName("extract_date"); + + b.Property("Gender") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("gender"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LocalAuthorityCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("local_authority_code") + .IsFixedLength(); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasColumnType("integer") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("Result") + .HasColumnType("integer") + .HasColumnName("result"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("TpsCsvExtractLoadItemId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("WithdrawalIndicator") + .HasMaxLength(1) + .HasColumnType("character(1)") + .HasColumnName("withdrawal_indicator") + .IsFixedLength(); + + b.HasKey("TpsCsvExtractItemId") + .HasName("pk_tps_csv_extract_items"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_csv_extract_items_key"); + + b.HasIndex("TpsCsvExtractId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasIndex("TpsCsvExtractLoadItemId") + .HasDatabaseName("ix_tps_csv_extract_items_tps_csv_extract_load_item_id"); + + b.HasIndex("Trn") + .HasDatabaseName("ix_tps_csv_extract_items_trn"); + + b.HasIndex("LocalAuthorityCode", "EstablishmentNumber") + .HasDatabaseName("ix_tps_csv_extract_items_la_code_establishment_number"); + + b.ToTable("tps_csv_extract_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.Property("TpsCsvExtractLoadItemId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_load_item_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_birth"); + + b.Property("DateOfDeath") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("date_of_death"); + + b.Property("EmploymentEndDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_end_date"); + + b.Property("EmploymentStartDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employment_start_date"); + + b.Property("Errors") + .HasColumnType("integer") + .HasColumnName("errors"); + + b.Property("EstablishmentEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_email_address"); + + b.Property("EstablishmentNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_number"); + + b.Property("EstablishmentPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("establishment_postcode"); + + b.Property("ExtractDate") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("extract_date"); + + b.Property("FullOrPartTimeIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("full_or_part_time_indicator"); + + b.Property("Gender") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("gender"); + + b.Property("LocalAuthorityCode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("local_authority_code"); + + b.Property("MemberEmailAddress") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_email_address"); + + b.Property("MemberId") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_id"); + + b.Property("MemberPostcode") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("member_postcode"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("national_insurance_number"); + + b.Property("TpsCsvExtractId") + .HasColumnType("uuid") + .HasColumnName("tps_csv_extract_id"); + + b.Property("Trn") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("trn"); + + b.Property("WithdrawalIndicator") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("withdrawal_indicator"); + + b.HasKey("TpsCsvExtractLoadItemId") + .HasName("pk_tps_csv_extract_load_items"); + + b.ToTable("tps_csv_extract_load_items", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.Property("TpsEmploymentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_employment_id"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_on"); + + b.Property("EmploymentType") + .HasColumnType("integer") + .HasColumnName("employment_type"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("EstablishmentId") + .HasColumnType("uuid") + .HasColumnName("establishment_id"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("key"); + + b.Property("LastExtractDate") + .HasColumnType("date") + .HasColumnName("last_extract_date"); + + b.Property("LastKnownTpsEmployedDate") + .HasColumnType("date") + .HasColumnName("last_known_tps_employed_date"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("PersonId") + .HasColumnType("uuid") + .HasColumnName("person_id"); + + b.Property("PersonPostcode") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("person_postcode"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_on"); + + b.Property("WithdrawalConfirmed") + .HasColumnType("boolean") + .HasColumnName("withdrawal_confirmed"); + + b.HasKey("TpsEmploymentId") + .HasName("pk_tps_employments"); + + b.HasIndex("EstablishmentId") + .HasDatabaseName("ix_tps_employments_establishment_id"); + + b.HasIndex("Key") + .HasDatabaseName("ix_tps_employments_key"); + + b.HasIndex("PersonId") + .HasDatabaseName("ix_tps_employments_person_id"); + + b.ToTable("tps_employments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishment", b => + { + b.Property("TpsEstablishmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("tps_establishment_id"); + + b.Property("EmployersName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("employers_name"); + + b.Property("EstablishmentCode") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_code") + .IsFixedLength(); + + b.Property("LaCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character(3)") + .HasColumnName("la_code") + .IsFixedLength(); + + b.Property("SchoolClosedDate") + .HasColumnType("date") + .HasColumnName("school_closed_date"); + + b.Property("SchoolGiasName") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("school_gias_name"); + + b.HasKey("TpsEstablishmentId") + .HasName("pk_tps_establishments"); + + b.HasIndex("LaCode", "EstablishmentCode") + .HasDatabaseName("ix_tps_establishments_la_code_establishment_number"); + + b.ToTable("tps_establishments", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEstablishmentType", b => + { + b.Property("TpsEstablishmentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("tps_establishment_type_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TpsEstablishmentTypeId")); + + b.Property("Description") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("description"); + + b.Property("EstablishmentRangeFrom") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_from") + .IsFixedLength(); + + b.Property("EstablishmentRangeTo") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("character(4)") + .HasColumnName("establishment_range_to") + .IsFixedLength(); + + b.Property("ShortDescription") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)") + .HasColumnName("short_description"); + + b.HasKey("TpsEstablishmentTypeId") + .HasName("pk_tps_establishment_types"); + + b.ToTable("tps_establishment_types", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequest", b => + { + b.Property("TrnRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("trn_request_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TrnRequestId")); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("IdentityUserId") + .HasColumnType("uuid") + .HasColumnName("identity_user_id"); + + b.Property("LinkedToIdentity") + .HasColumnType("boolean") + .HasColumnName("linked_to_identity"); + + b.Property("RequestId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("TeacherId") + .HasColumnType("uuid") + .HasColumnName("teacher_id"); + + b.Property("TrnToken") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("trn_token"); + + b.HasKey("TrnRequestId") + .HasName("pk_trn_requests"); + + b.HasIndex("ClientId", "RequestId") + .IsUnique() + .HasDatabaseName("ix_trn_requests_client_id_request_id"); + + b.ToTable("trn_requests", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequestMetadata", b => + { + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("RequestId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("VerifiedOneLoginUserSubject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("verified_one_login_user_subject"); + + b.HasKey("ApplicationUserId", "RequestId") + .HasName("pk_trn_request_metadata"); + + b.ToTable("trn_request_metadata", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Active") + .HasColumnType("boolean") + .HasColumnName("active"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("UserType") + .HasColumnType("integer") + .HasColumnName("user_type"); + + b.HasKey("UserId") + .HasName("pk_users"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator("UserType"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.Property("WebhookEndpointId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("address"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property>("CloudEventTypes") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("cloud_event_types"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.HasKey("WebhookEndpointId") + .HasName("pk_webhook_endpoints"); + + b.ToTable("webhook_endpoints", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.Property("WebhookMessageId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("webhook_message_id"); + + b.Property("ApiVersion") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("api_version"); + + b.Property("CloudEventId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("cloud_event_id"); + + b.Property("CloudEventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("cloud_event_type"); + + b.Property("Data") + .HasColumnType("jsonb") + .HasColumnName("data"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone") + .HasColumnName("delivered"); + + b.Property>("DeliveryAttempts") + .IsRequired() + .HasColumnType("timestamp with time zone[]") + .HasColumnName("delivery_attempts"); + + b.Property>("DeliveryErrors") + .IsRequired() + .HasColumnType("text[]") + .HasColumnName("delivery_errors"); + + b.Property("NextDeliveryAttempt") + .HasColumnType("timestamp with time zone") + .HasColumnName("next_delivery_attempt"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("WebhookEndpointId") + .HasColumnType("uuid") + .HasColumnName("webhook_endpoint_id"); + + b.HasKey("WebhookMessageId") + .HasName("pk_webhook_messages"); + + b.ToTable("webhook_messages", (string)null); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EarlyYearsTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("DqtMqEstablishmentId") + .HasColumnType("uuid") + .HasColumnName("dqt_mq_establishment_id"); + + b.Property("DqtSpecialismId") + .HasColumnType("uuid") + .HasColumnName("dqt_specialism_id"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("end_date"); + + b.Property("ProviderId") + .HasColumnType("uuid") + .HasColumnName("mq_provider_id"); + + b.Property("Specialism") + .HasColumnType("integer") + .HasColumnName("mq_specialism"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("start_date"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("mq_status"); + + b.HasDiscriminator().HasValue(0); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QualifiedTeacherStatusQualification", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification"); + + b.Property("AwardedDate") + .HasColumnType("date") + .HasColumnName("awarded_date"); + + b.Property("DqtQtsRegistrationId") + .HasColumnType("uuid") + .HasColumnName("dqt_qts_registration_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("ApiRoles") + .HasColumnType("varchar[]") + .HasColumnName("api_roles"); + + b.Property("ClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("client_secret"); + + b.Property("IsOidcClient") + .HasColumnType("boolean") + .HasColumnName("is_oidc_client"); + + b.Property("OneLoginAuthenticationSchemeName") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_authentication_scheme_name"); + + b.Property("OneLoginClientId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("one_login_client_id"); + + b.Property("OneLoginPostLogoutRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_post_logout_redirect_uri_path"); + + b.Property("OneLoginPrivateKeyPem") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("one_login_private_key_pem"); + + b.Property("OneLoginRedirectUriPath") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("one_login_redirect_uri_path"); + + b.Property>("PostLogoutRedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("post_logout_redirect_uris"); + + b.Property>("RedirectUris") + .HasColumnType("varchar[]") + .HasColumnName("redirect_uris"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_users_client_id") + .HasFilter("client_id is not null"); + + b.HasIndex("OneLoginAuthenticationSchemeName") + .IsUnique() + .HasDatabaseName("ix_users_one_login_authentication_scheme_name") + .HasFilter("one_login_authentication_scheme_name is not null"); + + b.HasDiscriminator().HasValue(2); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SystemUser", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.ToTable("users", (string)null); + + b.HasDiscriminator().HasValue(3); + + b.HasData( + new + { + UserId = new Guid("a81394d1-a498-46d8-af3e-e077596ab303"), + Active = true, + Name = "System", + UserType = 0 + }); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.User", b => + { + b.HasBaseType("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase"); + + b.Property("AzureAdUserId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("azure_ad_user_id"); + + b.Property("DqtUserId") + .HasColumnType("uuid") + .HasColumnName("dqt_user_id"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email") + .UseCollation("case_insensitive"); + + b.Property("Roles") + .IsRequired() + .HasColumnType("varchar[]") + .HasColumnName("roles"); + + b.HasIndex("AzureAdUserId") + .IsUnique() + .HasDatabaseName("ix_users_azure_ad_user_id"); + + b.HasDiscriminator().HasValue(1); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_authorizations_oidc_applications_application_id"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_oidc_tokens_oidc_applications_application_id"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId") + .HasConstraintName("fk_oidc_tokens_oidc_authorizations_authorization_id"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Alert", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", "AlertType") + .WithMany() + .HasForeignKey("AlertTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_alert_type"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Alerts") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alerts_person"); + + b.Navigation("AlertType"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertType", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", "AlertCategory") + .WithMany("AlertTypes") + .HasForeignKey("AlertCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_alert_types_alert_category"); + + b.Navigation("AlertCategory"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApiKey", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", "ApplicationUser") + .WithMany("ApiKeys") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_key_application_user"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EstablishmentSource", null) + .WithMany() + .HasForeignKey("EstablishmentSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_establishments_establishment_source_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", "EytsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("EytsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_eyts_awarded_emails_job_items_eyts_awarded_emails_jobs_eyts"); + + b.Navigation("EytsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", "InductionCompletedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InductionCompletedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_induction_completed_emails_job_items_induction_completed_em"); + + b.Navigation("InductionCompletedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", "InternationalQtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("InternationalQtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_international_qts_awarded_emails_job_items_international_qt"); + + b.Navigation("InternationalQtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithOne() + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", "PersonId") + .HasConstraintName("fk_one_login_users_persons_person_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("VerifiedByApplicationUserId") + .HasConstraintName("fk_one_login_users_application_users_verified_by_application_u"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJobItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", "QtsAwardedEmailsJob") + .WithMany("JobItems") + .HasForeignKey("QtsAwardedEmailsJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qts_awarded_emails_job_items_qts_awarded_emails_jobs_qts_aw"); + + b.Navigation("QtsAwardedEmailsJob"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", "Person") + .WithMany("Qualifications") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_qualifications_person"); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Country", null) + .WithMany() + .HasForeignKey("CountryId") + .HasConstraintName("fk_routes_countries_country_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany("Routes") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_routes_persons_person_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", "Qualification") + .WithOne("Route") + .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.Route", "QualificationId") + .HasConstraintName("fk_routes_qualifications_qualification_id"); + + b.Navigation("Qualification"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.SupportTask", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", null) + .WithMany() + .HasForeignKey("OneLoginUserSubject") + .HasConstraintName("fk_support_tasks_one_login_user"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .HasConstraintName("fk_support_tasks_person"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", null) + .WithMany() + .HasForeignKey("TpsCsvExtractLoadItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_items_tps_csv_extract_load_item_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtractLoadItem", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsCsvExtract", null) + .WithMany() + .HasForeignKey("TpsCsvExtractId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_csv_extract_load_items_tps_csv_extract_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TpsEmployment", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Establishment", null) + .WithMany() + .HasForeignKey("EstablishmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_establishment_id"); + + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", null) + .WithMany() + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_tps_employments_person_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_endpoints_application_users_application_user_id"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookMessage", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.WebhookEndpoint", "WebhookEndpoint") + .WithMany() + .HasForeignKey("WebhookEndpointId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_webhook_messages_webhook_endpoints_webhook_endpoint_id"); + + b.Navigation("WebhookEndpoint"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualification", b => + { + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.MandatoryQualificationProvider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .HasConstraintName("fk_qualifications_mandatory_qualification_provider"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.AlertCategory", b => + { + b.Navigation("AlertTypes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.EytsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InductionCompletedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.InternationalQtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Person", b => + { + b.Navigation("Alerts"); + + b.Navigation("Qualifications"); + + b.Navigation("Routes"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.QtsAwardedEmailsJob", b => + { + b.Navigation("JobItems"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.Qualification", b => + { + b.Navigation("Route"); + }); + + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", b => + { + b.Navigation("ApiKeys"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.cs new file mode 100644 index 000000000..a0573c139 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20241107134330_OneLoginUserVerifiedByApplicationUserId.cs @@ -0,0 +1,40 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TeachingRecordSystem.Core.DataStore.Postgres.Migrations +{ + /// + public partial class OneLoginUserVerifiedByApplicationUserId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "verified_by_application_user_id", + table: "one_login_users", + type: "uuid", + nullable: true); + + migrationBuilder.AddForeignKey( + name: "fk_one_login_users_application_users_verified_by_application_u", + table: "one_login_users", + column: "verified_by_application_user_id", + principalTable: "users", + principalColumn: "user_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "fk_one_login_users_application_users_verified_by_application_u", + table: "one_login_users"); + + migrationBuilder.DropColumn( + name: "verified_by_application_user_id", + table: "one_login_users"); + } + } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/TrsDbContextModelSnapshot.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/TrsDbContextModelSnapshot.cs index c04a0cd2e..a2b801398 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/TrsDbContextModelSnapshot.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/TrsDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("ProductVersion", "8.0.10") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -1676,12 +1676,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("subject"); b.Property("Email") - .IsRequired() .HasMaxLength(200) .HasColumnType("character varying(200)") .HasColumnName("email"); - b.Property("FirstOneLoginSignIn") + b.Property("FirstOneLoginSignIn") .HasColumnType("timestamp with time zone") .HasColumnName("first_one_login_sign_in"); @@ -1693,7 +1692,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("jsonb") .HasColumnName("last_core_identity_vc"); - b.Property("LastOneLoginSignIn") + b.Property("LastOneLoginSignIn") .HasColumnType("timestamp with time zone") .HasColumnName("last_one_login_sign_in"); @@ -1701,7 +1700,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone") .HasColumnName("last_sign_in"); - b.Property("MatchRoute") + b.Property("MatchRoute") .HasColumnType("integer") .HasColumnName("match_route"); @@ -1717,6 +1716,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("verification_route"); + b.Property("VerifiedByApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("verified_by_application_user_id"); + b.Property("VerifiedDatesOfBirth") .HasColumnType("jsonb") .HasColumnName("verified_dates_of_birth"); @@ -2645,6 +2648,28 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("trn_requests", (string)null); }); + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.TrnRequestMetadata", b => + { + b.Property("ApplicationUserId") + .HasColumnType("uuid") + .HasColumnName("application_user_id"); + + b.Property("RequestId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("request_id"); + + b.Property("VerifiedOneLoginUserSubject") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("verified_one_login_user_subject"); + + b.HasKey("ApplicationUserId", "RequestId") + .HasName("pk_trn_request_metadata"); + + b.ToTable("trn_request_metadata", (string)null); + }); + modelBuilder.Entity("TeachingRecordSystem.Core.DataStore.Postgres.Models.UserBase", b => { b.Property("UserId") @@ -3082,6 +3107,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("TeachingRecordSystem.Core.DataStore.Postgres.Models.OneLoginUser", "PersonId") .HasConstraintName("fk_one_login_users_persons_person_id"); + b.HasOne("TeachingRecordSystem.Core.DataStore.Postgres.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("VerifiedByApplicationUserId") + .HasConstraintName("fk_one_login_users_application_users_verified_by_application_u"); + b.Navigation("Person"); }); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/OneLoginUser.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/OneLoginUser.cs index 3987a5d5b..473e77c97 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/OneLoginUser.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/OneLoginUser.cs @@ -1,20 +1,80 @@ +using System.Diagnostics; + namespace TeachingRecordSystem.Core.DataStore.Postgres.Models; public class OneLoginUser { public required string Subject { get; init; } - public required string Email { get; set; } - public required DateTime FirstOneLoginSignIn { get; init; } - public required DateTime LastOneLoginSignIn { get; set; } + public string? Email { get; set; } + public DateTime? FirstOneLoginSignIn { get; set; } + public DateTime? LastOneLoginSignIn { get; set; } public DateTime? FirstSignIn { get; set; } public DateTime? LastSignIn { get; set; } - public Guid? PersonId { get; set; } + public Guid? PersonId { get; private set; } public Person? Person { get; } - public DateTime? VerifiedOn { get; set; } - public OneLoginUserVerificationRoute? VerificationRoute { get; set; } - public string[][]? VerifiedNames { get; set; } - public DateOnly[]? VerifiedDatesOfBirth { get; set; } + public DateTime? VerifiedOn { get; private set; } + public OneLoginUserVerificationRoute? VerificationRoute { get; private set; } + public string[][]? VerifiedNames { get; private set; } + public DateOnly[]? VerifiedDatesOfBirth { get; private set; } public string? LastCoreIdentityVc { get; set; } - public OneLoginUserMatchRoute MatchRoute { get; set; } - public KeyValuePair[]? MatchedAttributes { get; set; } + public OneLoginUserMatchRoute? MatchRoute { get; private set; } + public KeyValuePair[]? MatchedAttributes { get; private set; } + public Guid? VerifiedByApplicationUserId { get; private set; } + + public void SetVerified( + DateTime verifiedOn, + OneLoginUserVerificationRoute route, + Guid? verifiedByApplicationUserId, + string[][] verifiedNames, + DateOnly[] verifiedDatesOfBirth) + { + if (route == OneLoginUserVerificationRoute.External && !verifiedByApplicationUserId.HasValue) + { + throw new ArgumentException( + $"{nameof(verifiedByApplicationUserId)} must be non-null when {nameof(route)} is {OneLoginUserVerificationRoute.External}.", + nameof(verifiedByApplicationUserId)); + } + + if (route != OneLoginUserVerificationRoute.External && verifiedByApplicationUserId.HasValue) + { + throw new ArgumentException( + $"{nameof(verifiedByApplicationUserId)} must be null when {nameof(route)} is not {OneLoginUserVerificationRoute.External}.", + nameof(verifiedByApplicationUserId)); + } + + VerifiedOn = verifiedOn; + VerificationRoute = route; + VerifiedByApplicationUserId = verifiedByApplicationUserId; + VerifiedNames = verifiedNames; + VerifiedDatesOfBirth = verifiedDatesOfBirth; + } + + public void SetMatched( + Guid personId, + OneLoginUserMatchRoute route, + KeyValuePair[]? matchedAttributes) + { + Debug.Assert(VerifiedOn is not null); + + PersonId = personId; + MatchRoute = route; + MatchedAttributes = matchedAttributes; + } + + public void ClearVerifiedInfo() + { + // Used for testing only + VerifiedOn = null; + VerificationRoute = null; + VerifiedNames = null; + VerifiedDatesOfBirth = null; + } + + public void ClearMatchedPerson() + { + // Used for testing only + PersonId = null; + MatchRoute = null; + MatchedAttributes = null; + } } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/TrnRequestMetadata.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/TrnRequestMetadata.cs new file mode 100644 index 000000000..b07b3c416 --- /dev/null +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Models/TrnRequestMetadata.cs @@ -0,0 +1,8 @@ +namespace TeachingRecordSystem.Core.DataStore.Postgres.Models; + +public class TrnRequestMetadata +{ + public required Guid ApplicationUserId { get; init; } + public required string RequestId { get; init; } + public required string? VerifiedOneLoginUserSubject { get; init; } +} diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/TrsDbContext.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/TrsDbContext.cs index 1931fb8bb..0f1235e7a 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/TrsDbContext.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/TrsDbContext.cs @@ -99,6 +99,8 @@ public static TrsDbContext Create(string connectionString, int? commandTimeout = public DbSet WebhookMessages => Set(); + public DbSet TrnRequestMetadata => Set(); + public static void ConfigureOptions(DbContextOptionsBuilder optionsBuilder, string? connectionString = null, int? commandTimeout = null) { Action configureOptions = o => o.CommandTimeout(commandTimeout); diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserMatchRoute.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserMatchRoute.cs index 181dd8ead..aad267f41 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserMatchRoute.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserMatchRoute.cs @@ -7,4 +7,5 @@ public enum OneLoginUserMatchRoute TrnToken = 3, Support = 4, GetAnIdentityUser = 5, + TrnAllocation = 6, } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserVerificationRoute.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserVerificationRoute.cs index 20f111cec..224478fd0 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserVerificationRoute.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/Models/OneLoginUserVerificationRoute.cs @@ -3,5 +3,6 @@ namespace TeachingRecordSystem.Core.Models; public enum OneLoginUserVerificationRoute { OneLogin = 1, - Support = 2 + Support = 2, + External = 3, } diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.SupportUi/Pages/SupportTasks/ConnectOneLoginUser/Connect.cshtml.cs b/TeachingRecordSystem/src/TeachingRecordSystem.SupportUi/Pages/SupportTasks/ConnectOneLoginUser/Connect.cshtml.cs index 93ae644ca..fb6718c82 100644 --- a/TeachingRecordSystem/src/TeachingRecordSystem.SupportUi/Pages/SupportTasks/ConnectOneLoginUser/Connect.cshtml.cs +++ b/TeachingRecordSystem/src/TeachingRecordSystem.SupportUi/Pages/SupportTasks/ConnectOneLoginUser/Connect.cshtml.cs @@ -37,14 +37,17 @@ public async Task OnPost() }; _supportTask.Status = SupportTaskStatus.Closed; - var oneLoginUser = await dbContext.OneLoginUsers.SingleAsync(u => u.Subject == data.OneLoginUserSubject); - oneLoginUser.PersonId = PersonDetail!.PersonId; - oneLoginUser.MatchedAttributes = (await personMatchingService + var matchedAttributes = (await personMatchingService .GetMatchedAttributes( new(data.VerifiedNames!, data.VerifiedDatesOfBirth!, data.StatedNationalInsuranceNumber, data.StatedTrn, data.TrnTokenTrn), PersonDetail.PersonId)) .ToArray(); - oneLoginUser.MatchRoute = OneLoginUserMatchRoute.Support; + + var oneLoginUser = await dbContext.OneLoginUsers.SingleAsync(u => u.Subject == data.OneLoginUserSubject); + oneLoginUser.SetMatched( + PersonDetail!.PersonId, + OneLoginUserMatchRoute.Support, + matchedAttributes); await dbContext.SaveChangesAsync(); diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs index b54988977..629210f8f 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/HostFixture.cs @@ -7,6 +7,7 @@ using Microsoft.IdentityModel.Tokens; using TeachingRecordSystem.Api.Infrastructure.Security; using TeachingRecordSystem.Api.Tests.Infrastructure.Security; +using TeachingRecordSystem.Core.DataStore.Postgres; using TeachingRecordSystem.Core.Dqt; using TeachingRecordSystem.Core.Services.Certificates; using TeachingRecordSystem.Core.Services.GetAnIdentityApi; @@ -31,6 +32,8 @@ public HostFixture(IConfiguration configuration) _ = Services; // Start the host } + public static Guid DefaultApplicationUserId { get; } = new("c0c8c511-e8e4-4b8e-96e3-55085dafc05d"); + public HttpClientInterceptorOptions EvidenceFilesHttpClientInterceptorOptions { get; } = new(); public SigningCredentials JwtSigningCredentials { get; } @@ -95,6 +98,20 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) services.AddHttpClient("EvidenceFiles") .AddHttpMessageHandler(_ => EvidenceFilesHttpClientInterceptorOptions.CreateHttpMessageHandler()) .ConfigurePrimaryHttpMessageHandler(_ => new NotFoundHandler()); + + services.AddStartupTask(async sp => + { + await using var dbContext = await sp.GetRequiredService>().CreateDbContextAsync(); + + dbContext.ApplicationUsers.Add(new Core.DataStore.Postgres.Models.ApplicationUser() + { + UserId = DefaultApplicationUserId, + Name = "Tests", + ApiRoles = ApiRoles.All.ToArray() + }); + + await dbContext.SaveChangesAsync(); + }); }); } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/TestBase.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/TestBase.cs index 44c39186a..e6b5cf343 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/TestBase.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/TestBase.cs @@ -13,8 +13,6 @@ namespace TeachingRecordSystem.Api.Tests; public abstract class TestBase { - private static readonly Guid _defaultApplicationUserId = new Guid("c0c8c511-e8e4-4b8e-96e3-55085dafc05d"); - private readonly TestScopedServices _testServices; protected TestBase(HostFixture hostFixture) @@ -28,7 +26,9 @@ protected TestBase(HostFixture hostFixture) public Mock CertificateGeneratorMock => _testServices.CertificateGeneratorMock; - public Guid ApplicationUserId { get; } = _defaultApplicationUserId; + public Guid DefaultApplicationUserId => HostFixture.DefaultApplicationUserId; + + public Guid ApplicationUserId { get; } = HostFixture.DefaultApplicationUserId; public CrmQueryDispatcherSpy CrmQueryDispatcherSpy => _testServices.CrmQueryDispatcherSpy; @@ -102,7 +102,7 @@ public HttpClient GetHttpClientWithIdentityAccessToken(string trn, string scope protected void SetCurrentApiClient(IEnumerable roles, Guid? applicationUserId = null) { var currentUserProvider = HostFixture.Services.GetRequiredService(); - currentUserProvider.CurrentApiUserId = applicationUserId ?? _defaultApplicationUserId; + currentUserProvider.CurrentApiUserId = applicationUserId ?? DefaultApplicationUserId; currentUserProvider.Roles = roles.ToArray(); } diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/VNext/GetTrnRequestTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/VNext/GetTrnRequestTests.cs new file mode 100644 index 000000000..961d72deb --- /dev/null +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.Api.Tests/V3/VNext/GetTrnRequestTests.cs @@ -0,0 +1,87 @@ +namespace TeachingRecordSystem.Api.Tests.V3.VNext; + +public class GetTrnRequestTests : TestBase +{ + public GetTrnRequestTests(HostFixture hostFixture) : base(hostFixture) + { + SetCurrentApiClient(roles: [ApiRoles.CreateTrn]); + } + + [Fact] + public async Task Get_CompletedRequestWithOneLoginUserMetadata_AddsOneLoginUserToDb() + { + // Arrange + var requestId = Guid.NewGuid().ToString(); + + var person = await TestData.CreatePerson(p => p + .WithTrn() + .WithTrnRequestId(TrnRequestHelper.GetCrmTrnRequestId(ApplicationUserId, requestId))); + + var oneLoginUserSubject = TestData.CreateOneLoginUserSubject(); + + await WithDbContext(dbContext => + { + dbContext.TrnRequestMetadata.Add(new Core.DataStore.Postgres.Models.TrnRequestMetadata() + { + ApplicationUserId = ApplicationUserId, + RequestId = requestId, + VerifiedOneLoginUserSubject = oneLoginUserSubject + }); + + return dbContext.SaveChangesAsync(); + }); + + // Act + var response = await GetHttpClientWithApiKey().GetAsync($"v3/trn-requests?requestId={requestId}"); + + // Assert + await AssertEx.JsonResponse(response, expectedStatusCode: 200); + + await WithDbContext(async dbContext => + { + var oneLoginUser = await dbContext.OneLoginUsers.SingleOrDefaultAsync(u => u.Subject == oneLoginUserSubject); + Assert.NotNull(oneLoginUser); + Assert.Equal(person.PersonId, oneLoginUser.PersonId); + Assert.Equal(Clock.UtcNow, oneLoginUser.VerifiedOn); + Assert.Equal(OneLoginUserVerificationRoute.External, oneLoginUser.VerificationRoute); + Assert.Equal(ApplicationUserId, oneLoginUser.VerifiedByApplicationUserId); + }); + } + + [Fact] + public async Task Get_PendingRequestWithOneLoginUserMetadata_DoesNotAddOneLoginUserToDb() + { + // Arrange + var requestId = Guid.NewGuid().ToString(); + + var person = await TestData.CreatePerson(p => p + .WithoutTrn() + .WithTrnRequestId(TrnRequestHelper.GetCrmTrnRequestId(ApplicationUserId, requestId))); + + var oneLoginUserSubject = TestData.CreateOneLoginUserSubject(); + + await WithDbContext(dbContext => + { + dbContext.TrnRequestMetadata.Add(new Core.DataStore.Postgres.Models.TrnRequestMetadata() + { + ApplicationUserId = ApplicationUserId, + RequestId = requestId, + VerifiedOneLoginUserSubject = oneLoginUserSubject + }); + + return dbContext.SaveChangesAsync(); + }); + + // Act + var response = await GetHttpClientWithApiKey().GetAsync($"v3/trn-requests?requestId={requestId}"); + + // Assert + await AssertEx.JsonResponse(response, expectedStatusCode: 200); + + await WithDbContext(async dbContext => + { + var oneLoginUser = await dbContext.OneLoginUsers.SingleOrDefaultAsync(u => u.Subject == oneLoginUserSubject); + Assert.Null(oneLoginUser); + }); + } +} diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/OidcTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/OidcTests.cs index b58da813f..e6de31c88 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/OidcTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/OidcTests.cs @@ -11,7 +11,7 @@ public async Task SignInAndOut() var oneLoginUser = await TestData.CreateOneLoginUser(person); var coreIdentityVc = TestData.CreateOneLoginCoreIdentityVc(person.FirstName, person.LastName, person.DateOfBirth); - SetCurrentOneLoginUser(OneLoginUserInfo.Create(oneLoginUser.Subject, oneLoginUser.Email, coreIdentityVc)); + SetCurrentOneLoginUser(OneLoginUserInfo.Create(oneLoginUser.Subject, oneLoginUser.Email!, coreIdentityVc)); await using var context = await HostFixture.CreateBrowserContext(); var page = await context.NewPageAsync(); diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/SignInTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/SignInTests.cs index 1d012b7c2..a9eb97ae2 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/SignInTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.EndToEndTests/SignInTests.cs @@ -345,7 +345,7 @@ public async Task SignIn_KnownUser() var oneLoginUser = await TestData.CreateOneLoginUser(person); var coreIdentityVc = TestData.CreateOneLoginCoreIdentityVc(person.FirstName, person.LastName, person.DateOfBirth); - SetCurrentOneLoginUser(OneLoginUserInfo.Create(oneLoginUser.Subject, oneLoginUser.Email, coreIdentityVc)); + SetCurrentOneLoginUser(OneLoginUserInfo.Create(oneLoginUser.Subject, oneLoginUser.Email!, coreIdentityVc)); await using var context = await HostFixture.CreateBrowserContext(); var page = await context.NewPageAsync(); diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/SignInJourneyHelperTests.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/SignInJourneyHelperTests.cs index 1f69a1143..c3892590a 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/SignInJourneyHelperTests.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.AuthorizeAccess.Tests/SignInJourneyHelperTests.cs @@ -3,6 +3,7 @@ using GovUk.OneLogin.AspNetCore; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.Extensions.Options; +using Optional; using TeachingRecordSystem.Core.DataStore.Postgres; using TeachingRecordSystem.Core.Services.PersonMatching; using static TeachingRecordSystem.AuthorizeAccess.IdModelTypes; @@ -48,6 +49,45 @@ public Task OnOneLoginCallback_AuthenticationOnly_UserAlreadyExistsAndTeachingRe Assert.Equal($"{state.RedirectUri}?{journeyInstance.GetUniqueIdQueryParameter()}", redirectResult.Url); }); + [Fact] + public Task OnOneLoginCallback_AuthenticationOnly_UserAlreadyExistsWithSubjectOnlyAndTeachingRecordKnown_AssignsEmailAndSignInFieldsAndCompletesJourney() => + WithDbContext(async dbContext => + { + // Arrange + var helper = CreateHelper(dbContext); + + var person = await TestData.CreatePerson(p => p.WithTrn()); + var user = await TestData.CreateOneLoginUser(person, email: Option.Some((string?)null)); + Clock.Advance(); + + var state = new SignInJourneyState( + redirectUri: "/", + serviceName: "Test Service", + serviceUrl: "https://service", + oneLoginAuthenticationScheme: "dummy", + clientApplicationUserId: default); + var journeyInstance = await CreateJourneyInstance(state); + + var email = Faker.Internet.Email(); + var authenticationTicket = CreateOneLoginAuthenticationTicket(vtr: SignInJourneyHelper.AuthenticationOnlyVtr, sub: user.Subject, email); + + // Act + var result = await helper.OnOneLoginCallback(journeyInstance, authenticationTicket); + + // Assert + Assert.NotNull(state.AuthenticationTicket); + + user = await WithDbContext(dbContext => dbContext.OneLoginUsers.SingleAsync(u => u.Subject == user.Subject)); + Assert.Equal(email, user.Email); + Assert.Equal(Clock.UtcNow, user.FirstOneLoginSignIn); + Assert.Equal(Clock.UtcNow, user.LastOneLoginSignIn); + Assert.Equal(Clock.UtcNow, user.FirstSignIn); + Assert.Equal(Clock.UtcNow, user.LastSignIn); + + var redirectResult = Assert.IsType(result); + Assert.Equal($"{state.RedirectUri}?{journeyInstance.GetUniqueIdQueryParameter()}", redirectResult.Url); + }); + [Fact] public Task OnOneLoginCallback_AuthenticationOnly_UserAlreadyExistsButTeachingNotRecordKnown_RequestsIdentityVerification() => WithDbContext(async dbContext => @@ -237,7 +277,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Medium); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Medium); var firstName = person.FirstName; var lastName = person.LastName; @@ -296,7 +336,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Low, TrnAssociationSource.SupportUi); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Low, TrnAssociationSource.SupportUi); var firstName = person.FirstName; var lastName = person.LastName; @@ -355,7 +395,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Low, TrnAssociationSource.TrnToken); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Low, TrnAssociationSource.TrnToken); var firstName = person.FirstName; var lastName = person.LastName; @@ -414,7 +454,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Low); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Low); var firstName = person.FirstName; var lastName = person.LastName; @@ -463,7 +503,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Medium); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Medium); var firstName = person.FirstName; var lastName = TestData.GenerateChangedLastName(person.LastName); @@ -512,7 +552,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email, TrnVerificationLevel.Medium); + await CreateIdentityUser(person.FirstName, person.LastName, person.Trn!, user.Email!, TrnVerificationLevel.Medium); var firstName = person.FirstName; var lastName = person.LastName; @@ -561,7 +601,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - var trnToken = await CreateTrnToken(person.Trn!, user.Email); + var trnToken = await CreateTrnToken(person.Trn!, user.Email!); var firstName = person.FirstName; var lastName = person.LastName; @@ -670,7 +710,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - var trnToken = await CreateTrnToken(person.Trn!, user.Email, expires: TimeSpan.FromSeconds(-1)); + var trnToken = await CreateTrnToken(person.Trn!, user.Email!, expires: TimeSpan.FromSeconds(-1)); var firstName = person.FirstName; var lastName = person.LastName; @@ -720,7 +760,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - var trnToken = await CreateTrnToken(person.Trn!, user.Email, userId: Guid.NewGuid()); + var trnToken = await CreateTrnToken(person.Trn!, user.Email!, userId: Guid.NewGuid()); var state = new SignInJourneyState( redirectUri: "/", @@ -766,7 +806,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - var trnToken = await CreateTrnToken(person.Trn!, user.Email); + var trnToken = await CreateTrnToken(person.Trn!, user.Email!); var firstName = person.FirstName; var lastName = TestData.GenerateChangedLastName(person.LastName); @@ -816,7 +856,7 @@ public Task OnOneLoginCallback_AuthenticationAndVerification_VerificationSucceed var user = await TestData.CreateOneLoginUser(personId: null); Clock.Advance(); - var trnToken = await CreateTrnToken(person.Trn!, user.Email); + var trnToken = await CreateTrnToken(person.Trn!, user.Email!); var firstName = person.FirstName; var lastName = person.LastName; diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateConnectOneLoginUserSupportTask.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateConnectOneLoginUserSupportTask.cs index e3727816b..52d6978f6 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateConnectOneLoginUserSupportTask.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateConnectOneLoginUserSupportTask.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using TeachingRecordSystem.Core.DataStore.Postgres.Models; using TeachingRecordSystem.Core.Models.SupportTaskData; @@ -14,12 +15,13 @@ public Task CreateConnectOneLoginUserSupportTask( WithDbContext(async dbContext => { var user = await dbContext.OneLoginUsers.SingleAsync(u => u.Subject == oneLoginUserSubject); + Debug.Assert(user.Email is not null); var data = new ConnectOneLoginUserData() { Verified = user.VerificationRoute is not null, OneLoginUserSubject = user.Subject, - OneLoginUserEmail = user.Email, + OneLoginUserEmail = user.Email!, VerifiedNames = user.VerifiedNames, VerifiedDatesOfBirth = user.VerifiedDatesOfBirth, StatedNationalInsuranceNumber = statedNationalInsuranceNumber, diff --git a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateOneLoginUser.cs b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateOneLoginUser.cs index 84dfa97e5..8eb167e96 100644 --- a/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateOneLoginUser.cs +++ b/TeachingRecordSystem/tests/TeachingRecordSystem.TestCommon/TestData.CreateOneLoginUser.cs @@ -1,19 +1,20 @@ using System.Text.Json; using System.Text.Json.Nodes; +using Optional; using TeachingRecordSystem.Core.DataStore.Postgres.Models; namespace TeachingRecordSystem.TestCommon; public partial class TestData { - public Task CreateOneLoginUser(CreatePersonResult createPersonResult, string? subject = null, string? email = null) => + public Task CreateOneLoginUser(CreatePersonResult createPersonResult, Option subject = default, Option email = default) => CreateOneLoginUser( createPersonResult.PersonId, subject, email, verifiedInfo: ([createPersonResult.FirstName, createPersonResult.LastName], createPersonResult.DateOfBirth)); - public Task CreateOneLoginUser(string? subject = null, string? email = null, bool verified = false) => + public Task CreateOneLoginUser(Option subject = default, Option email = default, bool verified = false) => CreateOneLoginUser( personId: null, subject, @@ -22,8 +23,8 @@ public Task CreateOneLoginUser(string? subject = null, string? ema public Task CreateOneLoginUser( Guid? personId, - string? subject = null, - string? email = null, + Option subject = default, + Option email = default, (string[] Name, DateOnly DateOfBirth)? verifiedInfo = null) { if (personId is not null && verifiedInfo is null) @@ -33,24 +34,39 @@ public Task CreateOneLoginUser( return WithDbContext(async dbContext => { - subject ??= CreateOneLoginUserSubject(); - email ??= Faker.Internet.Email(); + var hasSignedInBefore = email != Option.Some((string?)null); var user = new OneLoginUser() { - Subject = subject, - Email = email, - FirstOneLoginSignIn = Clock.UtcNow, - LastOneLoginSignIn = Clock.UtcNow, - PersonId = personId + Subject = subject.ValueOr(CreateOneLoginUserSubject()) }; + if (hasSignedInBefore) + { + user.Email = email.ValueOr(Faker.Internet.Email()); + user.FirstOneLoginSignIn = Clock.UtcNow; + user.LastOneLoginSignIn = Clock.UtcNow; + } + if (verifiedInfo is not null) { - user.VerifiedOn = Clock.UtcNow; - user.VerificationRoute = OneLoginUserVerificationRoute.OneLogin; - user.VerifiedNames = [verifiedInfo!.Value.Name]; - user.VerifiedDatesOfBirth = [verifiedInfo!.Value.DateOfBirth]; + user.SetVerified( + Clock.UtcNow, + OneLoginUserVerificationRoute.OneLogin, + verifiedByApplicationUserId: null, + [verifiedInfo!.Value.Name], + [verifiedInfo!.Value.DateOfBirth]); + } + + if (personId is not null) + { + user.SetMatched(personId.Value, OneLoginUserMatchRoute.Automatic, matchedAttributes: null); + + if (hasSignedInBefore) + { + user.FirstSignIn = Clock.UtcNow; + user.LastSignIn = Clock.UtcNow; + } } dbContext.OneLoginUsers.Add(user);