[CLAUDE] Domain+Infra: Migration 18 PE workflow inner steps + User.PositionLevel (Chunk A)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
N-stage workflow approval — mỗi WorkflowStep cha (= 1 phase) cấu hình
được chuỗi InnerSteps con theo Department × PositionLevel với Order
sequential. Phase 9+ feature, mở rộng từ 2-stage Mig 16.
Schema:
- enum PositionLevel { NhanVien=1, PhoPhong=2, TruongPhong=3 } (Domain/Identity)
- ALTER Users + PositionLevel int? NULL (admin/system user vẫn null)
- CREATE TABLE PurchaseEvaluationWorkflowStepInnerSteps:
Id PK, PurchaseEvaluationWorkflowStepId FK Cascade,
Order int, DepartmentId FK Restrict, PositionLevel int,
Name nvarchar(200), SlaDays int?, IsRequired bit
- ALTER PurchaseEvaluationDepartmentApprovals + InnerStepId Guid? FK Restrict
(null cho data legacy 2-stage Review/Confirm Mig 16)
Backward compat: step KHÔNG có InnerSteps → service fallback logic
2-stage Stage=Review|Confirm cũ (Chunk C). Data Mig 16 hiện có giữ
nguyên, InnerStepId=null.
Verify:
- dotnet build SolutionErp.slnx pass (0 error, 2 pre-existing warning DocxRenderer)
- dotnet ef database update LocalDB applied OK
- dotnet test SolutionErp.slnx 83 pass (54 Domain + 29 Infra) — no regression
- 3-file rule: Migration.cs + Designer.cs + Snapshot updated
Pending Chunk B: Application CQRS — extend CreatePeWorkflowDefinitionCommand
với InnerSteps DTO + UpdateUserPositionLevelCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
src/Backend/SolutionErp.Domain/Identity/PositionLevel.cs
Normal file
16
src/Backend/SolutionErp.Domain/Identity/PositionLevel.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace SolutionErp.Domain.Identity;
|
||||
|
||||
// Cấp chức danh trong phòng ban — phục vụ N-stage workflow inner step (Mig 18).
|
||||
// Mỗi WorkflowStep cha (= 1 phase) có thể cấu hình 1 chuỗi inner step
|
||||
// con (Order asc) khớp Department × PositionLevel. Ai đúng phòng + đúng cấp
|
||||
// (+ Order tiếp theo chưa duyệt) thì duyệt được.
|
||||
//
|
||||
// Default null cho admin/system/external user không thuộc cấp cụ thể.
|
||||
// CanBypassReview=true ở User cho phép cấp cao hơn (TP) skip cấp dưới
|
||||
// (NV+PP) cùng Department khi duyệt 1 inner step block.
|
||||
public enum PositionLevel
|
||||
{
|
||||
NhanVien = 1, // NV
|
||||
PhoPhong = 2, // PP
|
||||
TruongPhong = 3, // TP
|
||||
}
|
||||
@ -18,6 +18,13 @@ public class User : IdentityUser<Guid>
|
||||
|
||||
// 2-stage department approval (Phase 9 — Migration 16): khi true, NV
|
||||
// được quyền duyệt thay TPB (skip Stage Review, đẩy thẳng Stage Confirm).
|
||||
// Cũng dùng cho N-stage inner step (Mig 18) — TP có CanBypassReview
|
||||
// skip NV+PP cùng Department.
|
||||
// Mặc định false (an toàn). Admin set ở UserManager UI.
|
||||
public bool CanBypassReview { get; set; }
|
||||
|
||||
// Cấp chức danh trong phòng — phục vụ N-stage workflow inner step (Mig 18).
|
||||
// Mỗi inner step yêu cầu user khớp DepartmentId + PositionLevel mới duyệt
|
||||
// được sub-step đó. Null cho admin/system/external user.
|
||||
public PositionLevel? PositionLevel { get; set; }
|
||||
}
|
||||
|
||||
@ -15,12 +15,18 @@ public class PurchaseEvaluationDepartmentApproval : AuditableEntity
|
||||
public Guid PurchaseEvaluationId { get; set; }
|
||||
public int PhaseAtApproval { get; set; } // snapshot PurchaseEvaluationPhase int
|
||||
public Guid DepartmentId { get; set; }
|
||||
public ApprovalStage Stage { get; set; } // 1=Review (NV), 2=Confirm (TPB)
|
||||
public ApprovalStage Stage { get; set; } // 1=Review (NV), 2=Confirm (TPB) — legacy 2-stage Mig 16
|
||||
public Guid ApproverUserId { get; set; }
|
||||
public string? ApproverRoleSnapshot { get; set; }
|
||||
public string? Comment { get; set; }
|
||||
public DateTime ApprovedAt { get; set; }
|
||||
public bool IsBypassed { get; set; }
|
||||
|
||||
// N-stage inner step link (Mig 18) — null cho data legacy 2-stage Review/Confirm.
|
||||
// Có giá trị khi step cha có InnerSteps configured → mỗi sub-step approve =
|
||||
// 1 row riêng với InnerStepId set. Cùng Stage=Confirm (legacy field giữ nguyên
|
||||
// cho backward compat — N-stage không dùng Review/Confirm semantics).
|
||||
public Guid? InnerStepId { get; set; }
|
||||
|
||||
public PurchaseEvaluation? PurchaseEvaluation { get; set; }
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
using SolutionErp.Domain.Contracts; // reuse WorkflowApproverKind
|
||||
using SolutionErp.Domain.Identity; // reuse PositionLevel
|
||||
|
||||
namespace SolutionErp.Domain.PurchaseEvaluations;
|
||||
|
||||
@ -34,6 +35,12 @@ public class PurchaseEvaluationWorkflowStep : BaseEntity
|
||||
|
||||
public PurchaseEvaluationWorkflowDefinition? Definition { get; set; }
|
||||
public List<PurchaseEvaluationWorkflowStepApprover> Approvers { get; set; } = new();
|
||||
|
||||
// Inner steps (Mig 18) — N-stage approval cấu hình động trong cùng 1 phase.
|
||||
// Empty list → fallback logic 2-stage Review/Confirm legacy (Mig 16) per dept.
|
||||
// Có item → service loop theo Order: user khớp Department × PositionLevel
|
||||
// duyệt sub-step. Tất cả required InnerSteps Done → cho phase transition.
|
||||
public List<PurchaseEvaluationWorkflowStepInnerStep> InnerSteps { get; set; } = new();
|
||||
}
|
||||
|
||||
public class PurchaseEvaluationWorkflowStepApprover : BaseEntity
|
||||
@ -44,3 +51,24 @@ public class PurchaseEvaluationWorkflowStepApprover : BaseEntity
|
||||
|
||||
public PurchaseEvaluationWorkflowStep? Step { get; set; }
|
||||
}
|
||||
|
||||
// Inner step (Mig 18 — Phase 9+) — sub-step level con cấu hình bên trong 1
|
||||
// WorkflowStep cha (= 1 phase). Cho phép admin định nghĩa thứ tự duyệt N-stage
|
||||
// theo Department × PositionLevel: NV.A → PP.A → TP.A → NV.B → PP.B → TP.B → ...
|
||||
//
|
||||
// User khớp DepartmentId + PositionLevel + Order tiếp theo chưa duyệt = approver
|
||||
// hợp lệ. CanBypassReview ở User cho TP skip NV+PP cùng dept (audit IsBypassed).
|
||||
//
|
||||
// IsRequired=false → cho phép skip không cần row approval (vd "PP optional").
|
||||
public class PurchaseEvaluationWorkflowStepInnerStep : BaseEntity
|
||||
{
|
||||
public Guid PurchaseEvaluationWorkflowStepId { get; set; }
|
||||
public int Order { get; set; } // thứ tự sequential trong cùng step cha
|
||||
public Guid DepartmentId { get; set; }
|
||||
public PositionLevel PositionLevel { get; set; } // NV / PP / TP
|
||||
public string? Name { get; set; } // hiển thị FE — vd "NV.PRO duyệt"
|
||||
public int? SlaDays { get; set; } // override step.SlaDays nếu set
|
||||
public bool IsRequired { get; set; } = true; // false → optional skip không cần row
|
||||
|
||||
public PurchaseEvaluationWorkflowStep? Step { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user