[CLAUDE] PE: Workflow designer admin UI + Ý kiến 4 phòng ban (P1 Session 5)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m51s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m51s
==== Task 1: PE Workflow Designer admin ====
BE (mirror Contract WorkflowAdminFeatures pattern):
- Application/PurchaseEvaluations/PeWorkflowAdminFeatures.cs ~250 LOC:
- GetPeWorkflowAdminOverviewQuery → list 2 EvaluationType (DuyetNcc / DuyetNccPhuongAn) với Active + History versions + count phiếu đang dùng
- CreatePeWorkflowDefinitionCommand + Validator: auto-increment Version per Code, deactivate Active cũ trong cùng EvaluationType (1 active per type invariant)
- DTOs: PeWorkflowStepApproverDto / PeWorkflowStepDto / PeWorkflowDefinitionDto / PeWorkflowTypeSummaryDto / PeWorkflowAdminOverviewDto
- Phase validation 1..7 (state thường, không bao gồm 99=TuChoi)
- Api/Controllers/PeWorkflowsController.cs: 2 endpoint GET /api/pe-workflows + POST. Reuse policy "Workflows.Read" + "Workflows.Create" (admin chung quyền cho cả 2 nhóm WF).
FE:
- pages/system/PeWorkflowsPage.tsx ~500 LOC mirror WorkflowsPage:
- Landing 2-card grid khi /system/pe-workflows (chưa pick type)
- TypePanel khi /system/pe-workflows/:typeCode (DuyetNcc / DuyetNccPhuongAn)
- DefinitionCard read-only view với active badge + version + steps + approvers (Role/User chip)
- PeWorkflowDesigner dialog: clone từ existing, edit Code/Name/Description, add/remove steps, +Role / +User approvers per step, save → version mới + deactivate cũ
- App.tsx route /system/pe-workflows + /system/pe-workflows/:typeCode
- Layout đã có resolver PeWf_<Code> → /system/pe-workflows/<code> từ session 3
==== Task 2: Ý kiến 4 phòng ban PE ====
Domain:
- PurchaseEvaluationDepartmentOpinion entity (AuditableEntity) — PEId + Kind + Opinion text + SignedAt + UserId + UserName denorm
- PeDepartmentKind enum (PheDuyet / Ccm / MuaHang / SmPm)
- PE entity + collection navigation DepartmentOpinions
Infrastructure:
- PurchaseEvaluationDepartmentOpinionConfiguration EF: UNIQUE(PEId, Kind) — max 1 row per phòng ban per phiếu (UPDATE in-place)
- ApplicationDbContext + IApplicationDbContext DbSet
- Migration 15 AddPurchaseEvaluationDepartmentOpinions (15 migration total / 52 DB tables)
Application:
- PeDepartmentOpinionFeatures.cs: UpsertPeDepartmentOpinionCommand (sign=true → set SignedAt+UserId, sign=false chỉ lưu text giữ chữ ký cũ) + DeletePeDepartmentOpinionCommand
- DTO bundle update: + DepartmentOpinions list trong PurchaseEvaluationDetailBundleDto
- GetPurchaseEvaluationQueryHandler load DepartmentOpinions + KindLabel resolution
API:
- POST /api/purchase-evaluations/{id}/opinions (upsert)
- DELETE /api/purchase-evaluations/{id}/opinions/{kind}
FE:
- types/purchaseEvaluation.ts: + PeDepartmentKind enum + PeDepartmentKindLabel + PeDepartmentOpinion type + departmentOpinions vào bundle
- PeDetailTabs Section "5. Ý kiến 4 phòng ban (sign-off)" — 2x2 grid OpinionBox per kind:
- Read mode (readOnly menu Duyệt): hiển thị text + chữ ký
- Edit mode: textarea + 2 button "Lưu text" / "Lưu & Ký"
- Badge "Đã ký" emerald + tên người ký + ngày khi signedAt != null
==== Task 3: User seed verify ====
Seed `SeedDemoUsersAsync` đã match đúng user list authoritative (5 PRO TPB+NV / 7 CCM TPB+NV / 1 ISO / 1 CEO) từ prior commit. DbInitializer reconcile sẽ tự sync khi API restart. Typo trong list user (soluttions / trương) đã fixed sensibly trong seed.
==== Build verify ====
- dotnet build clean (0 error)
- fe-admin TS build pass (1 module mới PeWorkflowsPage)
- fe-user TS build pass (PE detail mirror)
Total: 8 file mới (BE 4 + FE 1 + Migration 2 + 1 Domain) + 13 file modified.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -34,4 +34,5 @@ public class PurchaseEvaluation : AuditableEntity
|
||||
public List<PurchaseEvaluationApproval> Approvals { get; set; } = new();
|
||||
public List<PurchaseEvaluationChangelog> Changelogs { get; set; } = new();
|
||||
public List<PurchaseEvaluationAttachment> Attachments { get; set; } = new();
|
||||
public List<PurchaseEvaluationDepartmentOpinion> DepartmentOpinions { get; set; } = new();
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.PurchaseEvaluations;
|
||||
|
||||
// "Ý kiến 4 phòng ban" — sign-off block trên PHIẾU TRÌNH KÝ CHỌN TP/NCC.
|
||||
// 4 box: Phê duyệt / P.CCM / P.MuaHàng / SM-PM. Mỗi box có:
|
||||
// - Opinion text (text ý kiến)
|
||||
// - SignedAt date
|
||||
// - UserId người ký (lưu UserName denorm để render readable)
|
||||
//
|
||||
// Lưu thành table riêng (1:N với PurchaseEvaluation, max 4 row mỗi PE) để:
|
||||
// - Dễ query "phòng nào chưa ký"
|
||||
// - Audit history (mỗi update là 1 record? — không, dùng UPDATE in-place,
|
||||
// audit qua PurchaseEvaluationChangelog).
|
||||
// - Không bloat header với 12 column nullable.
|
||||
public enum PeDepartmentKind
|
||||
{
|
||||
PheDuyet = 1, // box "PHÊ DUYỆT" trên cùng — typically Drafter/PM ký xác nhận trình
|
||||
Ccm = 2, // P.CCM — Cost Control review
|
||||
MuaHang = 3, // P.MuaHàng (PRO) — Procurement
|
||||
SmPm = 4, // SM-PM — Site Manager / Project Manager
|
||||
}
|
||||
|
||||
public class PurchaseEvaluationDepartmentOpinion : AuditableEntity
|
||||
{
|
||||
public Guid PurchaseEvaluationId { get; set; }
|
||||
public PeDepartmentKind Kind { get; set; }
|
||||
|
||||
public string? Opinion { get; set; } // text ý kiến (max 2000)
|
||||
public DateTime? SignedAt { get; set; }
|
||||
public Guid? UserId { get; set; } // người ký
|
||||
public string? UserName { get; set; } // denorm cho readable render
|
||||
|
||||
public PurchaseEvaluation? PurchaseEvaluation { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user