diff --git a/src/Humans.Application/Interfaces/ICityPlanningService.cs b/src/Humans.Application/Interfaces/ICityPlanningService.cs index 94c34fdc..acf3be12 100644 --- a/src/Humans.Application/Interfaces/ICityPlanningService.cs +++ b/src/Humans.Application/Interfaces/ICityPlanningService.cs @@ -37,6 +37,7 @@ public interface ICityPlanningService Task UpdateOfficialZonesAsync(string geoJson, Guid userId, CancellationToken cancellationToken = default); Task DeleteOfficialZonesAsync(Guid userId, CancellationToken cancellationToken = default); Task UpdatePlacementDatesAsync(LocalDateTime? opensAt, LocalDateTime? closesAt, CancellationToken cancellationToken = default); + Task UpdateRegistrationInfoAsync(string? registrationInfo, CancellationToken cancellationToken = default); // Export Task ExportAsGeoJsonAsync(int year, CancellationToken cancellationToken = default); diff --git a/src/Humans.Domain/Entities/CityPlanningSettings.cs b/src/Humans.Domain/Entities/CityPlanningSettings.cs index a1a92e11..e63caf0d 100644 --- a/src/Humans.Domain/Entities/CityPlanningSettings.cs +++ b/src/Humans.Domain/Entities/CityPlanningSettings.cs @@ -19,6 +19,9 @@ public class CityPlanningSettings /// Informational scheduled close time shown in help modal. Not enforced. public LocalDateTime? PlacementClosesAt { get; set; } + /// Admin-editable markdown content shown at the top of the barrio registration page. Null/empty = hidden. + public string? RegistrationInfo { get; set; } + /// GeoJSON FeatureCollection defining the visual site boundary. Null until uploaded. public string? LimitZoneGeoJson { get; set; } diff --git a/src/Humans.Infrastructure/Data/Configurations/CityPlanningSettingsConfiguration.cs b/src/Humans.Infrastructure/Data/Configurations/CityPlanningSettingsConfiguration.cs index 9698b2a4..14307b53 100644 --- a/src/Humans.Infrastructure/Data/Configurations/CityPlanningSettingsConfiguration.cs +++ b/src/Humans.Infrastructure/Data/Configurations/CityPlanningSettingsConfiguration.cs @@ -12,6 +12,7 @@ public void Configure(EntityTypeBuilder builder) builder.HasIndex(s => s.Year).IsUnique(); + builder.Property(s => s.RegistrationInfo).HasColumnType("text"); builder.Property(s => s.LimitZoneGeoJson).HasColumnType("text"); builder.Property(s => s.OfficialZonesGeoJson).HasColumnType("text"); } diff --git a/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.Designer.cs b/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.Designer.cs new file mode 100644 index 00000000..3b441239 --- /dev/null +++ b/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.Designer.cs @@ -0,0 +1,4577 @@ +// +using System; +using Humans.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Humans.Infrastructure.Migrations +{ + [DbContext(typeof(HumansDbContext))] + [Migration("20260410145936_AddRegistrationInfoToCityPlanningSettings")] + partial class AddRegistrationInfoToCityPlanningSettings + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Humans.Domain.Entities.AccountMergeRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdminNotes") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PendingEmailId") + .HasColumnType("uuid"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResolvedByUserId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ResolvedByUserId"); + + b.HasIndex("SourceUserId"); + + b.HasIndex("Status"); + + b.HasIndex("TargetUserId"); + + b.ToTable("account_merge_requests", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Application", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdditionalInfo") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("BoardMeetingDate") + .HasColumnType("date"); + + b.Property("DecisionNote") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("Language") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("MembershipTier") + .IsRequired() + .HasColumnType("text"); + + b.Property("Motivation") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("RenewalReminderSentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewNotes") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ReviewStartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewedByUserId") + .HasColumnType("uuid"); + + b.Property("RoleUnderstanding") + .HasColumnType("text"); + + b.Property("SignificantContribution") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmittedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("TermExpiresAt") + .HasColumnType("date"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MembershipTier"); + + b.HasIndex("ReviewedByUserId"); + + b.HasIndex("Status"); + + b.HasIndex("SubmittedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Status"); + + b.ToTable("applications", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ApplicationStateHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ChangedByUserId") + .HasColumnType("uuid"); + + b.Property("Notes") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("ChangedAt"); + + b.HasIndex("ChangedByUserId"); + + b.ToTable("application_state_history", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.AuditLogEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ActorUserId") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("EntityId") + .HasColumnType("uuid"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ErrorMessage") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("OccurredAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ResourceId") + .HasColumnType("uuid"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Success") + .HasColumnType("boolean"); + + b.Property("SyncSource") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UserEmail") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.HasIndex("Action"); + + b.HasIndex("ActorUserId"); + + b.HasIndex("OccurredAt"); + + b.HasIndex("ResourceId"); + + b.HasIndex("EntityType", "EntityId"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.ToTable("audit_log", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BoardVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BoardMemberUserId") + .HasColumnType("uuid"); + + b.Property("Note") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Vote") + .IsRequired() + .HasColumnType("text"); + + b.Property("VotedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("BoardMemberUserId"); + + b.HasIndex("ApplicationId", "BoardMemberUserId") + .IsUnique(); + + b.ToTable("board_votes", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActorUserId") + .HasColumnType("uuid"); + + b.Property("BudgetYearId") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("EntityId") + .HasColumnType("uuid"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("FieldName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NewValue") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OccurredAt") + .HasColumnType("timestamp with time zone"); + + b.Property("OldValue") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ActorUserId"); + + b.HasIndex("BudgetYearId"); + + b.HasIndex("OccurredAt"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("budget_audit_logs", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllocatedAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("BudgetGroupId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpenditureType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("TeamId") + .HasFilter("\"TeamId\" IS NOT NULL"); + + b.HasIndex("BudgetGroupId", "SortOrder"); + + b.ToTable("budget_categories", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BudgetYearId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDepartmentGroup") + .HasColumnType("boolean"); + + b.Property("IsRestricted") + .HasColumnType("boolean"); + + b.Property("IsTicketingGroup") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("BudgetYearId", "SortOrder"); + + b.ToTable("budget_groups", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetLineItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("BudgetCategoryId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ExpectedDate") + .HasColumnType("date"); + + b.Property("IsAutoGenerated") + .HasColumnType("boolean"); + + b.Property("IsCashflowOnly") + .HasColumnType("boolean"); + + b.Property("Notes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ResponsibleTeamId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatRate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ResponsibleTeamId") + .HasFilter("\"ResponsibleTeamId\" IS NOT NULL"); + + b.HasIndex("BudgetCategoryId", "SortOrder"); + + b.ToTable("budget_line_items", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetYear", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Status"); + + b.HasIndex("Year") + .IsUnique(); + + b.ToTable("budget_years", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Camp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContactEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ContactPhone") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByUserId") + .HasColumnType("uuid"); + + b.Property("HideHistoricalNames") + .HasColumnType("boolean"); + + b.Property("IsSwissCamp") + .HasColumnType("boolean"); + + b.Property("Links") + .HasColumnType("jsonb"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TimesAtNowhere") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WebOrSocialUrl") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("Slug") + .IsUnique(); + + b.ToTable("camps", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampHistoricalName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CampId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CampId"); + + b.ToTable("camp_historical_names", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CampId") + .HasColumnType("uuid"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("StoragePath") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CampId"); + + b.ToTable("camp_images", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampLead", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CampId") + .HasColumnType("uuid"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LeftAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("CampId", "UserId") + .IsUnique() + .HasDatabaseName("IX_camp_leads_active_unique") + .HasFilter("\"LeftAt\" IS NULL"); + + b.ToTable("camp_leads", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampPolygon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AreaSqm") + .HasColumnType("double precision"); + + b.Property("CampSeasonId") + .HasColumnType("uuid"); + + b.Property("GeoJson") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastModifiedByUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CampSeasonId") + .IsUnique(); + + b.HasIndex("LastModifiedByUserId"); + + b.ToTable("camp_polygons", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampPolygonHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AreaSqm") + .HasColumnType("double precision"); + + b.Property("CampSeasonId") + .HasColumnType("uuid"); + + b.Property("GeoJson") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedByUserId") + .HasColumnType("uuid"); + + b.Property("Note") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.HasKey("Id"); + + b.HasIndex("ModifiedByUserId"); + + b.HasIndex("CampSeasonId", "ModifiedAt"); + + b.ToTable("camp_polygon_histories", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampSeason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AcceptingMembers") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("AdultPlayspace") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BlurbLong") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("BlurbShort") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("CampId") + .HasColumnType("uuid"); + + b.Property("ContainerCount") + .HasColumnType("integer"); + + b.Property("ContainerNotes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ElectricalGrid") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("HasPerformanceSpace") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("KidsAreaDescription") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("KidsVisiting") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("KidsWelcome") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Languages") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("MemberCount") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NameLockDate") + .HasColumnType("date"); + + b.Property("NameLockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PerformanceTypes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewNotes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ReviewedByUserId") + .HasColumnType("uuid"); + + b.Property("SoundZone") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("SpaceRequirement") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Vibes") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ReviewedByUserId"); + + b.HasIndex("Status"); + + b.HasIndex("CampId", "Year") + .IsUnique(); + + b.ToTable("camp_seasons", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OpenSeasons") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("PublicYear") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("camp_settings", (string)null); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0010-000000000001"), + OpenSeasons = "[2026]", + PublicYear = 2026 + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Campaign", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByUserId") + .HasColumnType("uuid"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("EmailBodyTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("EmailSubject") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ReplyToAddress") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.ToTable("campaigns", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CampaignId") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ImportOrder") + .HasColumnType("integer"); + + b.Property("ImportedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CampaignId", "Code") + .IsUnique(); + + b.ToTable("campaign_codes", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AssignedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CampaignCodeId") + .HasColumnType("uuid"); + + b.Property("CampaignId") + .HasColumnType("uuid"); + + b.Property("LatestEmailAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LatestEmailStatus") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RedeemedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CampaignCodeId") + .IsUnique(); + + b.HasIndex("UserId"); + + b.HasIndex("CampaignId", "UserId") + .IsUnique(); + + b.ToTable("campaign_grants", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CityPlanningSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPlacementOpen") + .HasColumnType("boolean"); + + b.Property("LimitZoneGeoJson") + .HasColumnType("text"); + + b.Property("OfficialZonesGeoJson") + .HasColumnType("text"); + + b.Property("OpenedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PlacementClosesAt") + .HasColumnType("timestamp without time zone"); + + b.Property("PlacementOpensAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RegistrationInfo") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Year") + .IsUnique(); + + b.ToTable("city_planning_settings", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CommunicationPreference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InboxEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("OptedOut") + .HasColumnType("boolean"); + + b.Property("UpdateSource") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Category") + .IsUnique(); + + b.ToTable("communication_preferences", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ConsentRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConsentedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ContentHash") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DocumentVersionId") + .HasColumnType("uuid"); + + b.Property("ExplicitConsent") + .HasColumnType("boolean"); + + b.Property("IpAddress") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("character varying(45)"); + + b.Property("UserAgent") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ConsentedAt"); + + b.HasIndex("DocumentVersionId"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "DocumentVersionId") + .IsUnique(); + + b.HasIndex("UserId", "ExplicitConsent", "ConsentedAt"); + + b.ToTable("consent_records", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ContactField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomLabel") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("DisplayOrder") + .HasColumnType("integer"); + + b.Property("FieldType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ProfileId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Visibility") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "Visibility"); + + b.ToTable("contact_fields", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.DocumentVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChangesSummary") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("CommitSha") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Content") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("LegalDocumentId") + .HasColumnType("uuid"); + + b.Property("RequiresReConsent") + .HasColumnType("boolean"); + + b.Property("VersionNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("CommitSha"); + + b.HasIndex("EffectiveFrom"); + + b.HasIndex("LegalDocumentId"); + + b.ToTable("document_versions", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.EmailOutboxMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CampaignGrantId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtraHeaders") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("HtmlBody") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastError") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("NextRetryAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PickedUpAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PlainTextBody") + .HasColumnType("text"); + + b.Property("RecipientEmail") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RecipientName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ReplyTo") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ShiftSignupId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CampaignGrantId"); + + b.HasIndex("UserId"); + + b.HasIndex("ShiftSignupId", "TemplateName") + .HasFilter("\"ShiftSignupId\" IS NOT NULL"); + + b.HasIndex("SentAt", "RetryCount", "NextRetryAt", "PickedUpAt"); + + b.ToTable("email_outbox_messages", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.EventSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BarriosEarlyEntryAllocation") + .HasColumnType("jsonb"); + + b.Property("BuildStartOffset") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EarlyEntryCapacity") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("EarlyEntryClose") + .HasColumnType("timestamp with time zone"); + + b.Property("EventEndOffset") + .HasColumnType("integer"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GateOpeningDate") + .HasColumnType("date"); + + b.Property("GlobalVolunteerCap") + .HasColumnType("integer"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsShiftBrowsingOpen") + .HasColumnType("boolean"); + + b.Property("ReminderLeadTimeHours") + .HasColumnType("integer"); + + b.Property("StrikeEndOffset") + .HasColumnType("integer"); + + b.Property("TimeZoneId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("IsActive"); + + b.ToTable("event_settings", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.FeedbackMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(5000) + .HasColumnType("character varying(5000)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FeedbackReportId") + .HasColumnType("uuid"); + + b.Property("SenderUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("FeedbackReportId"); + + b.HasIndex("SenderUserId"); + + b.ToTable("feedback_messages", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.FeedbackReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdditionalContext") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("AssignedToTeamId") + .HasColumnType("uuid"); + + b.Property("AssignedToUserId") + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(5000) + .HasColumnType("character varying(5000)"); + + b.Property("GitHubIssueNumber") + .HasColumnType("integer"); + + b.Property("LastAdminMessageAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastReporterMessageAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PageUrl") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResolvedByUserId") + .HasColumnType("uuid"); + + b.Property("ScreenshotContentType") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ScreenshotFileName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ScreenshotStoragePath") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssignedToTeamId"); + + b.HasIndex("AssignedToUserId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("ResolvedByUserId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId"); + + b.ToTable("feedback_reports", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GeneralAvailability", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.PrimitiveCollection("AvailableDayOffsets") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventSettingsId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EventSettingsId"); + + b.HasIndex("UserId", "EventSettingsId") + .IsUnique(); + + b.ToTable("general_availability", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GoogleResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DrivePermissionLevel") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ErrorMessage") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("GoogleId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("LastSyncedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ProvisionedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResourceType") + .IsRequired() + .HasColumnType("text"); + + b.Property("RestrictInheritedAccess") + .HasColumnType("boolean"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("Url") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GoogleId"); + + b.HasIndex("IsActive"); + + b.HasIndex("TeamId"); + + b.HasIndex("TeamId", "GoogleId") + .IsUnique() + .HasFilter("\"IsActive\" = true"); + + b.ToTable("google_resources", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GoogleSyncOutboxEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DeduplicationKey") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("FailedPermanently") + .HasColumnType("boolean"); + + b.Property("LastError") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("OccurredAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ProcessedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RetryCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DeduplicationKey") + .IsUnique(); + + b.HasIndex("UserId"); + + b.HasIndex("ProcessedAt", "OccurredAt"); + + b.HasIndex("TeamId", "UserId", "ProcessedAt"); + + b.ToTable("google_sync_outbox", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.LegalDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CurrentCommitSha") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("GitHubFolderPath") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("GracePeriodDays") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(7); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsRequired") + .HasColumnType("boolean"); + + b.Property("LastSyncedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("IsActive"); + + b.HasIndex("TeamId", "IsActive"); + + b.ToTable("legal_documents", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionLabel") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ActionUrl") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Body") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("Class") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResolvedByUserId") + .HasColumnType("uuid"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TargetGroupName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("NotificationId", "UserId"); + + b.HasIndex("UserId") + .HasDatabaseName("IX_NotificationRecipient_UserId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdminNotes") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("Bio") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("BoardNotes") + .HasColumnType("text"); + + b.Property("BurnerName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("City") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ConsentCheckAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConsentCheckNotes") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ConsentCheckStatus") + .HasColumnType("text"); + + b.Property("ConsentCheckedByUserId") + .HasColumnType("uuid"); + + b.Property("ContributionInterests") + .HasColumnType("text"); + + b.Property("CountryCode") + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DateOfBirth") + .HasColumnType("date"); + + b.Property("EmergencyContactName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("IsApproved") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("IsSuspended") + .HasColumnType("boolean"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("MembershipTier") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Volunteer"); + + b.Property("NoPriorBurnExperience") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("PlaceId") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ProfilePictureContentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ProfilePictureData") + .HasColumnType("bytea"); + + b.Property("Pronouns") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RejectedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RejectedByUserId") + .HasColumnType("uuid"); + + b.Property("RejectionReason") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ConsentCheckStatus"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("profiles", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ProfileLanguage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LanguageCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("Proficiency") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ProfileId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_languages", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.RoleAssignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByUserId") + .HasColumnType("uuid"); + + b.Property("Notes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("ValidTo") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("RoleName"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "RoleName") + .HasFilter("\"ValidTo\" IS NULL"); + + b.HasIndex("UserId", "RoleName", "ValidFrom"); + + b.ToTable("role_assignments", null, t => + { + t.HasCheckConstraint("CK_role_assignments_valid_window", "\"ValidTo\" IS NULL OR \"ValidTo\" > \"ValidFrom\""); + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Rota", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("EventSettingsId") + .HasColumnType("uuid"); + + b.Property("IsVisibleToVolunteers") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Period") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Policy") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PracticalInfo") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("TeamId"); + + b.HasIndex("EventSettingsId", "TeamId"); + + b.ToTable("rotas", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Shift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AdminOnly") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DayOffset") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("Duration") + .HasColumnType("bigint"); + + b.Property("IsAllDay") + .HasColumnType("boolean"); + + b.Property("MaxVolunteers") + .HasColumnType("integer"); + + b.Property("MinVolunteers") + .HasColumnType("integer"); + + b.Property("RotaId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("time"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("RotaId"); + + b.ToTable("shifts", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ShiftSignup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Enrolled") + .HasColumnType("boolean"); + + b.Property("EnrolledByUserId") + .HasColumnType("uuid"); + + b.Property("ReviewedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewedByUserId") + .HasColumnType("uuid"); + + b.Property("ShiftId") + .HasColumnType("uuid"); + + b.Property("SignupBlockId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("StatusReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EnrolledByUserId"); + + b.HasIndex("ReviewedByUserId"); + + b.HasIndex("ShiftId"); + + b.HasIndex("SignupBlockId"); + + b.HasIndex("UserId"); + + b.HasIndex("ShiftId", "Status"); + + b.ToTable("shift_signups", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ShiftTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("IX_shift_tags_name_unique"); + + b.ToTable("shift_tags", (string)null); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0003-000000000001"), + Name = "Heavy lifting" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000002"), + Name = "Working in the sun" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000003"), + Name = "Working in the shade" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000004"), + Name = "Organisational task" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000005"), + Name = "Meeting new people" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000006"), + Name = "Looking after folks" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000007"), + Name = "Exploring the site" + }, + new + { + Id = new Guid("00000000-0000-0000-0003-000000000008"), + Name = "Feeding and hydrating folks" + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.SyncServiceSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ServiceType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("SyncMode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedByUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ServiceType") + .IsUnique(); + + b.HasIndex("UpdatedByUserId"); + + b.ToTable("sync_service_settings", (string)null); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0002-000000000001"), + ServiceType = "GoogleDrive", + SyncMode = "None", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17730144000000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000002"), + ServiceType = "GoogleGroups", + SyncMode = "None", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17730144000000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000003"), + ServiceType = "Discord", + SyncMode = "None", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17730144000000000L) + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.SystemSetting", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.HasKey("Key"); + + b.ToTable("system_settings", (string)null); + + b.HasData( + new + { + Key = "IsEmailSendingPaused", + Value = "false" + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Team", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CallsToAction") + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomSlug") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("GoogleGroupPrefix") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("HasBudget") + .HasColumnType("boolean"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsHidden") + .HasColumnType("boolean"); + + b.Property("IsPublicPage") + .HasColumnType("boolean"); + + b.Property("IsSensitive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PageContent") + .HasMaxLength(50000) + .HasColumnType("character varying(50000)"); + + b.Property("PageContentUpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PageContentUpdatedByUserId") + .HasColumnType("uuid"); + + b.Property("ParentTeamId") + .HasColumnType("uuid"); + + b.Property("RequiresApproval") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ShowCoordinatorsOnPublicPage") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SystemTeamType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CustomSlug") + .IsUnique() + .HasFilter("\"CustomSlug\" IS NOT NULL"); + + b.HasIndex("GoogleGroupPrefix") + .IsUnique() + .HasFilter("\"GoogleGroupPrefix\" IS NOT NULL"); + + b.HasIndex("IsActive"); + + b.HasIndex("ParentTeamId"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("SystemTeamType"); + + b.ToTable("teams", (string)null); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "All active volunteers with signed required documents", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Volunteers", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "volunteers", + SystemTeamType = "Volunteers", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "All team coordinators", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Coordinators", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "coordinators", + SystemTeamType = "Coordinators", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "Board members with active role assignments", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Board", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "board", + SystemTeamType = "Board", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "Voting members with approved asociado applications", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Asociados", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "asociados", + SystemTeamType = "Asociados", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000005"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "Active contributors with approved colaborador applications", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Colaboradors", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "colaboradors", + SystemTeamType = "Colaboradors", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000006"), + CreatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L), + Description = "All active camp leads across all camps", + HasBudget = false, + IsActive = true, + IsHidden = false, + IsPublicPage = false, + IsSensitive = false, + Name = "Barrio Leads", + RequiresApproval = false, + ShowCoordinatorsOnPublicPage = true, + Slug = "barrio-leads", + SystemTeamType = "BarrioLeads", + UpdatedAt = NodaTime.Instant.FromUnixTimeTicks(17702491570000000L) + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamJoinRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Message") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("RequestedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReviewNotes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ReviewedByUserId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ReviewedByUserId"); + + b.HasIndex("Status"); + + b.HasIndex("TeamId"); + + b.HasIndex("UserId"); + + b.HasIndex("TeamId", "UserId", "Status"); + + b.ToTable("team_join_requests", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamJoinRequestStateHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ChangedByUserId") + .HasColumnType("uuid"); + + b.Property("Notes") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TeamJoinRequestId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ChangedAt"); + + b.HasIndex("ChangedByUserId"); + + b.HasIndex("TeamJoinRequestId"); + + b.ToTable("team_join_request_state_history", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LeftAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Role"); + + b.HasIndex("UserId"); + + b.HasIndex("TeamId", "UserId") + .IsUnique() + .HasDatabaseName("IX_team_members_active_unique") + .HasFilter("\"LeftAt\" IS NULL"); + + b.ToTable("team_members", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamRoleAssignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AssignedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("AssignedByUserId") + .HasColumnType("uuid"); + + b.Property("SlotIndex") + .HasColumnType("integer"); + + b.Property("TeamMemberId") + .HasColumnType("uuid"); + + b.Property("TeamRoleDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssignedByUserId"); + + b.HasIndex("TeamMemberId"); + + b.HasIndex("TeamRoleDefinitionId", "SlotIndex") + .IsUnique() + .HasDatabaseName("IX_team_role_assignments_definition_slot_unique"); + + b.HasIndex("TeamRoleDefinitionId", "TeamMemberId") + .IsUnique() + .HasDatabaseName("IX_team_role_assignments_definition_member_unique"); + + b.ToTable("team_role_assignments", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamRoleDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("IsManagement") + .HasColumnType("boolean"); + + b.Property("IsPublic") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Period") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Priorities") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasDefaultValueSql("''"); + + b.Property("SlotCount") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("TeamId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("TeamId"); + + b.HasIndex("TeamId", "Name") + .IsUnique() + .HasDatabaseName("IX_team_role_definitions_team_name_unique"); + + b.ToTable("team_role_definitions", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketAttendee", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AttendeeEmail") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("AttendeeName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("MatchedUserId") + .HasColumnType("uuid"); + + b.Property("Price") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SyncedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("TicketOrderId") + .HasColumnType("uuid"); + + b.Property("TicketTypeName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("VendorEventId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("VendorTicketId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("AttendeeEmail"); + + b.HasIndex("MatchedUserId"); + + b.HasIndex("TicketOrderId"); + + b.HasIndex("VendorTicketId") + .IsUnique(); + + b.ToTable("ticket_attendees", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationFee") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("BuyerEmail") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("BuyerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("DiscountAmount") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("DiscountCode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("DonationAmount") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("MatchedUserId") + .HasColumnType("uuid"); + + b.Property("PaymentMethod") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PaymentMethodDetail") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PaymentStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("PurchasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("StripeFee") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("StripePaymentIntentId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SyncedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("TotalAmount") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("VatAmount") + .HasPrecision(10, 2) + .HasColumnType("numeric(10,2)"); + + b.Property("VendorDashboardUrl") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("VendorEventId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("VendorOrderId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("BuyerEmail"); + + b.HasIndex("MatchedUserId"); + + b.HasIndex("PaymentMethod"); + + b.HasIndex("PurchasedAt"); + + b.HasIndex("VendorOrderId") + .IsUnique(); + + b.ToTable("ticket_orders", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketSyncState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LastError") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("LastSyncAt") + .HasColumnType("timestamp with time zone"); + + b.Property("StatusChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("SyncStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorEventId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("ticket_sync_state", (string)null); + + b.HasData( + new + { + Id = 1, + SyncStatus = "Idle", + VendorEventId = "" + }); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketingProjection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AverageTicketPrice") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("BudgetGroupId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DailySalesRate") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EventDate") + .HasColumnType("date"); + + b.Property("InitialSalesCount") + .HasColumnType("integer"); + + b.Property("StartDate") + .HasColumnType("date"); + + b.Property("StripeFeeFixed") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("StripeFeePercent") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TicketTailorFeePercent") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatRate") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("BudgetGroupId") + .IsUnique(); + + b.ToTable("ticketing_projections", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("ContactSource") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionEligibleAfter") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionRequestedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionScheduledFor") + .HasColumnType("timestamp with time zone"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("ExternalSourceId") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GoogleEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GoogleEmailStatus") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValue("Unknown"); + + b.Property("ICalToken") + .HasColumnType("uuid"); + + b.Property("LastConsentReminderSentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastLoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("MagicLinkSentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("PreferredLanguage") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasDefaultValue("en"); + + b.Property("ProfilePictureUrl") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("SuppressScheduleChangeEmails") + .HasColumnType("boolean"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UnsubscribedFromCampaigns") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("ContactSource", "ExternalSourceId") + .HasFilter("\"ExternalSourceId\" IS NOT NULL"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.UserEmail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DisplayOrder") + .HasColumnType("integer"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("IsNotificationTarget") + .HasColumnType("boolean"); + + b.Property("IsOAuth") + .HasColumnType("boolean"); + + b.Property("IsVerified") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("VerificationSentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Visibility") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique() + .HasFilter("\"IsVerified\" = true"); + + b.HasIndex("UserId"); + + b.ToTable("user_emails", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerEventProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Allergies") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("AllergyOtherText") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DietaryPreference") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IntoleranceOtherText") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Intolerances") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Languages") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("MedicalConditions") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("Quirks") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("volunteer_event_profiles", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerHistoryEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ProfileId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("volunteer_history_entries", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerTagPreference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ShiftTagId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ShiftTagId"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "ShiftTagId") + .IsUnique() + .HasDatabaseName("IX_volunteer_tag_preferences_user_tag_unique"); + + b.ToTable("volunteer_tag_preferences", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("role_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("user_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("user_logins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("user_roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("user_tokens", (string)null); + }); + + modelBuilder.Entity("RotaShiftTag", b => + { + b.Property("RotaId") + .HasColumnType("uuid"); + + b.Property("ShiftTagId") + .HasColumnType("uuid"); + + b.HasKey("RotaId", "ShiftTagId"); + + b.HasIndex("ShiftTagId"); + + b.ToTable("rota_shift_tags", (string)null); + }); + + modelBuilder.Entity("Humans.Domain.Entities.AccountMergeRequest", b => + { + b.HasOne("Humans.Domain.Entities.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "SourceUser") + .WithMany() + .HasForeignKey("SourceUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "TargetUser") + .WithMany() + .HasForeignKey("TargetUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ResolvedByUser"); + + b.Navigation("SourceUser"); + + b.Navigation("TargetUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Application", b => + { + b.HasOne("Humans.Domain.Entities.User", "ReviewedByUser") + .WithMany() + .HasForeignKey("ReviewedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("Applications") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReviewedByUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ApplicationStateHistory", b => + { + b.HasOne("Humans.Domain.Entities.Application", "Application") + .WithMany("StateHistory") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "ChangedByUser") + .WithMany() + .HasForeignKey("ChangedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("ChangedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.AuditLogEntry", b => + { + b.HasOne("Humans.Domain.Entities.User", "ActorUser") + .WithMany() + .HasForeignKey("ActorUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.GoogleResource", "Resource") + .WithMany() + .HasForeignKey("ResourceId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ActorUser"); + + b.Navigation("Resource"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BoardVote", b => + { + b.HasOne("Humans.Domain.Entities.Application", "Application") + .WithMany("BoardVotes") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "BoardMemberUser") + .WithMany() + .HasForeignKey("BoardMemberUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("BoardMemberUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetAuditLog", b => + { + b.HasOne("Humans.Domain.Entities.User", "ActorUser") + .WithMany() + .HasForeignKey("ActorUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.BudgetYear", "BudgetYear") + .WithMany("AuditLogs") + .HasForeignKey("BudgetYearId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ActorUser"); + + b.Navigation("BudgetYear"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetCategory", b => + { + b.HasOne("Humans.Domain.Entities.BudgetGroup", "BudgetGroup") + .WithMany("Categories") + .HasForeignKey("BudgetGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("BudgetGroup"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetGroup", b => + { + b.HasOne("Humans.Domain.Entities.BudgetYear", "BudgetYear") + .WithMany("Groups") + .HasForeignKey("BudgetYearId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetYear"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetLineItem", b => + { + b.HasOne("Humans.Domain.Entities.BudgetCategory", "BudgetCategory") + .WithMany("LineItems") + .HasForeignKey("BudgetCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.Team", "ResponsibleTeam") + .WithMany() + .HasForeignKey("ResponsibleTeamId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("BudgetCategory"); + + b.Navigation("ResponsibleTeam"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Camp", b => + { + b.HasOne("Humans.Domain.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampHistoricalName", b => + { + b.HasOne("Humans.Domain.Entities.Camp", "Camp") + .WithMany("HistoricalNames") + .HasForeignKey("CampId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Camp"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampImage", b => + { + b.HasOne("Humans.Domain.Entities.Camp", "Camp") + .WithMany("Images") + .HasForeignKey("CampId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Camp"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampLead", b => + { + b.HasOne("Humans.Domain.Entities.Camp", "Camp") + .WithMany("Leads") + .HasForeignKey("CampId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Camp"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampPolygon", b => + { + b.HasOne("Humans.Domain.Entities.CampSeason", "CampSeason") + .WithMany() + .HasForeignKey("CampSeasonId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CampSeason"); + + b.Navigation("LastModifiedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampPolygonHistory", b => + { + b.HasOne("Humans.Domain.Entities.CampSeason", "CampSeason") + .WithMany() + .HasForeignKey("CampSeasonId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "ModifiedByUser") + .WithMany() + .HasForeignKey("ModifiedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CampSeason"); + + b.Navigation("ModifiedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampSeason", b => + { + b.HasOne("Humans.Domain.Entities.Camp", "Camp") + .WithMany("Seasons") + .HasForeignKey("CampId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "ReviewedByUser") + .WithMany() + .HasForeignKey("ReviewedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Camp"); + + b.Navigation("ReviewedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Campaign", b => + { + b.HasOne("Humans.Domain.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignCode", b => + { + b.HasOne("Humans.Domain.Entities.Campaign", "Campaign") + .WithMany("Codes") + .HasForeignKey("CampaignId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Campaign"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignGrant", b => + { + b.HasOne("Humans.Domain.Entities.CampaignCode", "Code") + .WithOne("Grant") + .HasForeignKey("Humans.Domain.Entities.CampaignGrant", "CampaignCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.Campaign", "Campaign") + .WithMany("Grants") + .HasForeignKey("CampaignId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Campaign"); + + b.Navigation("Code"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CommunicationPreference", b => + { + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("CommunicationPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ConsentRecord", b => + { + b.HasOne("Humans.Domain.Entities.DocumentVersion", "DocumentVersion") + .WithMany("ConsentRecords") + .HasForeignKey("DocumentVersionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("ConsentRecords") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DocumentVersion"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ContactField", b => + { + b.HasOne("Humans.Domain.Entities.Profile", "Profile") + .WithMany("ContactFields") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.DocumentVersion", b => + { + b.HasOne("Humans.Domain.Entities.LegalDocument", "LegalDocument") + .WithMany("Versions") + .HasForeignKey("LegalDocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LegalDocument"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.EmailOutboxMessage", b => + { + b.HasOne("Humans.Domain.Entities.CampaignGrant", "CampaignGrant") + .WithMany("OutboxMessages") + .HasForeignKey("CampaignGrantId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.ShiftSignup", "ShiftSignup") + .WithMany() + .HasForeignKey("ShiftSignupId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CampaignGrant"); + + b.Navigation("ShiftSignup"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.FeedbackMessage", b => + { + b.HasOne("Humans.Domain.Entities.FeedbackReport", "FeedbackReport") + .WithMany("Messages") + .HasForeignKey("FeedbackReportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "SenderUser") + .WithMany() + .HasForeignKey("SenderUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("FeedbackReport"); + + b.Navigation("SenderUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.FeedbackReport", b => + { + b.HasOne("Humans.Domain.Entities.Team", "AssignedToTeam") + .WithMany() + .HasForeignKey("AssignedToTeamId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "AssignedToUser") + .WithMany() + .HasForeignKey("AssignedToUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssignedToTeam"); + + b.Navigation("AssignedToUser"); + + b.Navigation("ResolvedByUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GeneralAvailability", b => + { + b.HasOne("Humans.Domain.Entities.EventSettings", "EventSettings") + .WithMany() + .HasForeignKey("EventSettingsId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EventSettings"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GoogleResource", b => + { + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany("GoogleResources") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired(); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.GoogleSyncOutboxEvent", b => + { + b.HasOne("Humans.Domain.Entities.Team", null) + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Humans.Domain.Entities.LegalDocument", b => + { + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany("LegalDocuments") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Notification", b => + { + b.HasOne("Humans.Domain.Entities.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("Humans.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Profile", b => + { + b.HasOne("Humans.Domain.Entities.User", "User") + .WithOne("Profile") + .HasForeignKey("Humans.Domain.Entities.Profile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ProfileLanguage", b => + { + b.HasOne("Humans.Domain.Entities.Profile", "Profile") + .WithMany("Languages") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.RoleAssignment", b => + { + b.HasOne("Humans.Domain.Entities.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("RoleAssignments") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Rota", b => + { + b.HasOne("Humans.Domain.Entities.EventSettings", "EventSettings") + .WithMany("Rotas") + .HasForeignKey("EventSettingsId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EventSettings"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Shift", b => + { + b.HasOne("Humans.Domain.Entities.Rota", "Rota") + .WithMany("Shifts") + .HasForeignKey("RotaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Rota"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ShiftSignup", b => + { + b.HasOne("Humans.Domain.Entities.User", "EnrolledByUser") + .WithMany() + .HasForeignKey("EnrolledByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.User", "ReviewedByUser") + .WithMany() + .HasForeignKey("ReviewedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.Shift", "Shift") + .WithMany("ShiftSignups") + .HasForeignKey("ShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EnrolledByUser"); + + b.Navigation("ReviewedByUser"); + + b.Navigation("Shift"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.SyncServiceSettings", b => + { + b.HasOne("Humans.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedByUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Team", b => + { + b.HasOne("Humans.Domain.Entities.Team", "ParentTeam") + .WithMany("ChildTeams") + .HasForeignKey("ParentTeamId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ParentTeam"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamJoinRequest", b => + { + b.HasOne("Humans.Domain.Entities.User", "ReviewedByUser") + .WithMany() + .HasForeignKey("ReviewedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany("JoinRequests") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReviewedByUser"); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamJoinRequestStateHistory", b => + { + b.HasOne("Humans.Domain.Entities.User", "ChangedByUser") + .WithMany() + .HasForeignKey("ChangedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.TeamJoinRequest", "TeamJoinRequest") + .WithMany("StateHistory") + .HasForeignKey("TeamJoinRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChangedByUser"); + + b.Navigation("TeamJoinRequest"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamMember", b => + { + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("TeamMemberships") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamRoleAssignment", b => + { + b.HasOne("Humans.Domain.Entities.User", "AssignedByUser") + .WithMany() + .HasForeignKey("AssignedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.TeamMember", "TeamMember") + .WithMany("RoleAssignments") + .HasForeignKey("TeamMemberId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.TeamRoleDefinition", "TeamRoleDefinition") + .WithMany("Assignments") + .HasForeignKey("TeamRoleDefinitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssignedByUser"); + + b.Navigation("TeamMember"); + + b.Navigation("TeamRoleDefinition"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamRoleDefinition", b => + { + b.HasOne("Humans.Domain.Entities.Team", "Team") + .WithMany("RoleDefinitions") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketAttendee", b => + { + b.HasOne("Humans.Domain.Entities.User", "MatchedUser") + .WithMany() + .HasForeignKey("MatchedUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Humans.Domain.Entities.TicketOrder", "TicketOrder") + .WithMany("Attendees") + .HasForeignKey("TicketOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MatchedUser"); + + b.Navigation("TicketOrder"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketOrder", b => + { + b.HasOne("Humans.Domain.Entities.User", "MatchedUser") + .WithMany() + .HasForeignKey("MatchedUserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("MatchedUser"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketingProjection", b => + { + b.HasOne("Humans.Domain.Entities.BudgetGroup", "BudgetGroup") + .WithOne("TicketingProjection") + .HasForeignKey("Humans.Domain.Entities.TicketingProjection", "BudgetGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BudgetGroup"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.UserEmail", b => + { + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany("UserEmails") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerEventProfile", b => + { + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerHistoryEntry", b => + { + b.HasOne("Humans.Domain.Entities.Profile", "Profile") + .WithMany("VolunteerHistory") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.VolunteerTagPreference", b => + { + b.HasOne("Humans.Domain.Entities.ShiftTag", "ShiftTag") + .WithMany("VolunteerPreferences") + .HasForeignKey("ShiftTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ShiftTag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Humans.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Humans.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Humans.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RotaShiftTag", b => + { + b.HasOne("Humans.Domain.Entities.Rota", null) + .WithMany() + .HasForeignKey("RotaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Humans.Domain.Entities.ShiftTag", null) + .WithMany() + .HasForeignKey("ShiftTagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Application", b => + { + b.Navigation("BoardVotes"); + + b.Navigation("StateHistory"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetCategory", b => + { + b.Navigation("LineItems"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetGroup", b => + { + b.Navigation("Categories"); + + b.Navigation("TicketingProjection"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.BudgetYear", b => + { + b.Navigation("AuditLogs"); + + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Camp", b => + { + b.Navigation("HistoricalNames"); + + b.Navigation("Images"); + + b.Navigation("Leads"); + + b.Navigation("Seasons"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Campaign", b => + { + b.Navigation("Codes"); + + b.Navigation("Grants"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignCode", b => + { + b.Navigation("Grant"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.CampaignGrant", b => + { + b.Navigation("OutboxMessages"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.DocumentVersion", b => + { + b.Navigation("ConsentRecords"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.EventSettings", b => + { + b.Navigation("Rotas"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.FeedbackReport", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.LegalDocument", b => + { + b.Navigation("Versions"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Profile", b => + { + b.Navigation("ContactFields"); + + b.Navigation("Languages"); + + b.Navigation("VolunteerHistory"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Rota", b => + { + b.Navigation("Shifts"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Shift", b => + { + b.Navigation("ShiftSignups"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.ShiftTag", b => + { + b.Navigation("VolunteerPreferences"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.Team", b => + { + b.Navigation("ChildTeams"); + + b.Navigation("GoogleResources"); + + b.Navigation("JoinRequests"); + + b.Navigation("LegalDocuments"); + + b.Navigation("Members"); + + b.Navigation("RoleDefinitions"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamJoinRequest", b => + { + b.Navigation("StateHistory"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamMember", b => + { + b.Navigation("RoleAssignments"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TeamRoleDefinition", b => + { + b.Navigation("Assignments"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.TicketOrder", b => + { + b.Navigation("Attendees"); + }); + + modelBuilder.Entity("Humans.Domain.Entities.User", b => + { + b.Navigation("Applications"); + + b.Navigation("CommunicationPreferences"); + + b.Navigation("ConsentRecords"); + + b.Navigation("Profile"); + + b.Navigation("RoleAssignments"); + + b.Navigation("TeamMemberships"); + + b.Navigation("UserEmails"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.cs b/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.cs new file mode 100644 index 00000000..caf7f13f --- /dev/null +++ b/src/Humans.Infrastructure/Migrations/20260410145936_AddRegistrationInfoToCityPlanningSettings.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Humans.Infrastructure.Migrations +{ + /// + public partial class AddRegistrationInfoToCityPlanningSettings : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RegistrationInfo", + table: "city_planning_settings", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RegistrationInfo", + table: "city_planning_settings"); + } + } +} diff --git a/src/Humans.Infrastructure/Migrations/HumansDbContextModelSnapshot.cs b/src/Humans.Infrastructure/Migrations/HumansDbContextModelSnapshot.cs index afb218ba..220952da 100644 --- a/src/Humans.Infrastructure/Migrations/HumansDbContextModelSnapshot.cs +++ b/src/Humans.Infrastructure/Migrations/HumansDbContextModelSnapshot.cs @@ -1069,6 +1069,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PlacementOpensAt") .HasColumnType("timestamp without time zone"); + b.Property("RegistrationInfo") + .HasColumnType("text"); + b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); diff --git a/src/Humans.Infrastructure/Services/CityPlanningService.cs b/src/Humans.Infrastructure/Services/CityPlanningService.cs index 30fd946e..8e59a062 100644 --- a/src/Humans.Infrastructure/Services/CityPlanningService.cs +++ b/src/Humans.Infrastructure/Services/CityPlanningService.cs @@ -268,6 +268,14 @@ public async Task UpdatePlacementDatesAsync(LocalDateTime? opensAt, LocalDateTim await _dbContext.SaveChangesAsync(cancellationToken); } + public async Task UpdateRegistrationInfoAsync(string? registrationInfo, CancellationToken cancellationToken = default) + { + var settings = await GetSettingsAsync(cancellationToken); + settings.RegistrationInfo = string.IsNullOrWhiteSpace(registrationInfo) ? null : registrationInfo.Trim(); + settings.UpdatedAt = _clock.GetCurrentInstant(); + await _dbContext.SaveChangesAsync(cancellationToken); + } + public async Task ExportAsGeoJsonAsync(int year, CancellationToken cancellationToken = default) { var polygons = await _dbContext.CampPolygons diff --git a/src/Humans.Web/Controllers/CampAdminController.cs b/src/Humans.Web/Controllers/CampAdminController.cs index 6e566fef..b43fb3e1 100644 --- a/src/Humans.Web/Controllers/CampAdminController.cs +++ b/src/Humans.Web/Controllers/CampAdminController.cs @@ -20,17 +20,20 @@ namespace Humans.Web.Controllers; public class CampAdminController : HumansControllerBase { private readonly ICampService _campService; + private readonly ICityPlanningService _cityPlanningService; private readonly HumansDbContext _dbContext; private readonly ILogger _logger; public CampAdminController( ICampService campService, + ICityPlanningService cityPlanningService, HumansDbContext dbContext, UserManager userManager, ILogger logger) : base(userManager) { _campService = campService; + _cityPlanningService = cityPlanningService; _dbContext = dbContext; _logger = logger; } @@ -41,6 +44,7 @@ public async Task Index() try { var settings = await _campService.GetSettingsAsync(); + var cityPlanningSettings = await _cityPlanningService.GetSettingsAsync(); var allCamps = await _campService.GetAllCampsForYearAsync(settings.PublicYear); var pendingSeasons = await _campService.GetPendingSeasonsAsync(); @@ -105,6 +109,7 @@ public async Task Index() WithdrawnCamps = withdrawnSeasons, NameLockDates = nameLockDates, AllCampSummaries = summaries, + RegistrationInfo = cityPlanningSettings.RegistrationInfo, PendingCamps = pendingSeasons.Select(s => new CampCardViewModel { Id = s.CampId, @@ -338,6 +343,23 @@ public async Task ExportCamps() } } + [HttpPost("UpdateRegistrationInfo")] + [ValidateAntiForgeryToken] + public async Task UpdateRegistrationInfo([FromForm] string? registrationInfo) + { + try + { + await _cityPlanningService.UpdateRegistrationInfoAsync(registrationInfo); + SetSuccess("Registration info updated."); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to update registration info"); + SetError("Failed to update registration info."); + } + return RedirectToAction(nameof(Index)); + } + [HttpPost("Delete")] [ValidateAntiForgeryToken] [Authorize(Policy = PolicyNames.AdminOnly)] diff --git a/src/Humans.Web/Controllers/CampController.cs b/src/Humans.Web/Controllers/CampController.cs index e6502a29..3f5fe961 100644 --- a/src/Humans.Web/Controllers/CampController.cs +++ b/src/Humans.Web/Controllers/CampController.cs @@ -18,6 +18,7 @@ public class CampController : HumansCampControllerBase { private readonly ICampService _campService; private readonly ICampContactService _campContactService; + private readonly ICityPlanningService _cityPlanningService; private readonly INotificationService _notificationService; private readonly IClock _clock; private readonly ILogger _logger; @@ -26,6 +27,7 @@ public class CampController : HumansCampControllerBase public CampController( ICampService campService, ICampContactService campContactService, + ICityPlanningService cityPlanningService, INotificationService notificationService, UserManager userManager, IAuthorizationService authorizationService, @@ -36,6 +38,7 @@ public CampController( { _campService = campService; _campContactService = campContactService; + _cityPlanningService = cityPlanningService; _notificationService = notificationService; _clock = clock; _logger = logger; @@ -95,6 +98,12 @@ private async Task PopulateRegisterSeasonYearAsync() ViewData["SeasonYear"] = settings.OpenSeasons.OrderByDescending(y => y).FirstOrDefault(); } + private async Task PopulateRegistrationInfoAsync() + { + var cityPlanningSettings = await _cityPlanningService.GetSettingsAsync(); + ViewData["RegistrationInfo"] = cityPlanningSettings.RegistrationInfo; + } + [AllowAnonymous] [HttpGet("{slug}")] public async Task Details(string slug) @@ -246,6 +255,7 @@ public async Task Register() return RedirectToAction(nameof(Index)); } + await PopulateRegistrationInfoAsync(); return View(new CampRegisterViewModel()); } @@ -259,6 +269,7 @@ public async Task Register(CampRegisterViewModel model) if (!ModelState.IsValid) { await PopulateRegisterSeasonYearAsync(); + await PopulateRegistrationInfoAsync(); return View(model); } @@ -307,6 +318,7 @@ public async Task Register(CampRegisterViewModel model) _logger.LogWarning(ex, "Camp registration failed for user {UserId} in year {Year}", user.Id, year); ModelState.AddModelError(string.Empty, ex.Message); await PopulateRegisterSeasonYearAsync(); + await PopulateRegistrationInfoAsync(); return View(model); } } diff --git a/src/Humans.Web/Models/CampViewModels.cs b/src/Humans.Web/Models/CampViewModels.cs index 7ed80098..d3031ab6 100644 --- a/src/Humans.Web/Models/CampViewModels.cs +++ b/src/Humans.Web/Models/CampViewModels.cs @@ -170,6 +170,7 @@ public class CampAdminViewModel public int ActiveCamps { get; set; } public Dictionary NameLockDates { get; set; } = new(); public List AllCampSummaries { get; set; } = new(); + public string? RegistrationInfo { get; set; } } public class CampSummaryRowViewModel diff --git a/src/Humans.Web/Views/Camp/Register.cshtml b/src/Humans.Web/Views/Camp/Register.cshtml index 9c24d46e..77c030d8 100644 --- a/src/Humans.Web/Views/Camp/Register.cshtml +++ b/src/Humans.Web/Views/Camp/Register.cshtml @@ -14,8 +14,143 @@ +@{ + var registrationInfo = ViewData["RegistrationInfo"] as string; +} +@if (!string.IsNullOrWhiteSpace(registrationInfo)) +{ +
+
+ Important Information +
+
+ @Html.SanitizedMarkdown(registrationInfo) +
+
+} +
+@* Barrio Information Accordion *@ +
+
+ What You Need to Know Before Registering Your @Localizer["Camp_Singular"] +
+
+
+ @* Benefits *@ +
+

+ +

+
+
+
    +
  • + + Power access — connection to the electrical grid based on your selected tier +
  • +
  • + + Water supply — access to the shared water infrastructure on site +
  • +
  • + + Placement on the city map — your @Localizer["Camp_Singular"] will be placed in a zone matching your sound and space preferences +
  • +
  • + + Listing and publicity — your @Localizer["Camp_Singular"] appears in the official directory and event guide, visible to all attendees +
  • +
  • + + @Localizer["Camp_Singular"] support resources — access to shared infrastructure, community channels, and coordination support from the city planning team +
  • +
+
+
+
+ + @* Obligations *@ +
+

+ +

+
+
+
    +
  • + + Designate a contact person — at least one human must be reachable for coordination before and during the event +
  • +
  • + + Meet registration deadlines — complete your registration and provide all required information by the deadline set for the current season +
  • +
  • + + Participate in community shifts — contribute to shared duties such as gate shifts, setup, and teardown +
  • +
  • + + Leave No Trace — clean up your area completely at the end of the event, leaving the land as you found it +
  • +
  • + + Follow community guidelines — respect noise zones, fire safety rules, and the principles of the event +
  • +
+
+
+
+ + @* Resources *@ +
+

+ +

+
+
+
    +
  • + + Containers — shipping containers can be arranged for storage and structure; note your needs in the Placement section below +
  • +
  • + + Official pricing — pricing for power, water, and container rental will be shared with registered @Localizer["Camp_Plural"] before the season begins +
  • +
  • + + Recommended vendors — a list of recommended local suppliers for shade structures, generators, and other equipment will be shared after registration +
  • +
  • + + Best practices — first-time @Localizer["Camp_Singular"] leads are encouraged to connect with experienced leads through the community channels for advice on layout, logistics, and community building +
  • +
+
+
+
+
+
+
+
@Html.AntiForgeryToken() diff --git a/src/Humans.Web/Views/CampAdmin/Index.cshtml b/src/Humans.Web/Views/CampAdmin/Index.cshtml index 51c7d38a..539eebfc 100644 --- a/src/Humans.Web/Views/CampAdmin/Index.cshtml +++ b/src/Humans.Web/Views/CampAdmin/Index.cshtml @@ -246,6 +246,27 @@ +@* Registration Info *@ +
+
+ Registration Info +
+
+ + @Html.AntiForgeryToken() +
+ + +
Supports markdown: paragraphs, lists, links, **bold**, *italic*.
+
+ + +
+
+ @* Camp Summary Table *@ @if (Model.AllCampSummaries.Count > 0) {