[CLAUDE] Docs: chốt Session 18 wrap-up — PE V2 polish + Clone B + Mig 25 IsUserSelectable + 4 bug fix UAT

Session 18 (16:56 → 19:45, 7 commit `aaa1c6c` → `32a8d4d`):
- B1 Pe Duyệt filter cứng "Đã gửi duyệt"
- B2 HistoryTab filter Trả lại / Gửi lại
- B3 Clone V2 cho B (DuyetNccPhuongAn) — audit reuse pattern
- B4 Fix silent 403 ApprovalWorkflowsV2Controller
- B5 Fix sidebar highlight queryMatches transient keys
- B6 Mig 25 IsUserSelectable + Designer pin toggle + bỏ "(clone)" + Workspace filter
- B7 Cleanup orphan zip files

Updates:
- STATUS — header 24→25 mig + 43→44 gotcha + 1 row Recently Done top + session log link
- HANDOFF — TL;DR S18 đầy đủ + cảnh báo S19+ (giữ S17 narrative §6.5)
- CLAUDE.md root — count 25 mig + Mig 25 description block
- schema-diagram §14 — heading 22→25 + cột IsUserSelectable + filter logic section + Pending S19+ Mig 26/27
- gotchas — +#44 silent 403 + checklist debug 21
- migration-todos — Phase 9 S18 done section
- session log mới đầy đủ E2E narrative

Stats: 25 mig, 58 tables, ~141 endpoints, 81 test pass (no change), 44 gotcha, 14 memory entries, 6 skill, 7 commit S18.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-08 19:56:42 +07:00
parent 32a8d4db0b
commit daad79d282
7 changed files with 511 additions and 10 deletions

View File

@ -715,7 +715,7 @@ CREATE TABLE PurchaseEvaluationDepartmentOpinions (
CREATE UNIQUE INDEX IX_PEDeptOpinions_PEId_Kind ON PurchaseEvaluationDepartmentOpinions (PurchaseEvaluationId, Kind);
```
## 14. ApprovalWorkflow V2 schema (Migration 22-24, Session 17 — 3 bảng mới + 2 column)
## 14. ApprovalWorkflow V2 schema (Migration 22-25, Session 17-18 — 3 bảng mới + 3 column)
Schema riêng song song WorkflowDefinition V1 (Mig 21) — pin per phiếu PE.
V1 vẫn giữ cho phiếu cũ; V2 mới là active cho phiếu tạo từ Session 17 trở đi.
@ -727,6 +727,7 @@ ApprovalWorkflows
├── Id (PK), Code, Version (UNIQUE Code+Version)
├── ApplicableType (1=DuyetNcc, 2=DuyetNccPhuongAn, 3=Contract)
├── Name, Description, IsActive, ActivatedAt
├── IsUserSelectable (Mig 25, S18) — admin pin/unpin cho user pick lúc create phiếu
└── (audit) CreatedAt, UpdatedAt, CreatedBy, UpdatedBy
ApprovalWorkflowSteps (FK Cascade ApprovalWorkflowId, FK Restrict DepartmentId)
@ -761,7 +762,7 @@ Service iterate: `steps[CurrentStepIndex].Levels.Where(l => l.Order == CurrentLe
| Schema | Match logic | Approver type |
|---|---|---|
| V1 (Mig 21) | `actor.Dept == step.Dept && actor.PositionLevel >= step.PositionLevel` OR Approvers Role/User explicit | Group qua Dept+Level |
| V2 (Mig 22-24) | `actor.Id == any level.ApproverUserId where level.Order == currentLevelOrder` | NV cụ thể 1-1 |
| V2 (Mig 22-25) | `actor.Id == any level.ApproverUserId where level.Order == currentLevelOrder` | NV cụ thể 1-1 |
### State transitions (V2 + V1 cùng):
@ -792,10 +793,22 @@ else
- Mỗi Cấp có N NV (OR-of-N)
- Đổi Phòng → clear toàn bộ approvers (NV cũ có thể không thuộc Phòng mới)
### Pending Session 18+:
### IsUserSelectable filter logic (Mig 25, Session 18):
- Contract V2 wire (Mig 25): mirror PE pattern — thêm `Contract.ApprovalWorkflowId` + `CurrentApprovalLevelOrder`
- Drop legacy V1: sau khi không còn phiếu pin `WorkflowDefinitionId` → drop `WorkflowDefinitions` + `WorkflowSteps` + `WorkflowStepApprovers` + drop deprecated columns `RejectedAtStepIndex` / `RejectedFromPhase`
`IsUserSelectable` độc lập với `IsActive`:
- `IsActive` = "đang áp dụng (default mới)" — max 1 per ApplicableType
- `IsUserSelectable` = "cho user pick lúc create phiếu" — multiple version cùng selectable
Default behavior (sau Mig 25 backfill): active workflows tự động `IsUserSelectable=1` (giữ behavior cũ — Workspace dropdown vẫn hiện active workflow). Archived versions = `0` default, admin có thể toggle qua Designer khi muốn user pick lại version cũ.
`CreateAwDefinitionCommand` set `IsUserSelectable=true` cho version mới (mirror IsActive default). API `PATCH /api/approval-workflows-v2/{id}/user-selectable` — admin toggle stick/unstick (policy `Workflows.Create`).
Workspace `PeWorkspaceCreateView` query `.filter(w => w.isUserSelectable)` — chỉ hiện workflows admin đã ghim.
### Pending Session 19+:
- Contract V2 wire (Mig 26): mirror PE pattern — thêm `Contract.ApprovalWorkflowId` + `CurrentApprovalLevelOrder` + `ContractWorkflowService.ApproveV2Async`
- Drop legacy V1: sau khi không còn phiếu pin `WorkflowDefinitionId` → drop `WorkflowDefinitions` + `WorkflowSteps` + `WorkflowStepApprovers` + drop deprecated columns `RejectedAtStepIndex` / `RejectedFromPhase` (Mig 27 cleanup)
## 15. Liên quan