[CLAUDE] PurchaseEvaluation: Mig 26 PeLevelOpinions V2 dynamic — Chunk A Domain + EF
Schema mới cho Section 5 "Ý kiến cấp duyệt" V2 dynamic theo ApprovalWorkflowsV2 (Mig 22-25). Thay thế Mig 15 cố định 4 box (V1). Entity `PurchaseEvaluationLevelOpinion : AuditableEntity`: - (PEId, ApprovalWorkflowLevelId) UNIQUE composite - Comment nvarchar(2000) — text ý kiến hoặc "(duyệt — không ý kiến)" placeholder (Q4 bonus) - SignedAt datetime2 (luôn có khi UPSERT từ ApproveV2Async) - SignedByUserId Guid (NV chính chủ HOẶC Admin override) - SignedByFullName nvarchar(200) — denorm tránh user bị xóa/đổi tên EF: FK Cascade Pe + Restrict Level. SignedByUserId KHÔNG nav (denorm only). Migration 26 `AddPeLevelOpinionsForV2`: 1 CREATE TABLE + 2 FK + 2 index. 3-file rule commit đủ (.cs + Designer + Snapshot). Apply LocalDB SolutionErp_Dev OK (Mig 25 + 26 catchup). Verify: dotnet build pass + dotnet test 81 pass (no regression). Chunk B kế tiếp: Service V2 hook UPSERT auto trong ApproveV2Async.
This commit is contained in:
@ -62,4 +62,9 @@ public class PurchaseEvaluation : AuditableEntity
|
||||
public List<PurchaseEvaluationAttachment> Attachments { get; set; } = new();
|
||||
public List<PurchaseEvaluationDepartmentOpinion> DepartmentOpinions { get; set; } = new();
|
||||
public List<PurchaseEvaluationDepartmentApproval> DepartmentApprovals { get; set; } = new();
|
||||
|
||||
// Mig 26 (Session 19) — Ý kiến cấp duyệt V2 dynamic. UPSERT auto từ
|
||||
// ApproveV2Async theo Cấp hiện tại. Section 5 FE render dynamic theo
|
||||
// flow.steps[].levels[]. Phiếu V1 (WorkflowDefinitionId) KHÔNG dùng.
|
||||
public List<PurchaseEvaluationLevelOpinion> LevelOpinions { get; set; } = new();
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
using SolutionErp.Domain.ApprovalWorkflowsV2;
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.PurchaseEvaluations;
|
||||
|
||||
// "Ý kiến cấp duyệt" V2 — sign-off DYNAMIC theo workflow ApprovalWorkflowV2
|
||||
// (Mig 22-25). Thay thế `PurchaseEvaluationDepartmentOpinion` (Mig 15) cố
|
||||
// định 4 box (PheDuyet/Ccm/MuaHang/SmPm) cho phiếu V1.
|
||||
//
|
||||
// Mỗi row = 1 (PE × ApprovalWorkflowLevel). Service `ApproveV2Async` sau khi
|
||||
// approve thành công Cấp hiện tại sẽ UPSERT row này:
|
||||
// Comment = approval.Comment ?? "(duyệt — không ý kiến)" (Q4 bonus)
|
||||
// SignedAt = clock.UtcNow
|
||||
// SignedByUserId = actor.Id (NV chính chủ HOẶC Admin override)
|
||||
// SignedByFullName = actor.FullName (denorm — tránh user bị xóa/đổi tên)
|
||||
//
|
||||
// Reject (Trả lại / Từ chối) KHÔNG sync (vì không phải sign-off của level đó).
|
||||
// Khi user resubmit từ TraLai → workflow chạy lại từ Cấp 1, opinion cũ bị
|
||||
// OVERWRITE bằng UPSERT mới (latest-write-wins).
|
||||
//
|
||||
// Section 5 FE detect V2 qua `pe.approvalWorkflowId != null` → render dynamic
|
||||
// theo flow.steps[].levels[]. Phiếu V1 (WorkflowDefinitionId set) → fallback
|
||||
// message "phiếu cũ không có ý kiến dynamic" (Q3 chốt: chuyển V2 hết).
|
||||
public class PurchaseEvaluationLevelOpinion : AuditableEntity
|
||||
{
|
||||
public Guid PurchaseEvaluationId { get; set; }
|
||||
public Guid ApprovalWorkflowLevelId { get; set; }
|
||||
|
||||
public string? Comment { get; set; } // ý kiến (max 2000) hoặc placeholder "(duyệt — không ý kiến)"
|
||||
public DateTime SignedAt { get; set; } // luôn có khi UPSERT (Service set khi Approve)
|
||||
public Guid SignedByUserId { get; set; } // người ký thực sự (có thể là Admin thay NV)
|
||||
public string SignedByFullName { get; set; } = string.Empty; // snapshot tên — denorm
|
||||
|
||||
public PurchaseEvaluation? PurchaseEvaluation { get; set; }
|
||||
public ApprovalWorkflowLevel? Level { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user