Project Init
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>ColaFlow.Modules.ProjectManagement.Infrastructure</AssemblyName>
|
||||
<RootNamespace>ColaFlow.Modules.ProjectManagement.Infrastructure</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ColaFlow.Modules.ProjectManagement.Domain\ColaFlow.Modules.ProjectManagement.Domain.csproj" />
|
||||
<ProjectReference Include="..\ColaFlow.Modules.ProjectManagement.Application\ColaFlow.Modules.ProjectManagement.Application.csproj" />
|
||||
<ProjectReference Include="..\..\..\Shared\ColaFlow.Shared.Kernel\ColaFlow.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,298 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(PMDbContext))]
|
||||
[Migration("20251102220422_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("project_management")
|
||||
.HasAnnotation("ProductVersion", "9.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("ProjectId1")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("ProjectId1");
|
||||
|
||||
b.ToTable("Epics", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Projects", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ActualHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<Guid?>("AssigneeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<Guid>("EpicId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("EstimatedHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssigneeId");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("EpicId");
|
||||
|
||||
b.ToTable("Stories", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.WorkTask", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ActualHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<Guid?>("AssigneeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<decimal?>("EstimatedHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<Guid>("StoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssigneeId");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("StoryId");
|
||||
|
||||
b.ToTable("Tasks", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProjectId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", null)
|
||||
.WithMany("Epics")
|
||||
.HasForeignKey("ProjectId1");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.OwnsOne("ColaFlow.Modules.ProjectManagement.Domain.ValueObjects.ProjectKey", "Key", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b1.HasKey("ProjectId");
|
||||
|
||||
b1.HasIndex("Value")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("Projects", "project_management");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ProjectId");
|
||||
});
|
||||
|
||||
b.Navigation("Key")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("EpicId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.WorkTask", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("StoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.Navigation("Epics");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "project_management");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Projects",
|
||||
schema: "project_management",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
Description = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
|
||||
Key = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
OwnerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Projects", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Epics",
|
||||
schema: "project_management",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
Description = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
|
||||
ProjectId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
Priority = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
CreatedBy = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
ProjectId1 = table.Column<Guid>(type: "uuid", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Epics", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Epics_Projects_ProjectId",
|
||||
column: x => x.ProjectId,
|
||||
principalSchema: "project_management",
|
||||
principalTable: "Projects",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Epics_Projects_ProjectId1",
|
||||
column: x => x.ProjectId1,
|
||||
principalSchema: "project_management",
|
||||
principalTable: "Projects",
|
||||
principalColumn: "Id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Stories",
|
||||
schema: "project_management",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Title = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
Description = table.Column<string>(type: "character varying(4000)", maxLength: 4000, nullable: false),
|
||||
EpicId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
Priority = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
EstimatedHours = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ActualHours = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
AssigneeId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
CreatedBy = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Stories", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Stories_Epics_EpicId",
|
||||
column: x => x.EpicId,
|
||||
principalSchema: "project_management",
|
||||
principalTable: "Epics",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Tasks",
|
||||
schema: "project_management",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Title = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
Description = table.Column<string>(type: "character varying(4000)", maxLength: 4000, nullable: false),
|
||||
StoryId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
Priority = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
EstimatedHours = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
ActualHours = table.Column<decimal>(type: "numeric", nullable: true),
|
||||
AssigneeId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
CreatedBy = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Tasks", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Tasks_Stories_StoryId",
|
||||
column: x => x.StoryId,
|
||||
principalSchema: "project_management",
|
||||
principalTable: "Stories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Epics_CreatedAt",
|
||||
schema: "project_management",
|
||||
table: "Epics",
|
||||
column: "CreatedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Epics_ProjectId",
|
||||
schema: "project_management",
|
||||
table: "Epics",
|
||||
column: "ProjectId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Epics_ProjectId1",
|
||||
schema: "project_management",
|
||||
table: "Epics",
|
||||
column: "ProjectId1");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Projects_CreatedAt",
|
||||
schema: "project_management",
|
||||
table: "Projects",
|
||||
column: "CreatedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Projects_Key",
|
||||
schema: "project_management",
|
||||
table: "Projects",
|
||||
column: "Key",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Projects_OwnerId",
|
||||
schema: "project_management",
|
||||
table: "Projects",
|
||||
column: "OwnerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Stories_AssigneeId",
|
||||
schema: "project_management",
|
||||
table: "Stories",
|
||||
column: "AssigneeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Stories_CreatedAt",
|
||||
schema: "project_management",
|
||||
table: "Stories",
|
||||
column: "CreatedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Stories_EpicId",
|
||||
schema: "project_management",
|
||||
table: "Stories",
|
||||
column: "EpicId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_AssigneeId",
|
||||
schema: "project_management",
|
||||
table: "Tasks",
|
||||
column: "AssigneeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_CreatedAt",
|
||||
schema: "project_management",
|
||||
table: "Tasks",
|
||||
column: "CreatedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_StoryId",
|
||||
schema: "project_management",
|
||||
table: "Tasks",
|
||||
column: "StoryId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Tasks",
|
||||
schema: "project_management");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Stories",
|
||||
schema: "project_management");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Epics",
|
||||
schema: "project_management");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Projects",
|
||||
schema: "project_management");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(PMDbContext))]
|
||||
partial class PMDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("project_management")
|
||||
.HasAnnotation("ProductVersion", "9.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("ProjectId1")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("ProjectId1");
|
||||
|
||||
b.ToTable("Epics", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Projects", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ActualHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<Guid?>("AssigneeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<Guid>("EpicId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("EstimatedHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssigneeId");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("EpicId");
|
||||
|
||||
b.ToTable("Stories", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.WorkTask", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal?>("ActualHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<Guid?>("AssigneeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<decimal?>("EstimatedHours")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<Guid>("StoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssigneeId");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("StoryId");
|
||||
|
||||
b.ToTable("Tasks", "project_management");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProjectId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", null)
|
||||
.WithMany("Epics")
|
||||
.HasForeignKey("ProjectId1");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.OwnsOne("ColaFlow.Modules.ProjectManagement.Domain.ValueObjects.ProjectKey", "Key", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b1.HasKey("ProjectId");
|
||||
|
||||
b1.HasIndex("Value")
|
||||
.IsUnique();
|
||||
|
||||
b1.ToTable("Projects", "project_management");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ProjectId");
|
||||
});
|
||||
|
||||
b.Navigation("Key")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Epic", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("EpicId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.WorkTask", b =>
|
||||
{
|
||||
b.HasOne("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Story", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("StoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate.Project", b =>
|
||||
{
|
||||
b.Navigation("Epics");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
||||
using ColaFlow.Shared.Kernel.Common;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Entity configuration for Epic entity
|
||||
/// </summary>
|
||||
public class EpicConfiguration : IEntityTypeConfiguration<Epic>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Epic> builder)
|
||||
{
|
||||
builder.ToTable("Epics");
|
||||
|
||||
// Primary key
|
||||
builder.HasKey("Id");
|
||||
|
||||
// Id conversion
|
||||
builder.Property(e => e.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => EpicId.From(value))
|
||||
.IsRequired()
|
||||
.ValueGeneratedNever();
|
||||
|
||||
// ProjectId (foreign key)
|
||||
builder.Property(e => e.ProjectId)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => ProjectId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// Basic properties
|
||||
builder.Property(e => e.Name)
|
||||
.HasMaxLength(200)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(e => e.Description)
|
||||
.HasMaxLength(2000);
|
||||
|
||||
// Status enumeration
|
||||
builder.Property(e => e.Status)
|
||||
.HasConversion(
|
||||
s => s.Name,
|
||||
name => Enumeration.FromDisplayName<WorkItemStatus>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// Priority enumeration
|
||||
builder.Property(e => e.Priority)
|
||||
.HasConversion(
|
||||
p => p.Name,
|
||||
name => Enumeration.FromDisplayName<TaskPriority>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// CreatedBy conversion
|
||||
builder.Property(e => e.CreatedBy)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => UserId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// Timestamps
|
||||
builder.Property(e => e.CreatedAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(e => e.UpdatedAt);
|
||||
|
||||
// Ignore navigation properties (DDD pattern - access through aggregate)
|
||||
builder.Ignore(e => e.Stories);
|
||||
|
||||
// Foreign key relationship to Project
|
||||
builder.HasOne<Project>()
|
||||
.WithMany()
|
||||
.HasForeignKey(e => e.ProjectId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(e => e.ProjectId);
|
||||
builder.HasIndex(e => e.CreatedAt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
||||
using ColaFlow.Shared.Kernel.Common;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Entity configuration for Project aggregate root
|
||||
/// </summary>
|
||||
public class ProjectConfiguration : IEntityTypeConfiguration<Project>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Project> builder)
|
||||
{
|
||||
builder.ToTable("Projects");
|
||||
|
||||
// Primary key
|
||||
builder.HasKey(p => p.Id);
|
||||
|
||||
// Id conversion (StronglyTypedId to Guid)
|
||||
builder.Property(p => p.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => ProjectId.From(value))
|
||||
.IsRequired()
|
||||
.ValueGeneratedNever();
|
||||
|
||||
// Basic properties
|
||||
builder.Property(p => p.Name)
|
||||
.HasMaxLength(200)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(p => p.Description)
|
||||
.HasMaxLength(2000);
|
||||
|
||||
// ProjectKey as owned value object
|
||||
builder.OwnsOne(p => p.Key, kb =>
|
||||
{
|
||||
kb.Property(k => k.Value)
|
||||
.HasColumnName("Key")
|
||||
.HasMaxLength(20)
|
||||
.IsRequired();
|
||||
|
||||
kb.HasIndex(k => k.Value).IsUnique();
|
||||
});
|
||||
|
||||
// Status enumeration (stored as string)
|
||||
builder.Property(p => p.Status)
|
||||
.HasConversion(
|
||||
s => s.Name,
|
||||
name => Enumeration.FromDisplayName<ProjectStatus>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// OwnerId conversion
|
||||
builder.Property(p => p.OwnerId)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => UserId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// Timestamps
|
||||
builder.Property(p => p.CreatedAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(p => p.UpdatedAt);
|
||||
|
||||
// Relationships - Epics collection (owned by aggregate)
|
||||
// Note: We don't expose this as navigation property in DDD, epics are accessed through repository
|
||||
|
||||
// Indexes for performance
|
||||
builder.HasIndex(p => p.CreatedAt);
|
||||
builder.HasIndex(p => p.OwnerId);
|
||||
|
||||
// Ignore DomainEvents (handled separately)
|
||||
builder.Ignore(p => p.DomainEvents);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
||||
using ColaFlow.Shared.Kernel.Common;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Entity configuration for Story entity
|
||||
/// </summary>
|
||||
public class StoryConfiguration : IEntityTypeConfiguration<Story>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Story> builder)
|
||||
{
|
||||
builder.ToTable("Stories");
|
||||
|
||||
// Primary key
|
||||
builder.HasKey("Id");
|
||||
|
||||
// Id conversion
|
||||
builder.Property(s => s.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => StoryId.From(value))
|
||||
.IsRequired()
|
||||
.ValueGeneratedNever();
|
||||
|
||||
// EpicId (foreign key)
|
||||
builder.Property(s => s.EpicId)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => EpicId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// Basic properties
|
||||
builder.Property(s => s.Title)
|
||||
.HasMaxLength(200)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(s => s.Description)
|
||||
.HasMaxLength(4000);
|
||||
|
||||
// Status enumeration
|
||||
builder.Property(s => s.Status)
|
||||
.HasConversion(
|
||||
st => st.Name,
|
||||
name => Enumeration.FromDisplayName<WorkItemStatus>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// Priority enumeration
|
||||
builder.Property(s => s.Priority)
|
||||
.HasConversion(
|
||||
p => p.Name,
|
||||
name => Enumeration.FromDisplayName<TaskPriority>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// CreatedBy conversion
|
||||
builder.Property(s => s.CreatedBy)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => UserId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// AssigneeId (optional)
|
||||
builder.Property(s => s.AssigneeId)
|
||||
.HasConversion(
|
||||
id => id != null ? id.Value : (Guid?)null,
|
||||
value => value.HasValue ? UserId.From(value.Value) : null);
|
||||
|
||||
// Effort tracking
|
||||
builder.Property(s => s.EstimatedHours);
|
||||
builder.Property(s => s.ActualHours);
|
||||
|
||||
// Timestamps
|
||||
builder.Property(s => s.CreatedAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(s => s.UpdatedAt);
|
||||
|
||||
// Ignore navigation properties (DDD pattern - access through aggregate)
|
||||
builder.Ignore(s => s.Tasks);
|
||||
|
||||
// Foreign key relationship to Epic
|
||||
builder.HasOne<Epic>()
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.EpicId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(s => s.EpicId);
|
||||
builder.HasIndex(s => s.AssigneeId);
|
||||
builder.HasIndex(s => s.CreatedAt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
||||
using ColaFlow.Shared.Kernel.Common;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Entity configuration for WorkTask entity
|
||||
/// </summary>
|
||||
public class WorkTaskConfiguration : IEntityTypeConfiguration<WorkTask>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<WorkTask> builder)
|
||||
{
|
||||
builder.ToTable("Tasks");
|
||||
|
||||
// Primary key
|
||||
builder.HasKey("Id");
|
||||
|
||||
// Id conversion
|
||||
builder.Property(t => t.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => TaskId.From(value))
|
||||
.IsRequired()
|
||||
.ValueGeneratedNever();
|
||||
|
||||
// StoryId (foreign key)
|
||||
builder.Property(t => t.StoryId)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => StoryId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// Basic properties
|
||||
builder.Property(t => t.Title)
|
||||
.HasMaxLength(200)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(t => t.Description)
|
||||
.HasMaxLength(4000);
|
||||
|
||||
// Status enumeration
|
||||
builder.Property(t => t.Status)
|
||||
.HasConversion(
|
||||
s => s.Name,
|
||||
name => Enumeration.FromDisplayName<WorkItemStatus>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// Priority enumeration
|
||||
builder.Property(t => t.Priority)
|
||||
.HasConversion(
|
||||
p => p.Name,
|
||||
name => Enumeration.FromDisplayName<TaskPriority>(name))
|
||||
.HasMaxLength(50)
|
||||
.IsRequired();
|
||||
|
||||
// CreatedBy conversion
|
||||
builder.Property(t => t.CreatedBy)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => UserId.From(value))
|
||||
.IsRequired();
|
||||
|
||||
// AssigneeId (optional)
|
||||
builder.Property(t => t.AssigneeId)
|
||||
.HasConversion(
|
||||
id => id != null ? id.Value : (Guid?)null,
|
||||
value => value.HasValue ? UserId.From(value.Value) : null);
|
||||
|
||||
// Effort tracking
|
||||
builder.Property(t => t.EstimatedHours);
|
||||
builder.Property(t => t.ActualHours);
|
||||
|
||||
// Timestamps
|
||||
builder.Property(t => t.CreatedAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(t => t.UpdatedAt);
|
||||
|
||||
// Foreign key relationship to Story
|
||||
builder.HasOne<Story>()
|
||||
.WithMany()
|
||||
.HasForeignKey(t => t.StoryId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(t => t.StoryId);
|
||||
builder.HasIndex(t => t.AssigneeId);
|
||||
builder.HasIndex(t => t.CreatedAt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Project Management Module DbContext
|
||||
/// </summary>
|
||||
public class PMDbContext : DbContext
|
||||
{
|
||||
public PMDbContext(DbContextOptions<PMDbContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<Project> Projects => Set<Project>();
|
||||
public DbSet<Epic> Epics => Set<Epic>();
|
||||
public DbSet<Story> Stories => Set<Story>();
|
||||
public DbSet<WorkTask> Tasks => Set<WorkTask>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// Set default schema for this module (must be before configurations)
|
||||
modelBuilder.HasDefaultSchema("project_management");
|
||||
|
||||
// Apply all entity configurations from this assembly
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
|
||||
using ColaFlow.Shared.Kernel.Common;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Unit of Work implementation for ProjectManagement module
|
||||
/// </summary>
|
||||
public class UnitOfWork : IUnitOfWork
|
||||
{
|
||||
private readonly PMDbContext _context;
|
||||
|
||||
public UnitOfWork(PMDbContext context)
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Dispatch domain events before saving
|
||||
await DispatchDomainEventsAsync(cancellationToken);
|
||||
|
||||
// Save changes to database
|
||||
return await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task DispatchDomainEventsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Get all entities with domain events
|
||||
var domainEntities = _context.ChangeTracker
|
||||
.Entries<AggregateRoot>()
|
||||
.Where(x => x.Entity.DomainEvents.Any())
|
||||
.Select(x => x.Entity)
|
||||
.ToList();
|
||||
|
||||
// Get all domain events
|
||||
var domainEvents = domainEntities
|
||||
.SelectMany(x => x.DomainEvents)
|
||||
.ToList();
|
||||
|
||||
// Clear domain events from entities
|
||||
domainEntities.ForEach(entity => entity.ClearDomainEvents());
|
||||
|
||||
// TODO: Dispatch domain events to handlers
|
||||
// This will be implemented when we add MediatR
|
||||
// For now, we just clear the events
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
|
||||
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
||||
using ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;
|
||||
|
||||
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Project repository implementation using EF Core
|
||||
/// </summary>
|
||||
public class ProjectRepository : IProjectRepository
|
||||
{
|
||||
private readonly PMDbContext _context;
|
||||
|
||||
public ProjectRepository(PMDbContext context)
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
public async Task<Project?> GetByIdAsync(ProjectId id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Projects
|
||||
.Include(p => p.Epics)
|
||||
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Project?> GetByKeyAsync(string key, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Projects
|
||||
.FirstOrDefaultAsync(p => p.Key.Value == key, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<List<Project>> GetAllAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Projects
|
||||
.OrderByDescending(p => p.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task AddAsync(Project project, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _context.Projects.AddAsync(project, cancellationToken);
|
||||
}
|
||||
|
||||
public void Update(Project project)
|
||||
{
|
||||
_context.Projects.Update(project);
|
||||
}
|
||||
|
||||
public void Delete(Project project)
|
||||
{
|
||||
_context.Projects.Remove(project);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user