diff --git a/.github/workflows/dbml.yml b/.github/workflows/dbml.yml
index 49974d5e8a..737eae8b03 100644
--- a/.github/workflows/dbml.yml
+++ b/.github/workflows/dbml.yml
@@ -22,12 +22,21 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
+ volumes:
+ - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
+ - name: Create postgres configuration
+ run: |
+ echo '#!/bin/bash' > init-db.sh
+ echo 'echo "ALTER SYSTEM SET wal_level = '\''logical'\'';" > /docker-entrypoint-initdb.d/001-wal_level.sql' >> init-db.sh
+ echo 'pg_ctl -D "$PGDATA" restart' >> init-db.sh
+ chmod +x init-db.sh
+
- uses: extractions/setup-just@v2
- name: Install postgresql-client
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 00b2aa655d..765b3e9d9b 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -20,11 +20,12 @@ jobs:
services:
postgres:
- image: postgres
+ image: postgres:15
env:
POSTGRES_PASSWORD: trs
POSTGRES_DB: trs
options: >-
+ --name postgres
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
@@ -37,6 +38,14 @@ jobs:
with:
submodules: recursive
+ - name: Set postgres wal_level to logical
+ run: |
+ docker exec -i postgres bash << EOF
+ echo "wal_level = logical" >> /var/lib/postgresql/data/postgresql.conf
+ EOF
+
+ docker restart --time 0 postgres
+
- uses: extractions/setup-just@v2
- name: Install tools
@@ -192,7 +201,7 @@ jobs:
services:
postgres:
- image: postgres
+ image: postgres:15
env:
POSTGRES_PASSWORD: trs
POSTGRES_DB: trs
@@ -201,6 +210,8 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
+ volumes:
+ - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
ports:
- 5432:5432
mssql:
@@ -220,6 +231,13 @@ jobs:
steps:
- uses: actions/checkout@v4
+ - name: Create postgres configuration
+ run: |
+ echo '#!/bin/bash' > init-db.sh
+ echo 'echo "ALTER SYSTEM SET wal_level = '\''logical'\'';" > /docker-entrypoint-initdb.d/001-wal_level.sql' >> init-db.sh
+ echo 'pg_ctl -D "$PGDATA" restart' >> init-db.sh
+ chmod +x init-db.sh
+
- uses: extractions/setup-just@v2
- uses: Azure/login@v2
diff --git a/README.md b/README.md
index 8e1dec2bcb..bb81059784 100644
--- a/README.md
+++ b/README.md
@@ -87,6 +87,12 @@ just install-tools
Install Postgres then set a connection string configuration entry in user secrets for running the apps and another for running the tests.
Note you should use a different database for tests as the test database will be cleared down whenever tests are run.
+The server's `wal_level` must be set to `logical`:
+```
+ALTER SYSTEM SET wal_level = logical;
+```
+You may have to restart the server after amending this configuration.
+
e.g.
```shell
just set-secret ConnectionStrings:DefaultConnection "Host=localhost;Username=postgres;Password=your_postgres_password;Database=trs"
diff --git a/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20240723161331_DqtReportingSyncPublication.Designer.cs b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20240723161331_DqtReportingSyncPublication.Designer.cs
new file mode 100644
index 0000000000..a621274949
--- /dev/null
+++ b/TeachingRecordSystem/src/TeachingRecordSystem.Core/DataStore/Postgres/Migrations/20240723161331_DqtReportingSyncPublication.Designer.cs
@@ -0,0 +1,2248 @@
+//
+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("20240723161331_DqtReportingSyncPublication")]
+ partial class DqtReportingSyncPublication
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.7")
+ .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.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.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("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.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("PersonId", "EventName")
+ .HasDatabaseName("ix_events_person_id_event_name")
+ .HasFilter("person_id is not null");
+
+ NpgsqlIndexBuilderExtensions.IncludeProperties(b.HasIndex("PersonId", "EventName"), new[] { "Payload" });
+
+ 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.PersonEmployment", b =>
+ {
+ b.Property("PersonEmploymentId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasColumnName("person_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("LastKnownEmployedDate")
+ .HasColumnType("date")
+ .HasColumnName("last_known_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.HasKey("PersonEmploymentId")
+ .HasName("pk_person_employments");
+
+ b.HasIndex("EstablishmentId")
+ .HasDatabaseName("ix_person_employments_establishment_id");
+
+ b.HasIndex("Key")
+ .HasDatabaseName("ix_person_employments_key");
+
+ b.HasIndex("PersonId")
+ .HasDatabaseName("ix_person_employments_person_id");
+
+ b.ToTable("person_employments", (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.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("WithdrawlIndicator")
+ .HasMaxLength(1)
+ .HasColumnType("character(1)")
+ .HasColumnName("withdrawl_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