diff --git a/PrismaDotnetApi/PrismaApi.Api/Controllers/UsersController.cs b/PrismaDotnetApi/PrismaApi.Api/Controllers/UsersController.cs index 4a25ad4..920376c 100644 --- a/PrismaDotnetApi/PrismaApi.Api/Controllers/UsersController.cs +++ b/PrismaDotnetApi/PrismaApi.Api/Controllers/UsersController.cs @@ -61,4 +61,17 @@ public IActionResult AuthPlaceholder(CancellationToken ct = default) { return StatusCode(StatusCodes.Status501NotImplemented); } + + [HttpDelete("users/{userId}")] + // + // Deletes a user. Users can only delete themselves, and the user will be anonymized in the database, but the record will not be deleted for audit purposes. + // + // Thrown when a user attempts to delete a different user. + public async Task DeleteUser([FromRoute] string userId, CancellationToken ct = default) + { + var user = HttpContext.GetLoadedUser(); + + await _userService.DeleteUserAsync(userId, user, ct); + return NoContent(); + } } diff --git a/PrismaDotnetApi/PrismaApi.Application/Interfaces/Services/IUserService.cs b/PrismaDotnetApi/PrismaApi.Application/Interfaces/Services/IUserService.cs index 6d88cd2..2727cd7 100644 --- a/PrismaDotnetApi/PrismaApi.Application/Interfaces/Services/IUserService.cs +++ b/PrismaDotnetApi/PrismaApi.Application/Interfaces/Services/IUserService.cs @@ -9,4 +9,5 @@ public interface IUserService Task> SearchUsersAsync(string query); Task GetOrCreateUserFromContextAsync(HttpContext context); Task> GetByIdsAsync(IEnumerable ids); + Task DeleteUserAsync(string userId, UserOutgoingDto user, CancellationToken ct = default); } diff --git a/PrismaDotnetApi/PrismaApi.Application/Repositories/UserRepository.cs b/PrismaDotnetApi/PrismaApi.Application/Repositories/UserRepository.cs index 3bd33a0..feb022c 100644 --- a/PrismaDotnetApi/PrismaApi.Application/Repositories/UserRepository.cs +++ b/PrismaDotnetApi/PrismaApi.Application/Repositories/UserRepository.cs @@ -1,11 +1,13 @@ using Microsoft.EntityFrameworkCore; using PrismaApi.Application.Interfaces.Repositories; using PrismaApi.Application.Mapping; +using PrismaApi.Domain.Constants; using PrismaApi.Domain.Dtos; using PrismaApi.Domain.Entities; using PrismaApi.Infrastructure.Context; using PrismaApi.Infrastructure.Extensions; using System.Linq.Expressions; +using System.Reflection; namespace PrismaApi.Application.Repositories; @@ -79,4 +81,85 @@ public async Task GetOrAddByUserNameAsync(UserIncomingDto dto, Cancellatio return user; } + + /// + /// Deletes users by their ids. + /// Before deleting, it updates all auditable entities that reference the user to point to the deleted user entry. + /// This is done to avoid foreign key constraint violations when deleting a user. + /// Also, deletes all related project roles for the user + /// + public override async Task DeleteByIdsAsync(IEnumerable ids, Expression>? filterPredicate = null, CancellationToken ct = default) + { + var idsList = ids.ToList(); + var entries = await DbContext.Users + .OptionalWhere(filterPredicate) + .Where(u => idsList.Contains(u.Id)) + .ToListAsync(cancellationToken: ct); + + if (entries.Count == 0) + return; + + var auditableEntityTypes = DbContext.Model.GetEntityTypes() + .Where(t => typeof(AuditableEntity).IsAssignableFrom(t.ClrType) && !t.ClrType.IsAbstract) + .Select(t => t.ClrType) + .Distinct() + .ToList(); + + foreach (var auditableEntityType in auditableEntityTypes) + { + await UpdateAuditableReferencesByTypeAsync(auditableEntityType, idsList, DomainConstants.DeletedUserId, ct); + } + + // delete project roles + var projectRoles = await DbContext.ProjectRoles + .Where(e => idsList.Contains(e.UserId)) + .ToListAsync(cancellationToken: ct); + DbContext.ProjectRoles.RemoveRange(projectRoles); + + foreach (var entry in entries) + { + DbContext.Users.Remove(entry); + } + + await DbContext.SaveChangesAsync(ct); + } + + private async Task UpdateAuditableReferencesByTypeAsync( + Type auditableEntityType, + IReadOnlyCollection idsList, + string userId, + CancellationToken ct) + { + // Use reflection to call the generic method with the specific entity type + var UpdateAuditableReferencesByTypeMethod = typeof(UserRepository) + .GetMethod(nameof(UpdateAuditableReferencesByTypeAsync), BindingFlags.NonPublic | BindingFlags.Static)!; + var genericMethod = UpdateAuditableReferencesByTypeMethod.MakeGenericMethod(auditableEntityType); + var updateTask = (Task?)genericMethod.Invoke(null, [DbContext, idsList, userId, ct]); + if (updateTask == null) + { + throw new InvalidOperationException($"Could not execute auditable reference update for type '{auditableEntityType.Name}'."); + } + await updateTask; + } + + private static Task UpdateAuditableReferencesByTypeAsync( + AppDbContext dbContext, + List idsList, + string userId, + CancellationToken ct) where TEntity : AuditableEntity + { + // Use ExecuteUpdateAsync to update the CreatedById and UpdatedById properties to userId for all entities of type TEntity + return dbContext + .Set() + .Where(e => idsList.Contains(e.CreatedById) || idsList.Contains(e.UpdatedById)) + .ExecuteUpdateAsync( + setters => setters + .SetProperty( + e => e.CreatedById, + e => idsList.Contains(e.CreatedById) ? userId : e.CreatedById) + .SetProperty( + e => e.UpdatedById, + e => idsList.Contains(e.UpdatedById) ? userId : e.UpdatedById), + cancellationToken: ct); + } } diff --git a/PrismaDotnetApi/PrismaApi.Application/Services/UserService.cs b/PrismaDotnetApi/PrismaApi.Application/Services/UserService.cs index 5f1a271..d87b8f3 100644 --- a/PrismaDotnetApi/PrismaApi.Application/Services/UserService.cs +++ b/PrismaDotnetApi/PrismaApi.Application/Services/UserService.cs @@ -34,4 +34,14 @@ public Task GetOrCreateUserFromContextAsync(HttpContext context public Task> SearchUsersAsync(string query) => _userProvider.SearchUsersAsync(query); + + public async Task DeleteUserAsync(string userId, UserOutgoingDto user, CancellationToken ct = default) + { + // user is the user making the request, and only allows to delete itself. + if (userId != user.Id) + { + throw new InvalidOperationException("Users can only delete themselves."); + } + await _userRepository.DeleteByIdsAsync([userId], ct: ct); + } } diff --git a/PrismaDotnetApi/PrismaApi.Domain/Constants/DomainConstants.cs b/PrismaDotnetApi/PrismaApi.Domain/Constants/DomainConstants.cs index 3b4a721..2f69d79 100644 --- a/PrismaDotnetApi/PrismaApi.Domain/Constants/DomainConstants.cs +++ b/PrismaDotnetApi/PrismaApi.Domain/Constants/DomainConstants.cs @@ -12,6 +12,9 @@ public static class DomainConstants public const int MaxOpacity = 100; public const int MinOpacity = 0; public const int DefaultTextSize = 24; + public static readonly string DeletedUserId = + "d008bfdf-fe89-48f3-80a8-777bba4d9bbf"; + public static readonly string DeletedUserName = "Deleted User"; public static readonly Guid DefaultValueMetricId = Guid.Parse("288e0811-7ab6-5d24-b80c-9fa925b848a6"); public static readonly string DefaultValueMetricName = "value"; diff --git a/PrismaDotnetApi/PrismaApi.Domain/Entities/User.cs b/PrismaDotnetApi/PrismaApi.Domain/Entities/User.cs index 49b7ec6..81909c2 100644 --- a/PrismaDotnetApi/PrismaApi.Domain/Entities/User.cs +++ b/PrismaDotnetApi/PrismaApi.Domain/Entities/User.cs @@ -16,5 +16,12 @@ public static void OnModelConfiguring(ModelBuilder modelBuilder) entity.HasKey(e => e.Id); entity.Property(e => e.Name).HasMaxLength(DomainConstants.MaxShortStringLength); }); + modelBuilder.Entity().HasData(new User + { + Id = DomainConstants.DeletedUserId, + Name = DomainConstants.DeletedUserName, + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Utc).AddTicks(1), TimeSpan.Zero), + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Utc).AddTicks(2), TimeSpan.Zero) + }); } } diff --git a/PrismaDotnetApi/PrismaApi.Infrastructure/Context/AppDbContext.cs b/PrismaDotnetApi/PrismaApi.Infrastructure/Context/AppDbContext.cs index 01ce4a0..bcecfe0 100644 --- a/PrismaDotnetApi/PrismaApi.Infrastructure/Context/AppDbContext.cs +++ b/PrismaDotnetApi/PrismaApi.Infrastructure/Context/AppDbContext.cs @@ -167,7 +167,7 @@ private async Task EnforceMinimumProjectRoles(CancellationToken cancellationToke var currentFacilitatorCount = await ProjectRoles .AsNoTracking() .CountAsync(r => r.ProjectId == projectId && - r.Role.IsFacilitator(), + r.Role.ToLower() == ProjectRoleType.Facilitator.ToString().ToLower(), cancellationToken); if (currentFacilitatorCount - facilitatorsBeingRemoved <= 0) diff --git a/PrismaDotnetApi/PrismaApi.Test/Mocks/TestUserService.cs b/PrismaDotnetApi/PrismaApi.Test/Mocks/TestUserService.cs index fca16e9..7df34bd 100644 --- a/PrismaDotnetApi/PrismaApi.Test/Mocks/TestUserService.cs +++ b/PrismaDotnetApi/PrismaApi.Test/Mocks/TestUserService.cs @@ -55,4 +55,14 @@ public async Task> GetByIdsAsync(IEnumerable ids) var users = await _userRepository.GetByIdsAsync(ids, withTracking: false); return users.ToOutgoingDtos(); } + + public async Task DeleteUserAsync(string userId, UserOutgoingDto user, CancellationToken ct = default) + { + // user is the user making the request, and only allows to delete itself. + if (userId != user.Id) + { + throw new InvalidOperationException("Users can only delete themselves."); + } + await _userRepository.DeleteByIdsAsync([userId], ct: ct); + } } diff --git a/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.Designer.cs b/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.Designer.cs new file mode 100644 index 0000000..9fde198 --- /dev/null +++ b/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.Designer.cs @@ -0,0 +1,1840 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PrismaApi.Infrastructure.Context; + +#nullable disable + +namespace PrismaApi.Infrastructure.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260813065703_AddDeletedUser")] + partial class AddDeletedUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BoardSheetId") + .HasColumnType("uniqueidentifier"); + + b.Property("Color") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Data") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Height") + .HasColumnType("float"); + + b.Property("Opacity") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Rotation") + .HasColumnType("float"); + + b.Property("StrokeStyle") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(max)") + .HasDefaultValue("Solid"); + + b.Property("StrokeWidth") + .ValueGeneratedOnAdd() + .HasColumnType("real") + .HasDefaultValue(8f); + + b.Property("TextSize") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(24); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Width") + .HasColumnType("float"); + + b.Property("XPosition") + .HasColumnType("float"); + + b.Property("YPosition") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("BoardSheetId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("BoardNode", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("BoardSheet", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IssueId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Decisions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DecisionQualityAssessment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AppropriateFrame") + .HasColumnType("int"); + + b.Property("AssessmentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("CommitmentToAction") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("DoableAlternatives") + .HasColumnType("int"); + + b.Property("InformationReliability") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("ReasoningCorrectness") + .HasColumnType("int"); + + b.Property("TradeOffAnalysis") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DecisionQualityAssessments", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("OutcomeId") + .HasColumnType("uniqueidentifier"); + + b.Property("Probability") + .HasPrecision(53) + .HasColumnType("float(53)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UncertaintyId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("OutcomeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UncertaintyId"); + + b.ToTable("DiscreteProbabilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOption", b => + { + b.Property("DiscreteProbabilityId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentOptionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("DiscreteProbabilityId", "ParentOptionId"); + + b.HasIndex("ParentOptionId"); + + b.ToTable("DiscreteProbabilityParentOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOutcome", b => + { + b.Property("DiscreteProbabilityId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentOutcomeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("DiscreteProbabilityId", "ParentOutcomeId"); + + b.HasIndex("ParentOutcomeId"); + + b.ToTable("DiscreteProbabilityParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UtilityId") + .HasColumnType("uniqueidentifier"); + + b.Property("UtilityValue") + .HasPrecision(53) + .HasColumnType("float(53)"); + + b.Property("ValueMetricId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UtilityId"); + + b.HasIndex("ValueMetricId"); + + b.ToTable("DiscreteUtilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOption", b => + { + b.Property("DiscreteUtilityId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentOptionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("DiscreteUtilityId", "ParentOptionId"); + + b.HasIndex("ParentOptionId"); + + b.ToTable("DiscreteUtilityParentOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOutcome", b => + { + b.Property("DiscreteUtilityId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentOutcomeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("DiscreteUtilityId", "ParentOutcomeId"); + + b.HasIndex("ParentOutcomeId"); + + b.ToTable("DiscreteUtilityParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Edge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("HeadId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("TailId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("HeadId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TailId"); + + b.ToTable("Edges"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Boundary") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IssueId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Nodes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.NodeStyle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("NodeId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("XPosition") + .HasColumnType("float"); + + b.Property("YPosition") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("NodeId") + .IsUnique(); + + b.ToTable("NodeStyles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Objective", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Objectives"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("DecisionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Utility") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("DecisionId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Options"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Outcome", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UncertaintyId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Utility") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UncertaintyId"); + + b.ToTable("Outcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("EndDate") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("OpportunityStatement") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("ParentProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentProjectName") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Public") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Projects"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ProjectRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("ProjectRoles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ChildOptionId") + .HasColumnType("uniqueidentifier"); + + b.Property("ChildOutcomeId") + .HasColumnType("uniqueidentifier"); + + b.Property("ChildStateId") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("uniqueidentifier") + .HasComputedColumnSql("COALESCE([ChildOptionId], [ChildOutcomeId])", true); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("ParentOptionId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentOutcomeId") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentStateId") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("uniqueidentifier") + .HasComputedColumnSql("COALESCE([ParentOptionId], [ParentOutcomeId])", true); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("RestrictionTableId") + .HasColumnType("uniqueidentifier"); + + b.Property("RestrictionValue") + .ValueGeneratedOnAdd() + .HasPrecision(53) + .HasColumnType("float(53)") + .HasDefaultValue(1.0); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ChildOptionId"); + + b.HasIndex("ChildOutcomeId"); + + b.HasIndex("ParentOptionId"); + + b.HasIndex("ParentOutcomeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("RestrictionTableId"); + + b.HasIndex("ParentStateId", "ChildStateId", "RestrictionTableId") + .IsUnique(); + + b.ToTable("RestrictionEntries", t => + { + t.HasCheckConstraint("CK_RestrictionEntry_Child", "([ChildOptionId] IS NULL AND [ChildOutcomeId] IS NOT NULL) OR ([ChildOptionId] IS NOT NULL AND [ChildOutcomeId] IS NULL)"); + + t.HasCheckConstraint("CK_RestrictionEntry_Parent", "([ParentOptionId] IS NULL AND [ParentOutcomeId] IS NOT NULL) OR ([ParentOptionId] IS NOT NULL AND [ParentOutcomeId] IS NULL)"); + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("EdgeId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("EdgeId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("RestrictionTables"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IconColor") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Rationale") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Strategies"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.StrategyOption", b => + { + b.Property("StrategyId") + .HasColumnType("uniqueidentifier"); + + b.Property("OptionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("StrategyId", "OptionId"); + + b.HasIndex("OptionId"); + + b.ToTable("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IsKey") + .HasColumnType("bit"); + + b.Property("IssueId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Uncertainties"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "Deleted User", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("IssueId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Utilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ValueMetric", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("ValueMetrics"); + + b.HasData( + new + { + Id = new Guid("288e0811-7ab6-5d24-b80c-9fa925b848a6"), + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "value", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Assessments") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardNode", b => + { + b.HasOne("PrismaApi.Domain.Entities.BoardSheet", "BoardSheet") + .WithMany() + .HasForeignKey("BoardSheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("BoardNodes") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BoardSheet"); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardSheet", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("BoardSheets") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Decision") + .HasForeignKey("PrismaApi.Domain.Entities.Decision", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DecisionQualityAssessment", b => + { + b.HasOne("PrismaApi.Domain.Entities.Assessment", "Assessment") + .WithMany("DecisionQualityAssessments") + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Assessment"); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.HasOne("PrismaApi.Domain.Entities.Outcome", "Outcome") + .WithMany() + .HasForeignKey("OutcomeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Uncertainty", "Uncertainty") + .WithMany("DiscreteProbabilities") + .HasForeignKey("UncertaintyId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Outcome"); + + b.Navigation("Project"); + + b.Navigation("Uncertainty"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteProbability", "DiscreteProbability") + .WithMany("ParentOptions") + .HasForeignKey("DiscreteProbabilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteProbability"); + + b.Navigation("ParentOption"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOutcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteProbability", "DiscreteProbability") + .WithMany("ParentOutcomes") + .HasForeignKey("DiscreteProbabilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteProbability"); + + b.Navigation("ParentOutcome"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Utility", "Utility") + .WithMany("DiscreteUtilities") + .HasForeignKey("UtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.ValueMetric", "ValueMetric") + .WithMany() + .HasForeignKey("ValueMetricId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + + b.Navigation("Utility"); + + b.Navigation("ValueMetric"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteUtility", "DiscreteUtility") + .WithMany("ParentOptions") + .HasForeignKey("DiscreteUtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteUtility"); + + b.Navigation("ParentOption"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOutcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteUtility", "DiscreteUtility") + .WithMany("ParentOutcomes") + .HasForeignKey("DiscreteUtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteUtility"); + + b.Navigation("ParentOutcome"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Edge", b => + { + b.HasOne("PrismaApi.Domain.Entities.Node", "HeadNode") + .WithMany("HeadEdges") + .HasForeignKey("HeadId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Edges") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Node", "TailNode") + .WithMany("TailEdges") + .HasForeignKey("TailId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("HeadNode"); + + b.Navigation("Project"); + + b.Navigation("TailNode"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Issues") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Node") + .HasForeignKey("PrismaApi.Domain.Entities.Node", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Nodes") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.NodeStyle", b => + { + b.HasOne("PrismaApi.Domain.Entities.Node", "Node") + .WithOne("NodeStyle") + .HasForeignKey("PrismaApi.Domain.Entities.NodeStyle", "NodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Node"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Objective", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Objectives") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.HasOne("PrismaApi.Domain.Entities.Decision", "Decision") + .WithMany("Options") + .HasForeignKey("DecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Decision"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Outcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Uncertainty", "Uncertainty") + .WithMany("Outcomes") + .HasForeignKey("UncertaintyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + + b.Navigation("Uncertainty"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ProjectRole", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("ProjectRoles") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "User") + .WithMany("ProjectRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionEntry", b => + { + b.HasOne("PrismaApi.Domain.Entities.Option", "ChildOption") + .WithMany() + .HasForeignKey("ChildOptionId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ChildOutcome") + .WithMany() + .HasForeignKey("ChildOutcomeId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.RestrictionTable", "RestrictionTable") + .WithMany("RestrictionEntries") + .HasForeignKey("RestrictionTableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildOption"); + + b.Navigation("ChildOutcome"); + + b.Navigation("ParentOption"); + + b.Navigation("ParentOutcome"); + + b.Navigation("Project"); + + b.Navigation("RestrictionTable"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Edge", "Edge") + .WithOne() + .HasForeignKey("PrismaApi.Domain.Entities.RestrictionTable", "EdgeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Edge"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Strategies") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.StrategyOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.Option", "Option") + .WithMany("StrategyOptions") + .HasForeignKey("OptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Strategy", "Strategy") + .WithMany("StrategyOptions") + .HasForeignKey("StrategyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Option"); + + b.Navigation("Strategy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Uncertainty") + .HasForeignKey("PrismaApi.Domain.Entities.Uncertainty", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Utility") + .HasForeignKey("PrismaApi.Domain.Entities.Utility", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.Navigation("DecisionQualityAssessments"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.Navigation("Options"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.Navigation("ParentOptions"); + + b.Navigation("ParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.Navigation("ParentOptions"); + + b.Navigation("ParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.Navigation("Decision"); + + b.Navigation("Node"); + + b.Navigation("Uncertainty"); + + b.Navigation("Utility"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.Navigation("HeadEdges"); + + b.Navigation("NodeStyle"); + + b.Navigation("TailEdges"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.Navigation("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.Navigation("Assessments"); + + b.Navigation("BoardNodes"); + + b.Navigation("BoardSheets"); + + b.Navigation("Edges"); + + b.Navigation("Issues"); + + b.Navigation("Nodes"); + + b.Navigation("Objectives"); + + b.Navigation("ProjectRoles"); + + b.Navigation("Strategies"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.Navigation("RestrictionEntries"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.Navigation("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.Navigation("DiscreteProbabilities"); + + b.Navigation("Outcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.User", b => + { + b.Navigation("ProjectRoles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.Navigation("DiscreteUtilities"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.cs b/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.cs new file mode 100644 index 0000000..95eeeb4 --- /dev/null +++ b/PrismaDotnetApi/SqlServerMigrations/20260813065703_AddDeletedUser.cs @@ -0,0 +1,29 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PrismaApi.Infrastructure.Migrations +{ + /// + public partial class AddDeletedUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "Users", + columns: new[] { "Id", "CreatedAt", "Name", "UpdatedAt" }, + values: new object[] { "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), "Deleted User", new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Users", + keyColumn: "Id", + keyValue: "d008bfdf-fe89-48f3-80a8-777bba4d9bbf"); + } + } +} diff --git a/PrismaDotnetApi/SqlServerMigrations/AppDbContextModelSnapshot.cs b/PrismaDotnetApi/SqlServerMigrations/AppDbContextModelSnapshot.cs index 1a9083b..c2c052b 100644 --- a/PrismaDotnetApi/SqlServerMigrations/AppDbContextModelSnapshot.cs +++ b/PrismaDotnetApi/SqlServerMigrations/AppDbContextModelSnapshot.cs @@ -1023,6 +1023,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); b.ToTable("Users"); + + b.HasData( + new + { + Id = "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "Deleted User", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); }); modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => diff --git a/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.Designer.cs b/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.Designer.cs new file mode 100644 index 0000000..8f2596f --- /dev/null +++ b/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.Designer.cs @@ -0,0 +1,1835 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PrismaApi.Infrastructure.Context; + +#nullable disable + +namespace PrismaApi.Infrastructure.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260813065648_AddDeletedUser")] + partial class AddDeletedUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.10"); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsCompleted") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("BoardSheetId") + .HasColumnType("TEXT"); + + b.Property("Color") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Height") + .HasColumnType("REAL"); + + b.Property("Opacity") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Rotation") + .HasColumnType("REAL"); + + b.Property("StrokeStyle") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue("Solid"); + + b.Property("StrokeWidth") + .ValueGeneratedOnAdd() + .HasColumnType("REAL") + .HasDefaultValue(8f); + + b.Property("TextSize") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(24); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("REAL"); + + b.Property("XPosition") + .HasColumnType("REAL"); + + b.Property("YPosition") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.HasIndex("BoardSheetId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("BoardNode", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("BoardSheet", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Decisions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DecisionQualityAssessment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AppropriateFrame") + .HasColumnType("INTEGER"); + + b.Property("AssessmentId") + .HasColumnType("TEXT"); + + b.Property("Comment") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("CommitmentToAction") + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DoableAlternatives") + .HasColumnType("INTEGER"); + + b.Property("InformationReliability") + .HasColumnType("INTEGER"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("ReasoningCorrectness") + .HasColumnType("INTEGER"); + + b.Property("TradeOffAnalysis") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("DecisionQualityAssessments", (string)null); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("OutcomeId") + .HasColumnType("TEXT"); + + b.Property("Probability") + .HasPrecision(53) + .HasColumnType("REAL"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UncertaintyId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OutcomeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UncertaintyId"); + + b.ToTable("DiscreteProbabilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOption", b => + { + b.Property("DiscreteProbabilityId") + .HasColumnType("TEXT"); + + b.Property("ParentOptionId") + .HasColumnType("TEXT"); + + b.HasKey("DiscreteProbabilityId", "ParentOptionId"); + + b.HasIndex("ParentOptionId"); + + b.ToTable("DiscreteProbabilityParentOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOutcome", b => + { + b.Property("DiscreteProbabilityId") + .HasColumnType("TEXT"); + + b.Property("ParentOutcomeId") + .HasColumnType("TEXT"); + + b.HasKey("DiscreteProbabilityId", "ParentOutcomeId"); + + b.HasIndex("ParentOutcomeId"); + + b.ToTable("DiscreteProbabilityParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UtilityId") + .HasColumnType("TEXT"); + + b.Property("UtilityValue") + .HasPrecision(53) + .HasColumnType("REAL"); + + b.Property("ValueMetricId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UtilityId"); + + b.HasIndex("ValueMetricId"); + + b.ToTable("DiscreteUtilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOption", b => + { + b.Property("DiscreteUtilityId") + .HasColumnType("TEXT"); + + b.Property("ParentOptionId") + .HasColumnType("TEXT"); + + b.HasKey("DiscreteUtilityId", "ParentOptionId"); + + b.HasIndex("ParentOptionId"); + + b.ToTable("DiscreteUtilityParentOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOutcome", b => + { + b.Property("DiscreteUtilityId") + .HasColumnType("TEXT"); + + b.Property("ParentOutcomeId") + .HasColumnType("TEXT"); + + b.HasKey("DiscreteUtilityId", "ParentOutcomeId"); + + b.HasIndex("ParentOutcomeId"); + + b.ToTable("DiscreteUtilityParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Edge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("HeadId") + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("TailId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("HeadId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("TailId"); + + b.ToTable("Edges"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Boundary") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Nodes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.NodeStyle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("NodeId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("XPosition") + .HasColumnType("REAL"); + + b.Property("YPosition") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.HasIndex("NodeId") + .IsUnique(); + + b.ToTable("NodeStyles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Objective", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Objectives"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DecisionId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Utility") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.HasIndex("DecisionId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Options"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Outcome", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UncertaintyId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Utility") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UncertaintyId"); + + b.ToTable("Outcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OpportunityStatement") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("ParentProjectId") + .HasColumnType("TEXT"); + + b.Property("ParentProjectName") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("Public") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Projects"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ProjectRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("ProjectRoles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ChildOptionId") + .HasColumnType("TEXT"); + + b.Property("ChildOutcomeId") + .HasColumnType("TEXT"); + + b.Property("ChildStateId") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("TEXT") + .HasComputedColumnSql("COALESCE([ChildOptionId], [ChildOutcomeId])", true); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("ParentOptionId") + .HasColumnType("TEXT"); + + b.Property("ParentOutcomeId") + .HasColumnType("TEXT"); + + b.Property("ParentStateId") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("TEXT") + .HasComputedColumnSql("COALESCE([ParentOptionId], [ParentOutcomeId])", true); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("RestrictionTableId") + .HasColumnType("TEXT"); + + b.Property("RestrictionValue") + .ValueGeneratedOnAdd() + .HasPrecision(53) + .HasColumnType("REAL") + .HasDefaultValue(1.0); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChildOptionId"); + + b.HasIndex("ChildOutcomeId"); + + b.HasIndex("ParentOptionId"); + + b.HasIndex("ParentOutcomeId"); + + b.HasIndex("ProjectId"); + + b.HasIndex("RestrictionTableId"); + + b.HasIndex("ParentStateId", "ChildStateId", "RestrictionTableId") + .IsUnique(); + + b.ToTable("RestrictionEntries", t => + { + t.HasCheckConstraint("CK_RestrictionEntry_Child", "([ChildOptionId] IS NULL AND [ChildOutcomeId] IS NOT NULL) OR ([ChildOptionId] IS NOT NULL AND [ChildOutcomeId] IS NULL)"); + + t.HasCheckConstraint("CK_RestrictionEntry_Parent", "([ParentOptionId] IS NULL AND [ParentOutcomeId] IS NOT NULL) OR ([ParentOptionId] IS NOT NULL AND [ParentOutcomeId] IS NULL)"); + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EdgeId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("EdgeId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("RestrictionTables"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IconColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("Rationale") + .IsRequired() + .HasMaxLength(6000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ProjectId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Strategies"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.StrategyOption", b => + { + b.Property("StrategyId") + .HasColumnType("TEXT"); + + b.Property("OptionId") + .HasColumnType("TEXT"); + + b.HasKey("StrategyId", "OptionId"); + + b.HasIndex("OptionId"); + + b.ToTable("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsKey") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Uncertainties"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "Deleted User", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("TEXT"); + + b.Property("ProjectId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueId") + .IsUnique(); + + b.HasIndex("ProjectId"); + + b.ToTable("Utilities"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ValueMetric", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ValueMetrics"); + + b.HasData( + new + { + Id = new Guid("288e0811-7ab6-5d24-b80c-9fa925b848a6"), + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "value", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Assessments") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardNode", b => + { + b.HasOne("PrismaApi.Domain.Entities.BoardSheet", "BoardSheet") + .WithMany() + .HasForeignKey("BoardSheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("BoardNodes") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BoardSheet"); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.BoardSheet", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("BoardSheets") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Decision") + .HasForeignKey("PrismaApi.Domain.Entities.Decision", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DecisionQualityAssessment", b => + { + b.HasOne("PrismaApi.Domain.Entities.Assessment", "Assessment") + .WithMany("DecisionQualityAssessments") + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Assessment"); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.HasOne("PrismaApi.Domain.Entities.Outcome", "Outcome") + .WithMany() + .HasForeignKey("OutcomeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Uncertainty", "Uncertainty") + .WithMany("DiscreteProbabilities") + .HasForeignKey("UncertaintyId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Outcome"); + + b.Navigation("Project"); + + b.Navigation("Uncertainty"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteProbability", "DiscreteProbability") + .WithMany("ParentOptions") + .HasForeignKey("DiscreteProbabilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteProbability"); + + b.Navigation("ParentOption"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbabilityParentOutcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteProbability", "DiscreteProbability") + .WithMany("ParentOutcomes") + .HasForeignKey("DiscreteProbabilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteProbability"); + + b.Navigation("ParentOutcome"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Utility", "Utility") + .WithMany("DiscreteUtilities") + .HasForeignKey("UtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.ValueMetric", "ValueMetric") + .WithMany() + .HasForeignKey("ValueMetricId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + + b.Navigation("Utility"); + + b.Navigation("ValueMetric"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteUtility", "DiscreteUtility") + .WithMany("ParentOptions") + .HasForeignKey("DiscreteUtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteUtility"); + + b.Navigation("ParentOption"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtilityParentOutcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.DiscreteUtility", "DiscreteUtility") + .WithMany("ParentOutcomes") + .HasForeignKey("DiscreteUtilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("DiscreteUtility"); + + b.Navigation("ParentOutcome"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Edge", b => + { + b.HasOne("PrismaApi.Domain.Entities.Node", "HeadNode") + .WithMany("HeadEdges") + .HasForeignKey("HeadId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Edges") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Node", "TailNode") + .WithMany("TailEdges") + .HasForeignKey("TailId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("HeadNode"); + + b.Navigation("Project"); + + b.Navigation("TailNode"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Issues") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Node") + .HasForeignKey("PrismaApi.Domain.Entities.Node", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Nodes") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.NodeStyle", b => + { + b.HasOne("PrismaApi.Domain.Entities.Node", "Node") + .WithOne("NodeStyle") + .HasForeignKey("PrismaApi.Domain.Entities.NodeStyle", "NodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Node"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Objective", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Objectives") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.HasOne("PrismaApi.Domain.Entities.Decision", "Decision") + .WithMany("Options") + .HasForeignKey("DecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Decision"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Outcome", b => + { + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Uncertainty", "Uncertainty") + .WithMany("Outcomes") + .HasForeignKey("UncertaintyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + + b.Navigation("Uncertainty"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.ProjectRole", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("ProjectRoles") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "User") + .WithMany("ProjectRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionEntry", b => + { + b.HasOne("PrismaApi.Domain.Entities.Option", "ChildOption") + .WithMany() + .HasForeignKey("ChildOptionId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ChildOutcome") + .WithMany() + .HasForeignKey("ChildOutcomeId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Option", "ParentOption") + .WithMany() + .HasForeignKey("ParentOptionId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Outcome", "ParentOutcome") + .WithMany() + .HasForeignKey("ParentOutcomeId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.RestrictionTable", "RestrictionTable") + .WithMany("RestrictionEntries") + .HasForeignKey("RestrictionTableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildOption"); + + b.Navigation("ChildOutcome"); + + b.Navigation("ParentOption"); + + b.Navigation("ParentOutcome"); + + b.Navigation("Project"); + + b.Navigation("RestrictionTable"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Edge", "Edge") + .WithOne() + .HasForeignKey("PrismaApi.Domain.Entities.RestrictionTable", "EdgeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Edge"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.HasOne("PrismaApi.Domain.Entities.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany("Strategies") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Project"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.StrategyOption", b => + { + b.HasOne("PrismaApi.Domain.Entities.Option", "Option") + .WithMany("StrategyOptions") + .HasForeignKey("OptionId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Strategy", "Strategy") + .WithMany("StrategyOptions") + .HasForeignKey("StrategyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Option"); + + b.Navigation("Strategy"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Uncertainty") + .HasForeignKey("PrismaApi.Domain.Entities.Uncertainty", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.HasOne("PrismaApi.Domain.Entities.Issue", "Issue") + .WithOne("Utility") + .HasForeignKey("PrismaApi.Domain.Entities.Utility", "IssueId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PrismaApi.Domain.Entities.Project", "Project") + .WithMany() + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Issue"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Assessment", b => + { + b.Navigation("DecisionQualityAssessments"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Decision", b => + { + b.Navigation("Options"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteProbability", b => + { + b.Navigation("ParentOptions"); + + b.Navigation("ParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.DiscreteUtility", b => + { + b.Navigation("ParentOptions"); + + b.Navigation("ParentOutcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Issue", b => + { + b.Navigation("Decision"); + + b.Navigation("Node"); + + b.Navigation("Uncertainty"); + + b.Navigation("Utility"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Node", b => + { + b.Navigation("HeadEdges"); + + b.Navigation("NodeStyle"); + + b.Navigation("TailEdges"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Option", b => + { + b.Navigation("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Project", b => + { + b.Navigation("Assessments"); + + b.Navigation("BoardNodes"); + + b.Navigation("BoardSheets"); + + b.Navigation("Edges"); + + b.Navigation("Issues"); + + b.Navigation("Nodes"); + + b.Navigation("Objectives"); + + b.Navigation("ProjectRoles"); + + b.Navigation("Strategies"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.RestrictionTable", b => + { + b.Navigation("RestrictionEntries"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Strategy", b => + { + b.Navigation("StrategyOptions"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Uncertainty", b => + { + b.Navigation("DiscreteProbabilities"); + + b.Navigation("Outcomes"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.User", b => + { + b.Navigation("ProjectRoles"); + }); + + modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b => + { + b.Navigation("DiscreteUtilities"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.cs b/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.cs new file mode 100644 index 0000000..95eeeb4 --- /dev/null +++ b/PrismaDotnetApi/SqliteMigrations/20260813065648_AddDeletedUser.cs @@ -0,0 +1,29 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PrismaApi.Infrastructure.Migrations +{ + /// + public partial class AddDeletedUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "Users", + columns: new[] { "Id", "CreatedAt", "Name", "UpdatedAt" }, + values: new object[] { "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), "Deleted User", new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Users", + keyColumn: "Id", + keyValue: "d008bfdf-fe89-48f3-80a8-777bba4d9bbf"); + } + } +} diff --git a/PrismaDotnetApi/SqliteMigrations/AppDbContextModelSnapshot.cs b/PrismaDotnetApi/SqliteMigrations/AppDbContextModelSnapshot.cs index 032a4fd..1989b7c 100644 --- a/PrismaDotnetApi/SqliteMigrations/AppDbContextModelSnapshot.cs +++ b/PrismaDotnetApi/SqliteMigrations/AppDbContextModelSnapshot.cs @@ -1018,6 +1018,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); b.ToTable("Users"); + + b.HasData( + new + { + Id = "d008bfdf-fe89-48f3-80a8-777bba4d9bbf", + CreatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(1), new TimeSpan(0, 0, 0, 0, 0)), + Name = "Deleted User", + UpdatedAt = new DateTimeOffset(new DateTime(2020, 1, 1, 1, 1, 1, 1, DateTimeKind.Unspecified).AddTicks(2), new TimeSpan(0, 0, 0, 0, 0)) + }); }); modelBuilder.Entity("PrismaApi.Domain.Entities.Utility", b =>