All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
FE Admin:
- types/users.ts: User +positionLevel field + PositionLevel const +
PositionLevelLabel/Short maps (NV/PP/TP).
- PeWorkflowsPage.tsx Designer extend: InnerStepDto + EditInnerStep types,
copyFromDefinition include, departmentsList query, sub-section "Cấp duyệt
nhỏ trong phòng" per step card với 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.
- UsersPage.tsx: column "Cấp" badge NV/PP/TP emerald (— nếu null) +
action button cycle null→1→2→3→null call PATCH /users/{id}/position-level.
KHÔNG đụng fe-user — admin-only feature (PeWorkflowsPage + UsersPage ở
fe-admin only).
Docs:
- STATUS.md Last updated + Phase summary count (17→19 mig, 83→89 test,
55→56 bảng) + 1 row Recently Done Session 12 (KEEP narrative cũ).
- HANDOFF.md TL;DR Session 12 prepend + 8 cảnh báo Session 13+ + giữ
Session phase 2 narrative.
- migration-todos.md Phase 9 + Session 12 block 6 chunk + 5 defer task.
- session log NEW `2026-05-07-2300-n-stage-workflow.md` đầy đủ rationale
+ per-chunk + bug log + plan hierarchy.
Defer cron audit 2026-06-01: schema-diagram §15 Mig 18 + §16 Mig 19,
skill ef-core-migration Mig 18+19 row, skill contract-workflow N-stage
cross-ref section.
Verify:
- npm run build fe-admin pass (✓ built, 0 TS error)
- dotnet test 89 pass (no regression)
- dotnet build 0 error
🎉 SESSION 12 COMPLETE: N-stage workflow approval Phòng × PositionLevel
PE-only. Backward compat 100% với 2-stage Mig 16. 6 commit per-chunk
A→F. Total 89 test pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
590 lines
44 KiB
Markdown
590 lines
44 KiB
Markdown
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||
|
||
**Last updated:** 2026-05-07 (Session 12 — **N-stage workflow approval Phòng × PositionLevel cấu hình động — Mig 18+19. 6 commit per-chunk: Domain → App CQRS → Service logic → Tests +6 → API → FE Designer + UsersPage. 89 test pass. PE-only first.**)
|
||
|
||
## TL;DR Session 12 (07/05 — N-stage workflow approval per phase × dept × cấp)
|
||
|
||
User yêu cầu mở rộng từ 2-stage Mig 16 sang N-stage cấu hình động: 1 phase (WorkflowStep cha) có thể cấu hình chuỗi InnerSteps con theo Department × PositionLevel sequential. Mỗi phòng có NV → PP → TP duyệt thứ tự, có thể bypass cùng dept khi role cao + CanBypassReview.
|
||
|
||
**6 câu spec defaults chốt:**
|
||
- Q1 enum `PositionLevel { NhanVien=1, PhoPhong=2, TruongPhong=3 }` + `User.PositionLevel int?`
|
||
- Q2 Sequential pure (Order asc, mỗi inner step = 1 cấp duyệt)
|
||
- Q3 TP có CanBypassReview → skip NV+PP cùng dept (audit IsBypassed=true cho cấp dưới)
|
||
- Q4 Smart reject về DangSoanThao + RejectedFromPhase + clear N-stage rows tại phase reject
|
||
- Q5 PE first (Contract+Budget mirror sau khi PE stable UAT)
|
||
- Q6(a) Designer UI 1 sub-section "Cấp duyệt nhỏ trong phòng" drag-list per step
|
||
|
||
**6 chunk per-commit:**
|
||
|
||
- **Chunk A (`13ab533`)** Domain + Migration 18 — enum PositionLevel + entity InnerStep + ALTER User.PositionLevel + ALTER PEDeptApproval.InnerStepId + EF config Cascade/Restrict + 3-file rule
|
||
- **Chunk B (`0e56bd0`)** Application CQRS DTO — extend PeWorkflowStepDto + InnerStepDto + Validator + Handler atomic batch + UserDto +PositionLevel + SetUserPositionLevelCommand (default null backward compat existing PeWorkflowAdminTests)
|
||
- **Chunk C (`0c62e24`)** Service N-stage logic + **Migration 19** filtered unique (drop UNIQUE Mig 16 → recreate `WHERE InnerStepId IS NULL` legacy + new `WHERE InnerStepId IS NOT NULL` N-stage). Refactor TransitionAsync: load InnerSteps eager + reject clear rows + hasInnerSteps→N-stage / else→legacy 2-stage. Match firstPending Order asc, exact match upsert 1 row, bypass batch upsert NV+PP+TP audit IsBypassed
|
||
- **Chunk D (`3d76c6b`)** 6 test PE N-stage (FirstInner blocks / 3-level sequential pass / TP bypass skips / wrong dept 403 / reject clears rows / legacy fallback no inner). IdentityFixture extend +positionLevel arg. Helper SeedWorkflowDefinitionAsync 2 step adjacent. **83→89 test pass**
|
||
- **Chunk E (`83ffabd`)** API `PATCH /users/{id}/position-level` mirror SetBypassReview
|
||
- **Chunk F (current)** FE-Admin types/users.ts +positionLevel + PositionLevel const + Label/Short. PeWorkflowsPage Designer + sub-section InnerSteps drag-list { Phòng × Cấp + required } + button "+ Thêm cấp duyệt" emerald + departmentsList query + payload include. UsersPage column "Cấp" badge + cycle button. KHÔNG đụng fe-user (admin-only). Docs/Skill update.
|
||
|
||
**Verify:** dotnet build pass + dotnet ef database update Mig 18+19 LocalDB applied + dotnet test 89 pass + npm build fe-admin pass.
|
||
|
||
**Cumulative sau Session 12:**
|
||
|
||
| | Trước S12 | Sau S12 |
|
||
|---|---:|---:|
|
||
| BE LOC | ~14850 | ~15300 (+450 — Domain enum + entity + EF config + Service N-stage + App CQRS) |
|
||
| Migrations | 17 | **19** (+Mig 18 + Mig 19) |
|
||
| DB tables | 55 | **56** (+1 PEWorkflowStepInnerSteps) |
|
||
| DB columns mới | — | +2 (User.PositionLevel + PEDeptApproval.InnerStepId) |
|
||
| API endpoints | ~133 | **~134** (+1 PATCH /users/{id}/position-level) |
|
||
| FE pages | 32 | 32 (no change — extend existing 2 page) |
|
||
| Tests | 83 | **89** (+6 N-stage PE) |
|
||
| Commits | (after S11+++) | **+6** (A→F per-chunk) |
|
||
|
||
## ⚠️ CẢNH BÁO Session 13+
|
||
|
||
1. **N-stage chỉ áp PE first** — Contract + Budget vẫn 2-stage Mig 16 cũ. Mirror sau khi UAT PE 2-3 tuần ổn (giữ pattern, lặp lại Domain entity + Service logic + Tests).
|
||
|
||
2. **User.PositionLevel chưa seed cho 30 demo user hiện có** — admin phải set tay qua UsersPage cycle button. Hoặc seed migration sau (mapping Position text → PositionLevel int).
|
||
|
||
3. **Designer InnerSteps optional** — workflow definition KHÔNG có InnerSteps fallback logic 2-stage Mig 16 cũ. Backward compat 100%. Khi muốn enable N-stage cho 1 phase: clone version + add inner steps + Save.
|
||
|
||
4. **Bypass kế thừa cùng dept only** — TP với CanBypassReview chỉ skip NV+PP CÙNG dept của TP. KHÔNG cross-dept (NV.A bypass không skip NV.B).
|
||
|
||
5. **Reset N-stage rows khi reject** — clear chỉ rows tại phase reject. Phase trung gian khác vẫn giữ approvals nếu có. Resume sẽ jump tới RejectedFromPhase + cần re-approve N-stage tại phase đó.
|
||
|
||
6. **Wrong-level error message** — đã localize "phòng X cấp Y không khớp". UAT user cần feedback nếu confused.
|
||
|
||
7. **schema-diagram §15 Mig 18 + §16 Mig 19** chưa update — defer cho audit cron 2026-06-01 (small drift, không major).
|
||
|
||
8. **Skill `ef-core-migration` Mig 18+19 row** chưa add — defer audit 2026-06-01.
|
||
|
||
## TL;DR Session phase 2 (08/05 — B12-B14 polish iterate sau wrap-up `6e7a6db`)
|
||
|
||
User UAT live tiếp tục, áp rule strict verify khi rename/remove (lesson hotfix CI 0ae3fe2).
|
||
|
||
- **B12 (`378c993`)** PE detail polish 5 changes:
|
||
- "Lưu" no-close (chỉ toast + invalidate sync, KHÔNG đóng workspace)
|
||
- "Xóa phiếu" red bottom button CHỈ Bản nháp (soft-delete IsDeleted=true)
|
||
- Bỏ header bar workspace mode "Sửa header"/"Xóa"/"Đóng" (chuyển hết xuống bottom action bar)
|
||
- Section 4 column header: `s.supplierName` (master NCC name) thay `displayName`
|
||
- Section 3 row chặn xóa NCC khi đã có quotes + tooltip "xóa báo giá trước"
|
||
- **B13 (`e320027`)** InfoTab auto re-edit + pencil active visual:
|
||
- useEffect watch `[autoEdit, canEdit, ev.id, ...]` → re-trigger edit khi pencil click phiếu khác
|
||
- Sync values từ ev mới (tránh stale state)
|
||
- Pencil "sáng lên" active state (`bg-brand-100 + ring`) khi `editingRowId === p.id`
|
||
- **B14 (`d2306b8`)** QuoteDialog + winner column highlight + loading feedback:
|
||
- Bỏ checkbox "Chọn NCC này cho hạng mục" (consolidate winner ở Section 2.a)
|
||
- Winner column Section 4 matrix LUÔN xanh emerald (header `✓ ` prefix + cells full column)
|
||
- QuoteDialog full overlay loading + spinner khi save có delay
|
||
- NccSelectorRow inline spinner "Đang chọn NCC + sync cột giá Section 4…"
|
||
|
||
**Verify:** `npm run build` × 2 app pass · `dotnet test` 83 pass (KHÔNG regression). Push gitea OK.
|
||
|
||
## ⚠️ CẢNH BÁO Session 12+ (cập nhật)
|
||
|
||
Bổ sung từ wrap-up trước (xem TL;DR S10-11+++++++ phía dưới):
|
||
|
||
8. **`isSelected` per-quote BE field** — vẫn còn trong API payload nhưng UI ẩn. Nếu sau này muốn cho user chọn winner per-item (khác với winner per-phiếu) → re-enable checkbox QuoteDialog. Hiện tại chỉ gửi `existing?.isSelected ?? false` để giữ legacy data nếu có.
|
||
|
||
9. **Section 4 cell winner highlight** dùng `ev.selectedSupplierId === s.supplierId` (per-supplier check). Nếu BE workflow có multi-winner per-item (ít khả năng), cần điều chỉnh logic.
|
||
|
||
10. **Loading overlay QuoteDialog** chỉ áp QuoteDialog. Các dialog khác (AddSupplierDialog/EditSupplierDialog/DetailDialog) chỉ có button text feedback. Nếu UAT thấy delay → mở rộng pattern overlay sang các dialog khác.
|
||
|
||
11. **InfoTab re-edit useEffect deps** include 4 ev fields (tenGoiThau/diaDiem/moTa/paymentTerms). Có thể trigger re-set values nếu BE cập nhật ev (vd auto-save từ chỗ khác). Trade-off: chấp nhận để sync state. Nếu UAT thấy "values mất" → debug deps.
|
||
|
||
## TL;DR Session S10-11+++++++ (07/05 — PE Workspace UX overhaul đầy đủ)
|
||
|
||
User UAT live mode iterate liên tục. Áp rule [`feedback_uat_skip_verify`](../../../../Users/pqhuy/.claude/projects/D--Dropbox-CONG-VIEC-SOLUTION/memory/feedback_uat_skip_verify.md) skip dotnet test sau mỗi chunk, push ngay. Lesson hotfix CI `0ae3fe2`: rename/remove → BẮT BUỘC `npm run build` trước commit.
|
||
|
||
**11 batch deliverable** (23 commit total — xem STATUS Recently Done row đầu tiên cho narrative đầy đủ):
|
||
|
||
- **B1** PE Thao tác 2-panel workspace (S10)
|
||
- **B2** Migration 17 manual budget fields PE + HĐ (S11)
|
||
- **B3** BudgetFieldRow inline editor Section 2.b
|
||
- **B4** InfoTab inline edit Section 1 + PeListPanel pencil hover
|
||
- **B5** Workspace "new" sectioned create view 5 sections
|
||
- **B6** Danh sách view disable toàn bộ tương tác
|
||
- **B7** Workspace "new" lock Loại quy trình + payment preset Select
|
||
- **B8** PE display status meta (Bản nháp / Đã gửi duyệt / Trả lại / Đã duyệt / Từ chối)
|
||
- **B9** Phase TraLai = 98 + pencil always visible + edit gating
|
||
- **B10** Hotfix CI TS errors (forcedPhase rename + unused import)
|
||
- **B11** PE detail polish — NCC selector dropdown + Section 3 winner protect + Bottom action bar Lưu/Gửi Duyệt
|
||
|
||
## Stats sau wrap-up
|
||
|
||
| | Trước S10 | Sau S11+++++++ |
|
||
|---|---:|---:|
|
||
| BE LOC | ~14400 | ~14850 (+450 — Mig 17 + Domain TraLai + App CQRS) |
|
||
| Migrations | 16 | **17** (+1 Mig 17) |
|
||
| DB columns mới | — | +4 (PE+HĐ × Name+Amount manual budget) |
|
||
| FE pages | 31 | **32** (+1 Workspace 2-panel) |
|
||
| FE components mới | — | +5 (PeListPanel, PeHeaderForm, PeWorkspaceCreateView, BudgetFieldRow, NccSelectorRow inline) |
|
||
| PE phase enum | 8 | **9** (+TraLai = 98) |
|
||
| PE display status | — | **5** (gom phase chi tiết) |
|
||
| Tests | 83 | 83 (no test added — UAT iteration, áp rule §7 test-after defer) |
|
||
| Commits S10-S11+++++++ | — | **+23** |
|
||
|
||
## ⚠️ CẢNH BÁO Session 12+
|
||
|
||
1. **Workflow transition vào TraLai** — Domain enum đã có (98), FE label/color/badge sẵn. NHƯNG chưa wire button "← Trả lại" trong PeWorkflowPanel approver view + workflow service BE chưa transition logic vào TraLai. Khi UAT cần → thêm: button "Trả lại" trong Chuyển tiếp (hoặc Reject Dialog), workflow rule `Decision=3 (TraLai)` set phase=TraLai + ghi `RejectedFromPhase`. FE đã ready accept hiển thị TraLai phase.
|
||
|
||
2. **"Đã gửi duyệt" multi-phase filter** — display status "Đã gửi duyệt" gom 5 phase trung gian (ChoPurchasing/ChoDuAn/ChoCCM/ChoCEODuyetPA/ChoCEODuyetNCC). BE chưa hỗ trợ multi-phase param trong list endpoint → FE filter dropdown ẩn option này (chỉ exact-match Bản nháp/Đã duyệt/Từ chối). TODO: BE thêm `?phases=2,3,4,5,6` query param hoặc derive `displayStatus` field.
|
||
|
||
3. **`feedback_uat_skip_verify` exception** — khi commit có **rename/remove**, BẮT BUỘC `npm run build` 1 lần trước push (lesson hotfix `0ae3fe2`). Chỉ skip verify khi pure ADD (props, JSX, new file).
|
||
|
||
4. **Workspace + Danh sách + Duyệt** matrix:
|
||
- Workspace (Pe_*_Create): 2-panel, Section 5 disabled, edit only Bản nháp+Trả lại, pencil bright/disabled, bottom bar 2 nút Lưu/Gửi Duyệt
|
||
- Danh sách (Pe_*_List): 3-panel, **readOnly=true** toàn bộ (no edit/transition)
|
||
- Duyệt (Pe_*_Pending): 3-panel, PeDetailTabs readOnly + PeWorkflowPanel có Chuyển tiếp + Section 5 nhập opinion (chỗ này hiện vẫn disabled do code path cũ — verify nếu UAT user cần sign opinions ở đây)
|
||
|
||
5. **Mig 17 columns nullable** — backward compat OK. Cả 2 (BudgetId + manual fields) cùng null acceptable. Validation BE chưa XOR.
|
||
|
||
6. **CreateContractFromEvaluation carry-forward** manual fields PE→HĐ — đã wire. Verify UAT.
|
||
|
||
7. **CI deploy status** — sau hotfix `0ae3fe2` các run từ commit `4c0625c` trở đi sẽ xanh + deploy. User UAT live trên prod ngay sau push.
|
||
|
||
## TL;DR Session 11++ housekeeping (07/05 — InfoTab inline edit + pencil hover)
|
||
|
||
User feedback after BudgetFieldRow: muốn thêm nút edit kế bên row trong Panel 1 list, click sáng nội dung Section 1 lên cho sửa header inline.
|
||
|
||
- ✅ **InfoTab inline edit** — display mode + button "✎ Sửa" góc phải Section 1. Editing mode: card border brand-200 + 4 input (Tên / Dự án locked / Địa điểm / Mô tả / Payment) + Save (PUT /pe/:id) / Hủy.
|
||
- ✅ **PeListPanel pencil hover** — icon absolute right-2 top-2 mỗi row, group-hover opacity-100. Click → callback onEditClick(id).
|
||
- ✅ **URL flag `?editHeader=1`** — set bởi pencil click → autoEditHeader prop chain xuống PeDetailTabs → InfoTab tự open editing mode mount-time.
|
||
- ✅ **fe-admin** Chunk 1 (`5a89dd2`) · **fe-user mirror** Chunk 2 (this).
|
||
|
||
**Defer (chưa làm):** Refactor workspace "new" mode wrap PeHeaderForm trong sectioned layout giống detail view (5 sections visible). PeHeaderForm hiện tại single-card đủ dùng — chỉ làm thêm khi user feedback rõ.
|
||
|
||
## TL;DR Session 11+ housekeeping (07/05 — inline budget editor)
|
||
|
||
User feedback after Session 11: muốn toggle + 2 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. Empty values cứ empty.
|
||
|
||
- ✅ **BudgetFieldRow component** (~125 LOC) thay FormRow tĩnh cũ ở `b. Ngân sách`. canEdit=`!readOnly && isDraft`. Save dùng existing PUT endpoint (KHÔNG cần BE thay đổi).
|
||
- ✅ **fe-admin** Chunk 1 (commit `19712d8`) · **fe-user mirror** Chunk 2 (commit `d5c6f12`).
|
||
- ✅ **Verify**: 2 build pass + 0 TS error.
|
||
|
||
UX:
|
||
- **Workspace + Danh sách + isDraft** → editable inline: toggle + Select OR 2 input + nút Lưu khi dirty
|
||
- **Duyệt + !isDraft** → display only (link card / manual values / "—" empty)
|
||
- **Empty state**: hiển thị "—" thay vì "(chưa link)" verbose (per user)
|
||
|
||
## TL;DR Session 11 (07/05 — Migration 17 manual budget fields)
|
||
|
||
**Output session 11** — UX improvement cho user nhập ngân sách không cần Budget entity approved:
|
||
|
||
- ✅ **Migration 17** `AddManualBudgetFieldsToPeAndContract` — 4 ALTER (PE + HĐ × BudgetManualName nvarchar(200) + BudgetManualAmount decimal(18,2)). Applied LocalDB OK. Mirror logic PE ↔ HĐ (Q3 user chốt).
|
||
- ✅ **BE** Domain 2 entity (PE + Contract) +2 property + EF config HasMaxLength/HasPrecision. App CQRS Create/Update commands + DTO + Validator + diff log + carry-forward CreateContractFromEvaluation pe→contract.
|
||
- ✅ **FE** Toggle checkbox "Nhập tay (không link)" cạnh Label Ngân sách trong 4 chỗ: PeHeaderForm (workspace + /new page wrap), ContractCreatePage NewForm + EditForm. Khi ON: hide Select, show 2 input field grid 2-col (Tên + Số tiền formatted VND). Khi OFF (default): Select Budget approved cũ. Auto-detect manual mode khi load existing có manual data + !budgetId. Display fallback ở PeDetailTabs Section 1 "b. Ngân sách" + Contract EditForm read-only branch.
|
||
- ✅ **5 chunk per-commit** (build + 83 test pass mỗi chunk): C1 Domain+Infra Migration 17 (`ecd5f7e`) · C2 App CQRS (`0f7901c`) · C3 FE-Admin (`bab5031`) · C4 FE-User mirror (`14f8d9d`) · C5 Docs (current).
|
||
|
||
**Validation Q2 chốt:** cả BudgetId + manual fields có thể cùng null (PE/HĐ chưa có ngân sách gì). KHÔNG XOR enforce — BE prefer link nếu có (Phase=DaDuyet guarantee), manual fallback only.
|
||
|
||
**KHÔNG đụng:** Budget entity / Phase=DaDuyet validation (giữ invariant "PE/HĐ link Budget approved only"). Manual fields chỉ là note/display, KHÔNG join với Budget.Details cho per-row comparison ở PE matrix Section 4 (cột "So với ngân sách" vẫn require ev.budgetId — không có detail rows để compare).
|
||
|
||
## ⚠️ CẢNH BÁO session tiếp (Session 12+)
|
||
|
||
1. **UAT manual budget flow** — toggle ON/OFF + save + reload + verify auto-detect mode. Đặc biệt edit existing PE/HĐ có manual data → toggle phải auto-checked. Edit existing có Budget link → toggle auto-unchecked.
|
||
2. **Section 4 PE matrix "So với ngân sách"** vẫn require Budget link — manual amount KHÔNG render comparison column. Document giới hạn này nếu UAT thắc mắc.
|
||
3. **`docs/database/schema-diagram.md`** chưa cập nhật count 16→17 migration + 4 column mới. Defer cho audit định kỳ 2026-06-01 (per §6.4 cron) — nhỏ enough không phải selective rewrite.
|
||
4. **CreateContractFromEvaluation** đã carry forward manual fields PE→Contract. Verify khi UAT: PE có manual budget → tạo HĐ từ phiếu → HĐ inherit luôn.
|
||
5. **No new test added** (rule §7 — feature mới = test-after, soak UAT 2-3 tuần ổn → viết happy path).
|
||
6. **Schema fields nullable** — không phá HĐ/PE cũ (legacy null OK). Backward compatible.
|
||
|
||
## TL;DR Session 10 (07/05 — PE workspace 2-panel)
|
||
|
||
**Output session 10** — restructure leaf "Thao tác" PE từ page Create header riêng sang workspace 2-panel mirror HĐ Thầu phụ pattern:
|
||
|
||
- ✅ **Spec chốt 5 câu trước code** — Q1 Panel 2 chỉ data entry (KHÔNG Workflow/Approvals/History); Panel 1 pure picker (no inline edit/delete); Q2 mirror HĐ Thầu phụ (sticky "+ Thêm mới" + new→edit Panel 2); Q3 leaf "Danh sách" + "Duyệt" giữ 3-panel hiện tại; Q4 route mới `/workspace`; Q5 Section 5 Ý kiến 4PB disable trong workspace (nhập khi duyệt).
|
||
- ✅ **Chunk 1 fe-admin** (commit `ee0d360`) — 3 file mới: `PeListPanel.tsx` (~180 LOC pure picker reuse-able + sticky "+ Thêm mới"), `PeHeaderForm.tsx` (~210 LOC extract header form từ CreatePage), `PurchaseEvaluationWorkspacePage.tsx` (~120 LOC 2-panel `[320px_1fr]`). 3 file sửa: `PeDetailTabs.tsx` thêm prop `mode?: 'detail' \| 'workspace'` + Section 5 hint amber khi workspace + force `opinionsReadOnly`. `Layout.tsx` resolver `Pe_*_Create` → `/workspace?type=N`. `App.tsx` route mới.
|
||
- ✅ **Chunk 2 fe-user mirror** (commit `ecf3c59`) — 6 file y hệt content (rule §3.9 duplicate có chủ đích).
|
||
- ✅ **Verify**: 2 build pass + dotnet test 83 vẫn pass mỗi chunk.
|
||
|
||
**KHÔNG đụng BE / migration / schema / endpoint.** Route `/new` cũ giữ tồn tại cho deep-link "Sửa header" button.
|
||
|
||
## ⚠️ CẢNH BÁO session tiếp (Session 11+)
|
||
|
||
1. **UAT live workspace** với anh Kiệt + 2-3 user — feature mới UX khác (page Create cũ thành Dialog implicit qua sticky button + transition new→edit auto).
|
||
2. **Section 5 Ý kiến 4PB hint banner amber** ở workspace mode chỉ là text gợi ý — KHÔNG block. User vẫn thấy existing opinions read-only. Nếu UAT thấy confused → có thể đổi thành collapsible section.
|
||
3. **Mobile: workspace KHÔNG có fallback** — màn hình `<lg` (< 1024px) Panel 2 ẩn (lg:block). Cần test mobile redirect → `/purchase-evaluations/:id` nếu UAT phát hiện. Hiện chỉ admin desktop dùng workspace.
|
||
4. **Pe_*_Pending vẫn /purchase-evaluations?pendingMe=1** — leaf "Duyệt" 3-panel (giữ Panel 3 Workflow + readOnly Section 5 cho phép sign). UAT verify Drafter trình → TPB duyệt thấy Section 5 enable đúng.
|
||
5. **PE WorkflowPanel duplicate ở 2 chỗ** — leaf "Danh sách" + "Duyệt" Panel 3 (3-panel). KHÔNG có ở "Thao tác" workspace. Verify route resolver active state highlight đúng (queryMatches helper từ session 3).
|
||
6. **Sửa header trong workspace** — vẫn navigate sang `/new?id=` (button "Sửa header" trong PeDetailTabs). Chưa wire inline edit qua Dialog. Nếu UAT yêu cầu → thêm prop `onEditHeader` cho PeDetailTabs trigger Dialog reuse `PeHeaderForm`.
|
||
|
||
## Housekeeping today (sau Session 9)
|
||
|
||
- ✅ **Audit định kỳ 2026-05** — combined skill + doc drift (commit `7dc0233`). 5 drift patch (count 77→83 + 52→55 bảng), 1 skill content patch (contract-workflow Phase 9 cross-ref). KHÔNG tạo skill mới. Log `docs/changelog/skill-audit-2026-05.md`.
|
||
- ✅ **Optional polish — fe-user Inbox PE section** (commit `332a90f`). useQuery `/purchase-evaluations/inbox` + Panel 1 chia 2 section sticky header (HĐ + PE). PE click → navigate page riêng.
|
||
- ✅ **User Manual 7 file rewrite compact** (commit `16c2c9c`). User feedback "ko cần quá đầy đủ chi tiết, cho end-user họ làm". Bỏ field validation table + error troubleshoot table + FAQ chi tiết. Giữ tổng quan ngắn + numbered steps đơn giản. ~86 KB / 7 file (cũ ~123 KB ↓30%). Setup `package.json` + `npm install docx@9.5.0` + `npm run gen:all`. Lần sau sửa: edit `_gen-*.js` → run gen:all.
|
||
|
||
**Cron audit định kỳ:** Claude SDK CronCreate auto-expire 7 days → KHÔNG fit monthly cadence. User cần setup OS Task Scheduler `.bat` script ping API hoặc manual trigger mỗi đầu tháng. Lần kế: 2026-06-01.
|
||
|
||
**User Manual style rule (mới chốt session này):** end-user docs BỎ field/error tables, FAQ chi tiết, phím tắt — GIỮ tổng quan ngắn + numbered steps + note/warn/tip critical. Phân biệt với rule §6.5 (KHÔNG cắt narrative) — đây là rule cho audience end-user, không phải agent dev đọc rationale.
|
||
|
||
## TL;DR Session 9 (04/05 — Chunk E-bis sau Session 8)
|
||
|
||
**Output session 9** — đóng tất cả Chunk E-bis defer từ session 8:
|
||
|
||
- ✅ **FE PE WorkflowPanel** — Section "Tiến trình duyệt 2-cấp phòng ban" group by phase × dept, highlight amber chờ TPB confirm, badge fuchsia bypass (cả fe-admin + fe-user).
|
||
- ✅ **FE UsersPage UserManager** — Column "Bypass" + button ShieldCheck toggle CanBypassReview, badge fuchsia khi enabled. UserDto thêm field.
|
||
- ✅ **HĐ 2-stage logic** — `ContractWorkflowService` thêm UserManager DI + mirror logic từ PE service. `ContractDepartmentApprovalFeatures.cs` List query. Endpoint `GET /contracts/{id}/department-approvals`. FE `WorkflowHistoryPanel` section mới.
|
||
- ✅ **Budget 2-stage logic** — `TransitionBudgetCommandHandler` thêm INotificationService + IDateTime DI + 2-stage. `BudgetDepartmentApprovalFeatures.cs` + endpoint + FE `BudgetWorkflowPanel` section.
|
||
- ✅ **6 test PE 2-stage** — `IdentityFixture` setup full Identity stack (DbContext SQLite + AddIdentityCore + AddRoles<Role>) reusable. 6 scenario: NV_Review_Blocks / TPB_Confirm_Allows / NV_Bypass / Admin_Skip / Reject_Sets / Resume_Jumps_Back.
|
||
- ✅ **Verify**: Build pass + 83 test pass mỗi commit (54 Domain + 29 Infra: 17 codegen + 6 PE WF Application + 6 PE 2-stage).
|
||
- ✅ **5 commit pushed** Gitea (E2 → E6).
|
||
|
||
## ⚠️ CẢNH BÁO session tiếp (Session 10+)
|
||
|
||
1. **UAT live ngay** với anh Kiệt + 2-3 user — feature 2-stage đầy đủ cả 3 module + UX.
|
||
2. **Tests Contract + Budget 2-stage skipped** — logic identical PE (cùng pattern, cùng entity shape). Pattern `PeTwoStageApprovalTests` reusable nếu UAT phát hiện regression riêng.
|
||
3. **Bypass toggle audit** — chưa log Changelog khi admin toggle CanBypassReview. Audit qua Identity standard column UpdatedAt only. Có thể cần thêm audit row riêng nếu UAT yêu cầu.
|
||
4. **Notify TPB cùng dept** dùng `UserManager.GetRolesAsync` filter `DeptManager` — verify production có user role DeptManager đúng (data already seeded).
|
||
5. **fe-user KHÔNG có UsersPage** — admin-only function. Bypass toggle chỉ ở fe-admin.
|
||
6. **3 endpoint mới List dept-approvals** PE/HĐ/Budget cùng pattern, reuse policy authz `*Read`.
|
||
7. **Cron audit định kỳ 2026-05-01** vẫn EMPTY (`No scheduled jobs`). Có thể recreate khi user yêu cầu.
|
||
|
||
## TL;DR Session 8 (04/05 — code lớn, 5 commit per-chunk)
|
||
|
||
## TL;DR Session 8 (04/05 — code lớn, 5 commit per-chunk)
|
||
|
||
**Output session 8** — đóng bug anh Kiệt + thêm 3 ràng buộc workflow:
|
||
|
||
- ✅ **Migration 16** `AddTwoStageDeptApprovalAndSmartReject` — 4 ALTER (3 RejectedFromPhase int + Users.CanBypassReview bit) + 3 CREATE TABLE (`Contract/PE/Budget DepartmentApprovals` UNIQUE (TargetId, Phase, Dept, Stage)) + 12 indexes.
|
||
- ✅ **Lock edit** 17 handler thêm guard Phase != DangSoanThao (Contract Detail × 15 qua helper, PE Detail × 5 qua helper mới, Budget Detail × 3 inline).
|
||
- ✅ **Smart reject + Resume** 3 module — Reject = lưu phase nguồn + force về DangSoanThao. Resume = jump straight tới phase đã reject (skip phase trung gian, bypass policy guard).
|
||
- ✅ **PE 2-stage logic** trong `PurchaseEvaluationWorkflowService` — TPB/CanBypass → Confirm; NV → Review only, BLOCK transition cho đến khi TPB confirm.
|
||
- ✅ **3 endpoint mới**: `GET /pe/{id}/department-approvals` (List), `PATCH /users/{id}/bypass-review` (toggle), Notify TPB cùng dept khi NV review.
|
||
- ✅ **Verify**: Build + 77 test pass mỗi commit. Migration applied LocalDB OK. Schema verified.
|
||
- ✅ **6 commit pushed** (2 docs S7 + 5 code S8).
|
||
|
||
## ⚠️ CẢNH BÁO session tiếp (Session 9+)
|
||
|
||
1. **Bug fix anh Kiệt** chỉ áp PE workflow. **HĐ + Budget 2-stage scope DEFER** cho khi UAT PE OK.
|
||
2. **FE Workflow Panel chưa update** — workflow vẫn block đúng (BE), nhưng UX chưa hiển thị 2-stage progress. User test sẽ thấy phase không đổi mà không hiểu tại sao "stuck". Phải UAT với hint cho user trước khi code FE.
|
||
3. **FE UserManager toggle CanBypassReview chưa làm** — tạm thời SET qua HTTP PATCH:
|
||
```
|
||
PATCH /api/users/{userId}/bypass-review
|
||
Authorization: Bearer <admin>
|
||
{ "canBypassReview": true }
|
||
```
|
||
4. **Test thực tế bug fix flow**:
|
||
- Login `phuong.nguyen` (NV.PRO, role=Procurement, DeptId=PRO) tạo phiếu PE type A
|
||
- Trình DangSoanThao → ChoPurchasing
|
||
- phuong.nguyen click Duyệt phase ChoPurchasing → expect: phase KHÔNG đổi, có row Stage=Review
|
||
- `tra.bui` (TPB.PRO, role=DeptManager) click Duyệt → expect: phase chuyển ChoCCM
|
||
5. **Notify TPB cùng dept** dùng `UserManager.GetRolesAsync` filter `DeptManager`. Best effort, fail OK.
|
||
6. **Cron audit định kỳ 2026-05-01** đã quá hạn 3 ngày, vẫn EMPTY runtime. Cần manual trigger.
|
||
7. **Smart reject test**: Reject phase ChoCCM → DangSoanThao + RejectedFromPhase=ChoCCM. Drafter sửa Detail + trình lại → jump straight tới ChoCCM (skip ChoPurchasing).
|
||
8. **Lock edit test**: HĐ ở Phase=DangGopY → cố sửa Detail → expect 409 Conflict "đã trình duyệt, không thể chỉnh sửa".
|
||
|
||
## TL;DR Session 6 (30/04 — không code, chỉ docs)
|
||
|
||
**Output session 6** — pure docs work, không thay đổi code/test:
|
||
|
||
- ✅ **Compact 3 file core**: STATUS -27%, HANDOFF -32%, migration-todos -35% (-288 dòng tổng). 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), `permission-matrix` (12 menu → ~60 + inheritance roots), `ef-core-migration` (24 DbSet → 52 bảng).
|
||
- ✅ **Rule mới §7 Timing test**: 1 bảng 5-row compact — feature mới = test-after, bug = test-before, critical algorithm = test-before, spec change = update test cũ, skip 5 loại.
|
||
- ✅ **Rule mới §6.4 Audit + compact MD định kỳ**: cadence + checklist + anti-pattern. Cross-ref §9.4 skill audit. KHÔNG rewrite toàn bộ.
|
||
- ✅ **77 test vẫn pass** (Domain 54 + Infra 23). 0 thay đổi code.
|
||
- ✅ **Cron 2026-05-01 fire mai** — combined audit (skill + doc drift) theo §6.4 + §9.4.
|
||
|
||
**Session 5 (29/04)** đóng gần hết feature gap + bật test gate:
|
||
|
||
### 🎯 Headline outcomes
|
||
- ✅ **Budget feature-complete** — FE 3-panel pages cả 2 app, BE đã sẵn từ session 4
|
||
- ✅ **PE/HD ↔ Budget integration** — form select Budget filter Phase=DaDuyet + Project, cột "So với ngân sách" ở PE matrix với delta indicator
|
||
- ✅ **PE Detail UI restructure** match form chính thức PHIẾU TRÌNH KÝ (4 section đánh số)
|
||
- ✅ **PE Workflow Designer admin UI** `/system/pe-workflows/:typeCode` versioned với clone/edit/+Role/+User
|
||
- ✅ **Ý kiến 4 phòng ban** — migration 15 + section sign-off 2x2 grid (Phê duyệt/CCM/MuaHàng/SM-PM)
|
||
- ✅ **Tests Phase 1-2** — 71 unit test pass + CI gate fail-fast (Domain policy + Infra code generator)
|
||
|
||
**Session 4 (28/04)** đã có:
|
||
|
||
### A. Module Ngân sách (Budget) BE — migration 14, +4 bảng, +11 endpoint
|
||
|
||
- 4 entity: `Budget` (Header) + `BudgetDetail` (flat row) + `BudgetApproval` (history) + `BudgetChangelog` (audit log).
|
||
- Enum `BudgetPhase` 5 state (DangSoanThao→ChoCCM→ChoCEO→DaDuyet + TuChoi).
|
||
- `BudgetPolicy.Default` hardcoded simple 3-step (Drafter→CCM→CEO) — chưa versioned (TODO khi user cần admin config UI).
|
||
- Mã `NS-YYYYMM-XXXX` Random.Shared (chưa atomic — TODO khi format chính thức).
|
||
- Link nullable: `Contract.BudgetId?` + `PE.BudgetId?` đã có FK + index, FE chưa wire form.
|
||
- Menu seed `Budgets` root + 3 leaf (Bg_List/Bg_Create/Bg_Pending) order=27 icon Wallet.
|
||
- Application: 11 CQRS handler ~340 LOC (Create/UpdateDraft/Transition/List/GetDetail/Delete + Detail CRUD auto-recompute TongNganSach + ListChangelogs).
|
||
- Api: `BudgetsController` 11 endpoint REST.
|
||
- **FE chưa làm — Priority 0 session 5.**
|
||
|
||
### B. 14 demo user Solutions thật
|
||
|
||
- PRO 5 (TPB tra.bui + 4 NV) + CCM 7 (TPB ngocanh.huynh + 6 NV) + ISO 1 (chau.le) + CEO 1 (huy.duong).
|
||
- Pwd `User@123456`. Reconcile pattern (gotcha #38 4-field rename).
|
||
- Tổng 30 user (16 sample cũ giữ + 14 Solutions thật mới).
|
||
|
||
**Tổng cumulative:** 52 DB tables, ~128 endpoints, 15 migrations, **41 gotchas (+3 CI fixes)**,
|
||
**77 unit test (+6 PE WF Application)**, 11+ commit session 5 push lên Gitea.
|
||
|
||
### 🆕 CI/CD optimize (29/04 tối)
|
||
|
||
- ✅ **Manual checkout bypass github.com** — fix #108/#109 transient TCP timeout 21s. Run #110 pass.
|
||
- ✅ **Path filter docs-only skip** — `paths-ignore` trong on:push, commit MD-only KHÔNG trigger CI (verify `512880c` → no run #113).
|
||
- ⏸️ **npm junction cache** — thử ở #111 fail `tsc not found`, rollback. Cần debug session sau (gotcha #40 doc rồi).
|
||
- ✅ **Tests Phase 3 mini (PE Workflow Designer)** — 6 test versioning logic. Total 77.
|
||
|
||
## ⚠️ CẢNH BÁO session tiếp (Session 7+)
|
||
|
||
1. **CI test gate active** — code → `dotnet test SolutionErp.slnx` local → commit → push. Test fail = NO deploy. Workflow user §7 rules.md.
|
||
2. **Timing test rule live (§7)**: feature mới = test-after, bug = test-before BẮT BUỘC, critical algorithm = test-before merge, spec change = update test cũ + code chung commit.
|
||
3. **Doc audit cadence live (§6.4)**: cuối phase compact, đầu tháng cron audit, KHÔNG rewrite toàn bộ. Cron fire **mai (2026-05-01)** — combined skill + doc drift theo checklist.
|
||
4. **Login email** `admin@solutionerp.local` / `Admin@123456` — domain default chưa đổi sang `@solutions.com.vn` (chỉ demo user rebrand).
|
||
5. **Chưa xóa binding cũ `.huypham.vn`** — vẫn fallback. Sau verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS.
|
||
6. **win-acme scheduled task "unhealthy"** — fix trước cert expire 2026-06-18.
|
||
7. **Export phiếu PDF/Excel PE** — pending vô thời hạn (user nói không quan trọng).
|
||
8. **3 feature mới chưa test** (PE Opinion Upsert / Budget validate / Contract BudgetId carry) — đợi UAT phát sinh bug → áp rule §7 (regression test before fix). Hoặc soak 2-3 tuần ổn → viết happy path.
|
||
9. **G-084:** VPS shared VietReport — mọi reverse proxy mới phải `127.0.0.1` + bind loopback IPv4 explicit.
|
||
|
||
## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp
|
||
|
||
| Domain (3) | Ops (3) |
|
||
|---|---|
|
||
| `contract-workflow` — state machine + versioned WF | `dependency-audit-erp` — npm/dotnet CVE scan |
|
||
| `form-engine` — render docx/xlsx + PDF | `ef-core-migration` — EF migration + 3-file rule |
|
||
| `permission-matrix` — role × menu × CRUD | `iis-deploy-runbook` — 3 site IIS + win-acme + runner |
|
||
|
||
**Audit cron:** `0 9 1 * *` (9:00 AM ngày 1 mỗi tháng). Workflow: `docs/rules.md §9.4`. Lần kế: **2026-05-01**.
|
||
|
||
**Quy tắc:** KHÔNG bulk-clone repo skill 3rd party. Chỉ skill PROJECT-SPECIFIC. Đầy đủ: `docs/rules.md §9`.
|
||
|
||
## Ở đâu rồi?
|
||
|
||
| Phase | Trạng thái |
|
||
|---|---|
|
||
| 0 Draft | ✅ Done |
|
||
| 1 Alpha Core (foundation + đợt 2 CRUD + Permission) | ✅ Done |
|
||
| 2 Form Engine MVP + iter 2 (upload UI + .doc auto-convert + PDF export) | ✅ Done |
|
||
| 3 Workflow MVP (9 phase + code gen) + iter 2 (SLA job + attachment + notify) | ✅ Done |
|
||
| 4 Report MVP (Dashboard + Excel) + user-specific dashboard | ✅ Done |
|
||
| 5 Prep + 5.1 Security + Users Mgmt | ✅ Done |
|
||
| **5 Deploy prod** (3 domain HTTPS live) | ✅ Done |
|
||
| **Tier 3 (Attach + Realtime + Form builder + PDF + Versioned WF + Nested menu + Permission 3-panel)** | ✅ Done |
|
||
| **Skill governance** (6 skill project-level + audit cron 1/tháng) | ✅ Done |
|
||
| **3-panel List/Inbox/Thao tác + sidebar accordion + UserDashboard** | ✅ Done |
|
||
| **4-bảng data model** (Header + 7 Details + Workflow + Changelog audit) | ✅ Done |
|
||
| **Mã HĐ gen tại Create + backfill legacy** | ✅ Done |
|
||
| **4 master catalogs** (Units/Materials/Services/WorkItems) + datalist autocomplete | ✅ Done |
|
||
| **Roles VN labels (ShortName)** + Users dept/position + 13 demo users | ✅ Done |
|
||
| **RolesPage CRUD** `/system/roles` + custom role admin | ✅ Done |
|
||
| **7 demo HĐ varied phases** + details + comments + approvals workflow | ✅ Done |
|
||
| **User-kind approver runtime guard** + Warning 20% SLA | ✅ Done |
|
||
| **Edit detail row inline** (7 typed Update commands + EditRowDialog) | ✅ Done |
|
||
| **Master expand 15 NCC + 8 Project** + backfill demo HĐ diverse | ✅ Done |
|
||
| **Deps audit script** (`scripts/deps-audit.ps1`) | ✅ Done |
|
||
| **Module Duyệt NCC (tiền-HĐ) E2E** — 10 bảng + 2 workflow + Kế thừa HĐ | ✅ Done |
|
||
| **PE polish iter 2** — flat layout + per-NCC attachments + readOnly Duyệt + email rebrand | ✅ Done |
|
||
| **Domain rebrand huypham.vn → solutions.com.vn** — 3 subdomain + cert + CORS + FE bundle | ✅ Done |
|
||
| **Module Ngân sách BE + 30 user** — 4 bảng + 11 endpoint + workflow simple | ✅ Done (S4) |
|
||
| **Module Ngân sách FE** — 3-panel pages + Detail tabs + Workflow Panel cả 2 app | ✅ Done (S5) |
|
||
| **PE/Contract → Budget integration** — form Select + cột "So với ngân sách" PE matrix | ✅ Done (S5) |
|
||
| **PE Workflow designer admin UI** `/system/pe-workflows/:typeCode` | ✅ Done (S5) |
|
||
| **Ý kiến 4 phòng ban PE** — migration 15 + section sign-off 2x2 grid | ✅ Done (S5) |
|
||
| **Tests Phase 1-2 + CI gate** — 71 test (Domain policy + Infra code generator) | ✅ Done (S5) |
|
||
| **CI manual checkout bypass github.com + Path filter docs-only skip** | ✅ Done (S5) |
|
||
| **Tests Phase 3 mini** — 6 test PE Workflow Designer versioning (total 77) | ✅ Done (S5) |
|
||
| **Export phiếu PDF/Excel PE** — `IDocumentConverter` + template | 📝 Pending (không quan trọng) |
|
||
| **Tests Phase 3 full** — Application handlers (UpsertOpinion + Budget link validation, cần UserManager setup) | 📝 Pending |
|
||
| **Tests Phase 4-5** — API smoke + FE Vitest | 📝 Pending (làm khi cần) |
|
||
| **npm cache CI optimize** (debug junction Move-Item issue #40) | 📝 Pending |
|
||
| 9+ Post-launch (E-signature, Bravo/SAP, Mobile, AI) | 📝 Future |
|
||
|
||
## Run nhanh
|
||
|
||
```powershell
|
||
# Terminal 1 — API (auto seed 12 role + 9 dept + 5 supplier + 3 project + 8 template + 7 workflow definition + 28 ContractType menu + 7 workflow menu)
|
||
dotnet run --project src\Backend\SolutionErp.Api
|
||
|
||
# Terminal 2 — Admin FE
|
||
cd fe-admin && npm run dev # → http://localhost:8082
|
||
|
||
# Terminal 3 — User FE
|
||
cd fe-user && npm run dev # → http://localhost:8080
|
||
```
|
||
|
||
Login: `admin@solutionerp.local` / `Admin@123456`
|
||
|
||
## Quick sanity-check
|
||
|
||
**Admin (:8082):**
|
||
- `/dashboard` → "Của tôi" row 4 card + KPI cards + charts
|
||
- `/contracts` → list toàn bộ, filter phase/supplier/project
|
||
- `/contracts/new?type=5` → tạo HĐ Mua bán, pre-select type từ URL
|
||
- `/contracts/{id}` → timeline + action dialog + attachments drag-drop + WorkflowSummaryCard
|
||
- `/system/workflows` → 7-card landing (Thầu phụ/Giao khoán/NCC/Dịch vụ/Mua bán/NguyenTacNcc/NguyenTacDv)
|
||
- `/system/workflows/MuaBan` → DefinitionCard active + history + "Tạo phiên bản mới" modal với Steps + Approvers (+Role / +User)
|
||
- `/system/permissions` → 3-panel layout (Role list | Menu×CRUD matrix | Granted stats)
|
||
- `/system/users` → Users CRUD + assign roles
|
||
- `/forms` → upload .docx/.xlsx + render dialog Form↔JSON + Tải PDF
|
||
|
||
**User (:8080):**
|
||
- `/inbox?type=5` → HĐ Mua bán chờ role mình
|
||
- `/my-contracts?type=2` → HĐ Thầu phụ của tôi
|
||
- `/contracts/new?type=3` → tạo HĐ NCC
|
||
- Sidebar nested: 📄 Hợp đồng → expand 7 type → expand "HĐ Mua bán" → Danh sách / Thao tác / Duyệt
|
||
|
||
**Realtime check:**
|
||
- Login 2 tab (admin + user) → user tạo comment / transition → admin nhận toast + bell +1
|
||
|
||
## Cần làm kế tiếp
|
||
|
||
### 🔥 Priority 0 — Session 6 (Ops + UAT focus)
|
||
|
||
Đa số feature gap đã đóng. Còn lại chủ yếu Ops/UAT + optional polish.
|
||
|
||
**A. Hard blockers (chờ user / ops):**
|
||
1. **UAT thật 1 tuần với 2-3 user** — Drafter (QS/NV.PB) + CCM + BOD ghi bug/friction
|
||
2. **SMTP config** → bật Email outbox (BLOCKED chờ user cấp host/user/pass)
|
||
3. **Rotate credentials** — admin + 30 demo + SA + vrapp + JWT secret
|
||
4. **Schedule SQL backup daily** — `scripts/backup-sql.ps1` chưa schedule Task Scheduler
|
||
|
||
**B. PE feature gap còn lại:**
|
||
- **Export phiếu PDF/Excel** PE — pending (user nói không quan trọng lắm). Khi cần: tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`.
|
||
|
||
**C. Optional polish (làm khi UAT phát sinh):**
|
||
- Budget MaNganSach atomic sequence — chốt format → migration `AddBudgetCodeSequences` mirror Contract/PE
|
||
- 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):**
|
||
- Phase 3 — Application handler tests (CQRS + EF InMemory) ~15 test
|
||
- Phase 4 — API smoke tests (WebApplicationFactory) ~7 test
|
||
- Phase 5 — FE Vitest cho lib utility (queryMatches, fmtMoney) ~10 test
|
||
|
||
**Đã xong session 5 (check STATUS Recently Done):**
|
||
- ~~Module Ngân sách FE — 3-panel pages cả 2 app~~ ✅
|
||
- ~~PE/Contract → Budget integration + cột "So với ngân sách"~~ ✅
|
||
- ~~PE Detail UI restructure 4 section đánh số~~ ✅
|
||
- ~~PE Workflow Designer admin UI~~ ✅
|
||
- ~~Ý kiến 4 phòng ban (migration 15)~~ ✅
|
||
- ~~Tests Phase 1-2 + CI gate (71 test)~~ ✅
|
||
|
||
### A. Hard blockers (chờ user / ops)
|
||
|
||
1. **UAT thật 1 tuần với 2-3 user** — hard requirement từ roadmap. Kiến nghị:
|
||
- User A: Drafter (QS/NV.PB) — tạo 3 HĐ mỗi type, đi hết 9 phase
|
||
- User B: CCM — duyệt phase 6
|
||
- User C: BOD — duyệt phase 7
|
||
- Ghi bug / friction / đề xuất → backlog iter 2
|
||
2. **SMTP config** để bật Email outbox:
|
||
```json
|
||
"Email": {
|
||
"Host": "smtp.gmail.com",
|
||
"Port": 587,
|
||
"Username": "...",
|
||
"Password": "...",
|
||
"From": "noreply@solutionerp.local"
|
||
}
|
||
```
|
||
Khi có → thêm `MailKit`, `IEmailSender`, hook vào `NotificationService.CreateAsync` ngay trước khi enqueue realtime push.
|
||
3. **Rotate credentials** — SA SQL password, vrapp password, JWT secret prod, Gitea runner registration token
|
||
4. **Schedule SQL backup** — `schtasks /create /tn "SolutionErp Backup" /tr "powershell -File C:\...\scripts\backup-sql.ps1" /sc DAILY /st 03:00`
|
||
|
||
### A1. Định kỳ — Skill audit
|
||
|
||
**Cadence:** Mỗi đầu tháng (4 tuần). Lần audit kế tiếp: **2026-05-01**.
|
||
|
||
Workflow xem `docs/rules.md §9.4`. Tóm tắt:
|
||
1. Cross-check 6 skill hiện có với STATUS / gotchas / migration-todos
|
||
2. Check repo nguồn 3rd party (alirezarezvani/claude-skills) có gì mới
|
||
3. Update / archive / add skill nếu cần
|
||
4. Log vào `docs/changelog/skill-audit-2026-05.md`
|
||
|
||
Trigger: user nói "audit skill" hoặc tự chạy đầu Phase mới.
|
||
|
||
### B. Polish iterations (optional — khi UAT phát sinh)
|
||
|
||
- **Roles CRUD** — admin tạo custom role ngoài 12 hardcoded (`Domain.Identity.AppRoles`)
|
||
- **User-kind approver runtime** — data model `WorkflowStepApprover.Kind=User` + `AssignmentValue=userId` đã có, chỉ cần:
|
||
```csharp
|
||
// ContractWorkflowService.TransitionAsync (bổ sung):
|
||
var userApprovers = step.Approvers.Where(a => a.Kind == ApproverKind.User)
|
||
.Select(a => Guid.Parse(a.AssignmentValue));
|
||
if (userApprovers.Any() && !userApprovers.Contains(actorUserId))
|
||
throw new ForbiddenException();
|
||
```
|
||
- **Grant `Workflows.Read` cho non-admin role** trong PermissionsPage → menu Wf_* auto-visible (inheritance đã có)
|
||
- **Warning notification 20% SLA** — job emit khi `SlaDeadline - now < sla * 0.2 && !SlaWarningSent`, set flag
|
||
- **Reject → DangSoanThao E2E test** với 3 role khác nhau
|
||
- **Deps scan CI** — `dotnet list package --vulnerable` + `npm audit --audit-level=high`
|
||
|
||
### C. Non-goals / parked
|
||
|
||
- E-signature (VNPT CA / FPT CA) — Phase 6
|
||
- Bravo/SAP import NCC — Phase 6
|
||
- Mobile app — Phase 6
|
||
- AI OCR scan HĐ — Phase 6+
|
||
|
||
## Lưu ý kỹ thuật quan trọng
|
||
|
||
**Đọc [`gotchas.md`](gotchas.md) (41 bẫy) trước khi:**
|
||
|
||
- Thêm package mới → .NET 10 compat (MediatR 14 fail → dùng 12.4.1)
|
||
- Debug TS enum error → dùng const-object pattern (`erasableSyntaxOnly`)
|
||
- Expression tree lỗi → tách switch ra ngoài LINQ
|
||
- Deploy Windows Feature (WebSockets, etc.) → unlock section ở applicationHost (gotcha #25)
|
||
- Workflow transition 403 → check `Contract.WorkflowDefinitionId` pin đúng không
|
||
- Migration lỗi → 3 file đầy đủ (Designer + Migration + Snapshot)
|
||
|
||
## Versioned workflow — quick ref
|
||
|
||
`Contract.WorkflowDefinitionId` pin tại Create. `ContractWorkflowService.LoadAsync` resolve order: pinned def → admin override → hardcoded Registry.For(type). Invariant: HĐ cũ giữ policy cũ qua FK Restrict. Detail: [`workflow-contract.md §7bis`](workflow-contract.md).
|
||
|
||
## File đang active
|
||
|
||
Cấu trúc thư mục + file map: [`PROJECT-MAP.md`](PROJECT-MAP.md). Git state: `git log --oneline -10`.
|
||
|
||
## Credentials + URLs
|
||
|
||
```
|
||
admin@solutionerp.local / Admin@123456 ← Admin (QTV)
|
||
|
||
Demo users — 30 user (User@123456):
|
||
|
||
── 16 sample @solutionerp.local (giữ cho test legacy) ──
|
||
bod.huynh, bod.le Tổng GĐ + Phó GĐ NĐUQ
|
||
pm.nguyen GĐ Dự án FLOCK 01 (PM)
|
||
ccm.tran, pro.pham, fin.do TPB CCM/PRO/FIN
|
||
act.vu, equ.bui, hra.dang Kế toán trưởng / TPB EQU / TPB HRA
|
||
qs.hoang, qs.ngo QS công trường (NV.PB)
|
||
nv.cao, nv.dinh, nv.truong NV Cung ứng/Tài chính/CCM (NV.PB)
|
||
bod.tran, pm.le Bonus NĐUQ + PM thứ 2
|
||
|
||
── 14 Solutions thật @solutions.com.vn (session 4) ──
|
||
PRO 5: tra.bui (TPB) + phuong.nguyen, binh.lethanh, danh.huynh, dat.tran (NV)
|
||
CCM 7: ngocanh.huynh (TPB) + ha.dao, cuong.do, long.le, ha.nguyen,
|
||
dung.nguyen, anh.nguyen (NV)
|
||
ISO 1: chau.le
|
||
CEO 1: huy.duong
|
||
|
||
⚠ Rotate ALL passwords trước UAT thật
|
||
```
|
||
|
||
- API prod: https://api.solutions.com.vn — `/health/live`, `/health/ready`
|
||
- Admin FE prod: https://admin.solutions.com.vn
|
||
- User FE prod: https://eoffice.solutions.com.vn
|
||
- API dev: http://localhost:5443 — `/swagger` (Dev only)
|
||
- Admin FE dev: http://localhost:8082
|
||
- User FE dev: http://localhost:8080
|
||
- SQL dev: `(localdb)\MSSQLLocalDB` / `SolutionErp_Dev`
|
||
- SQL prod: `.\SQLEXPRESS` / `SolutionErp` / `vrapp` (⚠️ rotate)
|
||
|
||
## Đánh giá nhanh
|
||
|
||
**Tốt:**
|
||
- 3 domain HTTPS prod live, CI/CD xanh
|
||
- Tier 3 feature-complete: attachment, realtime, form builder (upload + DynamicForm + PDF), versioned workflow (admin-configurable per ContractType, pin per contract), nested menu per type, 3-panel permissions
|
||
- Clean-arch 3-project split đúng cho 2 cross-cutting service (realtime + document-converter)
|
||
- 26 gotchas tích lũy, 8 session log, 40 docs — agent onboard nhanh
|
||
- Invariant critical: "HĐ cũ giữ quy trình cũ" guaranteed by pinning (reference-based immutability, không snapshot copy)
|
||
|
||
**Rủi ro còn:**
|
||
- UAT thật chưa chạy → có thể phát hiện edge case missing
|
||
- SMTP chưa có → notification chỉ in-app (toast + bell), không email
|
||
- User-kind approver chưa enable guard runtime (designer cho pick, nhưng transition dùng Role fall-back)
|
||
- Credentials chưa rotate
|
||
- SQL backup chưa schedule Task Scheduler
|