[CLAUDE] Docs: S21 t5 Chunk D — chốt refactor Allow* per-NV (Mig 29)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m18s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m18s
Update docs theo rule §6.5 KEEP narrative:
- `docs/database/schema-diagram.md §14` title "Mig 22-29, S17-21":
- Update ApprovalWorkflows block: note Mig 28 cũ 6 column DROP, refactor per-NV
- Add 5 column Allow* trong ApprovalWorkflowLevels block (inline comment F1+F3)
- Add Users block với F2 AllowDrafterSkipToFinal Mig 29
- `docs/STATUS.md` Last updated S21 t5 + count 28→29 mig. UAT defer test count
unchanged 84.
- `docs/HANDOFF.md` Insert TL;DR S21 t5 đầy đủ (trước S21 t4):
- Trigger UAT feedback "cấu hình cho từng người"
- Q&A 2 lượt chốt scope
- 4 chunk narrative: A BE+Mig 29 + Service refactor → B FE Admin Designer
per-Level → C FE eOffice rename → D Docs
- Pattern reusable: EF migration reorder cho BACKFILL preserve data,
per-NV scope split theo role (Approver Level vs Drafter User)
- State table + Pending User Mgmt F2 UI defer
- NEW session log `docs/changelog/sessions/2026-05-13-1400-s21-turn5-refactor-allow-to-per-nv.md`:
- Code snippets BE/FE refactor
- 5 lessons learned (incl EF reorder pattern + backward compat backfill discipline)
- References file paths
Stats cumulative S21 t5:
- 29 mig (+1 Mig 29 refactor) · 59 tables · ~143 endpoints · 34 FE pages
- 84 test pass (UAT defer test-after §7) · 45 gotcha · 17 memory · 6 skills
- 4 commits S21 t5 cumulative ready push remote
Pending: bro confirm push `eea86fd..HEAD` 4 commits ahead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
144
docs/HANDOFF.md
144
docs/HANDOFF.md
@ -1,10 +1,152 @@
|
||||
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||||
|
||||
**Last updated:** 2026-05-13 1200 (Session 21 turn 4 — **🎯 F1+F2+F3 PE Workflow advanced options (Mig 28) — 5 chunk per-commit `0294693` (A schema) → `c56024b` (B BE) → `a508564` (C FE Admin) → `d27caaf` (D FE eOffice) → this (E Docs). **F1** 4 mode Trả lại admin tick stick (1 Cấp / 1 Bước / Người chỉ định / Người soạn thảo) — 3 mode đầu giữ Phase=ChoDuyet lùi pointer (peer review chain), mode Drafter giữ Phase=TraLai clear pointer (S17 backward compat). **F2** Drafter skip thẳng Cấp cuối — workflow tick + Workspace checkbox dynamic. **F3** Approver edit Section 2 (Hạng mục/NCC/Báo giá) khi workflow tick + actor match CurrentLevel.ApproverUserId + audit ghi PurchaseEvaluationChangelog. Mig 28 thêm 6 bit column lên `ApprovalWorkflows` (DEFAULT 1 cho AllowReturnToDrafter backward compat, 5 còn lại 0). BE Service extend signature 3 optional param (returnMode/returnTargetUserId/skipToFinal). Helper `EnsureEditableForDetailsAsync` mới gating Detail/Quote/Supplier CRUD theo Drafter scope OR F3 Approver scope + audit changelog Update/Delete (trước đây silent). FE Admin Designer "Cấu hình nâng cao" section 6 checkbox 3 group. FE eOffice 3 changes mirror 2 app. UAT mode skip dotnet test mỗi chunk, npm build × 2 app pass mỗi chunk. CHƯA push remote — chờ bro confirm.**)
|
||||
**Last updated:** 2026-05-13 1400 (Session 21 turn 5 — **🎯 Refactor Allow* sang PER-NV (Mig 29). 4 chunk per-commit `0366946` (A BE+Mig 29) → `63234b2` (B FE Admin Designer per-Level 5 checkbox) → `5ccb2a7` (C FE eOffice mirror 2 app rename) → this Chunk D Docs. **F1+F3** 5 flag MOVED xuống `ApprovalWorkflowLevels` (per slot Approver). **F2** MOVED xuống `Users` (per-Drafter). Mig 29 4-stage: ADD 5 Levels + 1 Users + BACKFILL bulk SQL preserve admin config S21 t4 + DROP 6 workflow column. Service refactor đọc `currentLevel.Allow*` + `drafterUser.AllowDrafterSkipToFinal`. DTO `AwLevelDto +5`, `PeDetailBundle.workflowOptions → currentLevelOptions + drafterAllowSkipToFinal`. FE Admin Designer 5 checkbox per Level slot inline (drop section workflow-level). 84 test PASS. CHƯA push remote — chờ bro confirm.**)
|
||||
**S21 turn 4:** 2026-05-13 1200 (Session 21 turn 4 — **🎯 F1+F2+F3 PE Workflow advanced options (Mig 28) — 5 chunk per-commit `0294693` (A schema) → `c56024b` (B BE) → `a508564` (C FE Admin) → `d27caaf` (D FE eOffice) → this (E Docs). **F1** 4 mode Trả lại admin tick stick (1 Cấp / 1 Bước / Người chỉ định / Người soạn thảo) — 3 mode đầu giữ Phase=ChoDuyet lùi pointer (peer review chain), mode Drafter giữ Phase=TraLai clear pointer (S17 backward compat). **F2** Drafter skip thẳng Cấp cuối — workflow tick + Workspace checkbox dynamic. **F3** Approver edit Section 2 (Hạng mục/NCC/Báo giá) khi workflow tick + actor match CurrentLevel.ApproverUserId + audit ghi PurchaseEvaluationChangelog. Mig 28 thêm 6 bit column lên `ApprovalWorkflows` (DEFAULT 1 cho AllowReturnToDrafter backward compat, 5 còn lại 0). BE Service extend signature 3 optional param (returnMode/returnTargetUserId/skipToFinal). Helper `EnsureEditableForDetailsAsync` mới gating Detail/Quote/Supplier CRUD theo Drafter scope OR F3 Approver scope + audit changelog Update/Delete (trước đây silent). FE Admin Designer "Cấu hình nâng cao" section 6 checkbox 3 group. FE eOffice 3 changes mirror 2 app. UAT mode skip dotnet test mỗi chunk, npm build × 2 app pass mỗi chunk. CHƯA push remote — chờ bro confirm.**)
|
||||
**S21 turn 3:** 2026-05-12 2100 (Session 21 turn 3 — **🔴 BUG FIX CRITICAL "Trả về nhưng hệ thống vẫn duyệt" PE workflow (gotcha #45 mới). 3 chunk per-commit: `de00887` (BE Chunk A guard + 3 test) + `4b29d00` (FE Chunk B fix 2 app mirror) + this Chunk C Docs. Root: `PeWorkflowPanel.tsx` `isReject` payload (L64-66) thiếu nhánh TraLai → button "← Trả lại" gửi `decision: 1` (Approve) thay vì `2` (Reject) khi target=TraLai(98) → BE skip Reject branch → enter APPROVE STEP → `ApproveV2Async` UPSERT opinion "đã duyệt" + advance Cấp tiếp theo. Inconsistency phụ: dialog `isSendBack` (L247-248) cùng pattern thiếu TraLai → dialog title sai `'✓ Duyệt → Trả lại'` + KHÔNG amber warning. Severity CRITICAL — data integrity issue khó rollback (BE đã `SaveChangesAsync`). Test-before §7 BẮT BUỘC: viết test reproduce → confirm FAIL (BE đi sâu vào ApproveV2Async throw "Phiếu chưa pin workflow") → thêm BE guard early throw ConflictException khi `target ∈ {TraLai, TuChoi} && decision != Reject` → confirm PASS. 3 regression test (Throws TraLai+Approve, Throws TuChoi+Approve consistency, happy path Reject+TraLai). Tổng `dotnet test SolutionErp.slnx` 84 PASS (58 Domain + 26 Infra = +3 from 81 baseline). `npm run build` × 2 app pass. Stats: 27 mig (no change) · 59 tables · ~142 endpoints · 34 FE pages · **84 test (+3)** · **45 gotcha (+1 #45)** · 17 memory · 6 skills · 4 sub-agents seeds-only. Em main solo S21 t3 — bug fix reasoning chain cross BE/FE Implementer REFUSE per multi-agent rule (decision tree: tightly coupled BE+FE+test). CHƯA push remote — chờ bro confirm sau Chunk C wrap.**)
|
||||
**S21 turn 2:** 2026-05-12 1800 (Session 21 turn 2 — **🎯 RAG Hybrid setup planning + Cách A validation deep dive. 2 commit (`1f8e9af` plan save 1223 LOC + this chốt). KHÔNG implement, plan only — defer chờ bro confirm 5 dự án future. Decision chốt: Cách A defensive (giữ blanket 120K em main + RAG retrieve) over Cách B aggressive (cắt 60-70% blanket). Industry-validated cross 4 Anthropic blog + 5 community tools (Cursor/Continue/Cline/Aider). Stack: Voyage-3-large + Qdrant + FastMCP + Streamlit dashboard. Multi-agent cost reality: 4 agents → ~520K cumulative blanket → heavy session ~560K (Cách A) vs ~700K (lazy). 3-layer pattern Phase 1-3 rollout (embeddings + BM25 + reranking, ~70% → ~92% recall). Stats: +1 memory entry (`feedback_rag_hybrid_pattern`) +1 plan file (`rag-setup-plan.md` 1500 LOC). Sub-agents vẫn 4 seeds-only, em main solo session.**)
|
||||
**S21 turn 1:** 2026-05-12 0030 (Session 21 turn 1 — **🎯 Add con thứ 4 cicd-monitor (Path A — post-deploy verifier). 1 commit `f1c61c9` pushed `36e21c8..f1c61c9 main -> main`. CI skipped per path filter (3 file `.md`). Cost reality update: ~750K spawn (3 → 4 agents) · ~1.35M heavy / ~700K optimized. Stats: 4 sub-agents seeds-only · 16 memory · 27 mig · 59 tables · ~142 endpoints · 81 test · 44 gotcha · 6 skills unchanged. KHÔNG flush 3 agent MEMORY.md (chưa spawn work — em main solo). Trial Week 1 kick-off S21 turn 2+ Plan B Contract V2 wire mirror PE pattern.**)
|
||||
|
||||
## TL;DR Session 21 turn 5 — Refactor Allow* sang PER-NV (Mig 29 drop Mig 28)
|
||||
|
||||
User feedback sau UAT S21 t4 deploy: "Cấu hình cho từng người nhé (chứ ko phải là cho toàn bộ quy trình duyệt), thêm table vào SQL luôn để cấu hình cho dễ."
|
||||
|
||||
→ Refactor 6 Allow* options từ workflow-level (Mig 28) sang per-NV scope:
|
||||
- **F1 (4 mode Trả lại) + F3 (Edit Section 2)** = 5 flag MOVE xuống `ApprovalWorkflowLevels` (per slot Approver — cùng table với ApproverUserId).
|
||||
- **F2 (AllowDrafterSkipToFinal)** MOVE xuống `Users` (per-Drafter user, admin config ở User Management page).
|
||||
|
||||
### Q&A clarify (2 lượt)
|
||||
|
||||
| Câu | User chốt |
|
||||
|---|---|
|
||||
| Scope "từng người" | **Per-Level**: 5 flag (4 F1 + 1 F3) gắn slot Designer. F2 per-Drafter user. |
|
||||
| Mig 28 cũ xử lý sao | **Migrate bốc → per-NV bulk + drop**: copy workflow → all Levels của workflow, set TRUE cho Drafter user từng dùng workflow F2, rồi drop 6 column workflow. |
|
||||
|
||||
### Chunk A — BE schema + Service refactor (`0366946`)
|
||||
|
||||
Mig 29 `RefactorAdvancedOptionsToPerLevelAndDrafterUser` — 4-stage (EF
|
||||
auto-generated drop-then-add đã REORDER manual):
|
||||
|
||||
1. **ADD 5 column** trên `ApprovalWorkflowLevels` (AllowReturnOneLevel/OneStep/
|
||||
ToAssignee/ToDrafter[default true]/AllowApproverEditDetails)
|
||||
2. **ADD 1 column** trên `Users` (AllowDrafterSkipToFinal default false)
|
||||
3. **BACKFILL bulk SQL** (preserve admin config Mig 28):
|
||||
```sql
|
||||
-- Levels: copy workflow.Allow* → all Levels của workflow
|
||||
UPDATE l SET l.AllowReturnOneLevel = w.AllowReturnOneLevel, ...
|
||||
FROM ApprovalWorkflowLevels l
|
||||
INNER JOIN ApprovalWorkflowSteps s ON s.Id = l.ApprovalWorkflowStepId
|
||||
INNER JOIN ApprovalWorkflows w ON w.Id = s.ApprovalWorkflowId;
|
||||
|
||||
-- Users: SET TRUE cho user từng Drafter PE link workflow Allow=true
|
||||
UPDATE u SET u.AllowDrafterSkipToFinal = 1
|
||||
FROM Users u WHERE EXISTS (
|
||||
SELECT 1 FROM PurchaseEvaluations pe
|
||||
INNER JOIN ApprovalWorkflows w ON w.Id = pe.ApprovalWorkflowId
|
||||
WHERE pe.DrafterUserId = u.Id AND w.AllowDrafterSkipToFinal = 1
|
||||
);
|
||||
```
|
||||
4. **DROP 6 column** workflow-level (Mig 28 cleanup)
|
||||
|
||||
Domain entity refactor:
|
||||
- `ApprovalWorkflow.cs` — REMOVE 6 Allow* (S21 t4 Mig 28 cũ)
|
||||
- `ApprovalWorkflowLevel.cs` — ADD 5 Allow* (F1 + F3)
|
||||
- `User.cs` — ADD 1 Allow* (F2 AllowDrafterSkipToFinal)
|
||||
|
||||
Service refactor `ApplyReturnModeAsync`:
|
||||
- Resolve currentLevel slot (CurrentWorkflowStepIndex + CurrentApprovalLevelOrder)
|
||||
- Read 5 Allow* từ `currentLevel.AllowXxx` thay vì workflow
|
||||
- Drafter mode validate AllowReturnToDrafter của currentLevel
|
||||
- V1 legacy phiếu → fallback Drafter tự động
|
||||
|
||||
DRAFTER trình refactor:
|
||||
- Permission check moved → `drafterUser.AllowDrafterSkipToFinal`
|
||||
- `userManager.FindByIdAsync(actorUserId)` get Drafter user entity
|
||||
- Admin bypass unchanged
|
||||
|
||||
Helper `EnsureEditableForDetailsAsync`:
|
||||
- Read `level.AllowApproverEditDetails` thay vì workflow
|
||||
- Error message rõ "Cấp Approver hiện tại (Bước X / Cấp Y)"
|
||||
|
||||
DTO refactor:
|
||||
- `AwLevelDto +5 Allow*` (admin Designer GET per-Level)
|
||||
- `AwDefinitionDto -6 Allow*` (no longer workflow-level)
|
||||
- `CreateAwLevelInput +5 Allow*` (admin Designer POST per-Level)
|
||||
- `ApprovalWorkflowOptionsDto` chỉ còn 5 flag (F2 separate field)
|
||||
- `PurchaseEvaluationDetailBundleDto`:
|
||||
- RENAME `WorkflowOptions` → `CurrentLevelOptions`
|
||||
- ADD `DrafterAllowSkipToFinal bool`
|
||||
|
||||
GetPe handler populate:
|
||||
- currentLevelOptions = 5 Allow* của Cấp hiện tại (null nếu V1 / no pointer)
|
||||
- drafterAllowSkipToFinal = User.AllowDrafterSkipToFinal từ DrafterUserId
|
||||
|
||||
### Chunk B — FE Admin Designer (`63234b2`)
|
||||
|
||||
ApprovalWorkflowsV2Page.tsx:
|
||||
- Types: `LevelDto +5 Allow*`, `DefinitionDto -6 Allow*`, `EditLevelEntry +5 Allow*`
|
||||
- Helper `makeDefaultLevelEntry(order, userId)` factory với 4 false + AllowReturnToDrafter=true
|
||||
- `copyFromDefinition` propagate 5 Allow* từ Levels cũ
|
||||
- REMOVE section "Cấu hình nâng cao" workflow-level (amber bg 6 checkbox)
|
||||
- REPLACE với info banner violet ngắn "ⓘ Cấu hình quyền duyệt riêng cho từng NV..."
|
||||
- Mỗi Level entry (NV row) ADD inline panel amber-50/30 5 checkbox grid-cols-2
|
||||
|
||||
fe-user KHÔNG mirror (Designer admin-only).
|
||||
|
||||
F2 cần UX riêng ở User Management page → defer commit sau (BE field đã sẵn,
|
||||
FE chỉ thêm 1 toggle UserEdit dialog khi admin UAT request).
|
||||
|
||||
### Chunk C — FE eOffice (`5ccb2a7`) mirror 2 app
|
||||
|
||||
Types:
|
||||
- `ApprovalWorkflowOptions` REMOVE allowDrafterSkipToFinal (5 flag)
|
||||
- `PeDetailBundle`:
|
||||
- RENAME `workflowOptions → currentLevelOptions`
|
||||
- ADD `drafterAllowSkipToFinal: boolean`
|
||||
|
||||
PeWorkflowPanel.tsx:
|
||||
- RENAME local `wfOptions → levelOptions`, source `evaluation.currentLevelOptions`
|
||||
|
||||
PeDetailTabs.tsx:
|
||||
- F3 approverEditMode: read `currentLevelOptions?.allowApproverEditDetails`
|
||||
- F2 allowSkipToFinal: read `drafterAllowSkipToFinal` (per-user)
|
||||
|
||||
Backward compat:
|
||||
- Backfill Mig 29 preserve admin config S21 t4
|
||||
- Phiếu V1 legacy → currentLevelOptions=null → fallback chỉ Drafter mode
|
||||
- drafterAllowSkipToFinal TRUE chỉ cho user từng Drafter PE link workflow Allow=true
|
||||
|
||||
### Chunk D — Docs (this commit)
|
||||
|
||||
- `docs/database/schema-diagram.md §14`: title "Mig 22-29, S17-21" + add 5 column
|
||||
Level inline comment + add 1 column User Mig 29 block
|
||||
- `docs/STATUS.md` Last updated S21 t5 + 28→29 mig
|
||||
- `docs/HANDOFF.md` TL;DR S21 t5 đầy đủ (file này)
|
||||
- Session log riêng
|
||||
|
||||
### State chốt S21 turn 5
|
||||
|
||||
| Metric | Trước (S21 t4) | Sau (S21 t5) | Δ |
|
||||
|---|---|---|---|
|
||||
| DB tables | 59 | 59 | 0 |
|
||||
| **Migrations** | 28 | **29** | **+1** (Mig 29 refactor per-NV) |
|
||||
| Endpoints | ~143 | ~143 | 0 (same body, different schema) |
|
||||
| FE pages | 34 | 34 | 0 |
|
||||
| Unit tests | 84 | 84 | 0 (UAT defer test-after §7) |
|
||||
| Gotchas | 45 | 45 | 0 |
|
||||
| Memory | 17 | 17 | 0 |
|
||||
| Skills | 6 | 6 | 0 |
|
||||
| Sub-agents | 4 seeds-only | 4 seeds-only | 0 |
|
||||
| **Commits S21 t5** | — | **4** | `0366946` → `63234b2` → `5ccb2a7` → this |
|
||||
|
||||
### Pending — defer / next session
|
||||
|
||||
- **User Management page F2 toggle**: thêm checkbox "Cho phép gửi PE thẳng Cấp cuối"
|
||||
vào UserEdit dialog (BE column sẵn, FE 1 toggle nhỏ — defer khi admin UAT request)
|
||||
- **Test-after carry** (Plan C bundle): Service ApplyReturnModeAsync 4 mode +
|
||||
EnsureEditableForDetailsAsync 3 scenario read-from-level + skipToFinal read-from-user
|
||||
|
||||
---
|
||||
|
||||
## TL;DR Session 21 turn 4 — F1+F2+F3 PE Workflow advanced options (Mig 28)
|
||||
|
||||
User request 3 tính năng mới trong PE V2 Workflow:
|
||||
|
||||
Reference in New Issue
Block a user