[CLAUDE] Workflow: Mig 22 schema mới ApprovalWorkflowsV2 (Chunk A)

Session 17 — schema riêng UAT trước khi drop legacy WorkflowDefinition.
Cấu trúc 3 bảng theo yêu cầu user:
  Quy trình (Code+Name+ApplicableType)
    Bước (Phòng A — DepartmentId hint)
      Cấp (NV X — ApproverUserId 1 user cụ thể, KHÔNG OR-of-many)

Khác Mig 21: Levels match 1 NV CHÍNH XÁC qua ApproverUserId, không
match group Dept+PositionLevel/Role/User. Service sau UAT iterate
Steps OrderBy Order → Levels OrderBy Order → ApproverUserId duyệt.

Files:
- Domain/ApprovalWorkflowsV2/ApprovalWorkflow.cs (3 entity + enum
  ApplicableType: DuyetNcc/DuyetNccPhuongAn/Contract)
- Infra/Persistence/Configurations/ApprovalWorkflowConfiguration.cs
  (FK Cascade Step→Workflow, Level→Step; Restrict Department + User)
- Infra/Persistence/ApplicationDbContext.cs (3 DbSet)
- Infra/Persistence/DbInitializer.cs (2 menu mới: ApprovalWorkflowsV2
  root dưới System icon Workflow + AwV2_DuyetNcc leaf icon FileCheck)
- Domain/Identity/MenuKeys.cs (2 const + All array)
- Migration 20260508053749_AddApprovalWorkflowsV2 (3 table CREATE +
  2 UNIQUE + 3 index)

Verify:
- Build OK, 77 test pass (54 Domain + 23 Infra) ~3s
- Mig applied cả _Design + _Dev LocalDB

Next chunks:
- B: Application CQRS (Get/Create) + ApprovalWorkflowsV2Controller
- C: FE Designer page /system/approval-workflows-v2/:typeCode
- D: Docs + STATUS update
This commit is contained in:
pqhuy1987
2026-05-08 12:39:37 +07:00
parent 21ee36390e
commit c847dc0b24
8 changed files with 4274 additions and 0 deletions

View File

@ -0,0 +1,63 @@
using SolutionErp.Domain.Common;
namespace SolutionErp.Domain.ApprovalWorkflowsV2;
// Quy trình duyệt mới (Mig 22 — Session 17, 2026-05-08).
// Schema riêng để UAT, KHÔNG đụng WorkflowDefinition cũ (Mig 21 flat). Sau UAT
// OK → migrate data PE/HĐ pin sang ApprovalWorkflowId + drop bảng cũ.
//
// Cấu trúc:
// Quy trình (Code + Name + ApplicableType)
// Bước 1 - Phòng A (DepartmentId optional hint)
// Cấp 1 - NV X (ApproverUserId specific)
// Cấp 2 - NV Y
// Bước 2 - Phòng B
// Cấp 1 - NV Z
// ...
//
// Service (sau khi UAT chốt): iterate Steps OrderBy Order. Mỗi step iterate
// Levels OrderBy Order. Mỗi level = 1 NV cụ thể duyệt. Hết level → next step.
// Hết step → DaDuyet.
public class ApprovalWorkflow : BaseEntity
{
public string Code { get; set; } = string.Empty; // Mã quy trình "QT-DN-V2-001"
public int Version { get; set; } // monotonically increases per Code
public ApprovalWorkflowApplicableType ApplicableType { get; set; } // module áp dụng
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public bool IsActive { get; set; }
public DateTime? ActivatedAt { get; set; }
public List<ApprovalWorkflowStep> Steps { get; set; } = new();
}
public enum ApprovalWorkflowApplicableType
{
DuyetNcc = 1, // PE module — Duyệt NCC (default test target)
DuyetNccPhuongAn = 2, // PE — Duyệt NCC + Giải pháp
Contract = 3, // HĐ general (any ContractType)
}
// Bước = Phòng. 1 quy trình có nhiều bước theo Order.
public class ApprovalWorkflowStep : BaseEntity
{
public Guid ApprovalWorkflowId { get; set; }
public int Order { get; set; } // 1-based
public string Name { get; set; } = string.Empty; // "Phòng A", "Phòng B" — display
public Guid? DepartmentId { get; set; } // hint phòng (optional, không strict match)
public ApprovalWorkflow? ApprovalWorkflow { get; set; }
public List<ApprovalWorkflowLevel> Levels { get; set; } = new();
}
// Cấp = 1 NV cụ thể. 1 bước có nhiều cấp theo Order. Approver = ApproverUserId
// chính xác (KHÔNG OR-of-many). Sequential trong cùng bước: cấp 1 → cấp 2 → ...
public class ApprovalWorkflowLevel : BaseEntity
{
public Guid ApprovalWorkflowStepId { get; set; }
public int Order { get; set; } // 1-based trong cùng step
public string? Name { get; set; } // "Cấp 1" — display optional
public Guid ApproverUserId { get; set; } // 1 NV cụ thể duyệt cấp này
public ApprovalWorkflowStep? Step { get; set; }
}

View File

@ -51,6 +51,20 @@ public static class MenuKeys
public const string PurchaseEvaluations = "PurchaseEvaluations"; // root group public const string PurchaseEvaluations = "PurchaseEvaluations"; // root group
public const string PeWorkflows = "PeWorkflows"; // workflow admin root public const string PeWorkflows = "PeWorkflows"; // workflow admin root
// ============================================================
// Quy trình duyệt MỚI (Mig 22 — Session 17, 2026-05-08):
// Schema riêng `ApprovalWorkflow` để UAT trước khi migrate hoàn toàn.
// Cấu trúc: Quy trình > Bước (Phòng) > Cấp (NV cụ thể).
// Mã + Tên Quy trình
// Bước 1 - Phòng A
// Cấp 1 - NV X
// Cấp 2 - NV Y
// Bước 2 - Phòng B
// ...
// ============================================================
public const string ApprovalWorkflowsV2 = "ApprovalWorkflowsV2"; // root admin (mới)
public const string ApprovalWorkflowDuyetNccV2 = "AwV2_DuyetNcc"; // leaf cho Duyệt NCC mới
// ============================================================ // ============================================================
// Module Ngân sách (Phase 7) — 4 bảng quản lý ngân sách dự án/gói thầu. // Module Ngân sách (Phase 7) — 4 bảng quản lý ngân sách dự án/gói thầu.
// 1 root + 3 leaf action (Danh sách / Thao tác / Duyệt). // 1 root + 3 leaf action (Danh sách / Thao tác / Duyệt).
@ -81,6 +95,7 @@ public static class MenuKeys
PurchaseEvaluations, PurchaseEvaluations,
Budgets, BudgetList, BudgetCreate, BudgetPending, Budgets, BudgetList, BudgetCreate, BudgetPending,
System, Users, Roles, Permissions, Workflows, PeWorkflows, System, Users, Roles, Permissions, Workflows, PeWorkflows,
ApprovalWorkflowsV2, ApprovalWorkflowDuyetNccV2, // Mig 22
]; ];
public static readonly string[] Actions = ["Read", "Create", "Update", "Delete"]; public static readonly string[] Actions = ["Read", "Create", "Update", "Delete"];

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Interfaces; using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Domain.ApprovalWorkflowsV2;
using SolutionErp.Domain.Budgets; using SolutionErp.Domain.Budgets;
using SolutionErp.Domain.Contracts; using SolutionErp.Domain.Contracts;
using SolutionErp.Domain.Contracts.Details; using SolutionErp.Domain.Contracts.Details;
@ -63,6 +64,11 @@ public class ApplicationDbContext
public DbSet<PurchaseEvaluationDepartmentOpinion> PurchaseEvaluationDepartmentOpinions => Set<PurchaseEvaluationDepartmentOpinion>(); public DbSet<PurchaseEvaluationDepartmentOpinion> PurchaseEvaluationDepartmentOpinions => Set<PurchaseEvaluationDepartmentOpinion>();
public DbSet<PurchaseEvaluationDepartmentApproval> PurchaseEvaluationDepartmentApprovals => Set<PurchaseEvaluationDepartmentApproval>(); public DbSet<PurchaseEvaluationDepartmentApproval> PurchaseEvaluationDepartmentApprovals => Set<PurchaseEvaluationDepartmentApproval>();
// Quy trình duyệt mới (Mig 22 — Session 17): schema riêng UAT.
public DbSet<ApprovalWorkflow> ApprovalWorkflows => Set<ApprovalWorkflow>();
public DbSet<ApprovalWorkflowStep> ApprovalWorkflowSteps => Set<ApprovalWorkflowStep>();
public DbSet<ApprovalWorkflowLevel> ApprovalWorkflowLevels => Set<ApprovalWorkflowLevel>();
// Module Ngân sách (Phase 7) — 4 bảng: Budget header + Details + Approvals + Changelogs. // Module Ngân sách (Phase 7) — 4 bảng: Budget header + Details + Approvals + Changelogs.
public DbSet<Budget> Budgets => Set<Budget>(); public DbSet<Budget> Budgets => Set<Budget>();
public DbSet<BudgetDetail> BudgetDetails => Set<BudgetDetail>(); public DbSet<BudgetDetail> BudgetDetails => Set<BudgetDetail>();

View File

@ -0,0 +1,69 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using SolutionErp.Domain.ApprovalWorkflowsV2;
namespace SolutionErp.Infrastructure.Persistence.Configurations;
// EF config Mig 22 — schema mới riêng cho Quy trình duyệt v2 (UAT before drop legacy).
public class ApprovalWorkflowConfiguration : IEntityTypeConfiguration<ApprovalWorkflow>
{
public void Configure(EntityTypeBuilder<ApprovalWorkflow> e)
{
e.ToTable("ApprovalWorkflows");
e.Property(x => x.Code).HasMaxLength(100).IsRequired();
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
e.Property(x => x.Description).HasMaxLength(1000);
e.Property(x => x.ApplicableType).HasConversion<int>();
e.HasIndex(x => new { x.Code, x.Version }).IsUnique();
e.HasIndex(x => new { x.ApplicableType, x.IsActive });
}
}
public class ApprovalWorkflowStepConfiguration : IEntityTypeConfiguration<ApprovalWorkflowStep>
{
public void Configure(EntityTypeBuilder<ApprovalWorkflowStep> e)
{
e.ToTable("ApprovalWorkflowSteps");
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
e.HasOne(x => x.ApprovalWorkflow)
.WithMany(d => d.Steps)
.HasForeignKey(x => x.ApprovalWorkflowId)
.OnDelete(DeleteBehavior.Cascade);
// Department FK Restrict (optional hint).
e.HasOne<SolutionErp.Domain.Master.Department>()
.WithMany()
.HasForeignKey(x => x.DepartmentId)
.OnDelete(DeleteBehavior.Restrict);
e.HasIndex(x => new { x.ApprovalWorkflowId, x.Order });
e.HasIndex(x => x.DepartmentId);
}
}
public class ApprovalWorkflowLevelConfiguration : IEntityTypeConfiguration<ApprovalWorkflowLevel>
{
public void Configure(EntityTypeBuilder<ApprovalWorkflowLevel> e)
{
e.ToTable("ApprovalWorkflowLevels");
e.Property(x => x.Name).HasMaxLength(200);
e.HasOne(x => x.Step)
.WithMany(s => s.Levels)
.HasForeignKey(x => x.ApprovalWorkflowStepId)
.OnDelete(DeleteBehavior.Cascade);
// ApproverUserId FK Restrict — không cấu hình nav để giữ nhẹ
// (1 chiều, query qua join nếu cần admin xem detail).
e.HasOne<SolutionErp.Domain.Identity.User>()
.WithMany()
.HasForeignKey(x => x.ApproverUserId)
.OnDelete(DeleteBehavior.Restrict);
e.HasIndex(x => new { x.ApprovalWorkflowStepId, x.Order });
e.HasIndex(x => x.ApproverUserId);
}
}

View File

@ -1308,6 +1308,10 @@ public static class DbInitializer
// Module Duyệt NCC (tiền-HĐ) // Module Duyệt NCC (tiền-HĐ)
(MenuKeys.PurchaseEvaluations, "Quy trình chọn Thầu phụ - NCC", null, 25, "ClipboardCheck"), (MenuKeys.PurchaseEvaluations, "Quy trình chọn Thầu phụ - NCC", null, 25, "ClipboardCheck"),
(MenuKeys.PeWorkflows, "Quy trình Duyệt NCC", MenuKeys.System, 95, "GitCompareArrows"), (MenuKeys.PeWorkflows, "Quy trình Duyệt NCC", MenuKeys.System, 95, "GitCompareArrows"),
// Quy trình duyệt MỚI (Mig 22 — Session 17, 2026-05-08): schema riêng
// UAT trước khi migrate hoàn toàn. Cấu trúc: Quy trình > Bước (Phòng) > Cấp (NV cụ thể).
(MenuKeys.ApprovalWorkflowsV2, "Quy trình duyệt (Mới)", MenuKeys.System, 96, "Workflow"),
(MenuKeys.ApprovalWorkflowDuyetNccV2, "Duyệt NCC (Mới)", MenuKeys.ApprovalWorkflowsV2, 1, "FileCheck"),
// Module Ngân sách (Phase 7) // Module Ngân sách (Phase 7)
(MenuKeys.Budgets, "Ngân sách", null, 27, "Wallet"), (MenuKeys.Budgets, "Ngân sách", null, 27, "Wallet"),
(MenuKeys.BudgetList, "Danh sách", MenuKeys.Budgets, 1, "List"), (MenuKeys.BudgetList, "Danh sách", MenuKeys.Budgets, 1, "List"),

View File

@ -0,0 +1,143 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SolutionErp.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class AddApprovalWorkflowsV2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApprovalWorkflows",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Code = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Version = table.Column<int>(type: "int", nullable: false),
ApplicableType = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
IsActive = table.Column<bool>(type: "bit", nullable: false),
ActivatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ApprovalWorkflows", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ApprovalWorkflowSteps",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ApprovalWorkflowId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Order = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DepartmentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ApprovalWorkflowSteps", x => x.Id);
table.ForeignKey(
name: "FK_ApprovalWorkflowSteps_ApprovalWorkflows_ApprovalWorkflowId",
column: x => x.ApprovalWorkflowId,
principalTable: "ApprovalWorkflows",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ApprovalWorkflowSteps_Departments_DepartmentId",
column: x => x.DepartmentId,
principalTable: "Departments",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "ApprovalWorkflowLevels",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ApprovalWorkflowStepId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Order = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
ApproverUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ApprovalWorkflowLevels", x => x.Id);
table.ForeignKey(
name: "FK_ApprovalWorkflowLevels_ApprovalWorkflowSteps_ApprovalWorkflowStepId",
column: x => x.ApprovalWorkflowStepId,
principalTable: "ApprovalWorkflowSteps",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ApprovalWorkflowLevels_Users_ApproverUserId",
column: x => x.ApproverUserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflowLevels_ApprovalWorkflowStepId_Order",
table: "ApprovalWorkflowLevels",
columns: new[] { "ApprovalWorkflowStepId", "Order" });
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflowLevels_ApproverUserId",
table: "ApprovalWorkflowLevels",
column: "ApproverUserId");
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflows_ApplicableType_IsActive",
table: "ApprovalWorkflows",
columns: new[] { "ApplicableType", "IsActive" });
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflows_Code_Version",
table: "ApprovalWorkflows",
columns: new[] { "Code", "Version" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflowSteps_ApprovalWorkflowId_Order",
table: "ApprovalWorkflowSteps",
columns: new[] { "ApprovalWorkflowId", "Order" });
migrationBuilder.CreateIndex(
name: "IX_ApprovalWorkflowSteps_DepartmentId",
table: "ApprovalWorkflowSteps",
column: "DepartmentId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ApprovalWorkflowLevels");
migrationBuilder.DropTable(
name: "ApprovalWorkflowSteps");
migrationBuilder.DropTable(
name: "ApprovalWorkflows");
}
}
}

View File

@ -125,6 +125,141 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
b.ToTable("UserTokens", (string)null); b.ToTable("UserTokens", (string)null);
}); });
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflow", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ActivatedAt")
.HasColumnType("datetime2");
b.Property<int>("ApplicableType")
.HasColumnType("int");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uniqueidentifier");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uniqueidentifier");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApplicableType", "IsActive");
b.HasIndex("Code", "Version")
.IsUnique();
b.ToTable("ApprovalWorkflows", (string)null);
});
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowLevel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("ApprovalWorkflowStepId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("ApproverUserId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Order")
.HasColumnType("int");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("ApproverUserId");
b.HasIndex("ApprovalWorkflowStepId", "Order");
b.ToTable("ApprovalWorkflowLevels", (string)null);
});
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowStep", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("ApprovalWorkflowId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("CreatedBy")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("DepartmentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Order")
.HasColumnType("int");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<Guid?>("UpdatedBy")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("DepartmentId");
b.HasIndex("ApprovalWorkflowId", "Order");
b.ToTable("ApprovalWorkflowSteps", (string)null);
});
modelBuilder.Entity("SolutionErp.Domain.Budgets.Budget", b => modelBuilder.Entity("SolutionErp.Domain.Budgets.Budget", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -3154,6 +3289,39 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowLevel", b =>
{
b.HasOne("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowStep", "Step")
.WithMany("Levels")
.HasForeignKey("ApprovalWorkflowStepId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SolutionErp.Domain.Identity.User", null)
.WithMany()
.HasForeignKey("ApproverUserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Step");
});
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowStep", b =>
{
b.HasOne("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflow", "ApprovalWorkflow")
.WithMany("Steps")
.HasForeignKey("ApprovalWorkflowId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SolutionErp.Domain.Master.Department", null)
.WithMany()
.HasForeignKey("DepartmentId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("ApprovalWorkflow");
});
modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetApproval", b => modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetApproval", b =>
{ {
b.HasOne("SolutionErp.Domain.Budgets.Budget", "Budget") b.HasOne("SolutionErp.Domain.Budgets.Budget", "Budget")
@ -3521,6 +3689,16 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
b.Navigation("Step"); b.Navigation("Step");
}); });
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflow", b =>
{
b.Navigation("Steps");
});
modelBuilder.Entity("SolutionErp.Domain.ApprovalWorkflowsV2.ApprovalWorkflowStep", b =>
{
b.Navigation("Levels");
});
modelBuilder.Entity("SolutionErp.Domain.Budgets.Budget", b => modelBuilder.Entity("SolutionErp.Domain.Budgets.Budget", b =>
{ {
b.Navigation("Approvals"); b.Navigation("Approvals");