[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:
@ -0,0 +1,27 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SolutionErp.Application.PurchaseEvaluations;
|
||||
|
||||
namespace SolutionErp.Api.Controllers;
|
||||
|
||||
// Versioned workflow admin cho module Duyệt NCC (PE). Reuse policy
|
||||
// "Workflows.Read" + "Workflows.Create" giống Contract — admin có quyền
|
||||
// quản lý cả 2 nhóm workflow (HĐ + PE).
|
||||
[ApiController]
|
||||
[Route("api/pe-workflows")]
|
||||
[Authorize(Policy = "Workflows.Read")]
|
||||
public class PeWorkflowsController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PeWorkflowAdminOverviewDto>> Overview(CancellationToken ct)
|
||||
=> Ok(await mediator.Send(new GetPeWorkflowAdminOverviewQuery(), ct));
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "Workflows.Create")]
|
||||
public async Task<ActionResult<object>> Create([FromBody] CreatePeWorkflowDefinitionCommand cmd, CancellationToken ct)
|
||||
{
|
||||
var id = await mediator.Send(cmd, ct);
|
||||
return Ok(new { id });
|
||||
}
|
||||
}
|
||||
@ -201,8 +201,29 @@ public class PurchaseEvaluationsController(IMediator mediator) : ControllerBase
|
||||
id, body.ContractType, body.TenHopDong, body.BypassProcurementAndCCM), ct);
|
||||
return Ok(new { contractId });
|
||||
}
|
||||
|
||||
// ========== Ý kiến 4 phòng ban ==========
|
||||
|
||||
// Upsert opinion (Add nếu chưa có, Update text + optional sign).
|
||||
[HttpPost("{id:guid}/opinions")]
|
||||
public async Task<ActionResult<object>> UpsertOpinion(
|
||||
Guid id, [FromBody] OpinionBody body, CancellationToken ct)
|
||||
{
|
||||
var resultId = await mediator.Send(new UpsertPeDepartmentOpinionCommand(
|
||||
id, body.Kind, body.Opinion, body.Sign), ct);
|
||||
return Ok(new { id = resultId });
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}/opinions/{kind}")]
|
||||
public async Task<IActionResult> DeleteOpinion(Guid id, PeDepartmentKind kind, CancellationToken ct)
|
||||
{
|
||||
await mediator.Send(new DeletePeDepartmentOpinionCommand(id, kind), ct);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
public record OpinionBody(PeDepartmentKind Kind, string? Opinion, bool Sign);
|
||||
|
||||
public record CreateContractFromEvaluationBody(
|
||||
Domain.Contracts.ContractType ContractType,
|
||||
string? TenHopDong,
|
||||
|
||||
Reference in New Issue
Block a user