Files
solution-erp/docs/changelog/sessions/2026-05-07-2600-tooltip-defer-drastic.md
pqhuy1987 38d10b7897 [CLAUDE] Docs: chốt Session 15 wrap-up — tooltip diagnose + drastic refactor DEFER
Session 15 (2026-05-07) docs update:

STATUS.md:
- Last updated Session 15 (1 commit `835cc7f` tooltip + working tree
  drastic refactor revert)
- Recently Done row Session 15 chi tiết (diagnose + plan drastic +
  attempt 12 file edits + REVERT decision)

HANDOFF.md:
- TL;DR Session 15 prepend với 2 phần: Diagnose tooltip + Drastic
  refactor DEFER decision
- 4 cảnh báo Session 16+: Drastic refactor pending (8-10h dedicated
  hoặc fallback Approach Y), Task 2 sample seed pending, schema-diagram
  defer cron audit, Hard blockers giữ nguyên

migration-todos.md:
- Phase 9 + Session 15 block với 1 task done (tooltip) + 1 defer
  (drastic refactor) + memory entry note
- Defer Session 16+ list

Session log NEW `2026-05-07-2600-tooltip-defer-drastic.md`:
- Bối cảnh user UAT báo button silent disabled
- Phần 1 — Diagnose tooltip (root cause + fix UX + "trùng ID" KHÔNG
  phải bug FE)
- Phần 2 — Plan drastic refactor flat workflow → DEFER:
  * User spec mới (Phòng × Cấp × Users[] flat)
  * Plan 6 chunk + estimate scope realistic ~8-10h
  * Attempt 12 file working tree edits → REVERT decision
  * Memory entry capture decision rule
- Plan organization sau S15 (defer queue)

Memory entry NEW `feedback_drastic_refactor_scope.md`:
- Quy tắc: drastic refactor cần dedicated session, scope conservative
  2x buffer
- Anti-patterns mid-session big refactor + commit broken state
- Defer pattern (revert working tree → document → memory entry → surface
  trade-off cho user)
- Cross-ref `feedback_per_chunk_commit.md` discipline

🎉 Session 15 wrap-up. Cumulative since session start (13h17): 16 commit
(1 button removal + 6 PE N-stage + 5 Contract N-stage + 1 3-button +
1 Session 14 wrap-up + 1 tooltip + 1 Session 15 wrap-up).

Verify: dotnet test 96 pass + working tree clean.

Defer Session 16+ priority order:
1. Drastic refactor flat workflow (dedicated session ~8-10h)
   OR fallback Approach Y (FE flat UI 5 phòng, 1-2h)
2. Task 2 sample data seed N-stage
3. Hard blockers Ops (UAT, SMTP, etc.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 21:03:56 +07:00

159 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Session 2026-05-07 (S15) — Tooltip diagnose "Lưu & Gửi Duyệt" + drastic refactor DEFER
**Dev:** Claude
**Duration:** ~1h
**Base commit:** `7c83ac8` (sau Session 14 wrap-up docs)
**Final commit:** `835cc7f` (+ working tree refactor revert)
**Total commits:** 1
## Bối cảnh
User UAT live screenshot phiếu PE Bản nháp "huy test 1" (PE/2026/A/004) trên `eoffice.solutions.com.vn/purchase-evaluations/workspace?type=1&id=...`. Báo button "Lưu & Gửi Duyệt" KHÔNG hoạt động + suy đoán "Hình nó đang bị trùng ID với thằng khác? Mỗi lần tạo mới Phiếu Duyệt NCC là 1 phiếu độc lập nhé".
## Phần 1 — Diagnose tooltip (commit `835cc7f`)
### Root cause analysis
`PeDetailTabs.tsx` line 220: `disabled={!canSubmitForApproval || submitForApproval.isPending}`. Khi `canSubmitForApproval=false` button visually clickable nhưng không fire onClick → user không biết tại sao silent.
`canSubmitForApproval = mode === 'workspace' && canEditPhase && !readOnly && evaluation.workflow.nextPhases.some(p => p !== TuChoi && p !== TraLai)`.
Hypothesis: phiếu pin `WorkflowDefinitionId` của 1 version cấu hình thiếu adjacent step → `policy.NextPhasesFrom(DangSoanThao)` empty (legacy data hoặc admin chưa setup workflow).
### Fix UX (PeDetailTabs.tsx, fe-admin + fe-user mirror)
```javascript
const forwardPhase = evaluation.workflow.nextPhases.find(p =>
p !== TuChoi && p !== TraLai)
const canSubmitForApproval = mode === 'workspace' && canEditPhase && !readOnly && forwardPhase != null
const submitDisabledReason = !canEditPhase
? `Phiếu đã ở phase X — chỉ Bản nháp / Trả lại mới sửa + gửi được.`
: readOnly
? 'Chế độ chỉ đọc.'
: !forwardPhase
? `Workflow không có phase tiếp theo từ X. Liên hệ admin kiểm tra cấu hình quy trình.`
: null
```
Button:
- `title={submitDisabledReason ?? "Gửi phiếu sang \"<forward phase label>\""}` — hover tooltip show reason hoặc forward phase
- Dialog confirm thay text generic "Gửi phiếu vào quy trình duyệt?" → explicit "Sẽ chuyển sang \"Chờ Purchasing\". Sau khi gửi sẽ KHÔNG sửa được nữa (trừ khi approver Trả lại)."
Mirror fe-admin + fe-user. KHÔNG đụng BE.
Build pass cả 2 app.
### "Trùng ID" KHÔNG phải bug FE
`PurchaseEvaluationWorkspacePage.tsx` URL state đúng:
- `+ Thêm mới``setParams({ mode: 'new', id: null })`
- POST tạo phiếu → BE gen new GUID + MaPhieu mới (atomic SERIALIZABLE qua `PurchaseEvaluationCodeGenerator`)
- Save → URL set `id=<new>` thay thế
Mỗi PE row unique GUID + MaPhieu (UNIQUE filtered). Không có path share ID. User suy đoán có thể do button silent disabled → tưởng load lại record cũ.
## Phần 2 — Plan drastic refactor flat workflow → DEFER
User chốt drastic refactor: "bỏ phase enum hoàn toàn, dùng ChoDuyet=10 đơn nhất + currentStepIndex tracking".
### Spec mới (theo user)
Workflow = list flat (Phòng × Cấp × Users[]). Ví dụ Quy trình A:
- Phòng A (2 cấp): cấp 1 NV A, cấp 2 NV B
- Phòng B (3 cấp): cấp 1 NV C, cấp 2 [NV D 1, D 2, D 3], cấp 3 NV E
- Phòng C (1 cấp): NV C
Rules:
- Phòng 1 cấp → 1 user duyệt = pass phòng đó
- Phòng N cấp → tuần tự cấp 1 → 2 → ... → N
- Cùng cấp + cùng phòng = OR (1 user duyệt = pass cấp)
- Hết tất cả phòng → DaDuyet
- PE pin Quy trình ID, không thay đổi giữa chừng
### Plan refactor 6 chunk (theo `feedback_per_chunk_commit.md`)
| Chunk | Scope | Estimate |
|---|---|---|
| A | Domain enum + entity changes + Migration 21 | 50min |
| B | App CQRS + Policy registry rewrite | 45min |
| C | PE Service rewrite TransitionAsync flat | 2-3h |
| D | Contract Service rewrite + Tests update (drop 12 N-stage tests) | 1.5h |
| E | FE Designer flat UI (PeWorkflowsPage + WorkflowsPage) | 1.5h |
| F | FE PeWorkflowPanel + Docs | 1h |
**Tổng realistic:** ~8-10h focused. Vượt session boundary + risk session deep ~30 commits.
### Attempt → REVERT
Edit working tree 12 file (Chunk A partial):
- `PurchaseEvaluationPhase.cs`: + ChoDuyet=10 enum value
- `ContractPhase.cs`: + ChoDuyet=10
- `PurchaseEvaluation.cs`: + CurrentWorkflowStepIndex, RejectedAtStepIndex
- `Contract.cs`: + same 2 fields
- `WorkflowDefinition.cs` (Contract): drop class WorkflowStepInnerStep + nav, WorkflowStep + DepartmentId, PositionLevel
- `PurchaseEvaluationWorkflowDefinition.cs`: same pattern
- `ContractDepartmentApproval.cs`: drop InnerStepId
- `PurchaseEvaluationDepartmentApproval.cs`: drop InnerStepId
- `WorkflowDefinitionConfiguration.cs`: drop InnerStep config + add DeptId/PositionLevel cấu hình + FK Restrict
- `PurchaseEvaluationConfiguration.cs`: same
- `DepartmentApprovalsConfiguration.cs`: drop InnerStepId FK + filtered indexes, restore simple unique non-filtered
- `ApplicationDbContext.cs`: drop DbSet<*WorkflowStepInnerStep> × 2
Realize codebase chưa compile (Service + App + Tests dùng `WorkflowStepInnerStep` đã drop). Need rewrite ALL dependent code trong cùng Chunk A → blow scope vượt session.
**Decision REVERT** working tree về `835cc7f` clean. Tests 96 pass intact.
### Memory entry mới
`feedback_drastic_refactor_scope.md` — decision rule: drastic refactor cần dedicated session với context fresh, scope estimation conservative (2x buffer), tránh mid-session big refactor (risk session context deep + breaking states giữa chunk + tests rewrite biggest risk).
## Verify
-`git restore` 12 files reverted
-`dotnet test` 96 pass (54 + 42) — state intact
- ✅ working tree clean (chỉ 2 untracked .zip backup files)
- ✅ commit `835cc7f` (tooltip) pushed gitea OK
## Stats cumulative (sau Session 15)
| | Trước S15 | Sau S15 | Diff |
|---|---:|---:|---:|
| BE LOC | ~15800 | ~15800 | 0 (FE-only commit + revert) |
| Migrations | 20 | 20 | 0 |
| DB tables | 57 | 57 | 0 |
| FE pages | 32 | 32 | 0 |
| Tests | 96 | 96 | 0 |
| Docs | ~58 | ~59 | +1 (session log này) |
| Memory entries | 11 | **12** | +1 (drastic refactor scope) |
| Commits S15 | — | **+1** | `835cc7f` |
## Plan organization sau Session 15
```
Plan cha: Phase 9 active — UAT
├── Plan con A-S14: Tất cả ✅ DONE (xem session logs trước)
├── Plan con S15: Tooltip diagnose + drastic refactor DEFER
│ ├── ✅ FE PE button "Lưu & Gửi Duyệt" tooltip + dialog reason rõ
│ └── ⏸ Drastic refactor flat workflow — DEFER session sau (~8-10h)
└── Plan con Defer S16+:
├── Drastic refactor flat workflow (Mig 21, ~8-10h, dedicated session)
│ OR fallback Approach Y (FE flat UI giới hạn 5 phòng, 1-2h)
├── Task 2 sample data seed N-stage (block DesignTime vs Runtime DB)
├── Budget N-stage (cần migration `AddBudgetVersionedWorkflow`)
├── schema-diagram §17-19 Mig 18-20 (defer cron audit 2026-06-01)
└── Hard blockers Ops (UAT, SMTP, Rotate creds, SQL backup, Remove huypham.vn, win-acme)
```
## Handoff
UAT iteration mode. Phiếu PE Bản nháp giờ có tooltip rõ reason khi không gửi được. User test hover → biết admin cần kiểm tra cấu hình workflow definition.
Drastic refactor pending dedicated session. Khi resume:
1. Fresh session start với context clean
2. Plan kỹ 6 chunk per-commit
3. Buffer 2x estimate (~16h thực tế nếu phát sinh)
4. Test rewrite biggest risk — pattern reusable nhưng nội dung phải mới hoàn toàn
**Cron audit kế:** 2026-06-01 (~25 ngày).