Files
solution-erp/docs/changelog/sessions/2026-06-11-S57bis-pe-workitem-perm-golive-prep.md
pqhuy1987 dd117b749c
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
[CLAUDE] PurchaseEvaluation: PE gắn Hạng mục công việc (Mig 49) + mở quyền Pe all-role + menu Cá nhân + khóa 14 demo user
Sếp chốt deadline 15:00 (Zalo 11:02-11:17): flow tạo phiếu chọn quy trình → dự án → HẠNG MỤC → NCC/TP; phiếu dạng «Dự án – Hạng mục»; all-user thấy Duyệt NCC + master config; clear data cũ.

- Mig 49 AddWorkItemToPurchaseEvaluation: PE.WorkItemId Guid? loose-Guid + index (KHÔNG FK vật lý — convention PE, database-agent design). Validator NotEmpty (create) + FK-guard AnyAsync(IsActive) → Conflict + UpdateDraft NULL-SAFE (client không gửi → giữ, chống null-hóa bug-class S42). 3 projection ListItemDto LEFT-join WorkItems.
- FE ×2 app: PeWorkspaceCreateView select «c. Hạng mục *» + PeHeaderForm (load existing + PUT gửi lại, SHA256 IDENTICAL) + PeDetailTabs (header «Dự án – Hạng mục» + FormRow + inline khóa) + types. Route reuse /catalogs/work-items.
- Perm: SeedAllRolesReviewReadPermissionsAsync extend Pe_* 11 key (factory — Pe leaf không nằm All) CanRead+CanCreate upgrade-only mọi role; PeWf_*/AwV2 GIỮ Admin. HRM/Office/Master/Catalogs CanRead (S57). Master write-lock Admin,CatalogManager ×3 controller.
- Menu «Cá nhân» (Personal root 30, mirror Puro) + Chấm công re-parent + HrmConfig→Master + parentBackfill idempotent + admin bỏ ẩn Master (đảo S29).
- LockDemoSampleUsersAsync: khóa 14/16 sample (GIỮ nv.cao+nv.truong IT-pool + catalog.manager) — ungated idempotent, IsActive=0+Lockout+SecurityStamp rotate.
- Tests +12 PeWorkItemGuardTests (validator/FK-guard/null-safe) → 240 PASS. npm ×2 + BE 0W/0E.
- Excel (3) đối chiếu: 62/71/3 identical S55 — no data change.
- Gate: em main evidence-checklist (2 reviewer-spawn die-0-byte — resume-kill; backstop 12 guard-test + authz-key/role-string/Mig-49 evidence-lệnh).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 12:13:26 +07:00

5.7 KiB
Raw Blame History

S57bis (2026-06-11) — PE gắn Hạng mục công việc (Mig 49) + mở quyền all-role + menu "Cá nhân" + khóa demo user + Harness-4 runtime-VERIFIED

Bối cảnh: sếp chốt qua Zalo 11:02-11:17 (deadline 15:00 cùng ngày): (1) kiểm tra mapping master data ngoài eoffice; (2) phân quyền TẤT CẢ user thấy Duyệt NCC + cấu hình master data; (3) flow tạo phiếu: chọn quy trình → chọn dự án → chọn hạng mục công việc → chọn/nhập NCC/TP → chuyển duyệt, phiếu dạng "Dự án (năm) Hạng mục công việc"; (4) clear dữ liệu cũ. Anh chốt scope qua AskUserQuestion: xóa demo = CHỈ khóa user sample · quyền PE = Xem + Tạo · hạng mục = header phiếu, 1 phiếu 1 hạng mục.

Việc đã làm

A — Đối chiếu Excel (3) vs master data S55: NO-CHANGE

  • Python openpyxl dump 7 sheet → diff vs scripts/master-import-data.generated.md: 62 Projects + 71 WorkItems (16VT/30TP/9MEP/16TB) + 3 Suppliers identical 100%. 2 sheet hợp đồng = catalog tham khảo, không thuộc DB. Không patch gì.

C — PE gắn Hạng mục công việc (Mig 49 AddWorkItemToPurchaseEvaluation)

  • Design (🔵 database-agent introspect LocalDB): PurchaseEvaluations.WorkItemId Guid? scalar loose-Guid + index, KHÔNG FK vật lý — nhất quán convention PE (ProjectId/SelectedSupplierId đều loose; duy nhất ApprovalWorkflowId có FK). Guard = validator + handler (mirror S43 FK-invariant). WorkItems = catalog GLOBAL (không ProjectId) → 2 dropdown độc lập; "Dự án (năm) Hạng mục" = chuỗi ghép hiển thị. KHÔNG đụng CodeSequences (mã phiếu giữ PE/{YYYY}/{A|B}/{Seq}).
  • BE: entity + config index + Mig 49 3-file (AddColumn nullable + CreateIndex, Down reversible) + Create/UpdateDraft command WorkItemId + validator NotEmpty (create bắt buộc; DB nullable backward-compat 4 phiếu cũ) + FK-guard AnyAsync(w.Id==x && w.IsActive) → Conflict + UpdateDraft null-safe (if (request.WorkItemId is not null) — client không gửi → GIỮ, chống null-hóa bug-class S42) + 3 projection ListItemDto (List/Inbox/CreateContractFrom) LEFT-join WorkItems.
  • FE ×2 app (logic-identical, PeHeaderForm SHA256 IDENTICAL): PeWorkspaceCreateView select "c. Hạng mục công việc *" sau Dự án (option [Category] Code — Name, canSubmit require) + PeHeaderForm (select + load existing + PUT/POST gửi workItemId) + PeDetailTabs (header subtitle "Dự án Hạng mục" + FormRow display + inline-edit khóa) + types +3 field. Route reuse /catalogs/work-items (không endpoint mới).
  • 🟪 Test +12 (PeWorkItemGuardTests): 228→240 PASS. Validator 3 + create-FK-guard 4 + update-null-safe 5. Finding: NotEmpty() trên Guid? không chặn Guid.Empty → FK-guard handler bắt (defense-in-depth, locked 2 test).

B — Mở quyền all-role (extend S57-WIP SeedAllRolesReviewReadPermissionsAsync)

  • Pe_ (11 key: root + 5 leaf × 2 type, build qua factory vì Pe_ leaf KHÔNG nằm MenuKeys.All — recon catch):** CanRead+CanCreate=true mọi role, upgrade-only (row cũ 7 role nâng cờ false→true, KHÔNG hạ, KHÔNG đụng Update/Delete). PeWf_*/AwV2/PeWorkflows GIỮ Admin (prefix Pe_ không match — ký tự thứ 3).
  • HRM/Office/Personal/Master/Catalogs: CanRead-only skip-existing (S57 giữ nguyên). PE controller [Authorize] class-level → mở menu không silent-403 (gotcha #44 không áp).

D — Khóa 14/16 demo sample user (LockDemoSampleUsersAsync)

  • Ungated idempotent NGAY trong DbInitializer (sau SeedDemoUsers + SeedItDepartmentStaff) → tự áp prod khi deploy, bền mọi startup. IsActive=0 + LockoutEnabled + LockoutEnd=Max + SecurityStamp rotate.
  • GIỮ ACTIVE có chủ đích: nv.cao + nv.truong (IT helpdesk round-robin pool S52 — khóa nốt SAU khi anh gán user thật vào dept IT, ops-pending S56) + catalog.manager (account chức năng).

S57-WIP ship kèm (từ 06-10, đã nằm working tree)

  • Menu nhóm "Cá nhân" (Personal root order 30, mirror Puro) + Chấm công re-parent Off→Personal + HrmConfig re-parent Hrm→Master + HrmDashboard order 1 + Contracts 30→31 + parentBackfill idempotent + admin bỏ ẩn Master (đảo S29) + Master write-lock [Authorize(Roles="Admin,CatalogManager")] ×3 controller.

Harness-4 closeout (governance, commit riêng)

  • Spawn-test 2 chiều post-restart PASS: H1 tooling-auditor (demote pin) self-report claude-opus-4-8[1m] + H2 harvest-curator (promote inherit) self-report claude-fable-5[1m] → nấc RUNTIME-VERIFIED 06-11 (adap-report §2/§5 + STATUS row promoted; [1m] 1M-resolve SE tự verify). Email update 2026-06-11-se-to-ai_infra-harness-4-runtime-verified (honest n=1/chiều; hmw.js executed-file giữ). Lesson env: CCD cache agent frontmatter — restart CLI mới ăn (proved 2 data-point 06-10/06-11).

Multi-agent & lessons

  • HMW-mode ON carry từ S55. Fan-out: 2 monitor (kiêm spawn-test) + 2 recon (investigator-codebase catch Pe_*-leaf-not-in-All + database-agent design Mig 49) + 2 builder + test-specialist + reviewer ×2.
  • ⚠️ 2 builder return-truncated giữa task (gotcha #53 — BE chết trước projection-3/migration, FE chết giữa mirror fe-admin) → em main solo vá cross-stack (disk/git truth, không tin return): fix CS7036 + CS8019 + Mig 49 + null-safe + mirror 7 edits PeHeaderForm + 3 edits PeDetailTabs ×2 app. Reviewer email-gate đầu cũng mất tích → gộp 1 gate trọn cuối.
  • Excel (3) đối chiếu bằng raw-dump trước parse (tránh lặp data-quality trap S55 MEP-col).