c12935ad74
A customer change request now flows through a guarded commercial pipeline: Requested -> Estimated -> Approved -> Paid -> Live. The cross-division work and its dependencies live on the request's steps (a division's slice + hours + an optional depends-on link), and estimating sums the steps into a total. Each transition is guarded on the ChangeRequest aggregate, so it can only move forward in order; guard violations surface as 400s. - Domain: ChangeRequest + ChangeRequestStep aggregates with stage guards - Persistence: two tables + EF migration (applied) - Endpoints under /api/orgboard/change-requests: create/list/detail, add/advance steps, and estimate/approve/pay/go-live/reject (reads need board-view, commercial actions are owner-level) - New Delivery pipeline page: request list with stage + step progress, a detail drawer with a stage stepper, the next commercial action, quote entry, and a per-division step breakdown with dependencies Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
599 lines
21 KiB
C#
599 lines
21 KiB
C#
// <auto-generated />
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
using Microsoft.EntityFrameworkCore.Migrations;
|
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
using TeamUp.Modules.OrgBoard.Persistence;
|
|
|
|
#nullable disable
|
|
|
|
namespace TeamUp.Modules.OrgBoard.Persistence.Migrations
|
|
{
|
|
[DbContext(typeof(OrgBoardDbContext))]
|
|
[Migration("20260617041239_AddChangeRequests")]
|
|
partial class AddChangeRequests
|
|
{
|
|
/// <inheritdoc />
|
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
{
|
|
#pragma warning disable 612, 618
|
|
modelBuilder
|
|
.HasDefaultSchema("orgboard")
|
|
.HasAnnotation("ProductVersion", "10.0.8")
|
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
|
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Agent", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid>("ApiConfigId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Autonomy")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.PrimitiveCollection<List<string>>("Docs")
|
|
.IsRequired()
|
|
.HasColumnType("text[]");
|
|
|
|
b.Property<Guid?>("FallbackApiConfigId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.PrimitiveCollection<List<Guid>>("McpServerIds")
|
|
.IsRequired()
|
|
.HasColumnType("uuid[]");
|
|
|
|
b.Property<string>("Monogram")
|
|
.HasMaxLength(8)
|
|
.HasColumnType("character varying(8)");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(120)
|
|
.HasColumnType("character varying(120)");
|
|
|
|
b.Property<string>("Persona")
|
|
.HasColumnType("text");
|
|
|
|
b.Property<Guid>("SeatId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.PrimitiveCollection<List<string>>("SkillKeys")
|
|
.IsRequired()
|
|
.HasColumnType("text[]");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("SeatId")
|
|
.IsUnique();
|
|
|
|
b.ToTable("agents", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.AgentProfile", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("AuthoredByMemberId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Body")
|
|
.IsRequired()
|
|
.HasColumnType("text");
|
|
|
|
b.Property<string>("ContentHash")
|
|
.IsRequired()
|
|
.HasMaxLength(64)
|
|
.HasColumnType("character varying(64)");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Monogram")
|
|
.HasMaxLength(8)
|
|
.HasColumnType("character varying(8)");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<Guid?>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<int>("Origin")
|
|
.HasColumnType("integer");
|
|
|
|
b.Property<string>("ProfileKey")
|
|
.IsRequired()
|
|
.HasMaxLength(128)
|
|
.HasColumnType("character varying(128)");
|
|
|
|
b.Property<string>("RecommendedAutonomy")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.PrimitiveCollection<List<string>>("Roles")
|
|
.IsRequired()
|
|
.HasColumnType("text[]");
|
|
|
|
b.PrimitiveCollection<List<string>>("SkillKeys")
|
|
.IsRequired()
|
|
.HasColumnType("text[]");
|
|
|
|
b.Property<string>("Status")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.Property<string>("Summary")
|
|
.HasMaxLength(1000)
|
|
.HasColumnType("character varying(1000)");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Version")
|
|
.IsRequired()
|
|
.HasMaxLength(32)
|
|
.HasColumnType("character varying(32)");
|
|
|
|
b.Property<string>("Visibility")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.HasIndex("OrganizationId", "ProfileKey", "Version")
|
|
.IsUnique();
|
|
|
|
NpgsqlIndexBuilderExtensions.AreNullsDistinct(b.HasIndex("OrganizationId", "ProfileKey", "Version"), false);
|
|
|
|
b.ToTable("agent_profiles", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.ChangeRequest", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<decimal?>("Amount")
|
|
.HasPrecision(12, 2)
|
|
.HasColumnType("numeric(12,2)");
|
|
|
|
b.Property<DateTimeOffset?>("ApprovedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Currency")
|
|
.IsRequired()
|
|
.HasMaxLength(8)
|
|
.HasColumnType("character varying(8)");
|
|
|
|
b.Property<string>("CustomerName")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<string>("Description")
|
|
.HasColumnType("text");
|
|
|
|
b.Property<decimal?>("EstimateHours")
|
|
.HasPrecision(9, 2)
|
|
.HasColumnType("numeric(9,2)");
|
|
|
|
b.Property<DateTimeOffset?>("EstimatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<DateTimeOffset?>("LiveAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset?>("PaidAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Status")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<string>("Title")
|
|
.IsRequired()
|
|
.HasMaxLength(300)
|
|
.HasColumnType("character varying(300)");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.ToTable("change_requests", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.ChangeRequestStep", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid>("ChangeRequestId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid?>("DependsOnStepId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("DivisionId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<decimal>("EstimateHours")
|
|
.HasPrecision(9, 2)
|
|
.HasColumnType("numeric(9,2)");
|
|
|
|
b.Property<int>("Order")
|
|
.HasColumnType("integer");
|
|
|
|
b.Property<string>("Status")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<string>("Title")
|
|
.IsRequired()
|
|
.HasMaxLength(300)
|
|
.HasColumnType("character varying(300)");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("ChangeRequestId");
|
|
|
|
b.ToTable("change_request_steps", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Division", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<Guid>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.ToTable("divisions", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Organization", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.ToTable("organizations", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Product", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid?>("DivisionId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Identity")
|
|
.HasColumnType("text");
|
|
|
|
b.Property<string>("Kind")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<Guid>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("DivisionId");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.ToTable("products", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.ProductProfile", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("AuthoredByMemberId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Body")
|
|
.IsRequired()
|
|
.HasColumnType("text");
|
|
|
|
b.Property<string>("ContentHash")
|
|
.IsRequired()
|
|
.HasMaxLength(64)
|
|
.HasColumnType("character varying(64)");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<Guid?>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Origin")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.Property<string>("ProfileKey")
|
|
.IsRequired()
|
|
.HasMaxLength(128)
|
|
.HasColumnType("character varying(128)");
|
|
|
|
b.Property<string>("Status")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.Property<string>("Summary")
|
|
.HasMaxLength(1000)
|
|
.HasColumnType("character varying(1000)");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Version")
|
|
.IsRequired()
|
|
.HasMaxLength(32)
|
|
.HasColumnType("character varying(32)");
|
|
|
|
b.Property<string>("Visibility")
|
|
.IsRequired()
|
|
.HasMaxLength(20)
|
|
.HasColumnType("character varying(20)");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.HasIndex("OrganizationId", "ProfileKey", "Version")
|
|
.IsUnique();
|
|
|
|
NpgsqlIndexBuilderExtensions.AreNullsDistinct(b.HasIndex("OrganizationId", "ProfileKey", "Version"), false);
|
|
|
|
b.ToTable("product_profiles", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Seat", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("AgentId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid?>("MemberId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("RoleName")
|
|
.IsRequired()
|
|
.HasMaxLength(120)
|
|
.HasColumnType("character varying(120)");
|
|
|
|
b.Property<string>("State")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<Guid>("TeamId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("TeamId");
|
|
|
|
b.ToTable("seats", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.Team", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<string>("Name")
|
|
.IsRequired()
|
|
.HasMaxLength(200)
|
|
.HasColumnType("character varying(200)");
|
|
|
|
b.Property<Guid>("OrganizationId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("ProductId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("OrganizationId");
|
|
|
|
b.HasIndex("ProductId");
|
|
|
|
b.ToTable("teams", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.WorkItem", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("AssigneeId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("AssigneeKind")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid>("CreatedByMemberId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Description")
|
|
.HasColumnType("text");
|
|
|
|
b.Property<Guid?>("ParentId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Status")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<Guid>("TeamId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("Title")
|
|
.IsRequired()
|
|
.HasMaxLength(300)
|
|
.HasColumnType("character varying(300)");
|
|
|
|
b.Property<string>("Type")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<DateTimeOffset>("UpdatedAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("TeamId");
|
|
|
|
b.HasIndex("AssigneeKind", "AssigneeId");
|
|
|
|
b.ToTable("work_items", "orgboard");
|
|
});
|
|
|
|
modelBuilder.Entity("TeamUp.Modules.OrgBoard.Domain.WorkItemTransition", b =>
|
|
{
|
|
b.Property<Guid>("Id")
|
|
.ValueGeneratedOnAdd()
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<Guid?>("ActorMemberId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("FromStatus")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<DateTimeOffset>("OccurredAtUtc")
|
|
.HasColumnType("timestamp with time zone");
|
|
|
|
b.Property<Guid>("TeamId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.Property<string>("ToStatus")
|
|
.IsRequired()
|
|
.HasMaxLength(16)
|
|
.HasColumnType("character varying(16)");
|
|
|
|
b.Property<Guid>("WorkItemId")
|
|
.HasColumnType("uuid");
|
|
|
|
b.HasKey("Id");
|
|
|
|
b.HasIndex("TeamId");
|
|
|
|
b.HasIndex("WorkItemId");
|
|
|
|
b.ToTable("work_item_transitions", "orgboard");
|
|
});
|
|
#pragma warning restore 612, 618
|
|
}
|
|
}
|
|
}
|