Files
solution-erp/docs/changelog/sessions/2026-05-15-s24-turn1-plan-aa-workflow-matrix.md
pqhuy1987 ac2c85901a
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
[CLAUDE] Docs: Plan AA Chunk C - S24 t1 wrap session log + STATUS+HANDOFF + 3 agent MEMORY drift
Documentation deliverables:
- docs/STATUS.md Recently Done newest entry S24 t1 (gop 3 commit + multi-agent ROI table + pattern reinforced 4 lessons)
- docs/HANDOFF.md "Last updated S24 t1" prepend on top (cumulative carry S23 chốt cuối)
- docs/changelog/sessions/2026-05-15-s24-turn1-plan-aa-workflow-matrix.md NEW ~9KB
  - Q&A 2 lượt chốt spec (Permission strategy + Matrix layout)
  - Pre-A Investigator findings 5Q + 3 surprises critical
  - Chunk A BE+Layout breakdown (MenuKeys + DbInitializer INSERT-OR-UPDATE-Order
    + Handler filter + Controller pass-through + sidebar widen + revert Plan U truncate)
  - Chunk B FE matrix page + types + App.tsx route
  - Chunk C Reviewer cumulative verdict (PASS 0 blocker)
  - Stats trước-sau + Multi-agent ROI table (~150K total ~25% solo equiv)
  - 4 pattern reinforced cross-project reusable
  - Pending S24+ checklist (7 items)

Agent MEMORY drift (auto-updated by agents + Investigator manual touch):
- .claude/agent-memory/investigator/MEMORY.md +1 FIFO entry S24 Pre-A audit
- .claude/agent-memory/implementer/MEMORY.md +1 FIFO entry S24 Chunk B PASS
- .claude/agent-memory/reviewer/MEMORY.md +1 FIFO entry S24 cumulative verify PASS

Stats S24 t1 chốt:
- 31 mig (no Mig mới)
- 59 tables
- ~146 endpoints (+1 GET filter param)
- 35 FE pages (+1 WorkflowMatrixViewPage)
- 111 test (unchanged UAT mode)
- 47 gotcha
- 21 memory user-level
- 6 skills
- 4 sub-agents (3 spawn S24 t1)
- 3 commits Plan AA push remote: ee776d5 (A) + c667802 (B) + this (C)

Pending: Bro UAT verify deploy + CICD Monitor spawn Run #210+ post-deploy.

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

238 lines
13 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 24 turn 1 — 2026-05-15 — Plan AA User Workflow Matrix view + Sidebar widen
**Dev:** Claude Opus 4.7 1M (em main + 3 sub-agent spawn)
**Duration:** ~2h
**Base commit:** `86d8806` (Plan U S23 t11 sidebar truncate)
**Final HEAD:** `<this Docs commit>` (after `ee776d5` Chunk A + `c667802` Chunk B)
**Total commits Plan AA:** **3** (A BE+Layout + B FE page + C Docs)
## 🎯 Trigger session
Bro UAT screenshot 2026-05-15 ~15:40, sau Plan U S23 t11 deploy:
> Cho hiển thị đầy đủ nhé, cần thì sliderbar to 1 chút cũng đc.
> Với thêm 1 menu là: Luồng duyệt phía trên Danh sách → Hiển thị ma trận phân quyền của cấu hình quy trình duyệt trong admin page ra ngoài để User có thể biết đc (Chú ý chỉ những quy trình có ghim).
2 yêu cầu:
1. **Sidebar widen + revert truncate** — Plan U S23 t11 vừa add `truncate` + tooltip "..." → bro muốn hiển thị đầy đủ label custom Mig 27 (DisplayLabel admin set).
2. **Menu "Luồng duyệt" + matrix view page** — read-only cho user xem cấu hình workflow V2 ghim trước khi tạo phiếu.
## 🌳 Q&A clarify (2 lượt)
| Câu | User chốt |
|---|---|
| Permission strategy BE | **Relax class-level [Authorize]** (gotcha #44 fix permanent từ S18) + server-side filter `IsUserSelectable=true` cho non-admin. Reuse endpoint hiện có, KHÔNG duplicate logic. |
| Matrix display layout | **Table 2D full 7 Allow* cột** (Bước/Cấp/NV/Mô tả + 7 cột flag Trả lại 4 mode + Edit Section 2 + Edit Budget + Skip Cấp cuối). User thấy đầy đủ quyền per slot Approver giống admin Designer read-only. |
## 🔍 Pre-A Investigator audit (🟦, ~32K tokens)
5Q audit verify trước code:
| Q | Verdict |
|---|---|
| **Q1 Endpoint permission** | ✅ Gotcha #44 đã fix permanent từ S18 (2026-05-08). Class-level chỉ `[Authorize]` bare, per-method admin Workflows.Create. Handler `GetAwAdminOverviewQuery` KHÔNG có IsUserSelectable filter — cần ADD param + conditional. |
| **Q2 Menu seed pattern** | ✅ `DbInitializer.cs:1429-1437` peOrder global increment. Permission seed `1541-1547` cho 7 role. Accounting KHÔNG trong list (admin manual grant). |
| **Q3 Admin Designer FE** | ✅ `ApprovalWorkflowsV2Page.tsx` 975 lines. 7 Allow* VI labels có sẵn line 892-948. AwLevelDto 13 fields. KHÔNG có usePermission wrap. |
| **Q4 Sidebar widen impact** | ✅ `w-72 xl:w-80` (288/320px) SAFE — sidebar 288 + main 992 → workspace 260+732 fit @ 1280px. `w-80 xl:w-96` THRESHOLD RISKY. |
| **Q5 ApplicableType enum** | ✅ {DuyetNcc=1, DuyetNccPhuongAn=2, Contract=3}. FE wire 2 type PE. |
**Surprises critical:**
- ⚠️ **PE Workspace là 2-panel** không phải 3-panel → memory `feedback_responsive_laptop_breakpoint.md` stale, sẽ update memory sau Plan AA.
- 📝 **Order strategy**: "Luồng duyệt" Order=2 first → cần shift existing leaves +1 → DbInitializer cần UPDATE Order existing (KHÔNG chỉ INSERT-if-not-exists).
- 🔸 Contract=3 chưa wire FE — chỉ DuyetNcc + DuyetNccPhuongAn.
## 🌳 Plan AA execution 3 chunk per-commit
### Chunk A — BE filter + menu seed + sidebar widen (`ee776d5`)
👤 **Chủ trì Solo** — Cross-stack tight coupling architectural decision. 6 files +73/-24 LOC.
#### BE changes (4 files)
**`MenuKeys.cs:85`** thêm helper:
```csharp
// [Plan AA S24 t1] User read-only view ma trận phân quyền của workflow V2
// admin Designer đã ghim (IsUserSelectable=true). Suffix _WfView distinct
// với admin PeWf_* (Designer write).
public static string PurchaseEvaluationWorkflowView(string typeCode) => $"Pe_{typeCode}_WfView";
```
**`DbInitializer.cs:1429-1437`** thêm tree.Add LuongDuyet (Order=2 first child) cho 2 type PE:
```csharp
tree.Add((MenuKeys.PurchaseEvaluationGroup(code), label, ..., peOrder++, "FileCheck"));
// [Plan AA S24 t1] "Luồng duyệt" leaf phía trên "Danh sách"
tree.Add((MenuKeys.PurchaseEvaluationWorkflowView(code), "Luồng duyệt", ..., peOrder++, "Network"));
tree.Add((MenuKeys.PurchaseEvaluationList(code), "Danh sách", ..., peOrder++, "List"));
tree.Add((MenuKeys.PurchaseEvaluationCreate(code), "Thao tác", ..., peOrder++, "Plus"));
tree.Add((MenuKeys.PurchaseEvaluationPending(code), "Duyệt", ..., peOrder++, "CheckCircle2"));
```
**`DbInitializer.cs:1447-1459`** refactor INSERT-only loop → INSERT-OR-UPDATE-Order:
```csharp
var existingItems = await db.MenuItems.ToDictionaryAsync(m => m.Key);
foreach (var (key, label, parent, o, icon) in tree)
{
if (existingItems.TryGetValue(key, out var existing))
{
if (existing.Order != o) { existing.Order = o; reordered++; }
continue;
}
db.MenuItems.Add(new MenuItem { Key = key, ... });
}
```
Idempotent: skip nếu Order match, UPDATE nếu mismatch. Shift existing prod rows Order+1 safe.
**`DbInitializer.cs:~1553`** SeedPurchaseEvaluationPermissionDefaultsAsync thêm WfView vào menuKeys list cho 7 role Read.
**`ApprovalWorkflowV2AdminFeatures.cs:89-110`** GetAwAdminOverviewQuery + handler:
```csharp
public record GetAwAdminOverviewQuery(
int? ApplicableType = null,
bool? IsUserSelectable = null) : IRequest<AwAdminOverviewDto>;
// Handler:
if (request.IsUserSelectable is bool ius)
query = query.Where(d => d.IsUserSelectable == ius);
```
**`ApprovalWorkflowsV2Controller.cs:21-26`** pass-through:
```csharp
public async Task<ActionResult<AwAdminOverviewDto>> Overview(
[FromQuery] int? applicableType,
[FromQuery] bool? isUserSelectable,
CancellationToken ct)
=> Ok(await mediator.Send(new GetAwAdminOverviewQuery(applicableType, isUserSelectable), ct));
```
#### FE Layout changes (2 files mirror rule §3.9)
**`fe-user/src/components/Layout.tsx:78`** resolvePath regex extend:
```ts
const peMatch = key.match(/^Pe_([^_]+)_(List|Create|Pending|WfView)$/)
// ...
if (action === 'WfView') return `/purchase-evaluations/workflow-matrix?type=${typeInt}`
```
**`fe-user` + `fe-admin` Layout.tsx**:
- Sidebar `w-60 xl:w-72``w-72 xl:w-80` (+48px lg, +32px xl)
- Revert Plan U S23 t11 truncate × 5 sites:
- fe-user: MenuGroup line 188 + MenuLeaf line 251 + StaticLeaf line 292
- fe-admin: MenuGroup line 148 + MenuLeaf line 208
- Keep `min-w-0 flex-1` parent + `shrink-0` icon/chevron + `title` tooltip (no harm — accessibility bonus)
**Verify Chunk A:** `dotnet build SolutionErp.slnx` PASS clean 0 err 2 warn pre-existing DocxRenderer.
### Chunk B — FE WorkflowMatrixViewPage (`c667802`)
🟨 **Implementer Case 2** — Cookie-cutter mirror Designer Designer read-only single file. 3 files +305 LOC.
#### NEW `fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx` ~215 LOC
```tsx
// useQuery GET /approval-workflows-v2?applicableType=N&isUserSelectable=true
// PageHeader "Luồng duyệt — {label}" + Network icon
// Loading/Error/Empty 3 state rõ ràng
// WorkflowCard per ghim version:
// header: code/version + badge "Đang dùng" emerald + "Được ghim" amber Pin
// table 10 cột read-only:
// Bước rowSpan | Cấp | NV duyệt + 7 Allow* flag (✓ emerald / — slate)
// FlagCell helper TS indexed-access type union 7 keys
```
#### NEW `fe-user/src/types/approvalWorkflowV2.ts` ~55 LOC
Subset DTO mirror BE `AwAdminOverviewDto`:
- `AwLevelDto` 13 fields (7 Allow*)
- `AwStepDto`, `AwDefinitionDto`, `AwTypeSummaryDto`, `AwAdminOverviewDto`
- Field name khớp BE record positional param (`history` not `versions`)
#### MODIFIED `fe-user/src/App.tsx` +2 LOC
```tsx
import { WorkflowMatrixViewPage } from '@/pages/pe/WorkflowMatrixViewPage'
// trong <Routes>:
<Route path="/purchase-evaluations/workflow-matrix" element={<WorkflowMatrixViewPage />} />
```
**Verify Chunk B:** `npm run build` fe-user PASS clean 0 TS err, 1907 modules, 2.61s, bundle 1282 KB.
### Chunk C — Cumulative Reviewer + Docs (this commit)
🟥 **Reviewer** adversarial pre-commit cumulative ~25K tokens:
| Category | Verdict |
|---|---|
| Wire BE/feature claim verify | ✅ End-to-end Controller → Mediator → Handler → FE useQuery wired |
| Schema integrity | ✅ 0 Mig mới, DbInitializer idempotent, 7 Allow* count match |
| Security | ✅ Class-level [Authorize] preserved, GET any-auth OK, POST admin policy. 1 Low note: non-admin pass `isUserSelectable=false` leak workflow chưa ghim (defer follow-up) |
| Code quality | ✅ BE 0 err + fe-user PASS + **fe-admin PASS 1926 modules 740ms 0 TS err** (Reviewer tự verify bonus) |
| Test coverage | ✅ Accept Phase 9 UAT exception per `feedback_uat_skip_verify` |
**Anti-fiddle:** 0% drift, ~346 LOC khớp spec.
**Mirror 2 FE app §3.9:** Sidebar widen + remove truncate mirror cả 2 ✓. WorkflowMatrixViewPage fe-user only (admin Designer riêng).
**Smart Friend guard:** Active, 0 critical/major/minor blocker.
#### Docs deliverables Chunk C
- `docs/STATUS.md` Recently Done newest entry S24 t1
- `docs/HANDOFF.md` Last updated S24 t1 prepend
- `docs/changelog/sessions/2026-05-15-s24-turn1-plan-aa-workflow-matrix.md` (file này)
- `.claude/agent-memory/investigator/MEMORY.md` FIFO entry S24 Pre-A
- `.claude/agent-memory/implementer/MEMORY.md` FIFO entry S24 Chunk B
- `.claude/agent-memory/reviewer/MEMORY.md` FIFO entry S24 cumulative verify
## 📊 Stats Plan AA chốt
| Metric | Trước (S23 t12) | Sau (S24 t1) | Δ |
|---|---|---|---|
| Migrations | 31 | 31 | 0 (no Mig mới) |
| DB tables | 59 | 59 | 0 |
| Endpoints | ~145 | **~146** | +1 (GET filter param) |
| FE pages | 34 | **35** | +1 (WorkflowMatrixViewPage) |
| Unit tests | 111 | 111 | 0 (UAT mode skip) |
| Gotchas | 47 | 47 | 0 |
| Memory entries user-level | 21 | 21 | 0 (no new — recommend memory responsive update sau) |
| Skills | 6 | 6 | 0 |
| Sub-agents | 4 | 4 (3 spawn S24 t1) | — |
| **Commits Plan AA** | — | **3** | `ee776d5` (A BE+Layout) · `c667802` (B FE) · this (C Docs) |
## 🎯 Multi-agent ROI Plan AA
| Spawn | Cost | Verdict | Catch / Value |
|---|---|---|---|
| 🟦 Investigator Pre-A | ~32K | ✅ | 5Q audit + 3 surprises (PE 2-panel + Order strategy + Contract enum unwired). Saved em main blind code 4 wrong assumptions. |
| 🟨 Implementer Chunk B | ~14K | ✅ | 3 files +305 LOC cookie-cutter Designer read-only mirror. Build PASS. shadcn fe-user no Card/Badge fallback inline div pattern. |
| 🟥 Reviewer Chunk C | ~25K | ✅ | 0 critical/major/minor block. Bonus catch fe-admin build (~7s) verify mirror app PASS. 1 Low note non-admin filter leak workflow chưa ghim defer. |
| 👤 Chủ trì Solo Chunk A + coordinate | ~80K | ✅ | BE 4 file + Layout 2 file cross-stack architectural decisions. Order shift refactor INSERT→UPDATE idempotent. |
**Total cost cumulative Plan AA:** ~150K (~25% solo equiv). Multi-agent leverage cache 70-90% per session.
## 📋 Pattern reinforced
1. **Gotcha #44 relax class-level [Authorize] PROVEN cross-stack reuse** — Workflows endpoint từ admin-only sang any-auth read accessible. Mảnh pattern reusable cho future read-only user view (Form template view, Department list view, etc.).
2. **DbInitializer INSERT-OR-UPDATE-Order pattern** — Idempotent re-deploy safe shift existing prod rows. Cross-project reusable cho menu re-ordering / label rename / icon change without migration.
3. **Plan U truncate revert pattern** — widen container + drop truncate + keep `min-w-0 flex-1` + `shrink-0` + `title` tooltip. Reusable cross-project sidebar / nav menu / breadcrumb.
4. **Read-only admin Designer mirror page** — Implementer Case 2 pattern: drop edit mutations + reuse types + filter via query param. Reusable cho future user view của admin config (Role permission view, Workflow template view, etc.).
## ⏭ Pending S24+
- 🟢 Bro UAT verify Plan AA deploy sau ~3-5 phút CI Run #210+
- 🟩 CICD Monitor spawn post-deploy verify bundle hash 2 app + smoke endpoint `?isUserSelectable=true` + DbInitializer Order shift idempotent
- 🟡 Plan B Contract V2 wire (Mig 32+33) — HIGH priority next (pre-allocated 5-6 chunk in HANDOFF)
- 📝 Memory `feedback_responsive_laptop_breakpoint.md` update: PE Workspace 2-panel (NOT 3-panel) — defer Chunk D bonus
- 🔍 Discovery #3 anomaly CI trigger docs-only (3× reinforced) — Investigator follow-up
- 🔍 Discovery #4 ASP.NET enum body deserialization (LOW polish)
- 🔧 Gotcha #47 paths-ignore agent-memory (pending bro chốt)
- ⚠️ Security follow-up: BE enforce `isUserSelectable=true` mandatory cho non-admin (Reviewer Low note)
## References
- Files: [WorkflowMatrixViewPage.tsx](../../../fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx) · [types/approvalWorkflowV2.ts](../../../fe-user/src/types/approvalWorkflowV2.ts) · [MenuKeys.cs:85](../../../src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs) · [DbInitializer.cs:1429-1459](../../../src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs)
- Rules: §3.9 mirror 2 FE app, §6.5 KEEP narrative, §7 test timing
- Cross-ref skill `permission-matrix` (menu structure) + `contract-workflow` (workflow V2)
- Memory cross-ref `feedback_per_nv_permission_scope.md` (7 Allow* per-Level slot) + `feedback_uat_skip_verify.md` (Phase 9 test-after)