Files
solution-erp/docs/STATUS.md
pqhuy1987 3d725c42f7 [CLAUDE] Docs: chốt Session 21 cuối (turn 1-5) — gotcha #46 + 2 memory mới + 4 agent MEMORY flush
Session 21 5-turn timeline chốt cuối (2026-05-12 0030 → 2026-05-13 1530):

| Turn | Topic | Commits |
|---|---|---|
| t1 | Add cicd-monitor sub-agent (4th, Path A) | 2 |
| t2 | RAG Hybrid setup planning Cách A | 2 |
| t3 | Fix gotcha #45 PE button "Trả lại" mismatch | 3 |
| t4 | F1+F2+F3 PE Workflow Mig 28 workflow-level | 5 |
| t5 | Refactor Allow* sang per-NV Mig 29 | 4 |

Cumulative 12 commits pushed remote `3a34831..c0af9e0`. No pending push.

**Gotcha mới #46** (`docs/gotchas.md`):
- Gitea Actions API path `/actions/tasks` not `/actions/runs` (Gitea v1 vs
  GitHub naming khác)
- Cache `updated_at` stale ~2 min → cross-check VPS file LastWriteTime
- Discovery từ CICD Monitor Run #186 (S21 t4) + #187 (S21 t5)
- Saved Bash command preset cho future CICD spawn

**2 Memory user-level mới** (`C:\Users\pqhuy\.claude\projects\D--Dropbox-CONG-VIEC-SOLUTION\memory\`):

1. `feedback_ef_migration_backfill_reorder.md` — Cross-project pattern:
   - EF auto-generated drop-then-add WRONG cho data preservation
   - Manual reorder ADD → BACKFILL SQL via migrationBuilder.Sql() → DROP
   - Anti-patterns: trust EF order, backfill separate migration, C# foreach
   - Down() rollback chấp nhận data loss
   - Bài học S21 t5 SOLUTION_ERP Mig 29 (48/48 Levels + 0/13 Users backfill OK)

2. `feedback_per_nv_permission_scope.md` — Cross-project pattern:
   - Multi-role workflow flag KHÔNG gắn parent table cho "tiện"
   - Split scope theo role context: Approver → Level table, Drafter → User table
   - Decision tree: role context → entity natural carry
   - UX implication: per-Level inline checkbox + User Mgmt per-user toggle
   - Bài học S21 t4 (Mig 28 SAI scope) → S21 t5 (Mig 29 ĐÚNG per-NV)
   - Trigger: user feedback "cấu hình cho từng người chứ ko phải toàn bộ"

**4 agent MEMORY.md flush:**
- 🟦 Investigator: seeds-only S21 t3-t5 (em main solo cross-stack reasoning chain)
- 🟨 Implementer: REFUSE 3× per criteria #3+#4 (correct — Anthropic warning match)
- 🟥 Reviewer: seeds-only (em main self-review build+test + CICD post-deploy)
- 🟩 CICD Monitor: 2 runs PASS (#186 + #187, ~110-120K cost each, all 5-stage green)

**Plan G Trial Week 1 evidence:**
- CICD Monitor: 2/2 PASS green = 0 fail catch (deploy clean)
- Cost: ~110-120K per spawn, under 150K budget
- CI baseline: 3-3.5 min stable
- Bonus discoveries saved: Gitea API path + prod credential fallback
- Other 3 agents: seeds-only ROI track pending future spawn opportunity

**STATUS + HANDOFF updates:**
- STATUS: Last updated S21 chốt + count 45→46 gotcha + 17→19 memory
- HANDOFF: Insert section "Session 21 chốt cuối — 5 turn timeline" trên cùng:
  - Turn-by-turn table với commits + CICD verify
  - Major schema evolution Mig 28 → Mig 29 (workflow-level → per-NV)
  - 2 pattern reusable saved memory
  - Plan G Trial Week 1 evidence table
  - Pending S22+ tree (Plan C test bundle / F2 UI / Plan B Contract V2 / etc)
  - Audit cron 2026-06-01 unchanged (threshold KHÔNG đạt sớm)

**MEMORY index user-level +2 entry** (memory MEMORY.md).

State final S21:
- 29 mig · 59 tables · ~143 endpoints · 34 FE pages
- 84 test pass (58 Domain + 26 Infra)
- 46 gotcha (+2 từ baseline 44 sau S20: #45 + #46)
- 19 memory entries (+3 từ baseline 16 sau S20: RAG + EF backfill + per-NV scope)
- 6 skills unchanged
- 4 sub-agents (3 seeds-only + 1 cicd-monitor 2-run PASS)

Pending: bro UAT continue. Plan C test-after bundle defer sau UAT 2-3 lần ổn.

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

90 KiB
Raw Blame History

STATUS — Snapshot hiện tại

Update rule: trước khi bắt đầu 1 task → ghi row vào 🔥 In Progress. Xong → chuyển sang ✅ Recently Done.

Last updated: 2026-05-13 1530 (Session 21 chốt cuối — 5 turn cumulative pushed remote, CICD verified PASS 2/2 run, 1 gotcha mới #46 Gitea API path, 2 memory entry mới — feedback_ef_migration_backfill_reorder + feedback_per_nv_permission_scope. Session 21 5 turn timeline: t1 cicd-monitor add → t2 RAG planning Cách A → t3 fix gotcha #45 → t4 F1+F2+F3 Mig 28 → t5 refactor Allow* per-NV Mig 29. Stats final: 29 mig · 59 tables · ~143 endpoints · 34 FE pages · 84 test pass · 46 gotcha (+2 từ S20: #45 PE button mismatch + #46 Gitea API) · 19 memory entries (+3 từ S20: RAG + EF backfill + per-NV scope) · 6 skills · 4 sub-agents (3 seeds-only + 1 cicd-monitor 2 runs PASS). 12 commits pushed 3a34831..c0af9e0. Plan G Trial Week 1 evidence: CICD Monitor catch 0 fail vì green 2/2 run, cost 110-120K/run under 150K budget, 3-3.5min CI time stable. KHÔNG còn pending push. UAT mode skip dotnet test mỗi chunk, test-after Plan C bundle cho tất cả turn 3-5 sau UAT 2-3 lần ổn.) S21 turn 5: 2026-05-13 1400 (Session 21 turn 5 — 🎯 Refactor F1+F2+F3 sang PER-NV (Mig 29 drop Mig 28 column workflow-level). 4 chunk per-commit 0366946 (A BE schema+Service refactor) → 63234b2 (B FE Admin Designer 5 checkbox per-Level row) → 5ccb2a7 (C FE eOffice rename currentLevelOptions + drafterAllowSkipToFinal) → this Chunk D Docs. F1+F3 5 flag MOVED xuống ApprovalWorkflowLevels (per slot Approver, mỗi NV có riêng quyền duyệt). F2 AllowDrafterSkipToFinal MOVED xuống Users (per-Drafter user, admin config ở User Management). Mig 29 4-stage: ADD 5 column Levels + 1 column Users + BACKFILL bulk SQL (copy workflow → all Levels, set TRUE cho Drafter user nào từng dùng workflow Allow) + DROP 6 column workflow ApprovalWorkflows. Service ApplyReturnModeAsync refactor đọc currentLevel.AllowXxx thay vì workflow.AllowXxx. Helper EnsureEditableForDetailsAsync read level.AllowApproverEditDetails. DRAFTER trình branch read userManager.FindByIdAsync(actorUserId).AllowDrafterSkipToFinal. DTO refactor: AwLevelDto +5 Allow*, AwDefinitionDto -6 Allow*, CreateAwLevelInput +5 Allow*, PeDetailBundle.workflowOptions → currentLevelOptions + drafterAllowSkipToFinal. FE Admin Designer drop section "Cấu hình nâng cao" workflow-level, replace 5 checkbox grid-cols-2 inline mỗi Level entry row (5 flag per slot). FE eOffice rename wfOptions → levelOptions đọc currentLevelOptions. Backward compat: backfill preserve admin config S21 t4. Test 84/84 PASS unchanged. Stats: 29 mig (+1) · 59 tables · ~143 endpoints · 34 FE pages · 84 test pass · 45 gotcha · 17 memory · 6 skills · 4 sub-agents seeds-only.) S21 turn 4: 2026-05-13 1200 (Session 21 turn 4 — 🎯 F1+F2+F3 PE Workflow advanced options (Mig 28) — 5 chunk per-commit 0294693c56024ba508564d27caaf→this Chunk E Docs. F1 4 mode Trả lại admin tick: "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 S17 fallback. F2 Drafter skip thẳng Cấp cuối — workflow tick + Workspace checkbox dynamic confirm. F3 Approver edit Section 2 (Hạng mục/NCC/Báo giá) khi workflow tick + actor match CurrentLevel + audit ghi PurchaseEvaluationChangelog. Mig 28 ApprovalWorkflows +6 bool Allow* (DEFAULT 1 cho AllowReturnToDrafter backward compat, 5 còn lại 0). BE Service TransitionAsync extend 3 optional param (returnMode/returnTargetUserId/skipToFinal) + helper ApplyReturnModeAsync switch 4 mode. Detail/Quote/Supplier helper EnsureEditableForDetailsAsync mới (kế thừa EnsureDraftAsync + add ChoDuyet+F3 branch + Admin bypass). FE Admin Designer "Cấu hình nâng cao" section 6 checkbox 3 group. FE eOffice 3 changes mirror 2 app: Trả lại radio picker 1-4 mode + Workspace skip checkbox violet + Section 2 itemsReadOnly approver banner. UAT mode skip dotnet test mỗi chunk (per feedback_uat_skip_verify), npm run build × 2 app pass mỗi chunk. Stats: 28 mig (+1) · 59 tables · ~143 endpoints (+1 user-selectable patch existed) · 34 FE pages (+1 Designer section) · 84 test pass unchanged (UAT defer test-after) · 45 gotcha unchanged · 17 memory · 6 skills · 4 sub-agents seeds-only.) 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). 2 chunk per-commit de00887 (BE Chunk A) + 4b29d00 (FE Chunk B) + Chunk C Docs this. 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 ApproveV2Async UPSERT opinion "đã duyệt" + advance Cấp. Inconsistency phụ: dialog isSendBack (L247-248) cùng pattern thiếu TraLai → dialog title sai. Fix BE defense-in-depth + FE 3 chỗ × 2 app mirror rule §3.9. Test-before §7 BẮT BUỘC: 3 regression test mới (2 reproduce bug + 1 happy path control) — dotnet test SolutionErp.slnx 84 PASS (58 Domain + 26 Infra = +3). npm run build × 2 app pass. Stats: 27 mig (no change) · 59 tables · ~142 endpoints · 34 FE pages · 84 test pass (+3) · 45 gotcha (+1 #45) · 17 memory entries (no new) · 6 skills. Em main solo (no sub-agent spawn S21 t3 — bug fix reasoning chain cross BE/FE Implementer REFUSE per multi-agent rule).) 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). Em main solo (no SOLUTION_ERP sub-agent spawn), delegate claude-code-guide × 2 research Anthropic + community practice. Decision chốt: Cách A defensive (giữ blanket 120K em main + RAG retrieve supplement) over Cách B aggressive (cắt 60-70% blanket). Industry-validated cross 4 Anthropic blog + 5 community tools (Cursor/Continue/Cline/Aider all hybrid). Stack: Voyage-3-large + Qdrant local + FastMCP Python + Streamlit dashboard 7 pages + SQLite event log. Multi-agent cost reality: 4 agents → ~520K cumulative blanket → heavy session ~560K (Cách A) vs ~700K (lazy), saving -20%. 3-layer pattern Phase 1-3 rollout (Layer 1 vector → Layer 2 +BM25 → Layer 3 +reranking, recall ~70% → ~92%). Stats: +1 memory entry (feedback_rag_hybrid_pattern.md) +1 plan file (rag-setup-plan.md 1500 LOC final). 4 sub-agents vẫn seeds-only. Plan I NEW deferred chờ bro confirm 5 dự án path + stack + Voyage API key + disk cleanup 5-8GB.) S21 turn 1: 2026-05-12 0030 (Session 21 turn 1 — 🎯 Add con thứ 4 cicd-monitor (Path A — post-deploy verifier green READ tier). 1 commit f1c61c9 pushed 36e21c8..f1c61c9 main -> main, CI skipped per path filter (**/*.md paths-ignore docs-only). Trade-off: +~150K spawn extra mỗi run, đổi lại catch deploy ship fail tự động (bundle hash unchanged / mig drift prod / endpoint 500) — recurring blind spot pattern em main solo S20 quên verify ~30% push. Cost reality update: ~750K spawn setup (3 → 4 agents) · ~1.35M heavy session · ~700K optimized cached. Stats: 4 sub-agents seeds-only (+1 cicd-monitor green) · 16 memory entries (no new, update existing feedback_multi_agent_setup.md 3 → 4 agents narrative) · 27 mig · 59 tables · ~142 endpoints · 81 test unchanged · 44 gotcha unchanged · 6 skills unchanged. KHÔNG flush 3 agent MEMORY.md (chưa spawn work S21 t1 nên KHÔNG có findings — em main solo via context + Write file).) S20 wrap: 2026-05-11 22:00 (Session 20 wrap turns 1-12 — 🎯 14 commit 9dee00dae1814c. PE Detail UI restructure 3 yêu cầu (t1-5) + Manual budget drop tên (t6) + Mig 27 admin menu eOffice (t7) + NCC palette 5-màu cycle + Winner icon ✓ đậm + AddSupplier auto-fill master + Responsive laptop nhỏ 4-tầng pattern (t8-11) + Multi-agent infrastructure setup 3 sub-agents (t12). 27 mig (+1) · 59 tables · ~142 endpoints (+1) · 34 FE pages (+1) · 61 menu key (+1) · 81 test pass unchanged · 44 gotcha · 16 memory entries (+2) · 3 sub-agents NEW. Phase 9 UAT iteration mode.) S20 turn 7: 2026-05-11 17:00 (Session 20 turn 7 — 🎯 Admin Ẩn/Hiện + Đổi tên menu eOffice (Mig 27). 5 chunk 2ea2d27ef394f8059bfcb1ed6530→Chunk E Docs. User Q2=b: DisplayLabel CHỈ áp fe-user, admin sidebar giữ Label gốc. Domain MenuItem +IsVisible(true) +DisplayLabel(200). Mig 27 AddVisibilityAndDisplayLabelToMenuItems. BE PATCH /api/menus/{key} [Authorize Policy=Permissions.Update]. NEW FE-admin MenuVisibilityPage ~210 LOC (table inline edit per-row + Save dirty + Khôi phục mặc định + Toggle Eye/EyeOff + 4 StatCard). fe-user Layout filterForUser 2 tầng (USER_HIDDEN_KEYS hardcode + !isVisible dynamic) + effectiveLabel(displayLabel || label) replace 3 callsite. fe-admin Layout KHÔNG đụng. +1 menu key MenuVisibility "Menu eOffice" leaf System Order=94. 27 mig, 59 tables, ~142 endpoints, 34 FE pages, 81 test pass (Q4 UAT defer).) S20 prev: 2026-05-11 (Session 20 — 🎯 PE Detail UI restructure 3 yêu cầu user UX. 4 chunk per-commit 9dee00d2bba851f2f01f4 → (current Chunk D Docs). Q1=a (giữ Section "Chọn NCC TP" riêng), Q2=a "1 hạng mục trước tiên" (NCC shared, demo 1 hạng mục), Q3=a (chỉ hiện NV đã ký), Q4 public luôn (skip dotnet test mỗi chunk theo memory feedback_uat_skip_verify, vẫn npm run build × 2 app mỗi chunk vì có rename/remove function). Chunk A (9dee00d): BE CreatePurchaseEvaluationCommandHandler thêm 1 PurchaseEvaluationDetail mặc định khi tạo phiếu — GroupCode="01", GroupName="Hạng mục chính", NoiDung=TenGoiThau, DonGiaNganSach=ThanhTienNganSach=Budget.TongNganSach hoặc BudgetManualAmount fallback 0; Changelog Insert audit. FE reorder PeDetailTabs (mirror 2 app) 1.Thông tin / 2.Hạng mục (lên #2) / 3.Chọn NCC / 4.NCC tham gia / 5.Ý kiến. Chunk B (2bba851): ItemsTab restructure thành list HangMucCard (1 card / 1 hạng mục, expanded=true mặc định cho 1 hạng mục demo). Header card: GroupCode + NoiDung + 3 stat (KL/ĐG/TT) + NS link Δ nếu có + Pencil/Trash actions + ▼/▶ toggle expand. Expand body: NCC inline table columns NCC / Liên hệ / Điều khoản TT / File báo giá / ĐG chưa VAT / ĐG có VAT / Thành tiền / Action. Quote inline click cell → QuoteDialog cũ reuse. Add NCC + Sửa NCC reuse AddSupplierDialog/EditSupplierDialog cũ. Winner ✓ button mỗi NCC row. Drop function SuppliersTab (dead code ~134 LOC, replace bằng HangMucCard expand panel). Giữ AddSupplierDialog + EditSupplierDialog + SupplierAttachmentsCell (HangMucCard call lại). Section layout cuối: 1.Thông tin / 2.Hạng mục + Báo giá NCC (nested) / 3.Chọn NCC TP thắng thầu / 4.Ý kiến cấp duyệt — 4 section. Chunk C (f2f01f4): Section Ý kiến restructure render layer (KHÔNG đụng Mig 26 schema — vẫn UPSERT 1 row / Level). LevelOpinionsSectionV2 forEach step → 1 StepOpinionsBox (replace grid-cols-2 cho N approver). Box header: "Bước N — Tên" + dept badge emerald + "X/Y đã duyệt" counter. Body: filter opinions theo step.order → sort levelOrder asc, signedAt asc → render StepOpinionEntry per signed opinion (tên NV + Cấp badge slate + admin override badge amber nếu có + emerald rounded-full timestamp + comment text). NV chưa duyệt KHÔNG hiển thị (Q3=a). Drop function LevelOpinionBox (replaced). Mirror fe-admin + fe-user. Verify build pass cả 2 app sau khi catch TS6133 SuppliersTab + SupplierAttachmentsCell unused (đã giải quyết: drop SuppliersTab, restore SupplierAttachmentsCell vào HangMucCard cột "File báo giá"). 81 test pass (no change — UAT defer))

📍 Phase hiện tại: Phase 9 active — UAT V2 testing với user thật59 DB tables, 29 migrations (Mig 28 +6 column workflow-level S21 t4 → Mig 29 refactor sang per-NV S21 t5 — 5 column trên ApprovalWorkflowLevels + 1 column trên Users + DROP 6 column workflow-level), ~143 API endpoints, 34 FE pages. 84 unit test pass (58 Domain + 26 Infra = +3 PE guard S21 t3, UAT defer test-after per §7 cho S21 t4+t5). 46 gotcha (+1 S21 t5 chốt: #46 Gitea API path/cache). 30 demo user + 1 test user UAT. 6 skill. 5 trạng thái phiếu (Nháp/Đã gửi duyệt/Trả lại/Từ chối/Đã duyệt). 2 Workflow schemas đồng tồn tại post-Session 17 + Per-NV refactor S21 t5: (1) Mig 21 WorkflowDefinition flat (V1) — pin với PE/Contract cũ. (2) Mig 22-29 ApprovalWorkflow (V2) — pin với PE mới, Mig 29 các flag per-NV ở Levels + Users. Service PE branch theo ApprovalWorkflowId. 4 sub-agents: 🟦 Investigator + 🟨 Implementer + 🟥 Reviewer (3 seeds-only S21 — em main solo cross-stack reasoning chain REFUSE) + 🟩 CICD Monitor (2 runs PASS, ~110-120K/run cost). 30 demo user + 1 test user UAT. 6 skill. 5 trạng thái phiếu (Nháp/Đã gửi duyệt/Trả lại/Từ chối/Đã duyệt). 2 Workflow schemas đồng tồn tại post-Session 17: (1) Mig 21 WorkflowDefinition flat (V1) — pin với PE/Contract cũ + match Dept+PositionLevel. (2) Mig 22-26 ApprovalWorkflow (V2) — pin với PE mới + match ApproverUserId 1-1, Steps/Levels group by Order, Bước (Phòng) > Cấp (N NV OR-of-N), Mig 25 +IsUserSelectable admin pin per version, Mig 26 +PeLevelOpinions sign-off dynamic theo Level. Service PE branch theo ApprovalWorkflowId set or null. Sau UAT chốt → migrate + drop V1 + Contract V2 wire.

🌐 Production URLs

🔥 In Progress — Session 7+ (Phase 9 active)

A. Hard blockers (chờ user / ops)

  • UAT thật 1 tuần với 2-3 user (Drafter / CCM / BOD) — hard requirement Phase 5 roadmap
  • SMTP config → Email outbox (BLOCKED chờ user cấp host/user/pass)
  • Rotate creds — admin + 30 demo + SA + vrapp + JWT secret + Gitea runner token
  • Schedule SQL backup dailyscripts/backup-sql.ps1 đã sẵn, chưa schedule Task Scheduler
  • Remove binding cũ .huypham.vn sau verify stable: ssh vietreport-vps ; .\migrate-domains.ps1 -RemoveOld -SkipCert
  • win-acme scheduled task "unhealthy" — auto-renew fix trước 2026-06-18

B. Carry over feature gap

  • Export phiếu PDF/Excel PE — tái dùng IDocumentConverter + template PE-TrinhDuyet.docx (user pending — không quan trọng lắm)

C. Optional polish (khi UAT phát sinh bug)

  • Budget MaNganSach atomic sequence (hiện Random.Shared → migration AddBudgetCodeSequences)
  • Budget versioned workflow (admin config UI thay hardcoded BudgetPolicy.Default)
  • Payment terms PE tách field (JSON blob → 6 column riêng)
  • Auto-map PE Details → Contract per-type Details khi gen HĐ
  • Matrix Quotes bulk paste từ Excel
  • fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi"

D. Tests Phase 3-5 (làm khi gặp bug recurring để justify ROI — rule §7)

  • Phase 3 full — Application handler tests cần UserManager DI helper (PE Opinion Upsert, Budget validate, CreateContractFromEvaluation BudgetId carry) ~15 test
  • Phase 4 — API smoke tests qua WebApplicationFactory ~7 test
  • Phase 5 — FE Vitest cho lib utility (queryMatches, fmtMoney) ~10 test

E. 2-stage dept approval — Chunk E-bis DONE (Session 9)

  • FE Workflow Panel PE — section "Tiến trình duyệt 2-cấp phòng ban" group by phase × dept, highlight amber khi chờ TPB confirm
  • FE UserManager toggle CanBypassReview — column "Bypass" badge fuchsia + button toggle ShieldCheck (UsersPage)
  • HĐ 2-stage mở rộng — ContractWorkflowService thêm UserManager DI + 2-stage logic mirror PE + ContractDepartmentApprovalFeatures.cs + endpoint GET /contracts/{id}/department-approvals + FE WorkflowHistoryPanel section mới
  • Budget 2-stage mở rộng — TransitionBudgetCommandHandler thêm INotificationService + IDateTime + 2-stage logic + BudgetDepartmentApprovalFeatures.cs + endpoint + FE BudgetWorkflowPanel section
  • Tests 2-stage (6 test) — IdentityFixture setup full Identity stack + 6 test PE workflow service: NV review block / TPB confirm allow / NV bypass / Admin skip / Reject set / Resume jump-back. Pattern reusable.

F. Audit định kỳ (cron tự fire)

  • 2026-05-01 (audit 2026-05-04 manual trigger sau trễ 4 ngày) — combined audit log docs/changelog/skill-audit-2026-05.md. Cron Claude SDK KHÔNG fit monthly cadence (auto-expire 7d) → user setup OS Task Scheduler nếu cần auto-remind.
  • 2026-06-01 — combined audit kế. Trigger thủ công khi đến ngày hoặc user nói "audit MD" / "kiểm tra docs" / "định kỳ kiểm tra".

Recently Done (newest on top)

Ngày Ai Task Commit
2026-05-12 Claude 🎯 SESSION 21 turn 2 — RAG Hybrid setup planning + Cách A validation deep dive (2 commit 1f8e9af plan save + this chốt) — Sau S21 turn 1 chốt cicd-monitor, user clarify 5 dự án future > 1M MD tokens → cuộc thảo luận deep ~15 turn về RAG infrastructure. Em main solo (no SOLUTION_ERP sub-agent spawn), delegate claude-code-guide × 2 spawn agent research Anthropic + community practice. Q&A deep dive 10 topics: (1) RAG fundamentals + Vector DB Qdrant role, (2) Embedding "AI nhúng" + Voyage AI cost mechanics ($0.18/M tokens), (3) Multi-project shared architecture (5 projects → single Qdrant + per-collection), (4) Audit procedure 3-tier (weekly auto + monthly deep + quarterly major), (5) UI/UX Streamlit dashboard 7 pages design (overview + drill-down + compare + audit + cost + change + admin), (6) Cách A defensive (giữ blanket 120K) vs Cách B aggressive (cắt 60-70%), (7) Reasoning depth comparison lazy 60% → A 90% → B 75-80%, (8) Industry validation Anthropic + Cursor + Continue + Cline + Aider all hybrid, (9) Multi-agent cost reality 8-10× multiplier ~520K cumulative blanket 5 entities, (10) 3-layer hybrid pattern Anthropic Contextual Retrieval Sept 2024. Quyết định chốt Cách A (defensive hybrid: giữ blanket 120K em main + RAG retrieve supplement, sub-agent spawn baseline ~100K each, 4 agents = ~400K cumulative, heavy session billed ~560K saving -20% vs lazy 700K, quality recall ~85%) over Cách B bỏ (aggressive cut 60-70% vi phạm priority em main control flow strong + reasoning fragmented + UX latency +1-2s/state Q + risk severe RAG fail). Why Cách A (bro priority chốt): em main control flow strong preserve, decision quality 90% multi-source cohesive, wall-clock -20% (12 phút vs 16), risk-averse graceful fallback, multi-agent leverage cache 70-90%, industry-validated 9 sources. 3-layer hybrid Phase rollout: P1 (W1-4) vector only Voyage-3-large recall ~70% $1.50/mo · P2 (M2) +BM25 bm25s free recall ~78% $1.50/mo · P3 (M3) +Voyage rerank-2 + Contextual prefix recall ~92% $4-5/mo. Stack validated cross-industry: Voyage AI embedding (Anthropic partner, multilingual 26 lang, $0.36 initial), Qdrant local (Rust 50MB, agent-native 2026 leader, ~3GB disk 5 project), FastMCP Python (official SDK, ~100 LOC), SQLite event log (5 tables + audit history), Streamlit 7 pages. Plan I NEW deferred — trigger bro confirm 5 dự án path + stack + pilot + Voyage API key + disk cleanup → dedicated session 10-14h weekend (per feedback_drastic_refactor_scope rule). Deliverables: docs/rag-setup-plan.md 1223 LOC commit 1f8e9af + extend S21 t2 ~300 LOC = ~1500 LOC final, memory feedback_rag_hybrid_pattern.md cross-project reusable, session log this chốt, MEMORY.md index +1 entry. CI skipped path filter (.md). 4 sub-agents vẫn seeds-only (KHÔNG spawn S21 turn 2 nên KHÔNG flush MEMORY.md per §6.5 KHÔNG add noise). Tests baseline 81 unchanged. 1f8e9af (plan save) · this chốt (commit final)
2026-05-12 Claude 🎯 SESSION 21 turn 1 — Add con thứ 4 cicd-monitor (Path A — post-deploy verifier green READ tier, 1 commit f1c61c9) — User chốt Path A sau pre-flight Plan G Trial Week 1: thêm sub-agent thứ 4 chuyên post-deploy verify (Gitea Actions poll + bundle hash 2 app verify + sqlcmd mig prod = repo latest + endpoint smoke). Trade-off: +~150K spawn extra mỗi run, đổi lại catch deploy ship fail tự động — recurring blind spot pattern em main solo S20 quên verify ~30% push. 2 file mới: .claude/agents/cicd-monitor.md (~7KB) — system prompt + 8-step workflow (verify push → poll Gitea API → fail log grep → live curl smoke → bundle hash × 2 app + verify changed → sqlcmd mig prod = repo latest → report PASS/FAIL/PARTIAL/TIMEOUT/SKIPPED-DOCS) + 5-stage report table + gotcha #25/#39/#40/#41/#44 cross-ref + skill iis-deploy-runbook/dependency-audit-erp/ef-core-migration preload + Anti-pattern 9 rules. .claude/agent-memory/cicd-monitor/MEMORY.md (~5KB seed) — recurring CI bug patterns + 5-stage checklist + baseline build/bundle metrics + bearer test pattern admin/nv.test. 1 file update repo: .claude/agents/README.md — 4-agent architecture diagram (green slot mới) + decision tree (after push code + prod issue diagnose branches) + memory routine 4 SendMessage + skills preload 4 agents + cost reality table 564K → 750K spawn / 1.2M → 1.35M heavy / 600K → 700K optimized + trial workflow Week 1-3 CI/CD Monitor spawn integrated + pass criteria + catch ≥1 deploy ship fail. Memory user-level update: feedback_multi_agent_setup.md — title 3 → 4 sub-agents, decision tree +CI/CD Monitor invocation branches (after push + user prod issue), skills preload list +CI/CD Monitor (iis-deploy-runbook + dependency-audit-erp + ef-core-migration), cost table update + trade-off rationale (recurring blind spot ~30% push S20). CI skipped: all 3 file changed .md → match paths-ignore: '**/*.md' per gotcha #41 → no Gitea Actions run → no IIS deploy (expected — agent infra là local Claude Code, không cần present trên prod). Push success 36e21c8..f1c61c9 main -> main. 3 (now 4) sub-agents vẫn seeds-only: chưa spawn work nào — em main solo via context paste + Write file. KHÔNG flush 3 agent MEMORY.md (chưa spawn work = không findings, per §6.5 KHÔNG add noise entry). cicd-monitor MEMORY.md có entry "setup 2026-05-12" trong seed. Trial Week 1 kick-off ở Session 21 turn 2+ với Plan B Contract V2 wire Mig 28+29 candidate (mirror PE pattern S17-S19 proven 1×). Tests baseline 81 unchanged (no test added — docs-only commit). f1c61c9 (Setup cicd-monitor + README 4-agent + memory update)
2026-05-11 Claude 🎯 SESSION 20 turns 6 + 8-12 — PE polish (NCC palette + autofill + responsive) + Multi-agent setup (7 commit f568945ae1814c) — Sau turn 7 wrap-up Mig 27, user iterate 7 polish/feature lớn nhỏ. Turn 6 (f568945) Manual budget "Nhập tay" drop tên field — 3 file × 2 app mirror (BudgetFieldRow + WorkspaceCreateView + HeaderForm) bỏ Input "Tên" UI khỏi manual mode, BE save budgetManualName: null luôn, VND format 1.000.000 + suffix đ. Turn 8 (3ec7b5a) AddSupplier +Số tiền inline + NCC 5-màu palette + Winner badge "🏆 Trúng thầu" — AddSupplierDialog +prop detailId? +form thanhTien, sequential POST /suppliers (response {id}) → POST /quotes (nếu detailId + thanhTien > 0). NCC_PALETTES const 5 màu literal Tailwind (blue/purple/sky/teal/pink) cycle theo idx. Winner row override emerald-500 border-l + bg-emerald-100/70 + shadow-sm + ring-1 emerald-300 + badge rounded-full bg-emerald-600 text-white "🏆 Trúng thầu". Turn 9 (83aae8e) User feedback bỏ badge → revert icon ✓ stick cũ nhưng đậm hơn (text-base font-bold emerald-700) + tên NCC winner text-emerald-900 + hover transition (winner hover:bg-emerald-200/70, non-winner hover:bg-white/80 hover:shadow-sm). Turn 10 (66551db) AddSupplierDialog auto-fill từ master data khi chọn NCC dropdown — onChange lookup picked supplier, setForm ghi đè 4 field (contactName ← contactPerson / contactPhone ← phone / contactEmail ← email / note ← note). Hint emerald "✓ Đã tự điền từ Master". User vẫn override được. Turn 11 (6e338f7) Responsive cho laptop màn hình nhỏ 1280-1366px — 4-tầng pattern: sidebar fe-admin + fe-user w-72w-60 xl:w-72 (+48px lg) / PE Workspace 2-panel lg:[320px_1fr]lg:[260px_1fr] xl:[320px_1fr] (+60px lg) / Section padding px-5 py-4px-3 py-3 sm:px-5 sm:py-4 (+16px xs) / HangMucCard gap-3 p-3flex-wrap gap-2 p-2 sm:gap-3 sm:p-3 (+8px xs). Net gain trên 1366px ~+132px width cho NCC table area. Memory feedback_responsive_laptop_breakpoint.md capture pattern. Turn 12 (ae1814c) SETUP MULTI-AGENT INFRASTRUCTURE 3 sub-agents (Investigator READ cyan + Implementer WRITE conditional yellow + Reviewer READ adversarial red) + em main coordinator. Pre-flight decision gate 6/6 . Phase 1-4 execute: .claude/agents/ 4 file (README ~9.7KB + investigator + implementer + reviewer) + .claude/agent-memory/ 3 MEMORY.md seed (~6KB each). Customize SOLUTION_ERP: skills preload mỗi agent (reuse 6 skills hiện có) + bearer test (admin@solutions / nv.test@solutions) + prod UAT URL + Phase 9 UAT mode + DB Dev/Design distinct. Windows MAX_PATH pitfall handled — drop isolation: worktree khỏi implementer.md (project path 51 chars + Dropbox-managed nested overflow 260+ chars). Memory feedback_multi_agent_setup.md capture decision gate + ACCEPT/REFUSE criteria + NAMGROUP s41-s43 ROI reference. 3 agents chưa spawn work ở S20 turn 12 — seeds-only state. Trial Week 1 candidate Contract V2 wire Mig 28+29 (mirror PE pattern proven). Stats cumulative S20: 27 mig (+1 Mig 27 from turn 7) · 59 tables · ~142 endpoints (+1 PATCH /menus/{key}) · 34 FE pages (+1 MenuVisibilityPage) · ~61 menu key (+1) · 81 test pass unchanged · 44 gotcha unchanged · 16 memory entries (+2: responsive + multi-agent) · 6 skills unchanged · 3 sub-agents NEW · 14 commits S20. f568945 (t6) · 3ec7b5a (t8) · 83aae8e (t9) · 66551db (t10) · 6e338f7 (t11) · ae1814c (t12) · (current Docs t13 wrap)
2026-05-11 Claude 🎯 SESSION 20 turn 7 — Admin Ẩn/Hiện + Đổi tên menu eOffice (Mig 27, 5 chunk 2ea2d27ef394f8059bfcb1ed6530→Chunk E Docs) — User UAT yêu cầu "tính năng Ẩn Hiện và Đổi tên hiển thị của các Menu bên ngoài Office, làm trong Trang Admin Page". Hỏi xác nhận "chưa có" — đúng. User clarify Q2=b "edit hiển thị bên ngoài, chỉ của eOffice thôi" → admin sidebar luôn giữ Label gốc, DisplayLabel CHỈ áp fe-user. Q1=a global (không per-role), Q3=a giữ USER_HIDDEN_KEYS hardcode + tầng IsVisible dynamic combine, Q4 UAT skip test. Chunk A Domain MenuItem +IsVisible bool=true +DisplayLabel string?(200) + EF config + Migration 27 AddVisibilityAndDisplayLabelToMenuItems (2 AddColumn) — 3-file rule, apply LocalDB _Dev + _Design OK. Chunk B BE API: MenuNodeDto + MenuItemDto +isVisible +displayLabel (sau CRUD flags trước Children). GetMyMenuTreeQueryHandler pass through, KHÔNG filter server-side — 2 FE app tự quyết. UpdateMenuItemCommand + Validator + Handler (trim DisplayLabel whitespace → null). MenusController +PATCH /api/menus/{key} [Authorize Policy=Permissions.Update] body {isVisible, displayLabel}. Chunk C Domain MenuKeys +MenuVisibility const + All[] + DbInitializer +leaf "Menu eOffice" Icon=Eye Order=94 (Workflows shift 94→95). Manual seed Mig 27 LocalDB _Dev (INSERT MenuItems + Permissions Admin). FE Admin: types/menu.ts +isVisible +displayLabel, lib/menuKeys.ts +MenuVisibility, Layout resolver +/system/menu-visibility, App.tsx +Route. NEW pages/system/MenuVisibilityPage.tsx ~210 LOC: PageHeader + 4 StatCard (Tổng/Hiển thị/Đã ẩn/Đã đổi tên) + Search + Table 5 cột (Key mono + parentKey ↳ / Tên gốc / Input "Tên hiển thị" inline placeholder "Mặc định: {label}" / Toggle button emerald-Eye / amber-EyeOff / Lưu khi dirty + Khôi phục khi custom). PATCH endpoint, invalidate ['menus','all'] + ['my-menu'] trigger live update sidebar. Row hidden bg-amber-50/40 highlight, custom label bg-brand-50/40. Chunk D fe-user types/menu.ts mirror. Layout.tsx filterForUser 2 tầng (USER_HIDDEN_KEYS structural + !isVisible dynamic). Helper effectiveLabel(n) = displayLabel?.trim()
2026-05-11 Claude 🎯 SESSION 20 — PE Detail UI restructure 3 yêu cầu UX (4 chunk: 9dee00d→2bba851→f2f01f4→Chunk D Docs) — User UAT live phản hồi "Logic OK rồi, điều chỉnh UI Duyệt NCC 1 tý": (1) Hạng mục lên trên + auto-tạo 1 row từ gói thầu, (2) NCC expand dưới hạng mục, (3) Section Ý kiến gộp đồng cấp cùng Phòng. Q&A clarify trước code (4 câu Q1=a/Q2=a "1 hạng mục"/Q3=a "chỉ hiện signed"/Q4 "public luôn demo thôi"). 4 chunk per-commit pattern feedback_per_chunk_commit. Chunk A BE CreatePurchaseEvaluationCommandHandler + INSERT 1 PurchaseEvaluationDetail mặc định + Changelog (GroupCode=01, NoiDung=TenGoiThau, ThanhTienNganSach=Budget.TongNganSach hoặc BudgetManualAmount fallback 0) + FE reorder PeDetailTabs section. Chunk B ItemsTab restructure list HangMucCard (1 card / hạng mục, expanded=true default cho demo 1 hạng mục). Header: GroupCode + NoiDung + 3 stat (KL/ĐG/TT) + NS link Δ + Pencil/Trash + ▼/▶ toggle. Expand body: NCC inline table 8 cột (NCC/Liên hệ/Điều khoản TT/File báo giá/ĐG chưa VAT/ĐG có VAT/Thành tiền/Action). Click cell quote → QuoteDialog reuse. Add NCC/Edit NCC reuse 2 dialog cũ. Winner ✓ button per row. Bỏ Section 4 "NCC tham gia" (gộp vào Section 2 nested) → 4 section final. Drop SuppliersTab function ~134 LOC dead code (replace bằng HangMucCard expand). Giữ AddSupplierDialog + EditSupplierDialog + SupplierAttachmentsCell (HangMucCard reuse). Chunk C Section Ý kiến gộp đồng cấp cùng Phòng. LevelOpinionsSectionV2 forEach step → 1 StepOpinionsBox (replace grid-cols-2 N approvers). Header: "Bước N — Tên" + dept badge emerald + "X/Y đã duyệt" counter. Body: filter opinions theo step.order → sort levelOrder asc + signedAt asc → render StepOpinionEntry per signed (tên NV + Cấp badge slate + admin override amber + timestamp emerald rounded-full + comment). NV chưa duyệt KHÔNG hiển thị (Q3=a). KHÔNG đụng Mig 26 schema (vẫn UPSERT 1 row / Level qua Service). Drop LevelOpinionBox function. Mirror fe-admin + fe-user mỗi chunk. Verify: dotnet build pass (Chunk A) + npm build × 2 app pass (Chunk B/C — catch TS6133 SuppliersTab unused + SupplierAttachmentsCell unused, fix re-add cột File báo giá vào nested table). Test skip Phase 9 UAT iteration (81 test pass unchanged). Stats unchanged: 26 mig, 59 DB tables, ~141 endpoint, 33 FE pages, 44 gotcha, 81 test. Pending S21+: Test regression B4 silent 403 (HIGH §7), Test V2 Service wire ApproveV2Async + Section gộp (Chunk C), Test Mig 25 PATCH user-selectable, Contract V2 (Mig 27/28 mirror PE), phân quyền strict V2, drop legacy V1 cleanup. 9dee00d (A) · 2bba851 (B) · f2f01f4 (C) · (current D Docs)
2026-05-09 Claude 🎯 SESSION 19 — PE Section 5 V2 dynamic theo ApprovalWorkflowLevel + Mig 26 (4 commit: 873e7a1 polish 3 button + 77a3058/90baa8e/6e913b3/Chunk D Mig 26) — User feedback Section 5 hiện CỨNG 4 box (PheDuyet/CCM/MuaHàng/SmPm Mig 15 từ Phase 8) → cần động theo Workflow V2 đã pin: forEach Step (Phòng) → forEach Level (Cấp) → forEach NV → 1 OpinionBox với ý kiến + tên người ý kiến. Bước 1 Phòng A có 2 NV → 2 box ngang hàng. 5 câu chốt spec trước code: Q1=1B (gắn — Service auto sync khi duyệt, KHÔNG form input rời), Q2=2A+Admin (NV chính chủ + Admin override với SignedByUserId track actual signer), Q3=chuyển V2 hết (phiếu V1 legacy fallback Mig 15 4 box readOnly), Q4=4C+bonus (Phase=DaDuyet/TuChoi khoá; Admin có quyền duyệt thay; comment empty → "(duyệt — không ý kiến)" placeholder), Q5=5A (layout group Step header "Bước N — Phòng X" + grid-cols-2 cho N approvers). 3 chunk per-commit (memory feedback_per_chunk_commit): Chunk A (77a3058) Domain entity PurchaseEvaluationLevelOpinion : AuditableEntity (PEId+LevelId UNIQUE composite, Comment nvarchar(2000), SignedAt datetime2, SignedByUserId Guid, SignedByFullName nvarchar(200) denorm) + EF config FK Cascade Pe + Restrict Level + ApplicationDbContext + IApplicationDbContext DbSet + Migration 26 AddPeLevelOpinionsForV2 (1 CREATE TABLE + 2 FK + 2 index — UNIQUE composite + IX LevelId). 3-file rule. Apply LocalDB SolutionErp_Dev OK. Chunk B (90baa8e) Service PurchaseEvaluationWorkflowService.ApproveV2Async sau line log approval → UPSERT row PurchaseEvaluationLevelOpinions cho Cấp hiện tại: match level theo ApproverUserId == actorUserId (multi-NV cùng Cấp OR-of-N), fallback first khi Admin override (FE detect SignedByUserId !== Level.ApproverUserId hiển thị "Admin duyệt thay"). Reject KHÔNG sync. Empty/whitespace comment → "(duyệt — không ý kiến)" placeholder. Helper ResolveActorFullNameAsync(actorUserId, isSystem) lookup denorm SignedByFullName từ Users (fallback "(System)" / "(unknown)"). DTO PurchaseEvaluationLevelOpinionDto 15 fields (LevelId/StepOrder/StepName/StepDepartmentId/StepDepartmentName/LevelOrder/LevelName/ApproverUserId/ApproverFullName/Comment/SignedAt/SignedByUserId/SignedByFullName). GET handler GetPurchaseEvaluationQueryHandler Include LevelOpinions + helper BuildLevelOpinionsAsync JOIN ApprovalWorkflows.Steps.Levels + Departments + Users → denorm DTO list. Empty list cho phiếu V1 / V2 chưa có cấp duyệt → FE fallback. Chunk C (6e913b3) FE Section 5 V2 dynamic: type PeLevelOpinion + PeDetailBundle.levelOpinions[]. Section 5 conditional: evaluation.approvalWorkflowId set → <LevelOpinionsSectionV2/> (V2 dynamic), else <DepartmentOpinionsSection/> readOnly fallback (V1 legacy giữ Mig 15 4 box). Component LevelOpinionsSectionV2 group theo step.order: header "Bước N — " + dept badge emerald + hint "(N người duyệt)" khi totalApprovers > 1; body grid-cols-2 cho step.levels.flatMap(level => level.approvers.map(approver => <LevelOpinionBox/>)); lookup opinion theo (stepOrder, levelOrder, approverUserId). LevelOpinionBox read-only: title "Cấp N — ", badge amber "⚠ Admin duyệt thay" khi override, badge emerald "✓ Đã duyệt", empty "— chưa duyệt" italic gray, footer timestamp signedAt format vi-VN. Workspace mode hint giữ amber "Ý kiến + chữ ký auto đồng bộ khi NV duyệt". Mirror fe-admin + fe-user (rule §3.9). Verify: dotnet build pass + dotnet test 81 pass + npm run build × 2 pass · 0 TS error. Chunk D docs (current) STATUS/HANDOFF/migration-todos/CLAUDE.md/schema-diagram §16 mới + session log. Phiếu V1 cũ KHÔNG migrate (giữ Mig 15 readOnly), drop sau UAT confirm. Stats: 26 mig (+1), 59 DB tables (+1), ~141 endpoints (no new), 33 FE pages, 81 test pass. Polish 3 button (873e7a1) Hành động đầu Session 19: rút gọn label "✓ Duyệt / ← Trả lại / ✗ Từ chối" + 3 màu khác nhau (emerald/amber/red) + font-bold cho cả 2 app. 873e7a1 (3 button) · 77a3058 (Chunk A Mig 26) · 90baa8e (Chunk B Service+DTO+GET) · 6e913b3 (Chunk C FE) · (current Chunk D Docs)
2026-05-08 19:45 Claude 🎯 SESSION 18 WRAP-UP — PE V2 polish + Clone B (DuyetNccPhuongAn) + 4 bug fix UAT + Mig 25 IsUserSelectable (7 commit aaa1c6c32a8d4d) — User UAT live tiếp Session 17, request chuỗi polish nhỏ + clone V2 cho type B. Áp memory feedback_uat_skip_verify (skip dotnet test mỗi chunk, push ngay) + lesson rename/remove → bắt buộc npm run build. B1 (aaa1c6c) Pe Duyệt (?pendingMe=1): bỏ dropdown "Tất cả trạng thái" + filter cứng client-side getPeDisplayStatus === DaGuiDuyet (loại Nháp/Trả lại/Đã duyệt/Từ chối). Hint amber "Lọc cố định: Đã gửi duyệt". Header count dùng rows.length (inbox không paged). Workaround BE /inbox loose UAT trả phiếu Nháp. Mirror fe-admin + fe-user. B2 (917446d) PeDetailTabs HistoryTab filter chỉ events Trả lại/Gửi duyệt lại: workflow transition về TraLai (phaseAtChange=98) + transition từ TraLai (summary chứa "TraLai →") + sửa nội dung khi phaseAtChange=TraLai. BE giữ audit data đầy đủ, chỉ FE filter (reversible). Empty state "Chưa có lịch sử trả lại / gửi duyệt lại". Mirror cả 2 app. B3 (937eb24) Clone V2 cho B (DuyetNccPhuongAn) — User chốt "Quy trình chọn thầu phụ - NCC → Duyệt NCC đúng. Clone toàn bộ updates sang Duyệt NCC và Giải pháp". Audit phát hiện 80% chung qua ApplicableType discriminator → chỉ thêm 3 file ~60 LOC: (a) MenuKeys.cs +const ApprovalWorkflowDuyetNccPhuongAnV2 + add vào All[]. (b) DbInitializer.SeedMenusAsync +leaf "Duyệt NCC và Giải pháp (Mới)" dưới root ApprovalWorkflowsV2 + new method SeedSampleApprovalWorkflowsV2Async seed QT-DN-PA-V2-001 v01 (1 Bước Phòng CCM × 1 Cấp NV test, idempotent). (c) fe-admin/lib/menuKeys.ts +AwV2_DuyetNccPhuongAn. KHÔNG migration / Service / Designer page (Layout regex ^AwV2_(.+)$ đã match dynamic, ApprovalWorkflowsV2Page có TYPE_CODE_TO_INT cả 3 type). Rút memory feedback_audit_reuse_before_clone.md. B4 (f77ea38) Fix permission silent 403 — Drafter nv.test Workspace dropdown empty mặc dù seed OK. Root: class-level [Authorize(Policy = "Workflows.Read")] → non-admin 403, TanStack Query catch silent → UI empty không warning. Fix: class-level [Authorize] only (any authenticated). GET = list workflow read-only không nhạy cảm; POST + DELETE giữ Workflows.Create admin-only. Pattern reusable cho Contract V2 sau. B5 (a9c0857) Fix sidebar highlight queryMatches — Click phiếu trong leaf "Danh sách" → URL ?type=1&id=abc → menu mất highlight (gotcha #34 cũ tái phát). Root: queryMatches exact-set equality {type} vs {type, id} length mismatch. Fix: TRANSIENT_QUERY_KEYS = {id, q, editHeader, page, phase, awId} strip trước compare. Edge case verified: Danh sách ?type=1 vs Pending ?type=1&pendingMe=1 distinct (không cross-highlight). Mirror cả 2 app Layout.tsx. B6 (2a53107) Mig 25 + Designer pin toggle + bỏ "(clone)" + Workspace filter — User feedback Admin Designer: bỏ "(clone)" auto-suffix khi clone version (version đã đủ phân biệt) + thêm pin toggle "Cho user pick lúc create phiếu" (multi-select, độc lập IsActive). Migration 25 AddIsUserSelectableToApprovalWorkflows: ALTER ApprovalWorkflows +IsUserSelectable bit NOT NULL DEFAULT 0 + Sql backfill UPDATE WHERE IsActive=1 SET 1 (giữ behavior cũ active workflow vẫn pickable). Domain ApprovalWorkflow +property. DTO AwDefinitionDto +field. CreateAwDefinitionCommand set default true cho version mới (mirror IsActive). New SetAwUserSelectableCommand + Handler. API PATCH /api/approval-workflows-v2/{id}/user-selectable policy Workflows.Create. DbInitializer SeedSampleApprovalWorkflowsV2Async +IsUserSelectable=true. FE Designer: DefinitionDto +field; badge amber "📌 Cho user chọn"; button "Ghim cho user / Bỏ ghim" + mutation toggleSelectable. Designer name = cloneFrom.name (bỏ (clone) suffix). Workspace fetch filter w.isUserSelectable === true (cả fe-admin + fe-user). B7 (32a8d4d) Cleanup orphan .claude.zip + docs.zip từ harness session start, +*.zip rule .gitignore. Cumulative Session 18: 25 mig (+1), 58 tables (no new), ~141 endpoints (+1), 33 FE pages, 81 test pass (no change — feature mới UAT defer test theo §7), 44 gotcha (+1 silent 403). Memory +1 entry. Pending Session 19+: Contract V2 wire (Mig 26 mirror PE), phân quyền strict V2, drop legacy V1 cleanup. aaa1c6c (B1) · 917446d (B2) · 937eb24 (B3) · f77ea38 (B4) · a9c0857 (B5) · 2a53107 (B6) · 32a8d4d (B7)
2026-05-08 Claude 🎯 SESSION 17 WRAP-UP — PE Workflow V2 schema + Service wire end-to-end (13 commit c847dc0de0f38d) — User chốt sau Session 16 "Thấy vẫn không đúng" → viết lại schema riêng + thêm Menu "Duyệt NCC (Mới)" UAT. Cấu trúc rõ ràng: Quy trình > Bước (Phòng) > Cấp (NV cụ thể qua ApproverUserId). 3 chunk lớn: Schema design + Designer (Mig 22 — c847dc0/f6047d5/2781c7e/12daa7f): 3 entity ApprovalWorkflow/Step/Level + enum ApplicableType (DuyetNcc/DuyetNccPhuongAn/Contract). Designer page /system/approval-workflows-v2/:typeCode — iter 1 lock 3 cấp (9712778, sai intent) → iter 2 đúng intent max 3 cấp × N NV/cấp + sequential gating C2/C3 disabled khi cấp trước empty + filter NV theo Phòng + no-dup same level (f3bea3c). Validator BE Order∈{1,2,3} + HaveSequentialOrders + HaveNoDuplicateApproverInSameLevel. State machine 5 trạng thái (ff21120): Nháp→Đã gửi duyệt→Đã duyệt (terminal) Trả lại (Phase riêng TraLai=98, KHÔNG revert DangSoanThao + KHÔNG jump-back)
2026-05-08 Claude 🎯 SESSION 16 — DRASTIC REFACTOR flat workflow Phòng × Cấp (Mig 21, 2 commit Chunk A+B) — Resume từ Session 15 defer plan. User chốt "bỏ phase enum hoàn toàn, dùng ChoDuyet=10 đơn nhất + currentStepIndex tracking". Per memory feedback_drastic_refactor_scope: dedicated session với context fresh, scope conservative 2x buffer (~8-10h estimate, actual ~3h). Chunk A (dbb0089) — Domain enum simplify (DangSoanThao=1, ChoDuyet=10 NEW, DaDuyet=7, TuChoi=99; legacy 2-6 + 98 deprecated giữ cho data cũ). WorkflowStep + DepartmentId Guid? FK Restrict + PositionLevel int? (PE + Contract mirror). PE/Contract entity + CurrentWorkflowStepIndex int? + RejectedAtStepIndex int?. Drop class WorkflowStepInnerStep + nav (PE + Contract). Drop *DepartmentApproval.InnerStepId column. EF Configurations: drop InnerStep config + restore simple unique non-filtered (Mig 19/20 filtered split reverse). DbContext drop DbSet<*WorkflowStepInnerStep> × 2. Migration 21 RefactorWorkflowToFlatModel GỘP: 4 ALTER cols (PE/Contract CurrentStepIndex+RejectedAtStepIndex) + 2 ALTER (WorkflowStep DeptId+PositionLevel) + DROP TABLE x 2 (PEWorkflowStepInnerSteps + WorkflowStepInnerSteps Mig 18+20) + DROP InnerStepId column x 2 (PE+Contract DeptApproval) + DROP filtered indexes x 2 + restore simple unique x 2. PE + Contract Service rewrite TransitionAsync: phase transitions DangSoanThao→ChoDuyet (Drafter trình init idx=0) / ChoDuyet→ChoDuyet (advance idx) / ChoDuyet→DaDuyet/DaPhatHanh (last step done) / ChoDuyet→DangSoanThao (Trả lại save RejectedAtStepIndex) / ChoDuyet→TuChoi (Từ chối khoá vĩnh viễn). Match approver: actor.Dept==step.Dept AND actor.PositionLevel>=step.PositionLevel (OR cùng cấp/dept) OR Approvers.Kind=User match OR Kind=Role match. Admin role bypass policy. Last step done → gen mã HĐ (Contract only). App CQRS WorkflowStepDto + WorkflowStepInput drop InnerStep, add DepartmentId/DepartmentName/PositionLevel (PE + Contract mirror). Tests rewrite: DROP PeNStageApprovalTests.cs (6) + ContractNStageApprovalTests.cs (6) + PeTwoStageApprovalTests.cs (7) — legacy N-stage/2-stage no longer applicable. UPDATE PeWorkflowAdminTests signature. 96 → 77 test pass (-19 legacy). 3-file rule Mig 21 (.cs + Designer + Snapshot) commit đủ. Chunk B (88a5be1) — FE-Admin Designer rewrite (PeWorkflowsPage + WorkflowsPage): drop InnerStepDto + EditInnerStep types, drop PHASE_OPTIONS auto-assign ChoDuyet=10, StepDto + EditStep + departmentId/positionLevel, copyFromDefinition simplified, Designer step UI rewrite (Tên + Phòng Select + Cấp Select + SLA + Approvers Role/User optional fallback, drop entire InnerSteps sub-section), DefinitionCard view hiển thị badge Phòng emerald + Cấp NV/PP/TP violet, save payload phase=10. types/purchaseEvaluation.ts (fe-admin + fe-user mirror) + ChoDuyet=10 enum + label "Đang duyệt" + color amber. Chunk C (FE PeWorkflowPanel) SKIP — existing UI compatible (workflow.nextPhases driven by BE simplified policy), reuse 3-button Trả lại/Từ chối logic Session 14 hoạt động trên ChoDuyet phase tự động. KHÔNG đụng Service Notify pattern + Changelog pattern (giữ hành vi Mig 16). Verify: dotnet build pass + Mig 21 LocalDB applied + 77 test pass + npm build × 2 pass. Memory feedback_drastic_refactor_scope.md validated: dedicated session approach hoạt động đúng dự đoán. dbb0089 (A) · 88a5be1 (B)
2026-05-07 Claude 🎯 SESSION 15 — Tooltip diagnose "Lưu & Gửi Duyệt" + Plan drastic refactor flat workflow → DEFER — User UAT live screenshot phiếu PE Bản nháp + báo "Lưu & Gửi Duyệt" KHÔNG hoạt động + suy đoán "trùng ID với phiếu khác". Chẩn đoán: button silent disabled khi evaluation.workflow.nextPhases không có forward phase (chỉ TuChoi/TraLai). FE chưa có visual feedback → user không biết. Improvement (commit 835cc7f): compute forwardPhase once + add submitDisabledReason string giải thích reason (canEditPhase=false / readOnly / !forwardPhase với hint admin kiểm tra cấu hình quy trình) + button title attribute show reason hover hoặc forward phase label khi enabled + Dialog confirm show forward phase explicit "Sẽ chuyển sang Chờ Purchasing". Mirror fe-admin + fe-user. Build pass cả 2. "Trùng ID" KHÔNG phải bug FEPurchaseEvaluationWorkspacePage URL state đúng (+ Thêm mới clear id, save set new), mỗi PE row unique GUID + MaPhieu. Tiếp theo plan drastic refactor: User chốt "bỏ phase enum hoàn toàn, dùng ChoDuyet=10 đơn nhất + currentStepIndex tracking" + workflow flat list (Phòng × Cấp × Users[]) thay InnerStep model. Surface 6 chunk plan + start Chunk A: edit Domain entities (Phase enum +ChoDuyet=10, WorkflowStep +DeptId/PositionLevel, drop InnerStep class+nav, PE/Contract +CurrentWorkflowStepIndex/RejectedAtStepIndex, *DeptApproval drop InnerStepId) + EF Configurations (drop InnerStep config + nav, restore simple unique non-filtered) + DbContext drop DbSets — 12 files trong working tree. Realize scope realistic ~8-10h (PolicyRegistry rewrite + 2 Service rewrite + App CQRS + 12 tests rewrite + Designer FE + Migration 21 + Docs) vượt session boundary + risk session context deep ~30 commits. REVERT working tree về 835cc7f clean. Add memory feedback_drastic_refactor_scope decision rule: drastic refactor cần dedicated session, ước tính conservative (2x buffer), tránh mid-session big refactor. Stats unchanged: 96 test pass, 20 mig, 57 bảng. 835cc7f
2026-05-07 Claude 🎯 SESSION 14 — PE 3-button workflow Duyệt/Trả lại/Từ chối + Task 2 sample seed in-progress — User chỉ thị thay 2-button approval bằng 3 hành động rõ ràng cho approver: Duyệt (forward), Trả lại (về DangSoanThao + Drafter sửa, smart reject Mig 16 + clear N-stage rows + Drafter resume jump-back), Từ chối (Phase=TuChoi, phiếu khoá vĩnh viễn 17 handler Mig 16 lock edit, Drafter phải tạo phiếu mới). 1 commit (0d77698): Domain PurchaseEvaluationPolicy.cs NccOnly + NccWithPlan thêm (X → TuChoi) transition cho mọi phase trung gian (ChoPurchasing/ChoCCM/ChoDuAn/ChoCEODuyetPA/ChoCEODuyetNCC) với roles của phase. FromDefinition expand: mỗi step (trừ DangSoanThao) thêm (step.Phase → TuChoi) với roles step. Service PurchaseEvaluationWorkflowService.TransitionAsync — Reject branch tách 2 case: target=TuChoi giữ nguyên (KHÔNG override + KHÔNG set RejectedFromPhase + KHÔNG clear N-stage); target khác (DangSoanThao) → smart reject (force DangSoanThao + RejectedFromPhase + clear N-stage). FE PeWorkflowPanel (admin + user mirror): render 3 button rõ ràng "✓ Duyệt → X" brand / "← Trả lại (về Drafter sửa)" red / "✗ Hủy / Từ chối" red. Decision logic: target=TuChoi
2026-05-07 Claude 🎯 SESSION 13 — Mirror N-stage workflow sang Contract (Mig 20, 5 commit per-chunk + skip Chunk E API) — User chỉ thị mirror N-stage từ PE sang Contract. Budget defer (cần versioned WF migration trước, hardcoded BudgetPolicy hiện tại chưa có WorkflowDefinition). 5 chunk per-commit (build + ef + test pass mỗi chunk): Chunk A (951ffa3) Domain entity WorkflowStepInnerStep (Domain/Contracts/) + nav WorkflowStep.InnerSteps + ALTER ContractDepartmentApproval.InnerStepId Guid? + EF config FK Cascade Step / Restrict Dept+InnerStep + Migration 20 AddContractWorkflowInnerStepsAndAlterDeptApprovalUnique GỘP 1 (CREATE TABLE WorkflowStepInnerSteps + ALTER InnerStepId + DropIndex old + Recreate filtered legacy WHERE InnerStepId IS NULL + new filtered N-stage WHERE InnerStepId IS NOT NULL + 3 IX + 3 FK). Chunk B (04cf2a0) Application CQRS DTO — WorkflowStepInnerStepDto + extend WorkflowStepDto + GetWorkflowAdminOverview Include InnerSteps + DeptNames map + CreateWorkflowStepInnerStepInput + CreateWorkflowStepInput extend (default null backward compat) + Validator child rules + Handler atomic batch insert. Chunk C (e247b67) ContractWorkflowService refactor mirror PE — load definition InnerSteps eager, reject branch clear N-stage rows tại fromPhase, dept approval block split hasInnerSteps→N-stage logic / else→legacy 2-stage. N-stage flow giống PE: yêu cầu actor có DeptId+PositionLevel, match firstPending Order asc + (exact level OR canBypass + level≥), exact upsert 1 row InnerStepId, bypass batch upsert NV+PP+TP cùng dept ≤ actor (audit IsBypassed cho cấp dưới), recheck stillPending → BLOCK + log "duyệt cấp X (còn Y pending)". Chunk D (7c0772a) Tests 6 N-stage Contract mirror PE pattern + helper SeedWorkflowDefinitionAsync 2 step adjacent (DangGopY + DangDamPhan) + SeedContractAsync với Project + Supplier seed + FakeChangelogService + FakeContractCodeGenerator stubs. Bug fix: legacy fallback test ban đầu fail (Standard policy DangGopY → DangDamPhan chỉ cho [Drafter, DeptManager], không Procurement) → switched phase pair sang DangKiemTraCCM → DangTrinhKy + role CostControl khớp. Total 89 → 95 test pass. Chunk E SKIP — WorkflowsController auto-bind [FromBody] CreateWorkflowDefinitionCommand record qua JSON, no code change cần. Chunk F (current) FE-Admin types/users.ts đã có PositionLevel const từ Session 12 reuse. WorkflowsPage Designer extend mirror PeWorkflowsPage Chunk F: InnerStepDto + EditInnerStep types + copyFromDefinition include + departmentsList query + sub-section "Cấp duyệt nhỏ trong phòng" drag-list { Phòng × Cấp + required } + button "+ Thêm cấp duyệt" emerald + payload include Order asc. Empty state hint fallback 2-cấp legacy. KHÔNG đụng fe-user (admin-only). Docs/Skill update. Backward compat 100%: workflow Contract no InnerSteps → fallback legacy 2-stage Mig 16. Data legacy InnerStepId=null vẫn enforce unique cũ qua filtered index. Defer Budget mirror cho session sau (cần migration AddBudgetVersionedWorkflow trước). 951ffa3 (A) · 04cf2a0 (B) · e247b67 (C) · 7c0772a (D) · (current F)
2026-05-07 Claude 🎯 SESSION 12 — N-stage workflow approval Phòng × PositionLevel cấu hình động (PE-only first, 6 commit per-chunk + Mig 18+19) — User yêu cầu mở rộng từ 2-stage Mig 16 (NV.Review/TPB.Confirm) sang N-stage cấu hình động: mỗi WorkflowStep cha (= 1 phase) có thể cấu hình chuỗi InnerSteps con theo Department × PositionLevel với Order sequential. Spec defaults chốt 6 câu (PositionLevel int 1=NV/2=PP/3=TP, sequential pure, bypass cùng dept TP skip NV+PP, smart reject reset N-stage rows về DangSoanThao, PE-only first, designer 1 sub-section InnerSteps). 6 chunk per-commit (build + ef + test pass mỗi chunk per feedback_per_chunk_commit.md): Chunk A (13ab533) Domain enum PositionLevel (NV/PP/TP) + entity PurchaseEvaluationWorkflowStepInnerStep + ALTER User.PositionLevel int? + ALTER PEDeptApprovals.InnerStepId Guid? + EF config + Migration 18 AddPeWorkflowInnerStepsAndPositionLevel (1 CREATE TABLE + 2 ALTER + 3 index + FK Cascade Step / Restrict Dept/InnerStep). 3-file rule. Chunk B (0e56bd0) Application CQRS DTO — PeWorkflowStepInnerStepDto + extend PeWorkflowStepDto + CreatePeWorkflowStepInnerStepInput (default null backward compat existing PeWorkflowAdminTests) + Validator child rules + Handler atomic batch insert + UserDto +PositionLevel field + SetUserPositionLevelCommand mirror SetBypassReview. Chunk C (0c62e24) Service N-stage logic — Migration 19 AlterPeDeptApprovalsUniqueFilteredForInnerSteps (filtered unique: legacy WHERE InnerStepId IS NULL + N-stage WHERE InnerStepId IS NOT NULL) cho phép multi-row cùng dept khác inner step. PurchaseEvaluationWorkflowService refactor: load definition InnerSteps eager + reject branch clear N-stage rows + dept block split hasInnerSteps→N-stage logic / else→legacy 2-stage. N-stage flow: yêu cầu actor có DeptId+PositionLevel, match firstPending (Order asc IsRequired) same dept + (exact level OR canBypass + level≥), exact match upsert 1 row InnerStepId, bypass batch upsert NV+PP+TP cùng dept ≤ actor level (audit IsBypassed cho cấp dưới skip), recheck stillPending → BLOCK + log "duyệt cấp X (còn Y pending)" / all done → fall through phase transition. Backward compat: workflow no InnerSteps fallback legacy + InnerStepId=null filter unique cũ vẫn enforce. Chunk D (3d76c6b) Tests N-stage 6 test mới (NV first blocks / 3-level sequential pass / TP bypass skips / wrong dept throws 403 / reject clears rows / legacy fallback no inner) + IdentityFixture extend +positionLevel arg + helper SeedWorkflowDefinitionAsync 2 step adjacent (ChoPurchasing+ChoCCM) cho FromDefinition build transition policy guard pass. Total 83→89 test pass. Chunk E (83ffabd) API PATCH /users/{id}/position-level mirror SetBypassReview pattern + body {positionLevel:int?} Authorize Users.Update. Chunk F (current) FE-Admin types/users.ts +positionLevel field + PositionLevel const + Label/Short maps. PeWorkflowsPage Designer extend: InnerStepDto type + EditInnerStep type + copyFromDefinition include + departmentsList query + sub-section "Cấp duyệt nhỏ trong phòng" per step card với drag-drop list { Phòng × Cấp + required checkbox } + button "+ Thêm cấp duyệt" (xanh emerald) + payload include innerSteps Order asc. UsersPage column "Cấp" badge NV/PP/TP emerald + action button cycle null→1→2→3→null call positionLevelMut PATCH. KHÔNG đụng fe-user (admin-only feature). Docs/Skill update. PE-only first. Backward compat 100%: workflow no InnerSteps + data legacy 2-stage rows không phá. 13ab533 (A) · 0e56bd0 (B) · 0c62e24 (C) · 3d76c6b (D) · 83ffabd (E) · (current F)
2026-05-08 00:30 Claude 🎯 SESSION PHASE 2 WRAP-UP — B12-B14 PE detail polish iterate (3 commit FE-only sau wrap-up 6e7a6db) — User UAT iteration tiếp, áp rule strict verify khi rename/remove (lesson hotfix CI). 3 batch nhỏ: B12 (378c993) "Lưu" no-close (chỉ toast + invalidate, KHÔNG đóng workspace) + nút "Xóa phiếu" red bottom CHỈ Bản nháp (soft-delete IsDeleted=true qua AuditableEntity, không xóa hoàn toàn DB) + bỏ header bar workspace mode "Sửa header"/"Xóa"/"Đóng" (chuyển hết xuống bottom action bar) + Section 4 column header dùng s.supplierName thay displayName (NCC master) + Section 3 row chặn xóa NCC khi đã có quotes (hasQuotes computed) + tooltip "xóa báo giá trước". B13 (e320027) InfoTab useEffect watch [autoEdit, canEdit, ev.id, ...] → re-trigger edit mode khi pencil click phiếu khác (fix useState mount-time only) + sync values từ ev mới (tránh stale state) + Pencil "sáng lên" active state khi editingRowId === p.id (bg-brand-100 + text-brand-700 + ring-brand-300 + shadow-sm + tooltip cập nhật) + wire editingRowId={autoEditHeader ? selectedId : null} từ Workspace → PeListPanel. B14 (d2306b8) QuoteDialog bỏ checkbox "Chọn NCC này cho hạng mục" (consolidate winner ở Section 2.a NccSelectorRow, isSelected vẫn gửi BE giữ trạng thái cũ) + winner column Section 4 matrix highlight emerald (header bg-emerald-50 + prefix + cells bg-emerald-50 font-semibold cho ENTIRE column, không chỉ cell có quote) + loading overlay full-screen QuoteDialog (bg-white/70 backdrop-blur-sm + spinner ring brand-600 + text "Đang lưu báo giá…"/"Đang xóa…") + NccSelectorRow inline spinner "Đang chọn NCC + sync cột giá Section 4…" + disable Hủy/Xóa/Lưu buttons khi isSaving. Verify: npm run build × 2 app pass mỗi commit · dotnet test 83 pass (KHÔNG regression). 378c993 (B12) · e320027 (B13) · d2306b8 (B14)
2026-05-07 Claude 🎯 SESSION WRAP-UP S10-11+++++++ — PE Workspace UX overhaul đầy đủ (23 commit / ~3500 LOC FE + Mig 17 BE) — User UAT live mode iterate liên tục, áp rule feedback_uat_skip_verify (skip dotnet test sau mỗi chunk, push ngay). 7 batch chính: B1 (S10) PE Thao tác 2-panel workspace — leaf Pe_*_Create từ page Create header riêng → workspace 2-panel [320px_1fr] mirror HĐ Thầu phụ; PeListPanel pure picker + sticky "+ Thêm mới"; PeDetailTabs mode='workspace' ẩn Workflow/Approvals/History + Section 5 disabled "nhập khi duyệt" (4 commit). B2 (S11) Migration 17 AddManualBudgetFieldsToPeAndContract — 4 ALTER (PE + HĐ × BudgetManualName nvarchar(200) + BudgetManualAmount decimal(18,2)) cho fallback "user nhập tay khi không link Budget entity approved". Domain + EF config + App CQRS Create/Update + DTO + Validator + carry-forward CreateContractFromEvaluation. FE toggle "Nhập tay" trong PeHeaderForm + ContractCreatePage NewForm/EditForm × 2 app (5 commit). B3 (S11+) BudgetFieldRow inline editor — Section 2 "b. Ngân sách" thay FormRow tĩnh → editable component (toggle + Select OR 2 input + Save dirty + Hủy). canEdit cho cả 3 view (Workspace/Danh sách/Duyệt mode), readOnly chỉ display (3 commit). B4 (S11++) InfoTab inline edit + PeListPanel pencil hover — Section 1 "✎ Sửa" button flip display↔inputs (Tên/Địa điểm/Mô tả/Payment editable, Dự án locked). PeListPanel thêm pencil icon group-hover absolute right + URL ?editHeader=1 chain → autoEditHeader prop trigger mount-time edit (3 commit). B5 (S11+++) Workspace "new" sectioned create viewPeWorkspaceCreateView.tsx ~230 LOC layout 5 sections giống PeDetailTabs visual. S1 + S2.b editable, S3-5 LockedHint "Lưu phiếu trước". POST trigger create. Replace PeHeaderForm trong workspace mode='new' (1 commit). B6 (S11++++) Danh sách disable toàn bộ interactions — PurchaseEvaluationsListPage readOnly={true} hardcoded cho PeDetailTabs + readOnly={!pendingMe} cho PeWorkflowPanel (List view → ẩn Chuyển tiếp + show hint "Vào menu Duyệt"; Pending vẫn approve được) (2 commit). B7 (S11+++++) Lock Loại quy trình + payment preset — workspace <Select> Loại quy trình → <Input disabled> theo URL ?type=N. <Textarea> JSON Điều khoản TT → <Select> 8 preset Việt + "Khác (nhập tay)" → text input fallback (1 commit). B8 (S11++++++) Display status metaPeDisplayStatus enum 4-5 trạng thái UI (Bản nháp / Đã gửi duyệt / Trả lại / Đã duyệt / Từ chối) gom phase chi tiết. getPeDisplayStatus() helper. Workflow timeline Panel 3 vẫn giữ phase chi tiết (1 commit). B9 (S11+++++++) Phase TraLai + pencil always visible + edit gating — Domain PurchaseEvaluationPhase thêm TraLai = 98 (giữa DaDuyet=7 + TuChoi=99). FE label/color + display status badge. isEditablePhase() helper: chỉ DangSoanThao + TraLai. PeListPanel pencil bỏ hover-only → LUÔN visible (bright khi editable / xám disabled khi không) + click guard. Workspace editableOnly filter client-side (1 commit). B10 (hotfix CI) — TS strict catch fail 2 commit B7+B8 do skip-verify (forcedPhase rename quên xóa destructuring args + unused PurchaseEvaluationType import). Update memory feedback_uat_skip_verify.md thêm exception "rename/remove → BẮT BUỘC npm run build" (1 commit). B11 (last) PE detail polishNccSelectorRow Section 2.a thay FormRow tĩnh → Select dropdown từ ev.suppliers (Section 3 list) wire /select-winner API. Section 2.c text rõ "(chọn NCC trước)" / "(chưa nhập báo giá)". Section 3 row khi isWinner → ẩn ✏ + 🗑 (chỉ giữ ✓ active). Bottom action bar workspace mode: 2 nút "Lưu (đóng)" + "Lưu & Gửi Duyệt →" confirm dialog → POST /transitions với targetPhase = first nextPhase skip TuChoi/TraLai → workflow chuyển từ Bản nháp/Trả lại → Đã gửi duyệt (ChoPurchasing) → onBack đóng workspace (1 commit). ee0d360 (S10 C1) → 4c0625c (B11) — 23 commit total
2026-05-07 Claude PE InfoTab inline edit Section 1 + PeListPanel pencil edit hover — User feedback 2026-05-07: muốn thêm nút edit kế bên row trong Panel 1, click sáng nội dung Section 1 lên cho user sửa header inline (KHÔNG cần đi "Sửa header" page). 2 chunk per-commit (build pass mỗi chunk): C1 fe-admin (3 file) — InfoTab thêm prop readOnly + autoEdit, canEdit=!readOnly && isDraft: display mode hiển thị FormRow + button "✎ Sửa" góc trên phải, editing mode card border brand-200 + 4 input (Tên */Dự án locked/Địa điểm/Mô tả/Payment) + Save (PUT /pe/:id full payload + invalidate detail+list)/Hủy. PeListPanel thêm prop onEditClick, pencil icon absolute right-2 top-2 mỗi row, opacity-0 group-hover:opacity-100. PurchaseEvaluationWorkspacePage đọc URL ?editHeader=1 → pass autoEditHeader xuống PeDetailTabs → trigger edit auto. C2 fe-user mirror y hệt 3 file (rule §3.9). KHÔNG đụng BE. KHÔNG refactor workspace "new" mode (defer — PeHeaderForm hiện tại đủ dùng, làm thêm khi user feedback). 5a89dd2 (C1) · (current C2) · (current C3 docs)
2026-05-07 Claude PE BudgetFieldRow inline editor — toggle + 2 fields trong Section 2 (cả 3 view) — User feedback after Session 11: muốn toggle "Nhập tay" + 2 input fields hiển thị trực tiếp trong Section 2 "b. Ngân sách" của PeDetailTabs — KHÔNG chỉ ở "Sửa header" page, mà cả 3 view (Workspace / Danh sách / Duyệt). Empty values cứ hiển thị empty (không text "(chưa link)" verbose). 2 chunk mirror per-commit (build pass mỗi chunk): C1 fe-admin BudgetFieldRow component (~125 LOC) thay FormRow tĩnh ở b. Ngân sách. canEdit=!readOnly && isDraft: render toggle + Select Budget OR 2 input grid 2-col + nút "Lưu ngân sách" (chỉ hiện khi dirty) + "Hủy thay đổi". Save: full PUT /pe/:id với current entity values + new budget payload. Read-only mode (Duyệt + !isDraft): chỉ display, KHÔNG toggle/inputs, empty hiển thị "—". C2 fe-user mirror y hệt 1 file (rule §3.9). Mỗi chunk: build pass + 0 TS error. KHÔNG đụng BE — re-use existing PUT endpoint. 19712d8 (C1) · d5c6f12 (C2) · (current C3)
2026-05-07 Claude Migration 17 — manual budget fields fallback cho PE + HĐ (toggle "Nhập tay") — User feedback: khi project chưa có Budget approved (Phase=DaDuyet eligible), user phải break flow đi tạo Budget + duyệt + quay lại link. UX kém. Solution: thêm fallback "Nhập tay" — checkbox toggle cạnh Label Ngân sách, khi ON → hide Select Budget, show 2 input field grid 2-col (Tên tham chiếu text + Số tiền number formatted VND). Lưu trên entity row, KHÔNG cần Budget entity. Q1-3 chốt: 1 = stick-toggle reveal 2 input fields; 2 = cả BudgetId + manual fields cùng null OK (KHÔNG XOR validate); 3 = mirror logic sang HĐ luôn (cả 7 ContractType qua ContractCreatePage). 5 chunk per-commit (build + 83 test pass mỗi chunk): C1 Migration 17 AddManualBudgetFieldsToPeAndContract 4 ALTER (PE + HĐ × Name nvarchar(200) + Amount decimal(18,2)) + Domain 2 entity + 2 EF config (HasMaxLength + HasPrecision) — applied LocalDB OK, 3-file rule. C2 App CQRS — CreatePurchaseEvaluationCommand + Update + DTO + Validator (>=0 when has value), CreateContractCommand + Update + DTO + diff log audit, CreateContractFromEvaluation carry forward pe.BudgetManualName/Amount → contract khi gen HĐ từ phiếu. C3 FE-Admin — types +2 field, PeHeaderForm toggle + 2 input + payload conditional (manual mode clear budgetId, link mode clear manual), PeDetailTabs Section "b. Ngân sách" fallback display "Tên · Số tiền + badge nhập tay" khi !budget + có manual data, refactor PurchaseEvaluationCreatePage wrap PeHeaderForm DRY (222→30 LOC), ContractCreatePage NewContractForm + EditContractForm cùng pattern + read-only display branch khi !isDraft. C4 fe-user mirror y hệt 6 file. C5 docs (this row + HANDOFF + session log). KHÔNG đụng Budget entity / Phase=DaDuyet validation (giữ invariant). ecd5f7e (C1) · 0f7901c (C2) · bab5031 (C3) · 14f8d9d (C4) · (current C5)
2026-05-07 Claude PE "Thao tác" 2-panel workspace + Panel 1 read-only picker + Section 5 disabled — User chỉ thị restructure leaf "Thao tác" (Pe_DuyetNcc_Create + Pe_DuyetNccPhuongAn_Create) từ page tạo header riêng (/purchase-evaluations/new?type=N — chỉ form Tên/Project/Địa điểm/Payment/Budget) sang workspace 2-panel mirror pattern HĐ Thầu phụ ContractCreatePage. 5 câu chốt spec trước code: Q1 Panel 2 KHÔNG render Workflow Panel + Approvals + History (chỉ data entry); Panel 1 = pure picker, KHÔNG inline edit/delete; Q2 mirror HĐ Thầu phụ pattern (sticky "+ Thêm mới" + Panel 2 transition new→edit form); Q3 leaf "Danh sách" + "Duyệt" giữ 3-panel hiện tại; Q4 route mới /purchase-evaluations/workspace?type={1|2}; Q5 Section 5 Ý kiến 4PB disable trong workspace (vì người ta nhập khi duyệt, không phải lúc nhập liệu). 2 chunk per-commit (build + 83 test pass mỗi chunk): C1 fe-admin (3 file mới PeListPanel.tsx ~180 LOC pure picker reuse + PeHeaderForm.tsx ~210 LOC extract + PurchaseEvaluationWorkspacePage.tsx ~120 LOC, 3 file sửa PeDetailTabs.tsx thêm prop mode?: 'detail' | 'workspace' + Section 5 hint banner amber + Layout.tsx resolver Pe_*_Create/workspace?type=N + App.tsx route mới). C2 fe-user mirror y hệt 6 file (rule §3.9). KHÔNG đụng BE / migration / schema / endpoint. Route /new cũ giữ tồn tại cho deep-link "Sửa header" button. Total +1142 LOC FE / 0 BE / 32 FE pages. ee0d360 (C1) · ecf3c59 (C2) · (current C3)
2026-05-04 Claude User Manual 7 file rewrite compact cho end-user — User feedback "ko cần quá đầy đủ chi tiết, cho end-user họ làm". Setup package.json + npm install docx@9.5.0 + script npm run gen:all. Rewrite 7 generator scripts theo style end-user friendly: BỎ field validation table 5 cột (Tên field/Kiểu/Bắt buộc/Validation/Ví dụ), BỎ error troubleshoot table 3 cột (Lỗi/Nguyên nhân/Cách xử lý), BỎ FAQ chi tiết 8 câu (giữ 1 chương "Khi gặp lỗi" 4-5 bullet), BỎ phím tắt table. GIỮ: tổng quan ngắn 1-2 câu mỗi chức năng, numbered steps đơn giản 3-7 bước, note/warn/tip chỉ critical, bullet liệt kê. 7 file: 01-Bat-dau (12.1KB cũ 21.7KB ↓44%) / 02-Hop-dong / 03-Duyet-Workflow (mention 2-stage NV/TPB Mig 16) / 04-PE-Phieu-Duyet-NCC (A/B + 4PB + tạo HĐ) / 05-Budget / 06-7-Loai-HD-Cheatsheet / admin-02-Quan-ly-Users-Roles (mention bypass review S9). Refactor user-01 dùng _helpers.js shared (trước có helpers inline 793 dòng, giờ ~110 dòng). Tổng output ~86KB / 7 file (cũ ~123KB ↓30%). 16c2c9c
2026-05-04 Claude Optional polish — fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi" — User chỉ thị "tiếp tục plan tổng" → pick task không blocked. useQuery thứ 2 cho /purchase-evaluations/inbox (endpoint có sẵn), peRows filter theo search. Stats overdue/dueSoon đếm cả PE rows (totalValue chỉ HĐ vì PE không có giá trị). Panel 1 chia 2 section sticky header: "Hợp đồng (N)" giữ behavior cũ click → inline detail Panel 2; "Phiếu Duyệt NCC (M)" click → navigate /purchase-evaluations/:id page riêng (PE entity shape khác Contract, không inline). EmptyState mới: "Không có HĐ hoặc Phiếu Duyệt NCC nào chờ". Chỉ fe-user (Drafter + TPB dùng Inbox) — fe-admin defer. Build pass. 332a90f
2026-05-04 Claude Audit định kỳ 2026-05 (combined skill + doc drift theo §6.4 + §9.4) — Cron solution-erp-skill-audit-monthly empty (No scheduled jobs), trễ 4 ngày so schedule 2026-05-01 → manual trigger sau Session 9 close. Phase 1 cross-check counts: tests=83, migrations=16, gotchas=41, skills=6, STATUS rows=12 (<30 chưa archive) — toàn bộ khớp. Drift patches 5 file: docs/CLAUDE.md (52→55 bảng + §14 DepartmentApprovals), docs/rules.md (Phase 8→9, 77→83 test), docs/architecture.md (77→83 test 2 chỗ), .claude/skills/ef-core-migration (77→83 + ghi 6 PE 2-stage), .claude/skills/dependency-audit-erp (26+→41 bẫy). Phase 2 skill staleness: contract-workflow thêm "Phase 9 cross-ref Mig 16" block + section "Phase 9 done" (2-stage + smart reject + lock edit + bypass). KHÔNG tạo skill mới (§9.5 anti-pattern "viết skill chỉ để có thêm" — pattern 2-stage đủ generic, đã ghi đủ Domain/Service/6 test reusable). Cron recreate SKIP (CronCreate Claude SDK auto-expire 7 days, không fit monthly cadence). Audit log docs/changelog/skill-audit-2026-05.md (1 page). 6 file ~+30/~12 line patch, validation §6.5 OK. 7dc0233
2026-05-04 Claude Session 9 — Chunk E-bis complete: FE 2-stage panel + UserManager bypass toggle + HĐ/Budget 2-stage mirror PE + 6 test + IdentityFixture — User chỉ thị "làm hết cho xong tính năng luôn". 5 chunk per-commit (build + 83 test pass mỗi chunk): (E2) FE PeWorkflowPanel section "Tiến trình duyệt 2-cấp phòng ban" group by phase × dept, highlight amber chờ TPB, badge fuchsia bypass — cả 2 app (rule §3.9). (E3) FE UsersPage column "Bypass" + ShieldCheck toggle button + UserDto.CanBypassReview field. (E4) ContractWorkflowService thêm UserManager DI + mirror 2-stage logic từ PE + ContractDepartmentApprovalFeatures.cs (List query) + endpoint GET /contracts/{id}/department-approvals + FE WorkflowHistoryPanel section. (E5) Budget mirror đầy đủ — TransitionBudgetCommandHandler thêm INotificationService + IDateTime DI + 2-stage logic + BudgetDepartmentApprovalFeatures.cs + endpoint + FE BudgetWorkflowPanel. (E6) IdentityFixture setup ServiceProvider với Identity stack đầy đủ (DbContext SQLite + AddIdentityCore + AddRoles + EF stores) + 6 test PE 2-stage: NV_Review_Blocks / TPB_Confirm_Allows / NV_Bypass / Admin_Skip / Reject_Sets_RejectedFromPhase / Resume_Jumps_Back. Tests Contract + Budget skip vì logic identical PE, ROI thấp. Total 77→83 test pass. 5 commit pushed lên Gitea. f8eebd5 (E2) · 4380bdc (E3) · b6f5a16 (E4) · 1fc439b (E5) · 8353fe8 (E6) · (current E7)
2026-05-04 Claude Session 8 — Migration 16: 2-stage dept approval + smart reject + lock edit (đóng bug anh Kiệt) — Anh Kiệt báo: NV.PRO tạo phiếu PE → duyệt được hết phase = phân quyền sai. Schema mới: 3 bảng *DepartmentApprovals (Contract/PE/Budget) UNIQUE (TargetId, Phase, Dept, Stage). 4 cột mới: Users.CanBypassReview bit + 3 RejectedFromPhase int. Logic 2-stage trong PurchaseEvaluationWorkflowService.TransitionAsync: user.DepartmentId != null → DeptManager (TPB) Stage=Confirm; CanBypassReview=true → Stage=Confirm+IsBypassed; else NV → Stage=Review only, BLOCK transition cho đến khi TPB confirm. Smart reject: Decision=Reject → set RejectedFromPhase, force về DangSoanThao. Resume sau reject: Drafter trình lại từ DangSoanThao + RejectedFromPhase != null → jump straight tới phase đã reject (skip phase trung gian). Lock edit: 17 handler thêm guard Phase != DangSoanThao (Contract Detail × 15, PE Detail × 5, Budget Detail × 3). 3 endpoint mới: GET /pe/{id}/department-approvals (FE Workflow Panel hiển thị progress) + PATCH /users/{id}/bypass-review (admin toggle) + Notify TPB cùng dept khi NV review. HĐ + Budget 2-stage scope defer (chỉ PE first đóng bug). FE update + Tests defer Chunk E-bis. 5fe61cc (A) · 14f3c9f (B) · 9747f8c (C) · a532ba6 (D) · (current)
2026-04-30 Claude Session 6 — MD audit + compact + 3 skill refresh + 2 rule mới — Compact 3 file core (-288 dòng): STATUS -27%, HANDOFF -32%, migration-todos -35%. Archive 51 row Recently Done Phase 0-7 → changelog/recently-done-archive-2026-04.md. Refresh 3 skill stale: form-engine (Phase 2 MVP → Tier 3 feature-complete + bỏ section duplicate gen mã HĐ), permission-matrix (12 menu → ~60 menu key + Bg_/Pe_/PeWf_* + inheritance roots), ef-core-migration (24 DbSet → 52 bảng + ERD update). Rule mới rules.md §7 Khi nào viết test — timing rule (5-row table compact, sau khi rút gọn từ 70 dòng overkill). Rule mới rules.md §6.4 Audit + compact MD định kỳ (cadence + checklist + anti-pattern, KHÔNG rewrite toàn bộ). rules.md §9.4 Skill audit mở rộng cross-ref §6.4. (current)
2026-04-29 Claude Tests Phase 3 mini + 3 gotcha CI mới (#39 #40 #41)tests/.../Application/PeWorkflowAdminTests.cs 6 test versioning logic (CreatePeWorkflowDefinition: first version IsActive=true, second deactivates first, different EvaluationType independent, persists steps ordered + approvers per step, third version increments to v3). Total 77 test (54 Domain + 17 Infra + 6 PE WF Application). Gotcha #39 act_runner github.com TCP timeout 21s + manual checkout fix. #40 npm junction cache fail tsc not found rolled back. #41 paths-ignore behavior + workflow file exclusion. b874743
2026-04-29 Claude CI Path filter docs-only skip livepaths-ignore trong on:push lookup docs/**/**/*.md/.claude/skills/**/.gitignore. Commit chỉ touch docs SKIP CI hoàn toàn (saving ~196s/commit, ~30% commit thuộc loại này). Verify 512880c (docs-only) → Gitea NO trigger run #113. 29eb5d9 · a21790d · 512880c
2026-04-29 Claude CI manual checkout bypass github.com (fix #108/#109) — Run #108/#109 fail TCP timeout 21s khi act_runner fetch actions/checkout@v4 từ github.com. Replace uses: actions/checkout@v4 + actions/upload-artifact@v4 bằng manual git init + git fetch từ Gitea internal. Token ${{ github.token }} auth tự sẵn per-job. Fetch by ref + depth=30. Run #110 pass 3m16s. 14b7d18 · 26075c4
2026-04-29 Claude Tests Phase 2 — Code generator format + sequence (SQLite in-memory)tests/SolutionErp.Infrastructure.Tests/ xUnit + EF SQLite 10. SqliteDbFixture + TestApplicationDbContext subclass override nvarchar(max) → TEXT (SQLite không support max). 17 test: ContractCodeGenerator (format RG-001 5 type + Framework year scope vs Project scope + sequence per prefix + year boundary reset + persistence verify) + PurchaseEvaluationCodeGenerator (format A/B + 3-digit pad + independent A/B sequences + year boundary). CI gate +1 step. Total 71 test pass / 2.1s. df5988b
2026-04-29 Claude Tests Phase 1 — Domain unit tests + CI gatetests/SolutionErp.Domain.Tests/ xUnit 2.9 + FluentAssertions 7.2 (pin trước v8 commercial). 54 test pure function (no DB/IO): WorkflowPolicy (Standard 9-phase + SkipCcm 7-phase + Registry per ContractType + FromDefinition versioned + UserKindApprover) / PEPolicy (NccOnly 3-step + NccWithPlan 5-step + reject paths) / BudgetPolicy (Default 3-step + terminals + SLA spec). .gitea/workflows/deploy.yml thêm step "Run unit tests" trước build, fail → exit $LASTEXITCODE → no deploy. SolutionErp.slnx + folder /tests/. d3f9346
2026-04-29 Claude PE Workflow designer admin UI + Ý kiến 4 phòng ban — Migration 15 AddPurchaseEvaluationDepartmentOpinions (UNIQUE PEId+Kind, 1 row/phòng/phiếu). Domain PurchaseEvaluationDepartmentOpinion + enum PeDepartmentKind (PheDuyet/Ccm/MuaHang/SmPm). BE: PeWorkflowAdminFeatures.cs ~250 LOC mirror Contract pattern (GetOverview + Create version, deactivate cũ atomic) + PeWorkflowsController 2 endpoint reuse policy Workflows.*. PeDepartmentOpinionFeatures.cs Upsert (sign=true→set SignedAt+UserId, sign=false giữ chữ ký cũ) + Delete + 2 endpoint. FE: PeWorkflowsPage.tsx ~500 LOC + designer dialog (clone version + add/remove steps + +Role/+User approvers). Section "5. Ý kiến 4 phòng ban (sign-off)" 2x2 grid OpinionBox (read mode chữ ký vs edit textarea + 2 button Lưu/Lưu&Ký). 5d94bb4
2026-04-29 Claude PE Detail UI restructure theo spec form PHIẾU TRÌNH KÝ — 4 section đánh số match form chính thức: "1. Thông tin gói thầu" (a/b chỉ Tên + Dự án) / "2. Chọn NCC/TP" (a NCC chọn / b Ngân sách / c Giá chào thầu auto-compute từ winner quotes / d Bản so sánh embed GeneralAttachments) / "3. NCC/TP tham gia" / "4. Hạng mục + Báo giá". FormRow helper (label 176px + value flex) thay cho dl grid 2-col cũ. 7e36241
2026-04-29 Claude PE/Contract → Budget integration + cột "So với ngân sách" — BE: BudgetSummaryDto shared (PE & Contract DetailBundle), Create/Update PE+Contract commands + BudgetId? validate cùng Project + Phase=DaDuyet. CreateContractFromEvaluation carry forward pe.BudgetId → contract.BudgetId. FE: PE & Contract Create form + Select "Ngân sách" filter Phase=DaDuyet + Project match. PE InfoTab + Contract Edit display Budget link clickable. PE ItemsTab matrix + cột "NS link · Δ" — match per-row qua key groupCode|itemCode, fetch /budgets/{id} riêng + footer aggregate (xanh dưới / đỏ vượt / xám khớp). 61e5d4d
2026-04-29 Claude Budget FE 3-panel pages cả 2 apptypes/budget.ts (BudgetPhase 5-state enum + DTO) + BudgetsListPage 3-panel [340px_1fr_360px] + filter Phase + Năm + alias ?phase=Pending + readOnly mode menu Duyệt + BudgetCreatePage form Header + BudgetDetailTabs flat (Section Thông tin Header + Section Hạng mục table CRUD inline auto-compute ThanhTien=KL×ĐG) + BudgetWorkflowPanel Panel 3 timeline + dialog comment + Approvals/Changelog. Mirror fe-user. App.tsx 3 route + Layout resolver Bg_*. TS build pass cả 2 app. df12fb1

51 row Phase 0-7 (2026-04-21..28) đã archive → changelog/recently-done-archive-2026-04.md

Session logs: P0 · P1f · P1.2 · P2 · P3 · P4 · P5prep · Tier 3 · Skill gov · Toolkit+4-bảng+Roles VN · Roles+Demo+Pending · PE polish iter 2 + rebrand · Budget BE + 14 Solutions users · Budget FE + PE/HD-Budget + PE WF Designer + Tests Phase 1-2 · Drastic refactor flat workflow Mig 21 · PE V2 schema end-to-end Mig 22-24 · S18 PE V2 polish + Clone B + Mig 25 IsUserSelectable

Docs entry points:

🎯 Next up

Hard blockers (chờ user / ops)

  • UAT 1 tuần 2-3 user thật — hard requirement từ roadmap Phase 5
  • Email outbox — MailKit + SMTP (BLOCKED chờ user cấp SMTP host/user/pass)
  • Rotate credentials — SA, vrapp, JWT secret, runner token (đã post chat)
  • SQL backup daily — Task Scheduler (script scripts/backup-sql.ps1 đã có, chưa schedule)

Optional polish (khi rảnh / UAT phát sinh)

  • Roles CRUD — admin tạo custom role ngoài 12 hardcoded (schema sẵn, chỉ cần CQRS + FE)
  • User-level approver targeting runtime — data model đã có (WorkflowStepApprover.Kind=User), chỉ cần wire User-kind vào ContractWorkflowService.TransitionAsync guard
  • PermissionsPage: grant Workflows.Read cho non-admin role → menu Wf_* visible
  • Warning notification khi còn 20% SLA (SlaWarningSent flag đã có, chỉ thiếu job emit)
  • E2E test reject → quay về DangSoanThao (multi-role)
  • Dependencies scan CI (dotnet list package --vulnerable, npm audit)

Tier 3 ERP roadmap ✓ (close)

  • Attachment upload BE + FE ✓
  • SignalR real-time push ✓
  • Form template builder CRUD + DynamicForm ✓
  • PDF export qua LibreOffice headless ✓
  • .doc/.xls → .docx/.xlsx auto-conversion ✓
  • Dynamic workflow policy per ContractType ✓
  • Versioned workflow (WorkflowDefinition pinned per Contract)
  • Admin workflow designer UI (per-type, per-step approvers)
  • Nested sidebar menu per ContractType (fe-user) + menu split admin/user
  • PermissionsPage 3-panel layout
  • Email outbox for Notification (blocked — SMTP config)

📊 Thông số cumulative

P0 P1f P1.2 P2 P3 P4 P5prep Tier3 +Toolkit +RolesPg+Demo +PE module +PE polish +Budget+30 users +Session 5
BE LOC 0 ~400 ~1500 ~1900 ~2700 ~3100 ~3300 ~4800 ~7800 ~8800 ~11100 ~11400 ~11750 ~13050 (+1300 PE WF Designer + Opinion + Budget integration)
DB tables 0 7 12 14 19 19 19 24 36 36 46 47 51 52 (+1 PEDepartmentOpinions)
API endpoints 0 4 20 23 31 33 35 ~50 ~80 ~93 ~110 ~113 ~124 ~128 (+2 PE WF + 2 Opinion)
Migrations 0 1 3 4 5 5 5 8 11 11 12 13 14 15 (AddPEDepartmentOpinions)
FE pages 0 2 6 7 14 16 16 ~20 ~22 ~23 ~26 ~26 ~26 ~31 (+5 Budget × 2 app + PeWorkflowsPage)
FE components many many+ +EditRowDialog +PE 5-tab +Compare section +Budget tabs/panel + PE OpinionBox + PE 4-section restructure
Scripts PS 0 0 0 1 1 1 3 4 4 5 5 6 6 6
CI/CD workflow 0 0 0 0 0 0 1 1 1 1 1 1 1 1+test gate+path filter+manual checkout
Tests 0 0 0 0 0 0 0 0 0 0 0 0 0 77 (54 Domain + 17 Infra + 6 PE WF Application)
Docs 10 13 14 24 26 30 35 ~40 ~42 ~44 ~46 ~48 ~50 ~52 (+session log + Test plan)
Demo data 0 0 empty 0 0 0 0 0 5+3 15+8+7+13+4 +PE 4 phiếu +rebrand email 30 user 30 user
Commits 1 2 3 5 6 7 8 ~25 ~47 ~52 ~63 ~70 ~75 ~82 (+6 session 5)

🚨 Blockers / risks

  • ⚠️ Email SMTP chưa có — blocker cho notification outbound
  • ⚠️ UAT real user chưa chạy — risk phát sinh bug edge-case quan trọng
  • ⚠️ Credentials leaked trong chat — cần rotate trước go-live thật
  • ⚠️ SQL backup không auto — risk data loss nếu VPS crash
  • ⚠️ Permission Workflows.Read cho non-admin — cần grant để họ thấy menu Wf_* (hiện chỉ admin thấy)
  • ⚠️ User-kind approver chưa enable runtime — designer cho chọn User nhưng guard fall back DeptManager

Credentials + URLs

admin@solutionerp.local / Admin@123456