[CLAUDE] Docs: Session 17 wrap-up — PE Workflow V2 end-to-end consolidation
User chốt MD wrap-up Session 17 (13 commit từc847dc0→de0f38d) — PE Workflow V2 schema + Service wire + UX iteration đầy đủ. MD updates: - STATUS.md — header counts (24 mig, 58 tables, 81 test, 43 gotcha) + Recently Done row consolidate Session 17 wrap-up (gộp 4 row iter cũ thành 1 row tổng, không cắt narrative quan trọng) - HANDOFF.md — TL;DR Session 17 + Chunk E (Designer iter + State machine + Service wire + UX) + Pending Session 18+ - CLAUDE.md — count (22→24 mig, 77→81 test) + V2 schema overview - changelog/migration-todos.md — section ✅ Session 17 done với 7 task ticked + Defer Session 18+ explicit - database/schema-diagram.md — §14 ApprovalWorkflow V2 schema (3 bảng + 2 column PE + state transitions + Service branch + Designer constraints + match approver V2 vs V1 table) - gotchas.md — +#42 Dual schema branch + #43 Step.Order ≠ index 0-based - skill contract-workflow — +section "Phase 9+ done Mig 22-24" với V2 spec + Service branch + match logic table + Designer constraints + UX V2-aware + Defer Session 18+ - changelog/sessions/2026-05-08-1100-pe-workflow-v2-end-to-end.md (NEW) — full session log với 13 commit timeline + stats + gotchas + pending Memory: - project_solution_erp.md — entry Session 17 wrap-up đầy đủ (KHÔNG tạo file feedback mới — decisions specific cho project, không reusable cross-project per §9.5 anti-pattern) Verify: - 81 test pass (58 Domain + 23 Infra) — không thay đổi sau wrap-up - 0 BE error - 2 FE builds OK (đã verify ở các commit trước) - Quy tắc consolidate §6.5: KHÔNG cắt narrative, chỉ phân tầng + remove duplicate. Session 17 row dài cố ý — cover full 13 commit context cho Session 18+ đọc lại.
This commit is contained in:
@ -362,6 +362,90 @@ transition cho mọi phase trung gian (trước chỉ DangSoanThao→TuChoi).
|
||||
- Phase TraLai = 98 (Domain enum từ S11+++++++) — orphan, KHÔNG wire (user
|
||||
Session 14 chốt không cần phase trung gian).
|
||||
|
||||
## Phase 9+ done (Mig 21 — Session 16) — Drastic refactor flat workflow
|
||||
|
||||
Bỏ phase enum legacy 2-9. Dùng `ChoDuyet=10` đơn nhất + `CurrentWorkflowStepIndex` tracking flat. WorkflowStep + DepartmentId/PositionLevel. Service iterate steps `OrderBy Order` advance pointer per approve. Match approver: actor.Dept+PositionLevel OR Approvers Role/User. 96→77 test pass (drop 19 N-stage/2-stage legacy). Phase legacy 2-6 + 98 deprecated giữ enum cho data cũ. Reject về DangSoanThao + RejectedAtStepIndex jump-back resume.
|
||||
|
||||
## Phase 9+ done (Mig 22-24 — Session 17) — V2 schema riêng + state machine 5 trạng thái
|
||||
|
||||
**Spec change (Session 17):** schema riêng `ApprovalWorkflowsV2` (3 bảng) song song V1 (Mig 21 vẫn live). Cấu trúc: Quy trình > Bước (Phòng) > Cấp (N NV cụ thể qua `ApproverUserId`). PE Service wire xong, Contract V2 chưa (defer Session 18+).
|
||||
|
||||
### State machine 5 trạng thái (mirror Contract sẽ áp dụng tương tự)
|
||||
|
||||
```
|
||||
Nháp (DangSoanThao) ──Drafter trình──► Đã gửi duyệt (ChoDuyet)
|
||||
Trả lại (TraLai=98) ──Drafter sửa+gửi lại──► Đã gửi duyệt (chạy LẠI từ Cấp 1 Bước 1)
|
||||
Đã gửi duyệt ──advance level/step──► Đã gửi duyệt
|
||||
──last cấp last bước done──► Đã duyệt (DaDuyet, terminal)
|
||||
──Approver Trả lại──► Trả lại
|
||||
──Approver Từ chối──► Từ chối (TuChoi, terminal)
|
||||
```
|
||||
|
||||
Khác Mig 21 (Session 16): Trả lại = Phase RIÊNG, KHÔNG revert DangSoanThao + KHÔNG jump-back. Drafter từ TraLai gửi lại = entry point thứ 2 mirror DangSoanThao. `RejectedAtStepIndex/RejectedFromPhase` deprecated (giữ DB column data cũ).
|
||||
|
||||
### Service branch theo schema pin
|
||||
|
||||
```csharp
|
||||
// PurchaseEvaluationWorkflowService.TransitionAsync (gotcha #42)
|
||||
if (evaluation.ApprovalWorkflowId is Guid awId)
|
||||
await ApproveV2Async(...) // V2: iterate AW.Steps + Levels match ApproverUserId
|
||||
else
|
||||
await ApproveV1LegacyAsync(...) // V1: iterate WorkflowSteps match Dept+PositionLevel
|
||||
```
|
||||
|
||||
### Match approver V2 — KHÁC V1
|
||||
|
||||
| Schema | Approver type | Match logic |
|
||||
|---|---|---|
|
||||
| V1 (Mig 21) | Group qua Dept+PositionLevel | actor.Dept == step.Dept AND actor.PositionLevel >= step.PositionLevel |
|
||||
| V2 (Mig 22-24) | NV cụ thể 1-1 | actor.Id == any level.ApproverUserId where level.Order == currentLevelOrder |
|
||||
| Cả 2 | Role-based fallback | Approvers explicit Kind=Role match actor.Roles |
|
||||
| Cả 2 | Admin bypass | actorRoles.Contains("Admin") → skip mọi check |
|
||||
|
||||
### Pin V2 (Mig 23-24)
|
||||
|
||||
```csharp
|
||||
public class PurchaseEvaluation : AuditableEntity
|
||||
{
|
||||
public Guid? WorkflowDefinitionId { get; set; } // V1 legacy (Mig 21)
|
||||
public Guid? ApprovalWorkflowId { get; set; } // V2 mới (Mig 23) — pin lúc create
|
||||
public int? CurrentWorkflowStepIndex { get; set; } // 0-based index Step (post-sort by Order)
|
||||
public int? CurrentApprovalLevelOrder { get; set; } // 1/2/3 Cấp đang chờ (Mig 24)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Designer V2 constraints
|
||||
|
||||
- Tối đa 3 Cấp/Bước (Order ∈ {1,2,3})
|
||||
- Sequential gating: 1 / 1+2 / 1+2+3 (chặn 2 hoặc 1+3)
|
||||
- Mỗi Cấp có N NV (multiple Level rows cùng Order = same Cấp, OR-of-N)
|
||||
- 3 section cố định C1/C2/C3 trong UI, button "+ Thêm NV" mỗi cấp
|
||||
- C2 disabled khi C1 empty, C3 disabled khi C2 empty
|
||||
- Filter NV theo Phòng đã chọn (đổi Phòng → clear approvers)
|
||||
- Validator BE: `HaveSequentialOrders` + `HaveNoDuplicateApproverInSameLevel`
|
||||
|
||||
### FE UX V2-aware
|
||||
|
||||
- Banner emerald "Đến lượt bạn" / amber "Không phải lượt bạn — chỉ {NV X / Y} duyệt được"
|
||||
- Button "Duyệt forward" disabled khi V2 + actor không trong Cấp + tooltip
|
||||
- Button "Trả lại" + "Từ chối" enabled cho mọi user (BE không gating reject theo cấp)
|
||||
- Inbox V2-aware (`ResolveV2InboxIdsAsync` precompute IDs khớp actor.Id ∈ Cấp hiện tại)
|
||||
- 2 dropdown filter "Quy trình" + "Trạng thái" (chỉ ở Duyệt, không Danh sách)
|
||||
- Panel 3 thay 4 phase cards bằng flow workflow thực tế: Bước (icon ✓/●/○) → Cấp với label "đang chờ"/"đã duyệt"
|
||||
|
||||
### DTO mới Session 17
|
||||
|
||||
- `PurchaseEvaluationCurrentApprovalDto` — Cấp hiện tại + N approvers (cho banner + button gating)
|
||||
- `PurchaseEvaluationApprovalFlowDto` — full Steps/Levels tree với Status Done/Current/Pending (cho Panel 3 render)
|
||||
|
||||
### Defer Session 18+
|
||||
|
||||
- Contract V2 wire (Mig 25) — mirror PE Mig 23-24 pattern
|
||||
- Phân quyền strict V2 (hiện loose UAT — mọi authenticated user thấy phiếu V2)
|
||||
- Drop legacy V1 sau khi không còn phiếu pin → drop tables WorkflowDefinitions/Steps/Approvers + drop deprecated columns RejectedAtStepIndex/RejectedFromPhase
|
||||
- Test Domain ApproveV2Async + match logic (defer khi có sample data UAT)
|
||||
|
||||
## Tier 4+ (còn thiếu / future)
|
||||
|
||||
- [ ] Warning notification 20% SLA (`SlaWarningSent` flag đã có)
|
||||
|
||||
Reference in New Issue
Block a user