Files
jobtrackingapp/JobTrackerApi/Migrations/JobTrackerContextModelSnapshot.cs
cesnimda a9a0ddecbc
CI and Deploy / test (pull_request) Successful in 2m1s
CI and Deploy / deploy (pull_request) Has been skipped
chore(db): resync stale EF ModelSnapshot + fix fresh-DB schema gap
Backlog item 1. The committed ModelSnapshot was empty/stale (21 lines, no
entities) -- `dotnet ef migrations add` scaffolded the whole database from
scratch against it, including the ASP.NET Identity tables, which have never
been created by a real EF migration in this repo (always provisioned via the
raw-SQL reconciler in StartupInitializationExtensions.cs -- see
EnsureIdentityTables' own comment). Applying that diff for real would throw
"table/column already exists" on every environment.

Fix: added migration 20260711181039_SyncModelSnapshot with an intentionally
empty Up()/Down() (see its doc comment) -- it only records itself in
__EFMigrationsHistory and regenerates the snapshot to match the live model,
so `dotnet ef migrations add` produces a real diff for the next schema
change instead of the whole database again. Verified zero side effects
against a copy of the dev DB (only inserts one history row) and against a
fresh empty DB (full migration + reconciler chain runs clean).

That fresh-DB verification surfaced a real, previously-undiscovered bug:
EnsureColumn/EnsureMySqlColumn calls for JobApplications/Correspondences/
Companies/Attachments ad-hoc columns all no-op on a truly fresh database
(the tables don't exist yet -- Migrate() creates them afterward), so a
brand-new deployment's first boot would be missing dozens of columns
(LastReminderEmailSentAt, RecruiterMessageDraft, salary fields, Correspondence
Provider/Subject/Channel/etc.) until the next restart. Also caught: my own b4
change (Correspondence.Provider backfill, already merged) had the same
unguarded-on-fresh-DB bug in isolation.

Fixed by promoting the schema-reconciliation helpers (Exec/HasTable/
HasColumn/EnsureColumn and their MySQL equivalents) from local functions to
class-level statics, extracting the ad-hoc-column blocks into
ReconcileCoreAppColumns/ReconcileCoreAppColumnsMySql, and calling them a
second time right after Migrate() succeeds (reusing the connection already
opened for the CoreSchemaReady check) -- idempotent, so free on every boot
except the first one, where it's now required. No inline logic changed,
pure extraction + one additional call site.

Also added Microsoft.EntityFrameworkCore.Design to JobTrackerApi.csproj
(dotnet-ef tooling requires it on the startup project since EF Core 6+;
previously only referenced by JobTrackerBackend, where the DbContext lives).

169/169 backend tests green. Verified live: full app boot against both a
fresh empty SQLite DB and a copy of the populated dev DB, both clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:32:07 +02:00

1168 lines
40 KiB
C#

// <auto-generated />
using System;
using JobTrackerApi.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace JobTrackerApi.Migrations
{
[DbContext(typeof(JobTrackerContext))]
partial class JobTrackerContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.14");
modelBuilder.Entity("JobTrackerApi.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<int>("AccessFailedCount")
.HasColumnType("INTEGER");
b.Property<string>("AvatarImageDataUrl")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("TEXT");
b.Property<int?>("CurrentCvExtractionRunId")
.HasColumnType("INTEGER");
b.Property<int?>("CurrentCvProfileVersion")
.HasColumnType("INTEGER");
b.Property<int?>("CurrentCvUploadArtifactId")
.HasColumnType("INTEGER");
b.Property<string>("DisplayName")
.HasColumnType("TEXT");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<bool>("EmailConfirmed")
.HasColumnType("INTEGER");
b.Property<string>("FirstName")
.HasColumnType("TEXT");
b.Property<string>("GoogleEmail")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("GoogleLinkedAt")
.HasColumnType("TEXT");
b.Property<string>("GoogleSubject")
.HasColumnType("TEXT");
b.Property<string>("LastName")
.HasColumnType("TEXT");
b.Property<bool>("LockoutEnabled")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("TEXT");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<string>("PasswordHash")
.HasColumnType("TEXT");
b.Property<string>("PhoneNumber")
.HasColumnType("TEXT");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("INTEGER");
b.Property<string>("ProfileCvStructureJson")
.HasColumnType("TEXT");
b.Property<string>("ProfileCvText")
.HasColumnType("TEXT");
b.Property<string>("SecurityStamp")
.HasColumnType("TEXT");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("INTEGER");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.Attachment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("FileName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FilePath")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("FileSize")
.HasColumnType("INTEGER");
b.Property<string>("FileType")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("JobApplicationId")
.HasColumnType("INTEGER");
b.Property<string>("Purpose")
.HasColumnType("TEXT");
b.Property<DateTime>("UploadDate")
.HasColumnType("TEXT");
b.Property<bool>("UseForAi")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("JobApplicationId");
b.ToTable("Attachments", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.Company", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime?>("LastContactedAt")
.HasColumnType("TEXT");
b.Property<string>("Location")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime?>("NextContactAt")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.HasColumnType("TEXT");
b.Property<string>("PipelineStage")
.HasColumnType("TEXT");
b.Property<string>("RecruiterEmail")
.HasColumnType("TEXT");
b.Property<string>("RecruiterLinkedIn")
.HasColumnType("TEXT");
b.Property<string>("RecruiterName")
.HasColumnType("TEXT");
b.Property<string>("Source")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("OwnerUserId");
b.ToTable("Companies", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.Correspondence", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AttachmentMetadataJson")
.HasColumnType("TEXT");
b.Property<string>("Channel")
.HasColumnType("TEXT");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("Date")
.HasColumnType("TEXT");
b.Property<string>("Direction")
.HasColumnType("TEXT");
b.Property<string>("ExternalFrom")
.HasColumnType("TEXT");
b.Property<string>("ExternalLabelsJson")
.HasColumnType("TEXT");
b.Property<string>("ExternalMessageId")
.HasColumnType("TEXT");
b.Property<string>("ExternalThreadId")
.HasColumnType("TEXT");
b.Property<string>("ExternalTo")
.HasColumnType("TEXT");
b.Property<string>("From")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("JobApplicationId")
.HasColumnType("INTEGER");
b.Property<string>("Provider")
.HasColumnType("TEXT");
b.Property<string>("Subject")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("JobApplicationId");
b.ToTable("Correspondences", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.CvExtractionRun", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("AppliedAtUtc")
.HasColumnType("TEXT");
b.Property<int?>("ArtifactId")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("CompletedAtUtc")
.HasColumnType("TEXT");
b.Property<string>("ErrorMessage")
.HasColumnType("TEXT");
b.Property<string>("LlmPromptVersion")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("NormalizedText")
.HasColumnType("TEXT");
b.Property<string>("NormalizerVersion")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ParserVersion")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("RawExtractedText")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("StartedAtUtc")
.HasColumnType("TEXT");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("StructuredProfileJson")
.HasColumnType("TEXT");
b.Property<string>("Trigger")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ArtifactId");
b.HasIndex("OwnerUserId", "StartedAtUtc");
b.ToTable("CvExtractionRuns", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.CvUploadArtifact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<long>("ByteSize")
.HasColumnType("INTEGER");
b.Property<string>("MimeType")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("OriginalFileName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Sha256")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("StoragePath")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("StoredFileName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("UploadedAtUtc")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("OwnerUserId", "UploadedAtUtc");
b.ToTable("CvUploadArtifacts", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.GmailConnection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("AccessTokenExpiresAt")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("ConnectedAt")
.HasColumnType("TEXT");
b.Property<string>("EncryptedAccessToken")
.HasColumnType("TEXT");
b.Property<string>("EncryptedRefreshToken")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("GmailAddress")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncAttemptedAt")
.HasColumnType("TEXT");
b.Property<string>("LastSyncError")
.HasColumnType("TEXT");
b.Property<string>("LastSyncMode")
.HasColumnType("TEXT");
b.Property<string>("LastSyncSource")
.HasColumnType("TEXT");
b.Property<string>("LastSyncStatus")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncSucceededAt")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncedAt")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Scope")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("OwnerUserId");
b.HasIndex("OwnerUserId", "GmailAddress")
.IsUnique();
b.ToTable("GmailConnections", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.GmailReviewDecision", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Decision")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("JobApplicationId")
.HasColumnType("INTEGER");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ThreadId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("GmailReviewDecisions", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.ImapConnection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("ConnectedAt")
.HasColumnType("TEXT");
b.Property<string>("EncryptedPassword")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Host")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncAttemptedAt")
.HasColumnType("TEXT");
b.Property<string>("LastSyncError")
.HasColumnType("TEXT");
b.Property<string>("LastSyncMode")
.HasColumnType("TEXT");
b.Property<string>("LastSyncSource")
.HasColumnType("TEXT");
b.Property<string>("LastSyncStatus")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncSucceededAt")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncedAt")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Port")
.HasColumnType("INTEGER");
b.Property<bool>("UseSsl")
.HasColumnType("INTEGER");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("ImapConnections", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CompanyId")
.HasColumnType("INTEGER");
b.Property<string>("CoverLetterText")
.HasColumnType("TEXT");
b.Property<DateTime>("DateApplied")
.HasColumnType("TEXT");
b.Property<DateTime?>("Deadline")
.HasColumnType("TEXT");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("DescriptionLanguage")
.HasColumnType("TEXT");
b.Property<DateTime?>("FeedbackRequestedAt")
.HasColumnType("TEXT");
b.Property<DateTime?>("FollowUpAt")
.HasColumnType("TEXT");
b.Property<bool>("HasCoverLetter")
.HasColumnType("INTEGER");
b.Property<bool>("HasOtherAttachment")
.HasColumnType("INTEGER");
b.Property<bool>("HasPortfolio")
.HasColumnType("INTEGER");
b.Property<bool>("HasResume")
.HasColumnType("INTEGER");
b.Property<bool>("IsDeleted")
.HasColumnType("INTEGER");
b.Property<string>("JobTitle")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("JobUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("LastReminderEmailSentAt")
.HasColumnType("TEXT");
b.Property<string>("Location")
.HasColumnType("TEXT");
b.Property<string>("NextAction")
.HasColumnType("TEXT");
b.Property<string>("Notes")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.HasColumnType("TEXT");
b.Property<string>("RecruiterMessageDraft")
.HasColumnType("TEXT");
b.Property<DateTime?>("ResponseDate")
.HasColumnType("TEXT");
b.Property<bool>("ResponseReceived")
.HasColumnType("INTEGER");
b.Property<string>("Salary")
.HasColumnType("TEXT");
b.Property<string>("SalaryCurrency")
.HasColumnType("TEXT");
b.Property<decimal?>("SalaryMax")
.HasColumnType("TEXT");
b.Property<decimal?>("SalaryMin")
.HasColumnType("TEXT");
b.Property<string>("SalaryPeriod")
.HasColumnType("TEXT");
b.Property<string>("ShortSummary")
.HasColumnType("TEXT");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Tags")
.HasColumnType("TEXT");
b.Property<string>("TailoredCvText")
.HasColumnType("TEXT");
b.Property<DateTime?>("TailoredCvUpdatedAt")
.HasColumnType("TEXT");
b.Property<string>("TranslatedDescription")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.HasIndex("OwnerUserId");
b.HasIndex("OwnerUserId", "FollowUpAt");
b.HasIndex("OwnerUserId", "IsDeleted");
b.ToTable("JobApplications", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.JobEvent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("At")
.HasColumnType("TEXT");
b.Property<int>("JobApplicationId")
.HasColumnType("INTEGER");
b.Property<string>("NewValue")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("OldValue")
.HasColumnType("TEXT");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("JobApplicationId");
b.ToTable("JobEvents", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.MicrosoftGraphConnection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("AccessTokenExpiresAt")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("ConnectedAt")
.HasColumnType("TEXT");
b.Property<string>("EncryptedAccessToken")
.HasColumnType("TEXT");
b.Property<string>("EncryptedRefreshToken")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncAttemptedAt")
.HasColumnType("TEXT");
b.Property<string>("LastSyncError")
.HasColumnType("TEXT");
b.Property<string>("LastSyncMode")
.HasColumnType("TEXT");
b.Property<string>("LastSyncSource")
.HasColumnType("TEXT");
b.Property<string>("LastSyncStatus")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncSucceededAt")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastSyncedAt")
.HasColumnType("TEXT");
b.Property<string>("MailAddress")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Scope")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("MicrosoftGraphConnections", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.RuleSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AppliedFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("AppliedGhostDays")
.HasColumnType("INTEGER");
b.Property<int>("FeedbackFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("FeedbackGhostDays")
.HasColumnType("INTEGER");
b.Property<int>("OfferFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("OfferGhostDays")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("RuleSettings", (string)null);
b.HasData(
new
{
Id = 1,
AppliedFollowUpDays = 14,
AppliedGhostDays = 30,
FeedbackFollowUpDays = 7,
FeedbackGhostDays = 14,
OfferFollowUpDays = 7,
OfferGhostDays = 14
});
});
modelBuilder.Entity("JobTrackerApi.Models.SystemEmailSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<bool?>("Enabled")
.HasColumnType("INTEGER");
b.Property<string>("From")
.HasColumnType("TEXT");
b.Property<string>("FromName")
.HasColumnType("TEXT");
b.Property<bool?>("SmtpEnableSsl")
.HasColumnType("INTEGER");
b.Property<string>("SmtpHost")
.HasColumnType("TEXT");
b.Property<string>("SmtpPassword")
.HasColumnType("TEXT");
b.Property<int?>("SmtpPort")
.HasColumnType("INTEGER");
b.Property<int?>("SmtpTimeoutMs")
.HasColumnType("INTEGER");
b.Property<string>("SmtpUser")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("SystemEmailSettings", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.TailoredCvDraft", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("CanonicalProfileVersion")
.HasColumnType("INTEGER");
b.Property<string>("CustomSectionsJson")
.HasColumnType("TEXT");
b.Property<string>("EducationJson")
.HasColumnType("TEXT");
b.Property<string>("ExperienceJson")
.HasColumnType("TEXT");
b.Property<string>("GenerationContextHash")
.HasColumnType("TEXT");
b.Property<string>("Headline")
.HasColumnType("TEXT");
b.Property<int>("JobApplicationId")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("LastEditedAtUtc")
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("LastGeneratedAtUtc")
.HasColumnType("TEXT");
b.Property<string>("OwnerUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("RenderOptionsJson")
.HasColumnType("TEXT");
b.Property<string>("SelectedSkillsJson")
.HasColumnType("TEXT");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("SummaryJson")
.HasColumnType("TEXT");
b.Property<string>("TemplateId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("JobApplicationId")
.IsUnique();
b.HasIndex("OwnerUserId", "JobApplicationId")
.IsUnique();
b.ToTable("TailoredCvDrafts", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.UserRuleSettings", b =>
{
b.Property<string>("OwnerUserId")
.HasColumnType("TEXT");
b.Property<int>("AppliedFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("AppliedGhostDays")
.HasColumnType("INTEGER");
b.Property<int>("FeedbackFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("FeedbackGhostDays")
.HasColumnType("INTEGER");
b.Property<int>("OfferFollowUpDays")
.HasColumnType("INTEGER");
b.Property<int>("OfferGhostDays")
.HasColumnType("INTEGER");
b.HasKey("OwnerUserId");
b.ToTable("UserRuleSettings", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ClaimType")
.HasColumnType("TEXT");
b.Property<string>("ClaimValue")
.HasColumnType("TEXT");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ClaimType")
.HasColumnType("TEXT");
b.Property<string>("ClaimValue")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("TEXT");
b.Property<string>("ProviderKey")
.HasColumnType("TEXT");
b.Property<string>("ProviderDisplayName")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.Property<string>("RoleId")
.HasColumnType("TEXT");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.Property<string>("LoginProvider")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("JobTrackerApi.Models.Attachment", b =>
{
b.HasOne("JobTrackerApi.Models.JobApplication", "JobApplication")
.WithMany("Attachments")
.HasForeignKey("JobApplicationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("JobApplication");
});
modelBuilder.Entity("JobTrackerApi.Models.Correspondence", b =>
{
b.HasOne("JobTrackerApi.Models.JobApplication", "JobApplication")
.WithMany("Messages")
.HasForeignKey("JobApplicationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("JobApplication");
});
modelBuilder.Entity("JobTrackerApi.Models.CvExtractionRun", b =>
{
b.HasOne("JobTrackerApi.Models.CvUploadArtifact", "Artifact")
.WithMany()
.HasForeignKey("ArtifactId")
.OnDelete(DeleteBehavior.SetNull);
b.Navigation("Artifact");
});
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
{
b.HasOne("JobTrackerApi.Models.Company", "Company")
.WithMany("Jobs")
.HasForeignKey("CompanyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
});
modelBuilder.Entity("JobTrackerApi.Models.JobEvent", b =>
{
b.HasOne("JobTrackerApi.Models.JobApplication", "JobApplication")
.WithMany("Events")
.HasForeignKey("JobApplicationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("JobApplication");
});
modelBuilder.Entity("JobTrackerApi.Models.TailoredCvDraft", b =>
{
b.HasOne("JobTrackerApi.Models.JobApplication", "JobApplication")
.WithOne("TailoredCvDraft")
.HasForeignKey("JobTrackerApi.Models.TailoredCvDraft", "JobApplicationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("JobApplication");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("JobTrackerApi.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("JobTrackerApi.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("JobTrackerApi.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("JobTrackerApi.Models.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("JobTrackerApi.Models.Company", b =>
{
b.Navigation("Jobs");
});
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
{
b.Navigation("Attachments");
b.Navigation("Events");
b.Navigation("Messages");
b.Navigation("TailoredCvDraft");
});
#pragma warning restore 612, 618
}
}
}