Files
solution-erp/docs/changelog/sessions/2026-06-16-S65-hrm-golive-employee-masterdetail-pe-link.md
pqhuy1987 fe28ca3993 [CLAUDE] Docs: S65 session-end closeout — HRM go-live + Hồ sơ NS master-detail + Department hierarchy + PE Link hồ sơ (6 deploy #289→#295)
Closeout S65 (~6 deploy prod-verified, anh + anh Kiệt FDC UAT realtime):
- STATUS/HANDOFF S65 (Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle admin BDwV5d0X / user DbVv6rsf Run #295) + session log #289→#295.
- gotcha #65 (build csproj con ≠ dotnet build slnx gồm tests → CS7036 Run #291 FAIL-gated; fix +trailing-optional sweep).
- CLAUDE.md root Mig 50→52 + PE row +Mig 52.
- Harvest: H2 GATE 2-MISS closed — 2 on-behalf record (PE-Workflow FE + reviewer empty-return #53) → impl-frontend + reviewer agent-memory. H1 tooling CLEAN (roster/skill/plugin 11/6/18).
- Memory (user-global): +feedback_workflow_fanout_reliability.
Carry-P1: cicd-monitor L1 82KB curate-L2 · mirror Employee page→fe-admin · test-after (HoSoLink/ParentId/HRM-perm).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:56:03 +07:00

63 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# S65 (2026-06-16) — HRM go-live + Hồ sơ Nhân sự master-detail (giống NamGroup) + Department hierarchy + PE Link hồ sơ
> ~6 deploy prod-verified Run #289→#295. Anh + anh Kiệt FDC UAT realtime (kiểu rapid-loop như S59). Workflow fan-out chạy THẬT lần đầu.
## Bối cảnh
Anh `/session-start` → chuỗi yêu cầu realtime từ screenshot eoffice + Zalo anh Kiệt FDC:
1. Screenshot eoffice "Public cho tất cả User module NHÂN SỰ".
2. "Trang trí toàn bộ giao diện cho đẹp, font/màu sắc" (đơn điệu).
3. Screenshot NamGroup HRM "bố trí hồ sơ nhân sự giống thế này".
4. Zalo anh Kiệt: "mục E Link hồ sơ (NAS hyperlink) dưới mục D" + "Dự trù PRO → Ngân Sách PRO".
5. "Sao không workflow fan-out ra?" (meta — HMW-mode ON).
6. "Gốc SOLUTION COMPANY rồi fan-out xuống phòng ban".
7. "Chữ đen đơn điệu đổi lại + panel phòng ban trên/User dưới + trang trí màu".
`/session-end`.
## Done — 6 deploy (Run #289→#295)
### #289 (`4004481`) — Public Hồ sơ Nhân sự cho mọi role (BE seed, em main solo)
- `SeedAllRolesHrmProfileReadPermissionsAsync` (DbInitializer): grant CanRead `Hrm`+`Hrm_HoSo` 13 role, gọi **SAU** `RevokeTemporarilyHiddenModulesAsync` (S58) để thắng revoke. **Upgrade-only** (nâng false→true trên row prod đã bị revoke set false — KHÔNG skip-existing như nhánh non-Pe; tránh NO-OP class S58). Giữ ẩn Dashboard NS + 6 `Hrm_Config*`.
- **Insight:** `EmployeesController` dùng policy-based `[Authorize(Policy="Hrm_HoSo.Read")]` (resolve qua `MenuPermissionHandler` đọc thẳng permission matrix) → grant CanRead mở **luôn cả menu lẫn API** trong 1 phát, không dính gotcha #44 (mở menu nhưng controller chặn cứng). FE 0 đổi (menu BE-driven).
- 🟥 reviewer PASS 7/7 (ordering · upgrade-path · scope · read-only · no-regression · idempotent · no-write-path). 🟩 cicd: non-admin GET /employees **200** (was 403), POST/PUT/DELETE **403**, DB 13 role CanRead=1.
### #290 (`c98030f`, 14 file) — Redesign màu foundation fe-user (🩷 designer)
- `index.css`: accent palette teal/violet/**amberx**/**greenx** (đặt tên né trùng built-in Tailwind) stop 50/100/500/600/700 + utilities `.app-gradient-brand`/`.card-accent`/`.icon-chip`/`.stat-value` + heading 600→700 + `.label-eyebrow` brand-600.
- primitives: Button gradient primary/danger · Input/Select/Textarea focus-glow mạnh · Dialog title-bar gradient · Label brand-600. **variant/size keys STABLE** (build PASS = type-contract intact, đòn bẩy TS strict).
- shell: Layout stripe + logo cap · PageHeader title lớn/đậm + accent bar · TopBar gradient hairline · DataTable thead gradient brand. brand #1F7DC1 + Be Vietnam Pro GIỮ.
- ⚠️ designer return bị cắt #53 (đang dựng showcase) → em main recover-disk: 14 file thuần className + 2 color-map (`contract/PE` phase color -700→-800), self-review toàn bộ + build PASS.
### #292 (`0f44d97` + `6ce5803` test-fix, Mig 51) — Department hierarchy + picker
- 🟨 implementer-backend: `Department.ParentId Guid?` **loose-Guid no-FK** (convention PE) + `GET /api/departments/tree` (`GetDepartmentTreeQuery`: load phẳng → đếm NV active GROUP BY `User.DepartmentId` [**recon catch: `EmployeeProfile` KHÔNG có DepartmentId**, link qua User Mig 11] → ráp cây in-memory + rollup TotalEmployeeCount + cycle-guard HashSet). Mig 51 `AddDepartmentParentId` (AddColumn+CreateIndex, no new table).
- em main A2: Create/Update command +ParentId + Update **cycle-guard** (chặn tự-làm-cha + đi ngược chuỗi cha gặp lại Id = vòng A→B→A).
- 🟧 implementer-frontend: picker "Phòng cha" fe-admin DepartmentsPage (Select + load-all query + exclude-self + cột "Thuộc"). Self-service org chart (anh chốt vs seed).
- ⚠️ **gotcha #65** (Run #291 FAIL CS7036): em build `Api.csproj` lẻ (không gồm tests) → push → CI `dotnet build slnx` bắt `CreateDepartmentCommand +ParentId` positional-required vỡ `MasterCatalogFilteredUniqueTests.cs:63` 4-arg. Fix +5th arg → Run #292 PASS. Lesson: đổi chữ ký BE → build full slnx trước push.
### #293 (`318860a` Phase B + `5a0aaa4` PE) — Employee master-detail + PE Link hồ sơ
- **Phase B** (🩷 designer, EmployeesListPage 1201-LOC rewrite): 3-panel master-detail (cây tổ chức consume `/tree` + list + chi tiết **5 tab** Tổng quan/Thân nhân/Trình độ/Kinh nghiệm/Hợp đồng + avatar header). **Giữ 100% 5 satellite CRUD** (16 endpoint, grep-verified). Recon: HRM port từ NamGroup nên model+satellite ~90% sẵn — chỉ thiếu org-tree + re-skin. Designer self-caught `网络Placeholder` mojibake import.
- **PE** (🔥 **Workflow fan-out** `pe-hoso-link-rename-pro` BE∥FE→review): Mig 52 `AddHoSoLinkToPurchaseEvaluation` (PE +`HoSoLink string?` hyperlink NAS — anh Kiệt "copy link thư mục NAS paste vào, dạng hyperlink"; `<a target=_blank rel=noopener>` null-safe; Create/Update **+trailing-optional =null** → backward-compat 0 call-site break) + rename "Dự trù PRO"→"Ngân sách PRO" (row+badge) ×2 app SHA256-mirror.
- ⚠️ **Workflow: FE+reviewer return RỖNG** (#53 die-empty trong fan-out) → em main recover-disk + self-gate: build ×3 PASS + mirror SHA256 + grep rename → **bắt badge "DỰ TRÙ PRO" sót** (agent đổi row label 1120/1126 nhưng sót badge 1078) → vá ×2 app.
### #294 (`ec517f7`) — Gốc cây "SOLUTION COMPANY"
- Anh: "để SOLUTION COMPANY rồi fan-out xuống phòng ban". Gộp nút "Tất cả phòng ban" + list phẳng thành 1 node gốc công ty (chevron `companyOpen` mở mặc định + bấm tên = pickDept(null) tất cả + CountBadge tổng) chứa phòng ban TreeNode depth=1 toả xuống (cha-con giống NamGroup "Nam Group").
### #295 (`456c7a7`) — Employee refine 2-cột + tô màu (🩷 designer)
- Anh góp ý live (screenshot eoffice): (1) layout 2 cột giống NamGroup gốc — cột TRÁI dọc = cây tổ chức (trên) + danh sách NV (dưới) chồng nhau · cột PHẢI = chi tiết rộng; (2)+(3) chữ đen đơn điệu → tô màu accent panel chi tiết (icon-chip/heading-700/rail/nhãn brand-tint).
- Designer (return ĐẦY ĐỦ lần này) tự bắt 2 bug: accent `-800` không tồn tại palette → `-700`; rail `before:content` thiếu.
## Lessons / insight
- **Workflow fan-out THẬT lần đầu** (`feedback_workflow_fanout_reliability`): parallelism thật (BE∥FE file-disjoint) NHƯNG return-reliability kém (2/3 empty #53) + reviewer-stage không tin được → verify-heavy prod task em main VẪN tự gác = tương đương spawn lẻ. Chọn tool theo bản chất task.
- **gotcha #65:** build csproj con ≠ `dotnet build slnx` (gồm tests) → miss test-compile khi đổi chữ ký command. Trailing-optional `=null` (HoSoLink) backward-compat vs positional-required (ParentId) vỡ test.
- **Policy-based authz** (`Hrm_HoSo.Read` qua MenuPermissionHandler) = mở quyền 1 phát cả menu+API, tránh gotcha #44.
- HRM module port từ NamGroup nên Employee model+5-satellite ~90% sẵn → "giống NamGroup" = re-skin + org-tree, không build mới.
## State sau S65
- **Mig 52** (51 AddDepartmentParentId + 52 AddHoSoLink — cả 2 AddColumn-only) · **88 bảng** · **263 test** (45D+218I, unchanged test-after defer) · **65 gotcha** · **menu 53**.
- Bundle final: admin **`BDwV5d0X`** / user **`DbVv6rsf`** (Run #295).
- HARVEST: H2 GATE 🟡 2-MISS (PE-Workflow FE+reviewer empty) → 2 on-behalf record APPEND. H1 tooling CLEAN (roster/skill/plugin), docs count-flush Mig 50→52. cicd-monitor L1 **82KB over-cap P1** (next-session curate).
## Carry → next session
- Mirror Employee page (+ gốc SOLUTION COMPANY + màu) sang **fe-admin** (fe-user only).
- test-after: HoSoLink + Department.ParentId/cycle-guard + HRM-permission seed.
- 🔴 cicd-monitor 82KB curate-L2 P1 · ef-core SKILL Mig flush · docs/CLAUDE.md full · schema-diagram §16+ ERD (monthly).
- Ops anh (S58/S59 carry): tzutil · anh Chương typo · 5 staff password · gán CNTT.