[CLAUDE] Domain+Infra: Migration 16 — 2-stage dept approval + smart reject schema
Chunk A của feature 2-stage department approval (Phase 9). 3 ràng buộc gộp 1 migration để rollback atomic. Schema changes: 1. Smart reject (3 ALTER): - Contracts.RejectedFromPhase int NULL - PurchaseEvaluations.RejectedFromPhase int NULL - Budgets.RejectedFromPhase int NULL Lưu phase nguồn khi reject để Drafter trình lại quay về đúng phase (skip phase trung gian đã duyệt) thay vì đi tuần tự từ DangSoanThao. 2. Bypass per-user (1 ALTER): - Users.CanBypassReview bit NOT NULL DEFAULT 0 Khi true → NV được duyệt thay TPB (skip Stage Review, đẩy thẳng Stage Confirm). Audit qua DepartmentApproval.IsBypassed=true. 3. 2-stage dept approval (3 CREATE TABLE): - ContractDepartmentApprovals - PurchaseEvaluationDepartmentApprovals - BudgetDepartmentApprovals Schema (chung): - Id, *Id FK Cascade, PhaseAtApproval int, DepartmentId FK - Stage enum (1=Review NV, 2=Confirm TPB) - ApproverUserId, ApproverRoleSnapshot, Comment, ApprovedAt - IsBypassed bit (mark NV bypass) - AuditableEntity (CreatedAt/By/UpdatedAt/By/IsDeleted/...) Indexes: - UNIQUE (TargetId, PhaseAtApproval, DepartmentId, Stage) - Single: TargetId, DepartmentId, ApproverUserId Files: - Domain: 4 entity update (Contract/PE/Budget/User add field) + 1 enum mới ApprovalStage + 3 entity DepartmentApproval mới - Infrastructure: 3 EntityConfiguration update + 1 file mới DepartmentApprovalsConfiguration với 3 config classes - IApplicationDbContext: thêm 3 DbSet - ApplicationDbContext: thêm 3 DbSet - Migration 16: 3 file (.cs + Designer.cs + Snapshot.cs) — 3-file rule Verify: - Build pass (2 warning DocxRenderer cũ, không liên quan) - 77 unit test pass (54 Domain + 23 Infra) — Domain policy chưa update, test pass nguyên không regression Note: KHÔNG khác PurchaseEvaluationDepartmentOpinion (Migration 15) — Opinion là sign-off block "Ý kiến 4 phòng ban" trên header phiếu. DepartmentApproval mới là 2-stage approval workflow per phase. Tổng sau Migration 16: 55 bảng (52+3), 16 migration. Chunk B-E sẽ implement Application + FE + Tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -35,6 +35,7 @@ public class ApplicationDbContext
|
||||
public DbSet<ContractAttachment> ContractAttachments => Set<ContractAttachment>();
|
||||
public DbSet<ContractCodeSequence> ContractCodeSequences => Set<ContractCodeSequence>();
|
||||
public DbSet<ContractChangelog> ContractChangelogs => Set<ContractChangelog>();
|
||||
public DbSet<ContractDepartmentApproval> ContractDepartmentApprovals => Set<ContractDepartmentApproval>();
|
||||
public DbSet<Notification> Notifications => Set<Notification>();
|
||||
public DbSet<WorkflowTypeAssignment> WorkflowTypeAssignments => Set<WorkflowTypeAssignment>();
|
||||
public DbSet<WorkflowDefinition> WorkflowDefinitions => Set<WorkflowDefinition>();
|
||||
@ -60,12 +61,14 @@ public class ApplicationDbContext
|
||||
public DbSet<PurchaseEvaluationWorkflowStepApprover> PurchaseEvaluationWorkflowStepApprovers => Set<PurchaseEvaluationWorkflowStepApprover>();
|
||||
public DbSet<PurchaseEvaluationCodeSequence> PurchaseEvaluationCodeSequences => Set<PurchaseEvaluationCodeSequence>();
|
||||
public DbSet<PurchaseEvaluationDepartmentOpinion> PurchaseEvaluationDepartmentOpinions => Set<PurchaseEvaluationDepartmentOpinion>();
|
||||
public DbSet<PurchaseEvaluationDepartmentApproval> PurchaseEvaluationDepartmentApprovals => Set<PurchaseEvaluationDepartmentApproval>();
|
||||
|
||||
// Module Ngân sách (Phase 7) — 4 bảng: Budget header + Details + Approvals + Changelogs.
|
||||
public DbSet<Budget> Budgets => Set<Budget>();
|
||||
public DbSet<BudgetDetail> BudgetDetails => Set<BudgetDetail>();
|
||||
public DbSet<BudgetApproval> BudgetApprovals => Set<BudgetApproval>();
|
||||
public DbSet<BudgetChangelog> BudgetChangelogs => Set<BudgetChangelog>();
|
||||
public DbSet<BudgetDepartmentApproval> BudgetDepartmentApprovals => Set<BudgetDepartmentApproval>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
|
||||
@ -15,6 +15,7 @@ public class BudgetConfiguration : IEntityTypeConfiguration<Budget>
|
||||
b.Property(x => x.TenNganSach).HasMaxLength(500).IsRequired();
|
||||
b.Property(x => x.Description).HasMaxLength(2000);
|
||||
b.Property(x => x.Phase).HasConversion<int>();
|
||||
b.Property(x => x.RejectedFromPhase).HasConversion<int?>();
|
||||
b.Property(x => x.TongNganSach).HasPrecision(18, 2);
|
||||
|
||||
b.HasIndex(x => x.MaNganSach).IsUnique().HasFilter("[MaNganSach] IS NOT NULL");
|
||||
|
||||
@ -14,6 +14,7 @@ public class ContractConfiguration : IEntityTypeConfiguration<Contract>
|
||||
b.Property(x => x.MaHopDong).HasMaxLength(100);
|
||||
b.Property(x => x.Type).HasConversion<int>();
|
||||
b.Property(x => x.Phase).HasConversion<int>();
|
||||
b.Property(x => x.RejectedFromPhase).HasConversion<int?>();
|
||||
b.Property(x => x.GiaTri).HasPrecision(18, 2);
|
||||
b.Property(x => x.TenHopDong).HasMaxLength(500);
|
||||
b.Property(x => x.NoiDung).HasMaxLength(2000);
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using SolutionErp.Domain.Budgets;
|
||||
using SolutionErp.Domain.Contracts;
|
||||
using SolutionErp.Domain.PurchaseEvaluations;
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Configurations;
|
||||
|
||||
// 3 bảng *DepartmentApprovals (Phase 9 — Migration 16) — 2-stage approval per
|
||||
// phase × phòng ban cho HĐ / PE / Budget.
|
||||
//
|
||||
// UNIQUE (TargetId, PhaseAtApproval, DepartmentId, Stage) — 1 phase × 1 phòng
|
||||
// × 1 stage = 1 row duy nhất. UPDATE in-place khi user đổi ý → audit qua
|
||||
// *Changelog.
|
||||
//
|
||||
// FK Cascade theo target (xóa HĐ/PE/Budget → xóa approval rows).
|
||||
|
||||
public class ContractDepartmentApprovalConfiguration
|
||||
: IEntityTypeConfiguration<ContractDepartmentApproval>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ContractDepartmentApproval> b)
|
||||
{
|
||||
b.ToTable("ContractDepartmentApprovals");
|
||||
b.HasKey(x => x.Id);
|
||||
|
||||
b.Property(x => x.Stage).HasConversion<int>();
|
||||
b.Property(x => x.ApproverRoleSnapshot).HasMaxLength(100);
|
||||
b.Property(x => x.Comment).HasMaxLength(1000);
|
||||
|
||||
b.HasIndex(x => new { x.ContractId, x.PhaseAtApproval, x.DepartmentId, x.Stage })
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_ContractDeptApprovals_Contract_Phase_Dept_Stage");
|
||||
b.HasIndex(x => x.ContractId);
|
||||
b.HasIndex(x => x.DepartmentId);
|
||||
b.HasIndex(x => x.ApproverUserId);
|
||||
|
||||
b.HasOne(x => x.Contract)
|
||||
.WithMany(c => c.DepartmentApprovals)
|
||||
.HasForeignKey(x => x.ContractId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
|
||||
public class PurchaseEvaluationDepartmentApprovalConfiguration
|
||||
: IEntityTypeConfiguration<PurchaseEvaluationDepartmentApproval>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PurchaseEvaluationDepartmentApproval> b)
|
||||
{
|
||||
b.ToTable("PurchaseEvaluationDepartmentApprovals");
|
||||
b.HasKey(x => x.Id);
|
||||
|
||||
b.Property(x => x.Stage).HasConversion<int>();
|
||||
b.Property(x => x.ApproverRoleSnapshot).HasMaxLength(100);
|
||||
b.Property(x => x.Comment).HasMaxLength(1000);
|
||||
|
||||
b.HasIndex(x => new { x.PurchaseEvaluationId, x.PhaseAtApproval, x.DepartmentId, x.Stage })
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_PEDeptApprovals_PE_Phase_Dept_Stage");
|
||||
b.HasIndex(x => x.PurchaseEvaluationId);
|
||||
b.HasIndex(x => x.DepartmentId);
|
||||
b.HasIndex(x => x.ApproverUserId);
|
||||
|
||||
b.HasOne(x => x.PurchaseEvaluation)
|
||||
.WithMany(c => c.DepartmentApprovals)
|
||||
.HasForeignKey(x => x.PurchaseEvaluationId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
|
||||
public class BudgetDepartmentApprovalConfiguration
|
||||
: IEntityTypeConfiguration<BudgetDepartmentApproval>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<BudgetDepartmentApproval> b)
|
||||
{
|
||||
b.ToTable("BudgetDepartmentApprovals");
|
||||
b.HasKey(x => x.Id);
|
||||
|
||||
b.Property(x => x.Stage).HasConversion<int>();
|
||||
b.Property(x => x.ApproverRoleSnapshot).HasMaxLength(100);
|
||||
b.Property(x => x.Comment).HasMaxLength(1000);
|
||||
|
||||
b.HasIndex(x => new { x.BudgetId, x.PhaseAtApproval, x.DepartmentId, x.Stage })
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_BudgetDeptApprovals_Budget_Phase_Dept_Stage");
|
||||
b.HasIndex(x => x.BudgetId);
|
||||
b.HasIndex(x => x.DepartmentId);
|
||||
b.HasIndex(x => x.ApproverUserId);
|
||||
|
||||
b.HasOne(x => x.Budget)
|
||||
.WithMany(c => c.DepartmentApprovals)
|
||||
.HasForeignKey(x => x.BudgetId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ public class PurchaseEvaluationConfiguration : IEntityTypeConfiguration<Purchase
|
||||
b.Property(x => x.MaPhieu).HasMaxLength(100);
|
||||
b.Property(x => x.Type).HasConversion<int>();
|
||||
b.Property(x => x.Phase).HasConversion<int>();
|
||||
b.Property(x => x.RejectedFromPhase).HasConversion<int?>();
|
||||
b.Property(x => x.TenGoiThau).HasMaxLength(500).IsRequired();
|
||||
b.Property(x => x.DiaDiem).HasMaxLength(500);
|
||||
b.Property(x => x.MoTa).HasMaxLength(2000);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,231 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddTwoStageDeptApprovalAndSmartReject : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "CanBypassReview",
|
||||
table: "Users",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "RejectedFromPhase",
|
||||
table: "PurchaseEvaluations",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "RejectedFromPhase",
|
||||
table: "Contracts",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "RejectedFromPhase",
|
||||
table: "Budgets",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BudgetDepartmentApprovals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
BudgetId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
PhaseAtApproval = table.Column<int>(type: "int", nullable: false),
|
||||
DepartmentId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Stage = table.Column<int>(type: "int", nullable: false),
|
||||
ApproverUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ApproverRoleSnapshot = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Comment = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
ApprovedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
IsBypassed = table.Column<bool>(type: "bit", 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),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BudgetDepartmentApprovals", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_BudgetDepartmentApprovals_Budgets_BudgetId",
|
||||
column: x => x.BudgetId,
|
||||
principalTable: "Budgets",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ContractDepartmentApprovals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ContractId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
PhaseAtApproval = table.Column<int>(type: "int", nullable: false),
|
||||
DepartmentId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Stage = table.Column<int>(type: "int", nullable: false),
|
||||
ApproverUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ApproverRoleSnapshot = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Comment = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
ApprovedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
IsBypassed = table.Column<bool>(type: "bit", 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),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ContractDepartmentApprovals", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ContractDepartmentApprovals_Contracts_ContractId",
|
||||
column: x => x.ContractId,
|
||||
principalTable: "Contracts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PurchaseEvaluationDepartmentApprovals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
PurchaseEvaluationId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
PhaseAtApproval = table.Column<int>(type: "int", nullable: false),
|
||||
DepartmentId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Stage = table.Column<int>(type: "int", nullable: false),
|
||||
ApproverUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
ApproverRoleSnapshot = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Comment = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||
ApprovedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
IsBypassed = table.Column<bool>(type: "bit", 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),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PurchaseEvaluationDepartmentApprovals", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PurchaseEvaluationDepartmentApprovals_PurchaseEvaluations_PurchaseEvaluationId",
|
||||
column: x => x.PurchaseEvaluationId,
|
||||
principalTable: "PurchaseEvaluations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetDepartmentApprovals_ApproverUserId",
|
||||
table: "BudgetDepartmentApprovals",
|
||||
column: "ApproverUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetDepartmentApprovals_BudgetId",
|
||||
table: "BudgetDepartmentApprovals",
|
||||
column: "BudgetId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BudgetDepartmentApprovals_DepartmentId",
|
||||
table: "BudgetDepartmentApprovals",
|
||||
column: "DepartmentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UX_BudgetDeptApprovals_Budget_Phase_Dept_Stage",
|
||||
table: "BudgetDepartmentApprovals",
|
||||
columns: new[] { "BudgetId", "PhaseAtApproval", "DepartmentId", "Stage" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ContractDepartmentApprovals_ApproverUserId",
|
||||
table: "ContractDepartmentApprovals",
|
||||
column: "ApproverUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ContractDepartmentApprovals_ContractId",
|
||||
table: "ContractDepartmentApprovals",
|
||||
column: "ContractId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ContractDepartmentApprovals_DepartmentId",
|
||||
table: "ContractDepartmentApprovals",
|
||||
column: "DepartmentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UX_ContractDeptApprovals_Contract_Phase_Dept_Stage",
|
||||
table: "ContractDepartmentApprovals",
|
||||
columns: new[] { "ContractId", "PhaseAtApproval", "DepartmentId", "Stage" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PurchaseEvaluationDepartmentApprovals_ApproverUserId",
|
||||
table: "PurchaseEvaluationDepartmentApprovals",
|
||||
column: "ApproverUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PurchaseEvaluationDepartmentApprovals_DepartmentId",
|
||||
table: "PurchaseEvaluationDepartmentApprovals",
|
||||
column: "DepartmentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PurchaseEvaluationDepartmentApprovals_PurchaseEvaluationId",
|
||||
table: "PurchaseEvaluationDepartmentApprovals",
|
||||
column: "PurchaseEvaluationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UX_PEDeptApprovals_PE_Phase_Dept_Stage",
|
||||
table: "PurchaseEvaluationDepartmentApprovals",
|
||||
columns: new[] { "PurchaseEvaluationId", "PhaseAtApproval", "DepartmentId", "Stage" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "BudgetDepartmentApprovals");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ContractDepartmentApprovals");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PurchaseEvaluationDepartmentApprovals");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CanBypassReview",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "RejectedFromPhase",
|
||||
table: "PurchaseEvaluations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "RejectedFromPhase",
|
||||
table: "Contracts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "RejectedFromPhase",
|
||||
table: "Budgets");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,6 +169,9 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int?>("RejectedFromPhase")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("SlaDeadline")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
@ -314,6 +317,77 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("BudgetChangelogs", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetDepartmentApproval", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("ApprovedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("ApproverRoleSnapshot")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<Guid>("ApproverUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("BudgetId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("nvarchar(1000)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("DepartmentId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<bool>("IsBypassed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("PhaseAtApproval")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Stage")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ApproverUserId");
|
||||
|
||||
b.HasIndex("BudgetId");
|
||||
|
||||
b.HasIndex("DepartmentId");
|
||||
|
||||
b.HasIndex("BudgetId", "PhaseAtApproval", "DepartmentId", "Stage")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_BudgetDeptApprovals_Budget_Phase_Dept_Stage");
|
||||
|
||||
b.ToTable("BudgetDepartmentApprovals", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetDetail", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@ -438,6 +512,9 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int?>("RejectedFromPhase")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("SlaDeadline")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
@ -701,6 +778,77 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("ContractComments", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Contracts.ContractDepartmentApproval", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("ApprovedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("ApproverRoleSnapshot")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<Guid>("ApproverUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("nvarchar(1000)");
|
||||
|
||||
b.Property<Guid>("ContractId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("DepartmentId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<bool>("IsBypassed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("PhaseAtApproval")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Stage")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ApproverUserId");
|
||||
|
||||
b.HasIndex("ContractId");
|
||||
|
||||
b.HasIndex("DepartmentId");
|
||||
|
||||
b.HasIndex("ContractId", "PhaseAtApproval", "DepartmentId", "Stage")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_ContractDeptApprovals_Contract_Phase_Dept_Stage");
|
||||
|
||||
b.ToTable("ContractDepartmentApprovals", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Contracts.Details.DichVuDetail", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@ -1598,6 +1746,9 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("CanBypassReview")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
@ -2222,6 +2373,9 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<Guid>("ProjectId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int?>("RejectedFromPhase")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid?>("SelectedSupplierId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
@ -2451,6 +2605,77 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("PurchaseEvaluationCodeSequences", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluationDepartmentApproval", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("ApprovedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("ApproverRoleSnapshot")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.Property<Guid>("ApproverUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("nvarchar(1000)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("DepartmentId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<bool>("IsBypassed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("PhaseAtApproval")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("PurchaseEvaluationId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("Stage")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ApproverUserId");
|
||||
|
||||
b.HasIndex("DepartmentId");
|
||||
|
||||
b.HasIndex("PurchaseEvaluationId");
|
||||
|
||||
b.HasIndex("PurchaseEvaluationId", "PhaseAtApproval", "DepartmentId", "Stage")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UX_PEDeptApprovals_PE_Phase_Dept_Stage");
|
||||
|
||||
b.ToTable("PurchaseEvaluationDepartmentApprovals", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluationDepartmentOpinion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@ -2904,6 +3129,17 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Budget");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetDepartmentApproval", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.Budgets.Budget", "Budget")
|
||||
.WithMany("DepartmentApprovals")
|
||||
.HasForeignKey("BudgetId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Budget");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Budgets.BudgetDetail", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.Budgets.Budget", "Budget")
|
||||
@ -2959,6 +3195,17 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Contract");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Contracts.ContractDepartmentApproval", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.Contracts.Contract", "Contract")
|
||||
.WithMany("DepartmentApprovals")
|
||||
.HasForeignKey("ContractId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Contract");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Contracts.Details.DichVuDetail", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.Contracts.Contract", "Contract")
|
||||
@ -3128,6 +3375,17 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("PurchaseEvaluation");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluationDepartmentApproval", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluation", "PurchaseEvaluation")
|
||||
.WithMany("DepartmentApprovals")
|
||||
.HasForeignKey("PurchaseEvaluationId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("PurchaseEvaluation");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluationDepartmentOpinion", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.PurchaseEvaluations.PurchaseEvaluation", "PurchaseEvaluation")
|
||||
@ -3212,6 +3470,8 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.Navigation("Changelogs");
|
||||
|
||||
b.Navigation("DepartmentApprovals");
|
||||
|
||||
b.Navigation("Details");
|
||||
});
|
||||
|
||||
@ -3225,6 +3485,8 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("DepartmentApprovals");
|
||||
|
||||
b.Navigation("DichVuDetails");
|
||||
|
||||
b.Navigation("GiaoKhoanDetails");
|
||||
@ -3265,6 +3527,8 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.Navigation("Changelogs");
|
||||
|
||||
b.Navigation("DepartmentApprovals");
|
||||
|
||||
b.Navigation("DepartmentOpinions");
|
||||
|
||||
b.Navigation("Details");
|
||||
|
||||
Reference in New Issue
Block a user