feat: Phase 0 foundation — Job entity, expanded pipeline, AI service lockdown, DateApplied history
Unblocks the documented core workflow and closes the AI-service exposure, without changing existing behaviour. Job/JobApplication split (additive; see ADR-002): - New Job entity (the opportunity) with owner-scoped query filter; nullable JobApplication.JobId FK. Nothing reads Job yet. - Migration AddJobEntityAndProspectStages, hand-edited to drop reconciler-owned tables the scaffolder re-emitted; verified against the real dev DB. Pipeline: 10 internal stages across three concerns kept separate — PipelineStage (workflow) / PipelineGroup (UI: NotApplied/Active/Closed) / PipelineCategory (analytics). Adds Saved/Interested/Preparing/Withdrawn; keeps Waiting and Ghosted. Kanban shows 3 grouped columns; cards keep a stage chip and full transitions; drag applies only safe transitions (never infers Ghosted/Withdrawn). DateApplied nullable + SavedAt. Cleared when leaving Applied so analytics stay accurate; the discarded date is preserved as an AppliedDateCleared JobEvent. AI service lockdown: no host port; private ai_internal network (backend is the only other member); X-Ai-Service-Token required on all non-/health endpoints; AI_SERVICE_TOKEN mandatory via compose. Verified backend-only against the live stack. Also carries two pre-existing working-tree files (views/ProfilePage.tsx, views/CareerWorkspacePage.tsx) so the tree is clean for the branch integration. Tests: +40 backend (247 total), +5 sidecar (16), +15 frontend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+1387
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace JobTrackerApi.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Phase 0 foundation change (2026-07-17):
|
||||
/// - adds the Job entity (the opportunity), additively; nothing reads it yet,
|
||||
/// - adds JobApplication.JobId (nullable FK) so the split can be completed later,
|
||||
/// - adds JobApplication.SavedAt (when the user captured the job),
|
||||
/// - makes JobApplication.DateApplied nullable so a job can be tracked before it is
|
||||
/// applied to (see the Prospect stages in JobPipeline).
|
||||
///
|
||||
/// HAND-EDITED after scaffolding. `dotnet ef migrations add` also emitted CreateTable for
|
||||
/// TrustedDevices / TwoFactorRecoveryCodes / UserSessions and AddColumn for the AspNetUsers
|
||||
/// Microsoft*/Totp* columns. Those were removed: they already exist in every real database,
|
||||
/// having been provisioned by the idempotent reconciler in StartupInitializationExtensions
|
||||
/// rather than by a migration, so the prior ModelSnapshot did not know about them and the
|
||||
/// scaffolder diffed them as missing. Re-creating them would fail with "table already
|
||||
/// exists" on any existing database. The reconciler still creates them on a fresh boot
|
||||
/// (CREATE TABLE IF NOT EXISTS), which is how this repo has always provisioned them.
|
||||
///
|
||||
/// IX_JobApplications_OwnerUserId_IsDeleted_Status was dropped from this migration for the
|
||||
/// same reason: the reconciler applies it, and on MySQL it needs a Status(50) prefix length
|
||||
/// that this scaffolded DDL does not carry (see JobTrackerContext.OnModelCreating).
|
||||
///
|
||||
/// See docs/decisions/ADR-002-job-application-model.md.
|
||||
/// </summary>
|
||||
public partial class AddJobEntityAndProspectStages : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// A job in a pre-application stage (Saved/Interested/Preparing) has no applied date.
|
||||
// On SQLite this is a table rebuild; EF carries over every column it knows about, and
|
||||
// all reconciler-added JobApplications columns are present in the model.
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DateApplied",
|
||||
table: "JobApplications",
|
||||
type: "TEXT",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "JobId",
|
||||
table: "JobApplications",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "SavedAt",
|
||||
table: "JobApplications",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
// Backfill: every pre-existing row is an applied job, so the best available estimate
|
||||
// of when it was captured is when it was applied. Without this each historic row keeps
|
||||
// the scaffolded 0001-01-01 sentinel, which would show as a bogus saved date and skew
|
||||
// the stage-entry maths that falls back to SavedAt.
|
||||
migrationBuilder.Sql("UPDATE JobApplications SET SavedAt = DateApplied WHERE DateApplied IS NOT NULL;");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Jobs",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
OwnerUserId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
CompanyId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
JobTitle = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Location = table.Column<string>(type: "TEXT", nullable: true),
|
||||
JobUrl = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: true),
|
||||
TranslatedDescription = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DescriptionLanguage = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ShortSummary = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Tags = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Deadline = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
Salary = table.Column<string>(type: "TEXT", nullable: true),
|
||||
SalaryMin = table.Column<decimal>(type: "TEXT", nullable: true),
|
||||
SalaryMax = table.Column<decimal>(type: "TEXT", nullable: true),
|
||||
SalaryCurrency = table.Column<string>(type: "TEXT", nullable: true),
|
||||
SalaryPeriod = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Source = table.Column<string>(type: "TEXT", nullable: true),
|
||||
CountryCode = table.Column<string>(type: "TEXT", nullable: true),
|
||||
SavedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Jobs", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Jobs_Companies_CompanyId",
|
||||
column: x => x.CompanyId,
|
||||
principalTable: "Companies",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_JobApplications_JobId",
|
||||
table: "JobApplications",
|
||||
column: "JobId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Jobs_CompanyId",
|
||||
table: "Jobs",
|
||||
column: "CompanyId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Jobs_OwnerUserId",
|
||||
table: "Jobs",
|
||||
column: "OwnerUserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_JobApplications_Jobs_JobId",
|
||||
table: "JobApplications",
|
||||
column: "JobId",
|
||||
principalTable: "Jobs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_JobApplications_Jobs_JobId",
|
||||
table: "JobApplications");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Jobs");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_JobApplications_JobId",
|
||||
table: "JobApplications");
|
||||
|
||||
// Reverting DateApplied to NOT NULL requires every row to have one. Rows sitting in a
|
||||
// pre-application stage legitimately do not, so fall back to SavedAt before the ALTER
|
||||
// rather than letting it fail. Runs before SavedAt is dropped. This direction is lossy
|
||||
// by nature (an unapplied job gains an applied date) and exists for local rollback.
|
||||
migrationBuilder.Sql("UPDATE JobApplications SET DateApplied = SavedAt WHERE DateApplied IS NULL;");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "DateApplied",
|
||||
table: "JobApplications",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SavedAt",
|
||||
table: "JobApplications");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,15 @@ namespace JobTrackerApi.Migrations
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("MicrosoftEmail")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("MicrosoftLinkedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("MicrosoftSubject")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
@@ -98,6 +107,15 @@ namespace JobTrackerApi.Migrations
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("TotpEnabledAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpPendingSecretEncrypted")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpSecretEncrypted")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -154,7 +172,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("JobApplicationId");
|
||||
|
||||
b.ToTable("Attachments", (string)null);
|
||||
b.ToTable("Attachments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.Company", b =>
|
||||
@@ -198,7 +216,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("Companies", (string)null);
|
||||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.Correspondence", b =>
|
||||
@@ -255,7 +273,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("JobApplicationId");
|
||||
|
||||
b.ToTable("Correspondences", (string)null);
|
||||
b.ToTable("Correspondences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.CvExtractionRun", b =>
|
||||
@@ -318,7 +336,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("OwnerUserId", "StartedAtUtc");
|
||||
|
||||
b.ToTable("CvExtractionRuns", (string)null);
|
||||
b.ToTable("CvExtractionRuns");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.CvUploadArtifact", b =>
|
||||
@@ -361,7 +379,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("OwnerUserId", "UploadedAtUtc");
|
||||
|
||||
b.ToTable("CvUploadArtifacts", (string)null);
|
||||
b.ToTable("CvUploadArtifacts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.GmailConnection", b =>
|
||||
@@ -423,7 +441,7 @@ namespace JobTrackerApi.Migrations
|
||||
b.HasIndex("OwnerUserId", "GmailAddress")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GmailConnections", (string)null);
|
||||
b.ToTable("GmailConnections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.GmailReviewDecision", b =>
|
||||
@@ -455,7 +473,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GmailReviewDecisions", (string)null);
|
||||
b.ToTable("GmailReviewDecisions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.ImapConnection", b =>
|
||||
@@ -512,7 +530,80 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ImapConnections", (string)null);
|
||||
b.ToTable("ImapConnections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.Job", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CompanyId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CountryCode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Deadline")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DescriptionLanguage")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("JobTitle")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("JobUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Location")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OwnerUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
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<DateTime>("SavedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ShortSummary")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TranslatedDescription")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CompanyId");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.ToTable("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
|
||||
@@ -527,7 +618,7 @@ namespace JobTrackerApi.Migrations
|
||||
b.Property<string>("CoverLetterText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("DateApplied")
|
||||
b.Property<DateTime?>("DateApplied")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Deadline")
|
||||
@@ -563,6 +654,9 @@ namespace JobTrackerApi.Migrations
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("JobId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("JobTitle")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@@ -609,6 +703,9 @@ namespace JobTrackerApi.Migrations
|
||||
b.Property<string>("SalaryPeriod")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("SavedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ShortSummary")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
@@ -632,13 +729,17 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("CompanyId");
|
||||
|
||||
b.HasIndex("JobId");
|
||||
|
||||
b.HasIndex("OwnerUserId");
|
||||
|
||||
b.HasIndex("OwnerUserId", "FollowUpAt");
|
||||
|
||||
b.HasIndex("OwnerUserId", "IsDeleted");
|
||||
|
||||
b.ToTable("JobApplications", (string)null);
|
||||
b.HasIndex("OwnerUserId", "IsDeleted", "Status");
|
||||
|
||||
b.ToTable("JobApplications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.JobEvent", b =>
|
||||
@@ -670,7 +771,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasIndex("JobApplicationId");
|
||||
|
||||
b.ToTable("JobEvents", (string)null);
|
||||
b.ToTable("JobEvents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.MicrosoftGraphConnection", b =>
|
||||
@@ -727,7 +828,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MicrosoftGraphConnections", (string)null);
|
||||
b.ToTable("MicrosoftGraphConnections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.RuleSettings", b =>
|
||||
@@ -756,7 +857,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RuleSettings", (string)null);
|
||||
b.ToTable("RuleSettings");
|
||||
|
||||
b.HasData(
|
||||
new
|
||||
@@ -806,7 +907,7 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SystemEmailSettings", (string)null);
|
||||
b.ToTable("SystemEmailSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.TailoredCvDraft", b =>
|
||||
@@ -871,7 +972,69 @@ namespace JobTrackerApi.Migrations
|
||||
b.HasIndex("OwnerUserId", "JobApplicationId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("TailoredCvDrafts", (string)null);
|
||||
b.ToTable("TailoredCvDrafts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.TrustedDevice", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceLabel")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LastSeenAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TokenHash");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("TrustedDevices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.TwoFactorRecoveryCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CodeHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("UsedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "UsedAtUtc");
|
||||
|
||||
b.ToTable("TwoFactorRecoveryCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.UserRuleSettings", b =>
|
||||
@@ -899,7 +1062,38 @@ namespace JobTrackerApi.Migrations
|
||||
|
||||
b.HasKey("OwnerUserId");
|
||||
|
||||
b.ToTable("UserRuleSettings", (string)null);
|
||||
b.ToTable("UserRuleSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.UserSession", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceLabel")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LastSeenAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("RevokedAtUtc")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserSessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
@@ -1062,6 +1256,17 @@ namespace JobTrackerApi.Migrations
|
||||
b.Navigation("Artifact");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.Job", b =>
|
||||
{
|
||||
b.HasOne("JobTrackerApi.Models.Company", "Company")
|
||||
.WithMany()
|
||||
.HasForeignKey("CompanyId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Company");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
|
||||
{
|
||||
b.HasOne("JobTrackerApi.Models.Company", "Company")
|
||||
@@ -1070,7 +1275,14 @@ namespace JobTrackerApi.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("JobTrackerApi.Models.Job", "Job")
|
||||
.WithMany("Applications")
|
||||
.HasForeignKey("JobId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Company");
|
||||
|
||||
b.Navigation("Job");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.JobEvent", b =>
|
||||
@@ -1151,6 +1363,11 @@ namespace JobTrackerApi.Migrations
|
||||
b.Navigation("Jobs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.Job", b =>
|
||||
{
|
||||
b.Navigation("Applications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("JobTrackerApi.Models.JobApplication", b =>
|
||||
{
|
||||
b.Navigation("Attachments");
|
||||
|
||||
Reference in New Issue
Block a user