From 1dbff1910fd6ecb4110bd39ea7c40044a48f9011 Mon Sep 17 00:00:00 2001 From: Jerry Phillips Date: Thu, 23 Apr 2026 11:21:44 -0400 Subject: [PATCH] fix(api): [AB#42] seed changelog entries both databases Added EF Core migration to seed 6 initial ChangelogEntry records covering Support Hub launch, live chat improvements, billing page, employee CSV import, grid improvements, and this UI fix. Migration applied to both local and staging databases. Changes: [1] Created SeedChangelogEntries migration with 6 InsertData entries (2 Feature, 2 Improvement, 2 Fix) [2] Applied migration to local JobFlow database [3] Applied migration to staging JobFlow-Staging database on Azure References: [1] [JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs:1](https://github.com/Katharix/JobFlow.API/blob/bugfix/42-seed-changelog-entries/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs#L1) --- ...423151531_SeedChangelogEntries.Designer.cs | 6211 +++++++++++++++++ .../20260423151531_SeedChangelogEntries.cs | 111 + .../JobFlowDbContextModelSnapshot.cs | 2 +- 3 files changed, 6323 insertions(+), 1 deletion(-) create mode 100644 JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.Designer.cs create mode 100644 JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs diff --git a/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.Designer.cs b/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.Designer.cs new file mode 100644 index 0000000..6852ab5 --- /dev/null +++ b/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.Designer.cs @@ -0,0 +1,6211 @@ +// +using System; +using JobFlow.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace JobFlow.Infrastructure.Persistence.Migrations +{ + [DbContext(typeof(JobFlowDbContext))] + [Migration("20260423151531_SeedChangelogEntries")] + partial class SeedChangelogEntries + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("JobFlow.Domain.Models.Assignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ActualEnd") + .HasColumnType("datetimeoffset"); + + b.Property("ActualStart") + .HasColumnType("datetimeoffset"); + + b.Property("Address1") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobId") + .HasColumnType("uniqueidentifier"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("ScheduleType") + .HasColumnType("int"); + + b.Property("ScheduledEnd") + .HasColumnType("datetimeoffset"); + + b.Property("ScheduledStart") + .HasColumnType("datetimeoffset"); + + b.Property("State") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ZipCode") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("JobId"); + + b.HasIndex("ScheduledStart"); + + b.ToTable("Assignment", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentAssignee", b => + { + b.Property("AssignmentId") + .HasColumnType("uniqueidentifier"); + + b.Property("EmployeeId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("IsLead") + .HasColumnType("bit"); + + b.HasKey("AssignmentId", "EmployeeId"); + + b.HasIndex("EmployeeId") + .HasDatabaseName("IX_AssignmentAssignee_EmployeeId"); + + b.ToTable("AssignmentAssignee", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AssignmentId") + .HasColumnType("uniqueidentifier"); + + b.Property("ChangedAt") + .HasColumnType("datetime2"); + + b.Property("ChangedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EventType") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("NewScheduledEnd") + .HasColumnType("datetime2"); + + b.Property("NewScheduledStart") + .HasColumnType("datetime2"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("OldScheduledEnd") + .HasColumnType("datetime2"); + + b.Property("OldScheduledStart") + .HasColumnType("datetime2"); + + b.Property("Reason") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId") + .HasDatabaseName("IX_AssignmentHistory_AssignmentId"); + + b.ToTable("AssignmentHistory", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentOrder", b => + { + b.Property("AssignmentId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrderId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.HasKey("AssignmentId", "OrderId"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("OrderId"); + + b.ToTable("AssignmentOrder", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DetailsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Method") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Path") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ResourceId") + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("ResourceType") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("StatusCode") + .HasColumnType("int"); + + b.Property("Success") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("UserAgent") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("UserId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("OrganizationId", "CreatedAt"); + + b.HasIndex("UserId", "CreatedAt"); + + b.ToTable("AuditLog", "security"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ChangelogEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Category") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsPublished") + .HasColumnType("bit"); + + b.Property("PublishedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Version") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("IsPublished"); + + b.ToTable("ChangelogEntries"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CompletedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ErrorMessage") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("FailedRows") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProcessedRows") + .HasColumnType("int"); + + b.Property("SourceSystem") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("StartedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("SucceededRows") + .HasColumnType("int"); + + b.Property("TotalRows") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Status"); + + b.HasIndex("OrganizationId", "CreatedAt"); + + b.ToTable("ClientImportJob", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportJobError", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientImportJobId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("RowNumber") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientImportJobId"); + + b.HasIndex("RowNumber"); + + b.ToTable("ClientImportJobError", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportUploadRow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientImportUploadSessionId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("RowDataJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RowNumber") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientImportUploadSessionId", "RowNumber") + .IsUnique(); + + b.ToTable("ClientImportUploadRow", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportUploadSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConsumedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ExpiresAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceSystem") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("TotalRows") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "Status", "ExpiresAtUtc"); + + b.ToTable("ClientImportUploadSession", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Conversation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.ToTable("Conversation", "messaging"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ConversationParticipant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConversationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("ConversationId", "UserId") + .IsUnique(); + + b.ToTable("ConversationParticipant", "messaging"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.CustomerPaymentProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultPaymentMethodId") + .HasColumnType("nvarchar(max)"); + + b.Property("EncryptedAccessToken") + .HasColumnType("nvarchar(max)"); + + b.Property("EncryptedRefreshToken") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDelinquent") + .HasColumnType("bit"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("OwnerId") + .HasColumnType("uniqueidentifier"); + + b.Property("OwnerType") + .HasColumnType("int"); + + b.Property("Provider") + .HasColumnType("int"); + + b.Property("ProviderCustomerId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SquareLocationId") + .HasColumnType("nvarchar(max)"); + + b.Property("TokenExpiresAtUtc") + .HasColumnType("datetime2"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("CustomerPaymentProfile", "payment"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.DataExportJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CompletedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ContentType") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DownloadCount") + .HasColumnType("int"); + + b.Property("ErrorMessage") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("ExpiresAtUtc") + .HasColumnType("datetime2"); + + b.Property("FileContent") + .HasColumnType("varbinary(max)"); + + b.Property("FileName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RequestedByUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "CreatedAt"); + + b.HasIndex("OrganizationId", "Status"); + + b.ToTable("DataExportJob", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Employee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("HireDate") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobTitle") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("ProfilePictureUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TerminationDate") + .HasColumnType("datetime2"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("Employees", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CompletedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)"); + + b.Property("FailedRows") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProcessedRows") + .HasColumnType("int"); + + b.Property("SourceSystem") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SucceededRows") + .HasColumnType("int"); + + b.Property("TotalRows") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("EmployeeImportJobs"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportJobError", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EmployeeImportJobId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RowNumber") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeImportJobId"); + + b.ToTable("EmployeeImportJobErrors"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportUploadRow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EmployeeImportUploadSessionId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("RowDataJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RowNumber") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeImportUploadSessionId"); + + b.ToTable("EmployeeImportUploadRows"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportUploadSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConsumedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ExpiresAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceSystem") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TotalRows") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("EmployeeImportUploadSessions"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessCount") + .HasColumnType("int"); + + b.Property("AccessIpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("AccessedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("InviteToken") + .HasMaxLength(128) + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("ShortCode") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Status") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(1); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("InviteToken") + .IsUnique(); + + b.HasIndex("OrganizationId"); + + b.HasIndex("RoleId"); + + b.HasIndex("ShortCode") + .IsUnique() + .HasFilter("[ShortCode] IS NOT NULL"); + + b.HasIndex("OrganizationId", "Email") + .IsUnique() + .HasFilter("[Status] = 1"); + + b.HasIndex("Status", "ExpiresAt"); + + b.ToTable("EmployeeInvites", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasMaxLength(240) + .HasColumnType("nvarchar(240)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("EmployeeRoles", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRolePreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(240) + .HasColumnType("nvarchar(240)"); + + b.Property("IndustryKey") + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsSystem") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("EmployeeRolePresets", (string)null); + + b.HasData( + new + { + Id = new Guid("1a2b3c4d-1111-1111-1111-111111111111"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Default roles for field service teams.", + IndustryKey = "home-services", + IsActive = true, + IsSystem = true, + Name = "Home services" + }, + new + { + Id = new Guid("1a2b3c4d-2222-2222-2222-222222222222"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Default roles for creative studios.", + IndustryKey = "creative", + IsActive = true, + IsSystem = true, + Name = "Creative" + }, + new + { + Id = new Guid("1a2b3c4d-3333-3333-3333-333333333333"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Default roles for consulting teams.", + IndustryKey = "consulting", + IsActive = true, + IsSystem = true, + Name = "Consulting" + }, + new + { + Id = new Guid("1a2b3c4d-4444-4444-4444-444444444444"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Default roles for repair shops.", + IndustryKey = "tech-repair", + IsActive = true, + IsSystem = true, + Name = "Tech repair" + }); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRolePresetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(240) + .HasColumnType("nvarchar(240)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("PresetId") + .HasColumnType("uniqueidentifier"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("PresetId"); + + b.ToTable("EmployeeRolePresetItems", (string)null); + + b.HasData( + new + { + Id = new Guid("2a2b3c4d-1111-1111-1111-111111111111"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Field technician for on-site work.", + IsActive = true, + Name = "Technician", + PresetId = new Guid("1a2b3c4d-1111-1111-1111-111111111111"), + SortOrder = 1 + }, + new + { + Id = new Guid("2a2b3c4d-1111-1111-1111-111111111112"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Lead for quality checks and approvals.", + IsActive = true, + Name = "Supervisor", + PresetId = new Guid("1a2b3c4d-1111-1111-1111-111111111111"), + SortOrder = 2 + }, + new + { + Id = new Guid("2a2b3c4d-1111-1111-1111-111111111113"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Routes schedules and job assignments.", + IsActive = true, + Name = "Dispatcher", + PresetId = new Guid("1a2b3c4d-1111-1111-1111-111111111111"), + SortOrder = 3 + }, + new + { + Id = new Guid("2a2b3c4d-1111-1111-1111-111111111114"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Back-office support and billing.", + IsActive = true, + Name = "Admin", + PresetId = new Guid("1a2b3c4d-1111-1111-1111-111111111111"), + SortOrder = 4 + }, + new + { + Id = new Guid("2a2b3c4d-2222-2222-2222-222222222221"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Primary creator and deliverable owner.", + IsActive = true, + Name = "Designer", + PresetId = new Guid("1a2b3c4d-2222-2222-2222-222222222222"), + SortOrder = 1 + }, + new + { + Id = new Guid("2a2b3c4d-2222-2222-2222-222222222222"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Owns timelines, approvals, and client comms.", + IsActive = true, + Name = "Producer", + PresetId = new Guid("1a2b3c4d-2222-2222-2222-222222222222"), + SortOrder = 2 + }, + new + { + Id = new Guid("2a2b3c4d-2222-2222-2222-222222222223"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Schedules tasks and supports delivery.", + IsActive = true, + Name = "Coordinator", + PresetId = new Guid("1a2b3c4d-2222-2222-2222-222222222222"), + SortOrder = 3 + }, + new + { + Id = new Guid("2a2b3c4d-2222-2222-2222-222222222224"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Operations and billing support.", + IsActive = true, + Name = "Admin", + PresetId = new Guid("1a2b3c4d-2222-2222-2222-222222222222"), + SortOrder = 4 + }, + new + { + Id = new Guid("2a2b3c4d-3333-3333-3333-333333333331"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Client-facing delivery specialist.", + IsActive = true, + Name = "Consultant", + PresetId = new Guid("1a2b3c4d-3333-3333-3333-333333333333"), + SortOrder = 1 + }, + new + { + Id = new Guid("2a2b3c4d-3333-3333-3333-333333333332"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Owns engagement delivery and quality.", + IsActive = true, + Name = "Lead", + PresetId = new Guid("1a2b3c4d-3333-3333-3333-333333333333"), + SortOrder = 2 + }, + new + { + Id = new Guid("2a2b3c4d-3333-3333-3333-333333333333"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Plans meetings and follow-ups.", + IsActive = true, + Name = "Coordinator", + PresetId = new Guid("1a2b3c4d-3333-3333-3333-333333333333"), + SortOrder = 3 + }, + new + { + Id = new Guid("2a2b3c4d-3333-3333-3333-333333333334"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Back-office support and billing.", + IsActive = true, + Name = "Admin", + PresetId = new Guid("1a2b3c4d-3333-3333-3333-333333333333"), + SortOrder = 4 + }, + new + { + Id = new Guid("2a2b3c4d-4444-4444-4444-444444444441"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Executes diagnostics and repairs.", + IsActive = true, + Name = "Repair Tech", + PresetId = new Guid("1a2b3c4d-4444-4444-4444-444444444444"), + SortOrder = 1 + }, + new + { + Id = new Guid("2a2b3c4d-4444-4444-4444-444444444442"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Final testing and release approvals.", + IsActive = true, + Name = "QA", + PresetId = new Guid("1a2b3c4d-4444-4444-4444-444444444444"), + SortOrder = 2 + }, + new + { + Id = new Guid("2a2b3c4d-4444-4444-4444-444444444443"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Client intake and status updates.", + IsActive = true, + Name = "Service Advisor", + PresetId = new Guid("1a2b3c4d-4444-4444-4444-444444444444"), + SortOrder = 3 + }, + new + { + Id = new Guid("2a2b3c4d-4444-4444-4444-444444444444"), + CreatedAt = new DateTime(2026, 3, 23, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Operations and billing support.", + IsActive = true, + Name = "Admin", + PresetId = new Guid("1a2b3c4d-4444-4444-4444-444444444444"), + SortOrder = 4 + }); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Estimate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("EstimateNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PublicToken") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PublicTokenExpiresAt") + .HasColumnType("datetimeoffset"); + + b.Property("SentAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subtotal") + .HasColumnType("decimal(18,2)"); + + b.Property("TaxTotal") + .HasColumnType("decimal(18,2)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("Total") + .HasColumnType("decimal(18,2)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.HasIndex("PublicToken") + .IsUnique(); + + b.HasIndex("OrganizationId", "EstimateNumber") + .IsUnique(); + + b.ToTable("Estimates", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateLineItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("EstimateId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PriceBookItemId") + .HasColumnType("uniqueidentifier"); + + b.Property("Quantity") + .HasColumnType("decimal(18,2)"); + + b.Property("Total") + .HasColumnType("decimal(18,2)"); + + b.Property("UnitPrice") + .HasColumnType("decimal(18,2)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("PriceBookItemId"); + + b.ToTable("EstimateLineItems", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateRevisionAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EstimateRevisionRequestId") + .HasColumnType("uniqueidentifier"); + + b.Property("FileData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("nvarchar(260)"); + + b.Property("FileSizeBytes") + .HasColumnType("bigint"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EstimateRevisionRequestId"); + + b.ToTable("EstimateRevisionAttachments", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateRevisionRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EstimateId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationResponseMessage") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("RequestMessage") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("RequestedAt") + .HasColumnType("datetimeoffset"); + + b.Property("ResolvedAt") + .HasColumnType("datetimeoffset"); + + b.Property("ReviewedAt") + .HasColumnType("datetimeoffset"); + + b.Property("RevisionNumber") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.HasIndex("EstimateId", "RevisionNumber") + .IsUnique(); + + b.ToTable("EstimateRevisionRequests", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateSequence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Day") + .HasColumnType("int"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastSequence") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("EstimateSequence", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpExecutionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AttemptedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Channel") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("FailureReason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("FollowUpRunId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("ScheduledFor") + .HasColumnType("datetimeoffset"); + + b.Property("StepOrder") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("WasSent") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("FollowUpRunId", "StepOrder"); + + b.ToTable("FollowUpExecutionLogs", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CompletedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("FollowUpSequenceId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastAttemptAt") + .HasColumnType("datetimeoffset"); + + b.Property("NextStepOrder") + .HasColumnType("int"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SequenceType") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("StopReason") + .HasColumnType("int"); + + b.Property("TriggerEntityId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("FollowUpSequenceId", "OrganizationClientId", "Status"); + + b.HasIndex("OrganizationId", "SequenceType", "TriggerEntityId", "Status"); + + b.ToTable("FollowUpRuns", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpSequence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultChannel") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SequenceType") + .HasColumnType("int"); + + b.Property("StopOnClientReply") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "SequenceType", "IsActive"); + + b.ToTable("FollowUpSequences", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ChannelOverride") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DelayHours") + .HasColumnType("int"); + + b.Property("FollowUpSequenceId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsEscalation") + .HasColumnType("bit"); + + b.Property("MessageTemplate") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("StepOrder") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("FollowUpSequenceId", "StepOrder") + .IsUnique(); + + b.ToTable("FollowUpSteps", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.HelpArticle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ArticleType") + .HasColumnType("int"); + + b.Property("Category") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsFeatured") + .HasColumnType("bit"); + + b.Property("IsPublished") + .HasColumnType("bit"); + + b.Property("PublishedAt") + .HasColumnType("datetimeoffset"); + + b.Property("PublishedBy") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("Summary") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Tags") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ArticleType"); + + b.HasIndex("Category"); + + b.HasIndex("IsPublished"); + + b.ToTable("HelpArticles"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.InventoryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Category") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CostPerUnit") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("QuantityInStock") + .HasColumnType("int"); + + b.Property("Unit") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "Name") + .IsUnique(); + + b.ToTable("InventoryItems", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AmountPaid") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("AmountRefunded") + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EstimateId") + .HasColumnType("uniqueidentifier"); + + b.Property("ExternalPaymentId") + .HasColumnType("nvarchar(max)"); + + b.Property("InvoiceDate") + .HasColumnType("datetime2"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrderId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PaidAt") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentProvider") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("JobId"); + + b.HasIndex("OrderId"); + + b.HasIndex("OrganizationClientId"); + + b.HasIndex("OrganizationId", "CreatedAt"); + + b.HasIndex("OrganizationId", "Status"); + + b.ToTable("Invoice"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.InvoiceLineItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("InvoiceId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("PriceBookItemId") + .HasColumnType("uniqueidentifier"); + + b.Property("Quantity") + .HasColumnType("decimal(18,2)"); + + b.Property("UnitPrice") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("PriceBookItemId"); + + b.ToTable("InvoiceLineItem", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.InvoiceSequence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastSequence") + .HasColumnType("int"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("InvoiceSequence", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Comments") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EstimateId") + .HasColumnType("uniqueidentifier"); + + b.Property("InvoicingWorkflow") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Latitude") + .HasColumnType("float"); + + b.Property("LifecycleStatus") + .HasColumnType("int"); + + b.Property("Longitude") + .HasColumnType("float"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EstimateId"); + + b.HasIndex("OrganizationClientId"); + + b.ToTable("Job", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobRecurrence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DaysOfWeekMask") + .HasColumnType("int"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Duration") + .HasColumnType("time"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("Frequency") + .HasColumnType("int"); + + b.Property("GenerateDaysAhead") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobId") + .HasColumnType("uniqueidentifier"); + + b.Property("ScheduleType") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("StartTime") + .HasColumnType("time"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("JobId", "IsActive") + .HasDatabaseName("IX_JobRecurrence_JobId_IsActive"); + + b.ToTable("JobRecurrence", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultInvoicingWorkflow") + .HasColumnType("int"); + + b.Property("Description") + .HasMaxLength(240) + .HasColumnType("nvarchar(240)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsSystem") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationTypeId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("OrganizationTypeId"); + + b.ToTable("JobTemplates", (string)null); + + b.HasData( + new + { + Id = new Guid("3a3b3c3d-0101-0101-0101-010101010101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Full or partial home remodel project.", + IsActive = true, + IsSystem = true, + Name = "Home renovation", + OrganizationTypeId = new Guid("bf489aa6-db19-42df-82bc-c116bd967e7e") + }, + new + { + Id = new Guid("3a3b3c3d-0101-0101-0101-010101010102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "New outdoor living space construction.", + IsActive = true, + IsSystem = true, + Name = "Deck / patio build", + OrganizationTypeId = new Guid("bf489aa6-db19-42df-82bc-c116bd967e7e") + }, + new + { + Id = new Guid("3a3b3c3d-0202-0202-0202-020202020201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Paint walls, ceilings, and trim for interior rooms.", + IsActive = true, + IsSystem = true, + Name = "Interior painting", + OrganizationTypeId = new Guid("393a5b3e-323e-4b76-aa86-0d4683ddcd49") + }, + new + { + Id = new Guid("3a3b3c3d-0202-0202-0202-020202020202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Prep and paint home exterior surfaces.", + IsActive = true, + IsSystem = true, + Name = "Exterior painting", + OrganizationTypeId = new Guid("393a5b3e-323e-4b76-aa86-0d4683ddcd49") + }, + new + { + Id = new Guid("3a3b3c3d-0303-0303-0303-030303030301"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Diagnose and fix leaks, clogs, or faults.", + IsActive = true, + IsSystem = true, + Name = "Plumbing repair", + OrganizationTypeId = new Guid("e01750b0-0d01-4e25-abf7-6efa23509035") + }, + new + { + Id = new Guid("3a3b3c3d-0303-0303-0303-030303030302"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Remove old unit and install replacement.", + IsActive = true, + IsSystem = true, + Name = "Water heater install", + OrganizationTypeId = new Guid("e01750b0-0d01-4e25-abf7-6efa23509035") + }, + new + { + Id = new Guid("3a3b3c3d-0404-0404-0404-040404040401"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Mow, edge, blow, and treat lawn.", + IsActive = true, + IsSystem = true, + Name = "Lawn maintenance", + OrganizationTypeId = new Guid("fbc6accf-0fb1-4908-b449-14f13b826f24") + }, + new + { + Id = new Guid("3a3b3c3d-0404-0404-0404-040404040402"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Design beds, select plants, and install.", + IsActive = true, + IsSystem = true, + Name = "Garden design & install", + OrganizationTypeId = new Guid("fbc6accf-0fb1-4908-b449-14f13b826f24") + }, + new + { + Id = new Guid("3a3b3c3d-0505-0505-0505-050505050501"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Troubleshoot and fix wiring or fixture issues.", + IsActive = true, + IsSystem = true, + Name = "Electrical repair", + OrganizationTypeId = new Guid("9362c957-0f41-4c20-9085-c01e449fdda2") + }, + new + { + Id = new Guid("3a3b3c3d-0505-0505-0505-050505050502"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Upgrade electrical panel for capacity or safety.", + IsActive = true, + IsSystem = true, + Name = "Panel upgrade", + OrganizationTypeId = new Guid("9362c957-0f41-4c20-9085-c01e449fdda2") + }, + new + { + Id = new Guid("3a3b3c3d-0606-0606-0606-060606060601"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Measure, build, and install custom shelves.", + IsActive = true, + IsSystem = true, + Name = "Custom shelving", + OrganizationTypeId = new Guid("8f0d3e93-425b-4a53-b4d2-4c5eb97e490f") + }, + new + { + Id = new Guid("3a3b3c3d-0606-0606-0606-060606060602"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Install baseboards, crown molding, and casings.", + IsActive = true, + IsSystem = true, + Name = "Trim & molding install", + OrganizationTypeId = new Guid("8f0d3e93-425b-4a53-b4d2-4c5eb97e490f") + }, + new + { + Id = new Guid("3a3b3c3d-0707-0707-0707-070707070701"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Seasonal heating/cooling system tune-up.", + IsActive = true, + IsSystem = true, + Name = "HVAC maintenance", + OrganizationTypeId = new Guid("37fc17e8-0a25-4119-9a71-7d160bb9c7b4") + }, + new + { + Id = new Guid("3a3b3c3d-0707-0707-0707-070707070702"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Remove old unit and install new AC system.", + IsActive = true, + IsSystem = true, + Name = "AC install / replacement", + OrganizationTypeId = new Guid("37fc17e8-0a25-4119-9a71-7d160bb9c7b4") + }, + new + { + Id = new Guid("3a3b3c3d-0808-0808-0808-080808080801"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Fell, section, and haul away tree.", + IsActive = true, + IsSystem = true, + Name = "Tree removal", + OrganizationTypeId = new Guid("f64f078f-ecfb-4f3e-8640-236219fcf01e") + }, + new + { + Id = new Guid("3a3b3c3d-0808-0808-0808-080808080802"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Prune branches for health and clearance.", + IsActive = true, + IsSystem = true, + Name = "Tree trimming", + OrganizationTypeId = new Guid("f64f078f-ecfb-4f3e-8640-236219fcf01e") + }, + new + { + Id = new Guid("3a3b3c3d-0909-0909-0909-090909090901"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Interior and exterior spray for common pests.", + IsActive = true, + IsSystem = true, + Name = "General pest treatment", + OrganizationTypeId = new Guid("bf3b9512-8a9c-4a73-9f88-cb914c1573cd") + }, + new + { + Id = new Guid("3a3b3c3d-0909-0909-0909-090909090902"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Full property inspection and treatment plan.", + IsActive = true, + IsSystem = true, + Name = "Termite inspection", + OrganizationTypeId = new Guid("bf3b9512-8a9c-4a73-9f88-cb914c1573cd") + }, + new + { + Id = new Guid("3a3b3c3d-1010-1010-1010-101010101001"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Standard whole-house cleaning visit.", + IsActive = true, + IsSystem = true, + Name = "Full home clean", + OrganizationTypeId = new Guid("1921d982-22f8-4ed5-b4e3-fca82c5767eb") + }, + new + { + Id = new Guid("3a3b3c3d-1010-1010-1010-101010101002"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Thorough clean for tenant turnover.", + IsActive = true, + IsSystem = true, + Name = "Move-out deep clean", + OrganizationTypeId = new Guid("1921d982-22f8-4ed5-b4e3-fca82c5767eb") + }, + new + { + Id = new Guid("3a3b3c3d-1111-1111-1111-111111111101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Remove all unwanted items from property.", + IsActive = true, + IsSystem = true, + Name = "Full property cleanout", + OrganizationTypeId = new Guid("408d2185-53b9-493d-8713-938114de90f5") + }, + new + { + Id = new Guid("3a3b3c3d-1111-1111-1111-111111111102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Clear and haul garage contents.", + IsActive = true, + IsSystem = true, + Name = "Garage cleanout", + OrganizationTypeId = new Guid("408d2185-53b9-493d-8713-938114de90f5") + }, + new + { + Id = new Guid("3a3b3c3d-1212-1212-1212-121212121201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Complete interior and exterior detail.", + IsActive = true, + IsSystem = true, + Name = "Full detail", + OrganizationTypeId = new Guid("33341b2d-957f-4efb-94f7-3a015ae1a718") + }, + new + { + Id = new Guid("3a3b3c3d-1212-1212-1212-121212121202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Deep clean seats, dash, carpet, and glass.", + IsActive = true, + IsSystem = true, + Name = "Interior only", + OrganizationTypeId = new Guid("33341b2d-957f-4efb-94f7-3a015ae1a718") + }, + new + { + Id = new Guid("3a3b3c3d-1313-1313-1313-131313131301"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Install and configure router, switches, and cabling.", + IsActive = true, + IsSystem = true, + Name = "Network setup", + OrganizationTypeId = new Guid("30530a32-a151-436d-a050-613eac4c22d5") + }, + new + { + Id = new Guid("3a3b3c3d-1313-1313-1313-131313131302"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Set up desktops, laptops, and peripherals.", + IsActive = true, + IsSystem = true, + Name = "Workstation deployment", + OrganizationTypeId = new Guid("30530a32-a151-436d-a050-613eac4c22d5") + }, + new + { + Id = new Guid("3a3b3c3d-1414-1414-1414-141414141401"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Fix miscellaneous issues around the home.", + IsActive = true, + IsSystem = true, + Name = "General repair", + OrganizationTypeId = new Guid("0f32e14a-5f70-45af-a647-04e59ad52e58") + }, + new + { + Id = new Guid("3a3b3c3d-1414-1414-1414-141414141402"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 1, + Description = "Mount and connect lights, fans, or hardware.", + IsActive = true, + IsSystem = true, + Name = "Fixture install", + OrganizationTypeId = new Guid("0f32e14a-5f70-45af-a647-04e59ad52e58") + }, + new + { + Id = new Guid("3a3b3c3d-1515-1515-1515-151515151501"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Measure, prep subfloor, and install hardwood.", + IsActive = true, + IsSystem = true, + Name = "Hardwood install", + OrganizationTypeId = new Guid("09786eab-d69f-45bf-bcec-5f368bd60be7") + }, + new + { + Id = new Guid("3a3b3c3d-1515-1515-1515-151515151502"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + DefaultInvoicingWorkflow = 0, + Description = "Lay tile with proper spacing and grout.", + IsActive = true, + IsSystem = true, + Name = "Tile install", + OrganizationTypeId = new Guid("09786eab-d69f-45bf-bcec-5f368bd60be7") + }); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTemplateItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(240) + .HasColumnType("nvarchar(240)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("TemplateId"); + + b.ToTable("JobTemplateItems", (string)null); + + b.HasData( + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Walk property and scope of work.", + IsActive = true, + Name = "Site assessment", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010101") + }, + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Remove old materials and prep surfaces.", + IsActive = true, + Name = "Demo & prep", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010101") + }, + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Construction, paint, and final touches.", + IsActive = true, + Name = "Build & finish", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010101") + }, + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Draft plan and pull permits.", + IsActive = true, + Name = "Design & permits", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010102") + }, + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Set footings, frame, and deck boards.", + IsActive = true, + Name = "Frame & build", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010102") + }, + new + { + Id = new Guid("4a4b4c4d-0101-0101-0101-010101010203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Stain/seal and final walkthrough.", + IsActive = true, + Name = "Finish & inspect", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0101-0101-0101-010101010102") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Confirm colors, tape, and cover surfaces.", + IsActive = true, + Name = "Color consult & prep", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020201") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Apply primer and two coats.", + IsActive = true, + Name = "Prime & paint", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020201") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Detail edges and remove coverings.", + IsActive = true, + Name = "Touch-up & clean", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020201") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Clean and prep exterior surfaces.", + IsActive = true, + Name = "Power wash & scrape", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020202") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Coat siding, fascia, and trim.", + IsActive = true, + Name = "Prime & paint", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020202") + }, + new + { + Id = new Guid("4a4b4c4d-0202-0202-0202-020202020203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Check coverage and clean site.", + IsActive = true, + Name = "Final inspection", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0202-0202-0202-020202020202") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Locate leak, blockage, or fault.", + IsActive = true, + Name = "Diagnose issue", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030301") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Fix or replace the faulty component.", + IsActive = true, + Name = "Perform repair", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030301") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Run water, check pressure, tidy area.", + IsActive = true, + Name = "Test & clean up", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030301") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Shut off supply and drain tank.", + IsActive = true, + Name = "Disconnect old unit", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030302") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Position, connect plumbing and power.", + IsActive = true, + Name = "Install new unit", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030302") + }, + new + { + Id = new Guid("4a4b4c4d-0303-0303-0303-030303030203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Check for leaks and set temperature.", + IsActive = true, + Name = "Test & verify", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0303-0303-0303-030303030302") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Cut grass and trim borders.", + IsActive = true, + Name = "Mow & edge", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040401") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Clear clippings from walks and drives.", + IsActive = true, + Name = "Blow & clean", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040401") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Apply treatment as needed.", + IsActive = true, + Name = "Treat & fertilize", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040401") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Plan beds, paths, and plant selection.", + IsActive = true, + Name = "Design layout", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040402") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Amend soil and install plants.", + IsActive = true, + Name = "Prep & plant", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040402") + }, + new + { + Id = new Guid("4a4b4c4d-0404-0404-0404-040404040203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Top-dress and initial watering.", + IsActive = true, + Name = "Mulch & water", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0404-0404-0404-040404040402") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Test circuits and locate issue.", + IsActive = true, + Name = "Diagnose fault", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050501") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Replace or repair faulty components.", + IsActive = true, + Name = "Repair wiring", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050501") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Confirm power and safety.", + IsActive = true, + Name = "Test & verify", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050501") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Kill main and label circuits.", + IsActive = true, + Name = "Shut down & disconnect", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050502") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Mount new box and reconnect breakers.", + IsActive = true, + Name = "Swap panel", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050502") + }, + new + { + Id = new Guid("4a4b4c4d-0505-0505-0505-050505050203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Restore power and run tests.", + IsActive = true, + Name = "Energize & inspect", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0505-0505-0505-050505050502") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Take dimensions and plan layout.", + IsActive = true, + Name = "Measure & design", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060601") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Build shelving units.", + IsActive = true, + Name = "Cut & assemble", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060601") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Mount, sand, and apply finish.", + IsActive = true, + Name = "Install & finish", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060601") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Measure runs and miter cut pieces.", + IsActive = true, + Name = "Measure & cut", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060602") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Attach molding and set nails.", + IsActive = true, + Name = "Nail & set", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060602") + }, + new + { + Id = new Guid("4a4b4c4d-0606-0606-0606-060606060203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Fill gaps, prime, and paint.", + IsActive = true, + Name = "Caulk & paint", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0606-0606-0606-060606060602") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Check airflow and swap filter.", + IsActive = true, + Name = "Inspect & replace filter", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070701") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Remove buildup from outdoor unit.", + IsActive = true, + Name = "Clean condenser coils", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070701") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Verify settings and calibration.", + IsActive = true, + Name = "Test thermostat", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070701") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Disconnect and haul away.", + IsActive = true, + Name = "Remove old unit", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070702") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Set unit, connect lines and electric.", + IsActive = true, + Name = "Install new system", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070702") + }, + new + { + Id = new Guid("4a4b4c4d-0707-0707-0707-070707070203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Add refrigerant and run cycles.", + IsActive = true, + Name = "Charge & test", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0707-0707-0707-070707070702") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Evaluate drop zone and rigging.", + IsActive = true, + Name = "Assess & plan", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080801") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Cut tree and process limbs.", + IsActive = true, + Name = "Fell & section", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080801") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Remove debris and rake site.", + IsActive = true, + Name = "Haul & clean", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080801") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Identify dead or problem branches.", + IsActive = true, + Name = "Inspect canopy", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080802") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Cut for shape, clearance, and health.", + IsActive = true, + Name = "Prune branches", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080802") + }, + new + { + Id = new Guid("4a4b4c4d-0808-0808-0808-080808080203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Chip or haul brush.", + IsActive = true, + Name = "Clean up", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0808-0808-0808-080808080802") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Identify pest activity and entry points.", + IsActive = true, + Name = "Inspect property", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090901") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Spray interior and exterior perimeter.", + IsActive = true, + Name = "Apply treatment", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090901") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Log findings and next visit.", + IsActive = true, + Name = "Document & recommend", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090901") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Check foundation, crawl, and attic.", + IsActive = true, + Name = "Full property scan", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090902") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Tap and test for damage.", + IsActive = true, + Name = "Probe suspect areas", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090902") + }, + new + { + Id = new Guid("4a4b4c4d-0909-0909-0909-090909090203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Findings and treatment estimate.", + IsActive = true, + Name = "Deliver report", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-0909-0909-0909-090909090902") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Assess rooms and special requests.", + IsActive = true, + Name = "Walkthrough", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101001") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Scrub fixtures, counters, appliances.", + IsActive = true, + Name = "Deep clean kitchen & baths", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101001") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "All hard and carpeted surfaces.", + IsActive = true, + Name = "Vacuum & mop", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101001") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Clear remaining items, dust surfaces.", + IsActive = true, + Name = "Empty & prep", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101002") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Walls, baseboards, inside cabinets.", + IsActive = true, + Name = "Scrub all rooms", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101002") + }, + new + { + Id = new Guid("4a4b4c4d-1010-1010-1010-101010100203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Verify quality before handoff.", + IsActive = true, + Name = "Final walkthrough", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1010-1010-1010-101010101002") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Tag items and plan truck loads.", + IsActive = true, + Name = "Walk & inventory", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111101") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Remove items to truck.", + IsActive = true, + Name = "Load & haul", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111101") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Clean site, dump or donate.", + IsActive = true, + Name = "Sweep & dispose", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111101") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Separate keep, donate, and trash.", + IsActive = true, + Name = "Sort items", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111102") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Move discards to truck.", + IsActive = true, + Name = "Load out", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111102") + }, + new + { + Id = new Guid("4a4b4c4d-1111-1111-1111-111111110203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Broom clean and organize keepers.", + IsActive = true, + Name = "Sweep garage", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1111-1111-1111-111111111102") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Hand wash, clay bar, and dry.", + IsActive = true, + Name = "Exterior wash & clay", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121201") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Vacuum, shampoo, and condition.", + IsActive = true, + Name = "Interior deep clean", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121201") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Compound, wax, and dress tires.", + IsActive = true, + Name = "Polish & protect", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121201") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "All seats, dash, and crevices.", + IsActive = true, + Name = "Vacuum & dust", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121202") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Extract and clean fabric or leather.", + IsActive = true, + Name = "Shampoo upholstery", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121202") + }, + new + { + Id = new Guid("4a4b4c4d-1212-1212-1212-121212120203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Clean interior glass and surfaces.", + IsActive = true, + Name = "Glass & final wipe", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1212-1212-1212-121212121202") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Map runs and plan equipment placement.", + IsActive = true, + Name = "Site survey", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131301") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Pull cable and install hardware.", + IsActive = true, + Name = "Run cable & mount", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131301") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Set up network and verify connectivity.", + IsActive = true, + Name = "Configure & test", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131301") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Prep hardware and install OS/software.", + IsActive = true, + Name = "Unbox & image", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131302") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Place at desk and join network.", + IsActive = true, + Name = "Deploy & connect", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131302") + }, + new + { + Id = new Guid("4a4b4c4d-1313-1313-1313-131313130203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Verify apps and orient user.", + IsActive = true, + Name = "User walkthrough", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1313-1313-1313-131313131302") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Inspect problem area and plan fix.", + IsActive = true, + Name = "Assess issue", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141401") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Fix or replace components.", + IsActive = true, + Name = "Repair", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141401") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Test fix and tidy work area.", + IsActive = true, + Name = "Verify & clean up", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141401") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Mark placement and run wiring if needed.", + IsActive = true, + Name = "Prep location", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141402") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Secure and connect.", + IsActive = true, + Name = "Mount fixture", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141402") + }, + new + { + Id = new Guid("4a4b4c4d-1414-1414-1414-141414140203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Confirm operation and patch holes.", + IsActive = true, + Name = "Test & finish", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1414-1414-1414-141414141402") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150101"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Level, clean, and lay moisture barrier.", + IsActive = true, + Name = "Prep subfloor", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151501") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150102"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Lay and nail or click into place.", + IsActive = true, + Name = "Install planks", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151501") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150103"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Install transitions and clean.", + IsActive = true, + Name = "Trim & finish", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151501") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150201"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Dry-fit pattern and mix thinset.", + IsActive = true, + Name = "Layout & prep", + SortOrder = 1, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151502") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150202"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Lay tiles with spacers.", + IsActive = true, + Name = "Set tile", + SortOrder = 2, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151502") + }, + new + { + Id = new Guid("4a4b4c4d-1515-1515-1515-151515150203"), + CreatedAt = new DateTime(2026, 4, 8, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Fill joints, clean haze, and seal.", + IsActive = true, + Name = "Grout & seal", + SortOrder = 3, + TemplateId = new Guid("3a3b3c3d-1515-1515-1515-151515151502") + }); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTracking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EmployeeId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobId") + .HasColumnType("uniqueidentifier"); + + b.Property("Latitude") + .HasColumnType("decimal(9,6)"); + + b.Property("Longitude") + .HasColumnType("decimal(9,6)"); + + b.Property("RecordedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETUTCDATE()"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("JobId"); + + b.ToTable("JobTracking"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobId") + .HasColumnType("uniqueidentifier"); + + b.Property("Message") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("OccurredAt") + .HasColumnType("datetimeoffset"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("JobId", "OccurredAt"); + + b.ToTable("JobUpdates", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobUpdateAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("FileData") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("nvarchar(260)"); + + b.Property("FileSizeBytes") + .HasColumnType("bigint"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("JobUpdateId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("JobUpdateId"); + + b.ToTable("JobUpdateAttachments", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AttachmentUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConversationId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ExternalSenderName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExternalSenderPhone") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("ExternalSenderType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("SenderId") + .HasColumnType("uniqueidentifier"); + + b.Property("SentAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ConversationId"); + + b.HasIndex("SenderId"); + + b.ToTable("Message", "messaging"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TotalAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.ToTable("Order", "payment"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Address1") + .HasColumnType("nvarchar(max)"); + + b.Property("Address2") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .HasColumnType("nvarchar(max)"); + + b.Property("ContactFirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("ContactLastName") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultTaxRate") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("EmailAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("EnableTax") + .HasColumnType("bit"); + + b.Property("HasFreeAccount") + .HasColumnType("bit"); + + b.Property("IndustryKey") + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsSquareConnected") + .HasColumnType("bit"); + + b.Property("IsStripeConnected") + .HasColumnType("bit"); + + b.Property("OnBoardingComplete") + .HasColumnType("bit"); + + b.Property("OnboardingPresetAppliedAt") + .HasColumnType("datetimeoffset"); + + b.Property("OnboardingPresetKey") + .HasColumnType("nvarchar(max)"); + + b.Property("OnboardingTrack") + .HasColumnType("nvarchar(max)"); + + b.Property("OnboardingTrackSelectedAt") + .HasColumnType("datetimeoffset"); + + b.Property("OrganizationName") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationTypeId") + .HasColumnType("uniqueidentifier"); + + b.Property("PaymentProvider") + .HasColumnType("int"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("SquareMerchantId") + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .HasColumnType("nvarchar(max)"); + + b.Property("StripeConnectAccountId") + .HasColumnType("nvarchar(max)"); + + b.Property("SubscriptionExpiresAt") + .HasColumnType("datetime2"); + + b.Property("SubscriptionPlanName") + .HasColumnType("nvarchar(max)"); + + b.Property("SubscriptionStatus") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ZipCode") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationTypeId"); + + b.ToTable("Organization", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationBranding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BusinessName") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("FooterNote") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LogoUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PrimaryColor") + .HasColumnType("nvarchar(max)"); + + b.Property("SecondaryColor") + .HasColumnType("nvarchar(max)"); + + b.Property("Tagline") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationBranding", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Address1") + .HasColumnType("nvarchar(max)"); + + b.Property("Address2") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EmailAddress") + .HasColumnType("nvarchar(450)"); + + b.Property("FirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ZipCode") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "EmailAddress") + .IsUnique() + .HasFilter("[EmailAddress] IS NOT NULL AND [IsActive] = 1"); + + b.ToTable("OrganizationClient", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationClientPortalSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("nvarchar(320)"); + + b.Property("ExpiresAt") + .HasColumnType("datetimeoffset"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RedeemedAt") + .HasColumnType("datetimeoffset"); + + b.Property("TokenHash") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationClientId"); + + b.HasIndex("TokenHash") + .IsUnique(); + + b.ToTable("OrganizationClientPortalSession"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationInvoicingSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultWorkflow") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("DepositPercentage") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.Property("DepositRequired") + .HasColumnType("bit"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationInvoicingSettings"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationOnboardingStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CompletedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("StepName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "StepName") + .IsUnique(); + + b.ToTable("OrganizationOnboardingSteps", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationScheduleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AutoNotifyReschedule") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("DefaultWindowMinutes") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(120); + + b.Property("EnforceTravelBuffer") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("TravelBufferMinutes") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(20); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationScheduleSettings"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationService", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ServiceName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationService", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("TypeName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("OrganizationType", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationWorkflowStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("StatusKey") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "Category", "StatusKey") + .IsUnique(); + + b.ToTable("OrganizationWorkflowStatus"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PaymentHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AmountPaid") + .HasColumnType("bigint"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CustomerId") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EntityId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityType") + .HasColumnType("int"); + + b.Property("EventType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("InvoiceId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("PaidAt") + .HasColumnType("datetime2"); + + b.Property("PaymentProvider") + .HasColumnType("int"); + + b.Property("RawEventJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeInvoiceId") + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntentId") + .HasColumnType("nvarchar(max)"); + + b.Property("SubscriptionId") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("EntityId", "PaidAt"); + + b.ToTable("PaymentHistory"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PriceBookCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId", "Name") + .IsUnique(); + + b.ToTable("PriceBookCategories", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PriceBookItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("Cost") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("InventoryItemId") + .HasColumnType("uniqueidentifier"); + + b.Property("InventoryUnitsPerSale") + .ValueGeneratedOnAdd() + .HasColumnType("decimal(18,4)") + .HasDefaultValue(1.0m); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsTaxable") + .HasColumnType("bit"); + + b.Property("ItemType") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PartNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("PricePerUnit") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Unit") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("InventoryItemId"); + + b.HasIndex("OrganizationId", "Name") + .IsUnique(); + + b.ToTable("PriceBookItems", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SecurityAlert", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("DetailsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("EvidenceCount") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("RuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Severity") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("WindowEndUtc") + .HasColumnType("datetime2"); + + b.Property("WindowStartUtc") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("RuleKey", "Status", "CreatedAt"); + + b.ToTable("SecurityAlert", "security"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ShortLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessCount") + .HasColumnType("int"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastAccessedAt") + .HasColumnType("datetime2"); + + b.Property("TargetUrl") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique() + .HasFilter("[IsActive] = 1"); + + b.HasIndex("CreatedAt"); + + b.ToTable("ShortLink", "notifications"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SubscriptionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CanceledAt") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("PaymentProfileId") + .HasColumnType("uniqueidentifier"); + + b.Property("PlanName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Provider") + .HasColumnType("int"); + + b.Property("ProviderPriceId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderSubscriptionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentProfileId"); + + b.ToTable("SubscriptionRecord", "payment"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("FileName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("FileUrl") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("SenderId") + .HasColumnType("uniqueidentifier"); + + b.Property("SenderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("SenderRole") + .HasColumnType("int"); + + b.Property("SentAt") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("SentAt"); + + b.HasIndex("SessionId"); + + b.ToTable("SupportChatMessage", "support"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportChatSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AssignedRepId") + .HasColumnType("uniqueidentifier"); + + b.Property("AssignedRepName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClosedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomerEmail") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("nvarchar(320)"); + + b.Property("CustomerId") + .HasColumnType("uniqueidentifier"); + + b.Property("CustomerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EstimatedWaitSeconds") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("StartedAt") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AssignedRepId"); + + b.HasIndex("CustomerEmail"); + + b.HasIndex("CustomerId"); + + b.HasIndex("Status"); + + b.ToTable("SupportChatSession", "support"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportHubInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetimeoffset"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("RedeemedAt") + .HasColumnType("datetimeoffset"); + + b.Property("RedeemedByUid") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Role") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("SupportHubInvites"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportHubSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AgentName") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("EndedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SupportHubSessions"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportHubTicket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastActivityAt") + .HasColumnType("datetimeoffset"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Summary") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SupportHubTickets"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SystemRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasDefaultValueSql("NEWID()"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + + b.HasData( + new + { + Id = new Guid("e88fbbe6-8bdf-4aca-b941-912785a94f0b"), + Name = "OrganizationAdmin" + }, + new + { + Id = new Guid("079e4277-0eb2-4222-82e4-5a751ede48f6"), + Name = "OrganizationEmployee" + }, + new + { + Id = new Guid("3da14c58-562a-437a-a2a6-47706b40eb70"), + Name = "OrganizationClient" + }, + new + { + Id = new Guid("5bc0d325-a915-4e17-8184-428ee533cf89"), + Name = "KatharixAdmin" + }, + new + { + Id = new Guid("92193eb2-dba0-433c-814e-9fca95bde016"), + Name = "KatharixEmployee" + }, + new + { + Id = new Guid("dfe36ebc-bfb5-4583-b68e-59be8ba60fa9"), + Name = "SuperAdmin" + }); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DeactivatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("FirebaseUid") + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LastName") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PreferredLanguage") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.Property("UpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.UserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Assignment", b => + { + b.HasOne("JobFlow.Domain.Models.Job", "Job") + .WithMany("Assignments") + .HasForeignKey("JobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Job"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentAssignee", b => + { + b.HasOne("JobFlow.Domain.Models.Assignment", "Assignment") + .WithMany("AssignmentAssignees") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentHistory", b => + { + b.HasOne("JobFlow.Domain.Models.Assignment", "Assignment") + .WithMany() + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.AssignmentOrder", b => + { + b.HasOne("JobFlow.Domain.Models.Assignment", "Assignment") + .WithMany("AssignmentOrders") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.Order", "Order") + .WithMany("AssignmentOrders") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportJob", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportJobError", b => + { + b.HasOne("JobFlow.Domain.Models.ClientImportJob", "ClientImportJob") + .WithMany("Errors") + .HasForeignKey("ClientImportJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ClientImportJob"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportUploadRow", b => + { + b.HasOne("JobFlow.Domain.Models.ClientImportUploadSession", "Session") + .WithMany("Rows") + .HasForeignKey("ClientImportUploadSessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Session"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportUploadSession", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Conversation", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ConversationParticipant", b => + { + b.HasOne("JobFlow.Domain.Models.Conversation", "Conversation") + .WithMany("Participants") + .HasForeignKey("ConversationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Conversation"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.CustomerPaymentProfile", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", null) + .WithMany("PaymentProfiles") + .HasForeignKey("OrganizationClientId"); + + b.HasOne("JobFlow.Domain.Models.Organization", null) + .WithMany("PaymentProfiles") + .HasForeignKey("OrganizationId"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.DataExportJob", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Employee", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany("Employees") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.EmployeeRole", "Role") + .WithMany("Employees") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.User", "User") + .WithMany("Employees") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Organization"); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportJob", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportJobError", b => + { + b.HasOne("JobFlow.Domain.Models.EmployeeImportJob", "EmployeeImportJob") + .WithMany("Errors") + .HasForeignKey("EmployeeImportJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmployeeImportJob"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportUploadRow", b => + { + b.HasOne("JobFlow.Domain.Models.EmployeeImportUploadSession", "Session") + .WithMany("Rows") + .HasForeignKey("EmployeeImportUploadSessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Session"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportUploadSession", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeInvite", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.EmployeeRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRole", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany("EmployeeRoles") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRolePreset", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRolePresetItem", b => + { + b.HasOne("JobFlow.Domain.Models.EmployeeRolePreset", "Preset") + .WithMany("Items") + .HasForeignKey("PresetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Preset"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Estimate", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateLineItem", b => + { + b.HasOne("JobFlow.Domain.Models.Estimate", "Estimate") + .WithMany("LineItems") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.PriceBookItem", "PriceBookItem") + .WithMany() + .HasForeignKey("PriceBookItemId"); + + b.Navigation("Estimate"); + + b.Navigation("PriceBookItem"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateRevisionAttachment", b => + { + b.HasOne("JobFlow.Domain.Models.EstimateRevisionRequest", "RevisionRequest") + .WithMany("Attachments") + .HasForeignKey("EstimateRevisionRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RevisionRequest"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateRevisionRequest", b => + { + b.HasOne("JobFlow.Domain.Models.Estimate", "Estimate") + .WithMany("RevisionRequests") + .HasForeignKey("EstimateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Estimate"); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpExecutionLog", b => + { + b.HasOne("JobFlow.Domain.Models.FollowUpRun", "Run") + .WithMany("ExecutionLogs") + .HasForeignKey("FollowUpRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpRun", b => + { + b.HasOne("JobFlow.Domain.Models.FollowUpSequence", "Sequence") + .WithMany() + .HasForeignKey("FollowUpSequenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Sequence"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpStep", b => + { + b.HasOne("JobFlow.Domain.Models.FollowUpSequence", "Sequence") + .WithMany("Steps") + .HasForeignKey("FollowUpSequenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Sequence"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Invoice", b => + { + b.HasOne("JobFlow.Domain.Models.Job", "Job") + .WithMany() + .HasForeignKey("JobId"); + + b.HasOne("JobFlow.Domain.Models.Order", "Order") + .WithMany("Invoices") + .HasForeignKey("OrderId"); + + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Job"); + + b.Navigation("Order"); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.InvoiceLineItem", b => + { + b.HasOne("JobFlow.Domain.Models.Invoice", "Invoice") + .WithMany("LineItems") + .HasForeignKey("InvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.PriceBookItem", "PriceBookItem") + .WithMany() + .HasForeignKey("PriceBookItemId"); + + b.Navigation("Invoice"); + + b.Navigation("PriceBookItem"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Job", b => + { + b.HasOne("JobFlow.Domain.Models.Estimate", "Estimate") + .WithMany() + .HasForeignKey("EstimateId"); + + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany("Jobs") + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Estimate"); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobRecurrence", b => + { + b.HasOne("JobFlow.Domain.Models.Job", "Job") + .WithMany() + .HasForeignKey("JobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Job"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTemplate", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("JobFlow.Domain.Models.OrganizationType", "OrganizationType") + .WithMany() + .HasForeignKey("OrganizationTypeId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Organization"); + + b.Navigation("OrganizationType"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTemplateItem", b => + { + b.HasOne("JobFlow.Domain.Models.JobTemplate", "Template") + .WithMany("Items") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTracking", b => + { + b.HasOne("JobFlow.Domain.Models.User", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.Job", "Job") + .WithMany("JobTrackings") + .HasForeignKey("JobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("Job"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobUpdate", b => + { + b.HasOne("JobFlow.Domain.Models.Job", "Job") + .WithMany("JobUpdates") + .HasForeignKey("JobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Job"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobUpdateAttachment", b => + { + b.HasOne("JobFlow.Domain.Models.JobUpdate", "JobUpdate") + .WithMany("Attachments") + .HasForeignKey("JobUpdateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JobUpdate"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Message", b => + { + b.HasOne("JobFlow.Domain.Models.Conversation", "Conversation") + .WithMany("Messages") + .HasForeignKey("ConversationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.User", "Sender") + .WithMany() + .HasForeignKey("SenderId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Conversation"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Order", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Organization", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationType", "OrganizationType") + .WithMany() + .HasForeignKey("OrganizationTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("OrganizationType"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationBranding", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationClient", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationClientPortalSession", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "OrganizationClient") + .WithMany() + .HasForeignKey("OrganizationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationClient"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationOnboardingStep", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany("OnboardingSteps") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationService", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PaymentHistory", b => + { + b.HasOne("JobFlow.Domain.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("InvoiceId"); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PriceBookItem", b => + { + b.HasOne("JobFlow.Domain.Models.PriceBookCategory", "Category") + .WithMany("Items") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("JobFlow.Domain.Models.InventoryItem", "InventoryItem") + .WithMany() + .HasForeignKey("InventoryItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Category"); + + b.Navigation("InventoryItem"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SubscriptionRecord", b => + { + b.HasOne("JobFlow.Domain.Models.CustomerPaymentProfile", "PaymentProfile") + .WithMany() + .HasForeignKey("PaymentProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentProfile"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportChatMessage", b => + { + b.HasOne("JobFlow.Domain.Models.SupportChatSession", "Session") + .WithMany("Messages") + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Session"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportChatSession", b => + { + b.HasOne("JobFlow.Domain.Models.User", "AssignedRep") + .WithMany() + .HasForeignKey("AssignedRepId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("JobFlow.Domain.Models.User", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("AssignedRep"); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportHubSession", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportHubTicket", b => + { + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.User", b => + { + b.HasOne("JobFlow.Domain.Models.OrganizationClient", "Client") + .WithMany() + .HasForeignKey("ClientId"); + + b.HasOne("JobFlow.Domain.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.UserRole", b => + { + b.HasOne("JobFlow.Domain.Models.SystemRole", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JobFlow.Domain.Models.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Assignment", b => + { + b.Navigation("AssignmentAssignees"); + + b.Navigation("AssignmentOrders"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportJob", b => + { + b.Navigation("Errors"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.ClientImportUploadSession", b => + { + b.Navigation("Rows"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Conversation", b => + { + b.Navigation("Messages"); + + b.Navigation("Participants"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportJob", b => + { + b.Navigation("Errors"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeImportUploadSession", b => + { + b.Navigation("Rows"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRole", b => + { + b.Navigation("Employees"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EmployeeRolePreset", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Estimate", b => + { + b.Navigation("LineItems"); + + b.Navigation("RevisionRequests"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.EstimateRevisionRequest", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpRun", b => + { + b.Navigation("ExecutionLogs"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.FollowUpSequence", b => + { + b.Navigation("Steps"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Invoice", b => + { + b.Navigation("LineItems"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Job", b => + { + b.Navigation("Assignments"); + + b.Navigation("JobTrackings"); + + b.Navigation("JobUpdates"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobTemplate", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.JobUpdate", b => + { + b.Navigation("Attachments"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Order", b => + { + b.Navigation("AssignmentOrders"); + + b.Navigation("Invoices"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.Organization", b => + { + b.Navigation("EmployeeRoles"); + + b.Navigation("Employees"); + + b.Navigation("OnboardingSteps"); + + b.Navigation("PaymentProfiles"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.OrganizationClient", b => + { + b.Navigation("Jobs"); + + b.Navigation("PaymentProfiles"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.PriceBookCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SupportChatSession", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.SystemRole", b => + { + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("JobFlow.Domain.Models.User", b => + { + b.Navigation("Employees"); + + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs b/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs new file mode 100644 index 0000000..a51a4d9 --- /dev/null +++ b/JobFlow.Infrastructure.Persistence/Migrations/20260423151531_SeedChangelogEntries.cs @@ -0,0 +1,111 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace JobFlow.Infrastructure.Persistence.Migrations +{ + /// + public partial class SeedChangelogEntries : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "ChangelogEntries", + columns: new[] { "Id", "Title", "Description", "Version", "Category", "IsPublished", "PublishedAt", "CreatedBy", "UpdatedBy", "CreatedAt", "UpdatedAt", "IsActive", "DeactivatedAtUtc" }, + values: new object[,] + { + { + new Guid("a1b2c3d4-e5f6-7890-abcd-ef1234567890"), + "Support Hub launched", + "The JobFlow Support Hub is now live. Support agents can manage tickets, handle live chat queues, and review customer billing — all from a single dashboard.", + "2026.04.0", + 0, // Feature + true, + new DateTimeOffset(2026, 4, 1, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 1, 0, 0, 0, DateTimeKind.Utc), + null, true, null + }, + { + new Guid("b2c3d4e5-f6a7-8901-bcde-f12345678901"), + "Live chat queue improvements", + "The live chat queue now shows estimated wait times, supports agent pick-up from the queue panel, and persists session state across page refreshes.", + "2026.04.1", + 1, // Improvement + true, + new DateTimeOffset(2026, 4, 7, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 7, 0, 0, 0, DateTimeKind.Utc), + null, true, null + }, + { + new Guid("c3d4e5f6-a7b8-9012-cdef-123456789012"), + "Billing page — payment events & disputes", + "Support agents can now view a full history of payment events and disputes for any organization. Paginated tables with cursor-based navigation are available on the Billing page.", + "2026.04.2", + 0, // Feature + true, + new DateTimeOffset(2026, 4, 10, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 10, 0, 0, 0, DateTimeKind.Utc), + null, true, null + }, + { + new Guid("d4e5f6a7-b8c9-0123-def0-234567890123"), + "Employee CSV import", + "Organization administrators can now bulk-import employees using a CSV file. The importer validates each row, reports errors inline, and supports role assignment on import.", + "2026.04.3", + 0, // Feature + true, + new DateTimeOffset(2026, 4, 14, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 14, 0, 0, 0, DateTimeKind.Utc), + null, true, null + }, + { + new Guid("e5f6a7b8-c9d0-1234-ef01-345678901234"), + "JobFlow Grid — sort and search", + "All admin data grids now support multi-column sorting and a live search bar. Server-side pagination is available for large datasets.", + "2026.04.4", + 1, // Improvement + true, + new DateTimeOffset(2026, 4, 18, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 18, 0, 0, 0, DateTimeKind.Utc), + null, true, null + }, + { + new Guid("f6a7b8c9-d0e1-2345-f012-456789012345"), + "UI spacing and login button branding fix", + "Fixed padding on the JobFlow Grid wrapper, increased gap between billing table cards, and updated the Support Hub login button to match brand styling.", + "2026.04.5", + 2, // Fix + true, + new DateTimeOffset(2026, 4, 23, 0, 0, 0, TimeSpan.Zero), + "system", null, + new DateTime(2026, 4, 23, 0, 0, 0, DateTimeKind.Utc), + null, true, null + } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "ChangelogEntries", + keyColumn: "Id", + keyValues: new object[] + { + new Guid("a1b2c3d4-e5f6-7890-abcd-ef1234567890"), + new Guid("b2c3d4e5-f6a7-8901-bcde-f12345678901"), + new Guid("c3d4e5f6-a7b8-9012-cdef-123456789012"), + new Guid("d4e5f6a7-b8c9-0123-def0-234567890123"), + new Guid("e5f6a7b8-c9d0-1234-ef01-345678901234"), + new Guid("f6a7b8c9-d0e1-2345-f012-456789012345") + }); + } + } +} + diff --git a/JobFlow.Infrastructure.Persistence/Migrations/JobFlowDbContextModelSnapshot.cs b/JobFlow.Infrastructure.Persistence/Migrations/JobFlowDbContextModelSnapshot.cs index d3b6ef1..325eafb 100644 --- a/JobFlow.Infrastructure.Persistence/Migrations/JobFlowDbContextModelSnapshot.cs +++ b/JobFlow.Infrastructure.Persistence/Migrations/JobFlowDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("ProductVersion", "10.0.7") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);