Commit Graph

177 Commits

Author SHA1 Message Date
37752eb914 [CLAUDE] FE: Hồ sơ NS — tên NV đen→trắng (ép text-white! thắng rule h1-h4 ngoài @layer, Tailwind v4) + thu nhỏ text-lg font-bold — x2 app SHA256
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 19:54:46 +07:00
6983609c7b [CLAUDE] FE: Hồ sơ NS — header chi tiết NV nổi bật (tên text-xl extrabold + drop-shadow · meta 13px font-medium trắng · badge trạng thái màu emerald/amber/slate) — x2 app SHA256
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m48s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 19:34:35 +07:00
536dd6b569 [CLAUDE] FE-PE: Link hồ sơ ổ mạng — render link file:// bấm-thử mở Explorer + giữ Copy dự phòng (x2 app SHA256)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m38s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:52:25 +07:00
6df1b2d7c1 [CLAUDE] FE-PE: Link hồ sơ auto-detect — http(s) -> hyperlink bấm-mở / đường dẫn ổ mạng -> chữ + nút Copy (x2 app SHA256)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m22s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:28:51 +07:00
91aaf058fb [CLAUDE] FE: Hồ sơ NS — list pane flex-row gọn (hết tràn ngang rail) + đồng nhất cỡ chữ (x2 app SHA256)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:20:23 +07:00
ab4e681e8e [CLAUDE] FE-User: Hồ sơ NS — đồng nhất font/size + chữ đen sang xanh đậm (brand-800)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:41:33 +07:00
456c7a721b [CLAUDE] FE-User: Hồ sơ Nhân sự — layout 2 cột (tree+list trái, detail phải) + tô màu chi tiết
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m19s
Anh góp ý từ eoffice live (3 việc): (1) layout 2 cột giống NamGroup — 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 (panel
list chuyển từ giữa xuống dưới tree); (2)+(3) tô màu panel chi tiết — hệ accent 5 tone
(brand/teal/violet/amberx/greenx) icon-chip + heading -700 + rail màu + nhãn field
brand-tint (trước slate-400 đơn điệu). Responsive <lg = 1 cột.
GIỮ 100%: 5 satellite CRUD (16 endpoint), cây SOLUTION COMPANY, 5 tab, search/filter,
query keys (grep + tsc verified). Build PASS fe-user. Designer tự bắt 2 bug (accent -800
không tồn tại palette -> -700; rail before:content). fe-admin mirror defer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:35:31 +07:00
ec517f7174 [CLAUDE] FE-User: cây tổ chức gốc "SOLUTION COMPANY" -> toả xuống phòng ban
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
Anh: hiển thị cha-con với gốc SOLUTION COMPANY trên cùng, phòng ban fan-out xuống
(giống NamGroup "Nam Group" là gốc). Gộp nút "Tất cả phòng ban" + list phẳng thành
1 node gốc công ty trong EmployeesListPage org-tree panel: chevron mở/gập
(companyOpen, mở mặc định) + bấm tên = pickDept(null) tất cả NV + CountBadge tổng;
các phòng ban render TreeNode depth=1 toả xuống dưới. Build PASS fe-user (tsc -b).
fe-user only (mirror fe-admin defer cùng Phase B).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:23:58 +07:00
5a0aaa4e83 [CLAUDE] PurchaseEvaluation: +mục E "Link hồ sơ" (hyperlink NAS) + rename "Dự trù PRO"->"Ngân sách PRO"
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m25s
Anh Kiệt (FDC UAT): (1) thêm mục "e. Link hồ sơ" dưới mục "d. Bản so sánh" — 1 ô dán
hyperlink tới thư mục hồ sơ trên NAS công ty, hiện dạng <a> bấm-mở (target _blank rel
noopener noreferrer), null-safe; (2) đổi nhãn "Dự trù PRO"->"Ngân sách PRO" (cả badge
+ row label; GIỮ "Ghi chú từ PRO" + field-code/biến).
- BE: PurchaseEvaluation +HoSoLink string? (Mig AddHoSoLinkToPurchaseEvaluation —
  nvarchar(1000) nullable, no new table, Down reversible) + Create/Update command
  (+trailing optional =null -> backward-compat, 0 call-site break) + Detail DTO + projection.
  Build slnx PASS.
- FE x2 app SHA256 mirror (PeDetailTabs + PeWorkspaceCreateView): mục E input/hyperlink +
  rename. types +hoSoLink.
Workflow fan-out (BE song song FE -> review); FE+reviewer return-rỗng -> em main recover
disk + build-verify x3 + self-gate (bắt badge sót rename).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:13:39 +07:00
318860a38e [CLAUDE] FE-User: Hồ sơ Nhân sự master-detail 3-panel + 5 tab (giống NamGroup)
Anh: bố trí Hồ sơ Nhân sự giống NamGroup HRM. Dựng lại EmployeesListPage:
- Panel trái: cây tổ chức (consume GET /departments/tree) — expand/collapse + badge
  số đếm (totalEmployeeCount) + click lọc theo phòng. Co thành toggle màn hẹp.
- Panel giữa: list (search + status filter) + avatar gradient + status badge.
- Panel phải: chi tiết 5 tab (Tổng quan/Thân nhân/Trình độ/Kinh nghiệm/Hợp đồng) +
  avatar header lớn (gradient brand). Tổng quan 2 cột.
GIỮ 100% 5 satellite CRUD (16 endpoint byte-identical grep-verified) + search + filter
+ query keys. Foundation màu mới + brand #1F7DC1 giữ. Build PASS (tsc -b). fe-admin mirror defer.
(frontend-designer return-rỗng/#53 → em main recover từ disk + build-verify + self-gate.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:13:39 +07:00
c98030f27c [CLAUDE] FE-User: redesign foundation "nâng màu giữ brand" — gradient/accent/badge bắt mắt hơn
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
Anh: giao diện đơn điệu, muốn đẹp + bắt mắt, font/màu đẹp hơn. Hướng anh chốt
"nâng màu, giữ nền xanh brand" (eoffice trước). Foundation lan tỏa toàn app, KHÔNG
đụng 65 trang lẻ.
- index.css: +accent palette teal/amberx/violet/greenx (đặt tên né trùng Tailwind)
  + utilities .app-gradient-brand / .card-accent / .icon-chip / .stat-value;
  heading 600->700 đậm hơn; .label-eyebrow brand-600. Brand #1F7DC1 + Be Vietnam Pro GIỮ.
- primitives: Button primary/danger gradient nổi bật; Input/Select/Textarea focus-glow
  mạnh hơn; Label brand-600; Dialog title-bar gradient. variant/size keys STABLE.
- shell: Layout stripe dày hơn + logo cap; PageHeader title lớn/đậm + accent bar cao;
  TopBar gradient hairline; DataTable thead gradient brand chữ trắng.
- Dashboard: KPI cards accent + icon chips.
- color maps (contract/PE phase + PE display status): -700->-800 đậm chữ, phase nháp tint brand.

Visual-only — props/handler/signature nguyên. Build PASS (tsc -b 0 error). a11y:
contrast AA + prefers-reduced-motion. fe-admin mirror đợt sau.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:12:40 +07:00
7926c2129c [CLAUDE] PurchaseEvaluation: cho luu khi vuot ngan sach - chi canh bao mem (bo chan so am "Gia tri thuc hien du kien con lai") (UAT anh Kiet S62)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m40s
- Root cause: o "Gia tri thuc hien du kien con lai" (row 8 bang Tong hop ngan sach) khi gia tri NCC vuot ngan sach -> so du con lai ra AM; BE validator ExpectedRemainingAmount>=0 + FE VndInlineEdit khong bat allowNegative -> chan cung "am ko luu duoc" (testing bao qua anh Kiet)
- BE: AdjustPurchaseEvaluationBudgetCommandValidator GO rule ExpectedRemainingAmount.GreaterThanOrEqualTo(0) -> cho luu so am (mirror tien le LeaveBalance AllowsNegativeRemaining). GIU BudgetPeriodAmount>0 + submit-guard "da nhap NS ky nay" khong doi
- FE x2 app SHA256 identical: (a) allowNegative cho VndInlineEdit row 8; (b) banner amber "Vuot ngan sach - van luu & gui duyet duoc" trong PeBudgetSummaryTable khi cmpPeriod<0 || cmpFull<0. Tang to mau do cu GIU NGUYEN
- Spec change: flip test AdjustBudget_Validator_ExpectedRemainingNegative_FailsValidation -> _PassesValidation (am gio hop le); test BudgetPeriodZero_FailsValidation GIU (budget>0 van enforced)
- Build FE x2 PASS + test 263 PASS (45 Domain + 218 Infra, 0 fail/skip). Reviewer PASS 0 issue (row8 am an toan arithmetic additive-only, submit guard nguyen, mirror byte-identical, no scope creep)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 11:13:10 +07:00
79ef8da9f4 [CLAUDE] PurchaseEvaluation: ngan sach goi thau theo Excel anh Kiet - bang tong hop 2 block + nhap theo role PRO/CCM + xoa module Budget cu (Mig 50)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m31s
- Mig 50 ReplaceBudgetModuleWithPeWorkItemBudgets: bang moi PeWorkItemBudgets (1 record/cap Du an x Hang muc, UNIQUE filtered [IsDeleted]=0) + drop 5 bang Budget cu + PE/Contracts drop BudgetId + backfill BudgetManualAmount->BudgetPeriodAmount TRUOC DropColumn (phieu UAT giu so) + DELETE menu/permission Bg_* IN-list children-first
- BE: PUT {id}/budget/pro (role Procurement) + {id}/budget/ccm (role CostControl, Adjustment cho phep AM) fail-closed Forbidden-truoc-side-effect + EnsureTrackedAsync race-safe (catch unique -> re-fetch winner, loi khac rethrow) + auto-create record khi tao phieu + budgetSummary DTO (luy ke trinh-truoc/chon-thau-truoc/de-xuat-ky-nay + full fallback du-tru-PRO + canEdit flags) + submit-guard (3) doi predicate BudgetPeriodAmount -> "chua nhap Ngan sach ky nay" + PATCH budget-adjust absolute-set 2 field moi + Contract GIU BudgetManual* (HD nhap tay khong doi) + ke thua HD map BudgetPeriodAmount
- FE x2 app SHA256 identical: bang "TONG HOP NGAN SACH TRINH KY" block A (full dam + ban hanh + V0 hieu chinh + du tru PRO + ghi chu, editable theo canEditPro/canEditCcm) + block B 9 dong cong thuc Excel (5=1+3, 6=2+4, 7=full-5, 8 tu nhap default 7, 9=4+8) + to mau vuot ngan sach #C00000 / am do / red-soft row8>row7 + "Chua chon" khi count=0 + banner phieu chua gan Hang muc + o "Ngan sach ky nay" o create/header + XOA pages/components/types budgets + routes + menuKeys + Layout staticMap 4-place
- Tests: +22 PeWorkItemBudgetTests (auto-create x3, ensure/race x2, authz matrix PRO x5 + CCM x3, budgetSummary aggregates x5, adjust x4) - 14 BudgetPolicyTests xoa theo module - 1 test via-BudgetId -> 263 PASS (45 Domain + 218 Infra, 0 fail)
- database-agent advise adopted: khong FK vat ly PE/Contracts->Budgets (DropColumn khong can DropForeignKey) + DropIndex truoc DropColumn (SQL 5074) + IN-list thay LIKE Bg_% (underscore wildcard + miss root) + khong Serializable wrap (nested-tx conflict codegen)
- Reviewer PASS-with-minor 0 blocker (verdict-first survived); 2 minor da sua truoc commit (comment adjustMut absolute-set + dead key budgetId); note: F4 approver-edit-budget UI entry tam drafter-only, BE van cho approver scope - cho UAT anh Kiet
- Scaffold-bug caught: EF tu sinh RenameColumn BudgetManualAmount->ExpectedRemainingAmount (SAI semantics) -> thay bang Add+UPDATE+Drop

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 01:07:27 +07:00
6db195dd42 [CLAUDE] PurchaseEvaluation: go han hanh dong "Tu choi" - chi con Duyet hoac Tra lai (UAT anh Kiet S60 14:14)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
- Domain policy: xoa MOI transition -> TuChoi o ca 4 policy (NccOnly + NccWithPlan + ForV2Schema + FromDefinition) -> NextPhases het tra TuChoi, nut FE tu bien mat
- Service guard S60: chan targetPhase=TuChoi moi caller ke ca Admin (dung truoc moi branch — spec bo han, khong escape hatch); message huong dan dung Tra lai / Xoa nhap
- FE x2 app: filter phong thu next.filter(p != TuChoi) PeWorkflowPanel (SHA256 identical); dialog/isCancel giu dead-safe de flip lai de
- Enum TuChoi + phieu TuChoi cu + tab filter "Tu choi" GIU display (data cu render binh thuong)
- SlaExpiryJob chi dung Contract — PE khong auto-TuChoi, khong anh huong
- Tests spec-change cung commit: Domain flip BothPolicies_TuChoi_RemovedFromAllTransitions_S60 + NEW V2SchemaPolicy fact; Infra NEW TargetTuChoi_WithRejectDecision_Throws_TuChoiRemoved_S60 (guard #45 test cu giu nguyen PASS — van dung truoc)
- Test 254 -> 256 PASS (59 Domain + 197 Infra)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:30:38 +07:00
37122f0f64 [CLAUDE] PurchaseEvaluation: rang buoc du 4 thong tin muc 3 moi gui duyet + bypass nguoi soan trong chuoi duyet (UAT anh Kiet S60)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m38s
- Rename muc 3: "Chon NCC / TP thang thau" -> "Don vi NCC/TP duoc chon" (anh Kiet chot chu) x2 app + wording phu nhat quan
- Guard gui duyet du CA 4 (anh chot): don vi duoc chon + gia chao thau >0 + ngan sach (Budget link HOAC nhap tay) + bang so sanh dinh kem
  + BE ConflictException gop moi muc thieu 1 lan, ap ca Admin (TransitionAsync submit branch)
  + FE pre-check missingForApproval cung predicate -> disable nut + tooltip liet ke du (computeGiaChaoThau extract single-source)
- Bypass drafter-in-chain (luat GENERIC theo cap, anh chot): V2-only, BUOC DAU only - nguoi soan la approver cap k -> auto qua Cap 1..k khi gui
  + Audit 3 tang: Approval row AutoApprove per cap + LevelOpinion CHI slot chinh chu (khong gan chu ky NV bi skip) + Changelog
  + Pointer: k<max -> Cap k+1; het buoc -> Buoc 2 Cap 1; workflow 1 buoc -> terminal DaDuyet
  + TraLai resubmit ap lai idempotent (opinion UPSERT)
- Tests: +14 PeSubmitGuardAndBypassTests (240 -> 254 PASS)
- Reviewer die mid-run (gotcha #53 class) -> em main self-gate evidence-checklist PASS 0 blocker

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:53:50 +07:00
792c0307e9 [CLAUDE] PurchaseEvaluation: bo nut "+ Them hang muc" Section 2 (UAT vong 6 - anh chot)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m0s
- 1 phieu = 1 hang muc chon tu header (S57bis/S58, hang muc dau auto-seed khi tao
  phieu) -> nut them hang muc thu 2+ sai mo hinh nghiep vu, go khoi ItemsTab header.
- AddItemDialog giu (dead code) de flip lai de neu doi y.
- SHA256 mirror x2 app IDENTICAL, build x2 PASS.
2026-06-11 18:37:27 +07:00
80b64dd514 [CLAUDE] PurchaseEvaluation: go field "Dieu khoan thanh toan" khoi TAT CA form phieu (UAT vong 5 - anh chot "bo not ra luon tat ca cac form")
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
- PeWorkspaceCreateView: bo Select preset + Textarea custom + PAYMENT_PRESETS/
  PAYMENT_CUSTOM/paymentMode drop, payload paymentTerms: null.
- PeHeaderForm + PeDetailTabs inline-edit: bo Textarea; state paymentTerms GIU
  (load tu phieu cu + save giu nguyen -> data cu KHONG mat, van hien read-only).
- GIU cot "Dieu khoan TT" per-NCC trong bang so sanh (data tung NCC, khac field).
- SHA256 mirror x2 app IDENTICAL, build tsc+vite x2 PASS.
2026-06-11 18:33:33 +07:00
69997da74f [CLAUDE] PurchaseEvaluation: bo o "Ten ngan sach" o manual budget (UAT vong 4 - anh chot "cho ten ngan sach bo di nhe")
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m23s
- PeDetailTabs Section 5 Dieu chinh ngan sach: bo input "Ten (khong bat buoc)"
  (user khong hieu "y nghia du phong la gi") - manual budget chi con So tien (VND).
  State manualName drop, payload budgetManualName: null. Ten cu phieu truoc van
  hien read-only, ve null khi Luu dieu chinh lan toi.
- PeHeaderForm: payload budgetManualName null + hasManual detect theo CA amount
  (phieu moi name=null sau khi bo o Ten -> van nhan dung manual mode).
- PeWorkspaceCreateView: khong doi (chua tung co o Ten, payload '' || null = null san).
- SHA256 mirror x2 app IDENTICAL, build tsc+vite x2 PASS.
2026-06-11 18:22:26 +07:00
f21c55d04a [CLAUDE] PurchaseEvaluation: bang NCC tham gia table-fixed + width tung cot (UAT vong 3 - "them file giao dien bi thay doi khong can xung")
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
- Bang NCC trong HangMucCard dung auto-layout -> cell File (chip ten file dai) phinh,
  bop doc cot NCC tung chu. Fix: table-fixed + w-% tung cot (NCC 24 / SDT 9 / Email 14 /
  DKTT 14 / File 22 / So tien 12 / action w-10) + min-w-[860px] (panel hep -> scroll
  ngang qua wrapper overflow-x-auto thay vi bop nat) + email span block truncate.
- Chip file/email truncate san - kich hoat khi cell khoa width.
- SHA256 mirror x2 app IDENTICAL, build tsc+vite x2 PASS.
2026-06-11 18:17:56 +07:00
9c330d26c4 [CLAUDE] PurchaseEvaluation: UAT dot 2 - an Tra lai/Tu choi khi tu duyet phieu minh soan + quick-add NCC ngay form + NCC go-tim sort A-Z + upload nhieu file 1 lan
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m25s
- PeWorkflowPanel x2: nguoi duyet == nguoi soan (drafterUserId == currentUser.id)
  -> an ca "Tra lai" + "Tu choi" (anh chot: tra cho chinh minh vo nghia, huy phieu
  = nho cap khac tu choi / xoa phieu Nhap).
- SuppliersController: POST tao NCC mo cho moi user dang nhap (anh chot - nghiep vu
  di thau phat sinh NTP moi lien tuc); PUT/DELETE van khoa Admin+CatalogManager (S57).
- PeDetailTabs AddSupplierDialog x2: Select -> SearchableSelect (go-tim bo dau,
  sort A-Z theo ma) + nut "+ NCC moi" quick-create (Ma/Ten/Loai/SDT/Email) ->
  POST /suppliers -> auto-select vao phieu.
- Upload file bao gia + bang so sanh x2: input multiple + upload tuan tu tung file
  (UAT "moi lan chi chon duoc 1 file").
- SHA256 mirror x2 app, build tsc+vite x2 PASS, BE 0 err, test 240/240 PASS local.
2026-06-11 17:51:28 +07:00
faed59f4c4 [CLAUDE] FE-Admin+FE-User: UX form tao phieu theo UAT feedback - combobox go-de-loc (Hang muc + Du an) + auto dia diem + dieu khoan da dong
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m31s
- NEW ui/SearchableSelect: combobox tu render, go loc theo label, match BO DAU
  tieng Viet (go "be tong" trung "Be tong"), keyboard arrows/Enter/Esc, clear (x),
  style mirror ui/Input density S55. Khong them lib ngoai.
- PeWorkspaceCreateView + PeHeaderForm: Hang muc + Du an doi Select -> SearchableSelect
  (UAT: "nen co loc de tu danh chu" / "nen co tu go chu" - 70+ muc kho do).
- Auto dia diem (UAT "dia chi nen tu auto"): chon Du an tu dien diaDiem tu
  Project.Location (S55), chi ghi de khi user chua go tay (track lastAutoLoc ref).
- Dieu khoan thanh toan nhap tay: Input 1 dong -> Textarea 3 dong (UAT "khong cho
  xuong dong?") o CreateView + PeDetailTabs inline-edit; render detail da pre-wrap san.
- SHA256 mirror x2 app (4 file IDENTICAL), build tsc+vite x2 PASS.
2026-06-11 17:39:17 +07:00
c869d2617d [CLAUDE] PurchaseEvaluation: rename 71 WorkItems theo format PMH anh Kiet FDC chot (MAT-n/SUB-n/MEP-SUB-n/MEP-EQU-n + ten "STT nhom ten") + FE sort numeric
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
- anh Kiet 16:59: "MA CV gom chu MEP-SUB-1 roi ten 1 MEP Sub MEP (Full) - dung kieu vay".
- DbInitializer seed tuples 71 ma moi (VT->MAT, TP->SUB, MEP-0n->MEP-SUB-n, TB->MEP-EQU-n).
- scripts/s59-rename-workitems-pmh.sql DA CHAY prod + LocalDB Dev TRUOC push (UPDATE giu Id,
  71/71, OLD-CODES=0, verify JSON qua API prod tieng Viet nguyen ven).
- FE x2 app (SHA256 mirror): PeWorkspaceCreateView + PeHeaderForm sort numeric-aware
  (ma khong pad -> string-sort loan "10"<"2") + tree Panel 1 workItemName numeric:true.
- scripts/master-import-data.generated.md sync 71 dong W| + note mapping.
2026-06-11 17:14:06 +07:00
0eafcd36e7 [CLAUDE] PurchaseEvaluation: tree Panel 1 chot 4 tang "Nam > Du an > Hang muc cong viec > Phieu" (anh chot follow-up, SHA256 mirror x2 app)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m51s
- Doi tu "Du an (Nam)" gop 1 node -> Nam la tang ngoai cung (DESC, bg-slate-50),
  trong Nam chua Du an (A-Z vi), trong Du an chua Hang muc cong viec, roi phieu.
- yearGroups useMemo thay projectGroups + expand-state localStorage key v3.
- Build x2 PASS, SHA256 mirror identical 95D524EE.
2026-06-11 16:36:59 +07:00
56882acc4f [CLAUDE] PurchaseEvaluation: tree Panel 1 doi nhom theo anh Kiet FDC "Du an (Nam) > Hang muc cong viec > Phieu" (bo tang NCC, SHA256 mirror x2 app) + wipe testing data prod S59
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m27s
- Tree Panel 1: moi cap (Du an, Nam-tao-phieu) = 1 folder label "Ten du an (Nam)",
  level 2 = Hang muc cong viec (WorkItemId Mig 49, phieu cu null -> "(Chua gan hang muc)"),
  bo tang NCC khoi tree (van hien o card/detail). Expand-state localStorage key v2.
- scripts/s59-wipe-testing-data.sql DA CHAY prod (anh chot AskUserQuestion): xoa 10 PE
  + 7 HD [DEMO] + 64 notif + 1 workflow V2 cu inactive; reset PeSeq/CtSeq -> ma moi tu 001;
  GIU master 70/86/22 + users 55 + templates 9 + 7 workflow ghim. Uploads orphan da don.
2026-06-11 15:35:25 +07:00
3ebaf84531 [CLAUDE] PurchaseEvaluation: gop Ten goi thau = chon Hang muc cong viec (anh Kiet FDC chot 14:06) - 1 select set ca workItemId + tenGoiThau, phieu cu giu-nguyen null-safe, SHA256 mirror x2 app (S58)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
2026-06-11 14:14:15 +07:00
ea793a43fa [CLAUDE] FE-Admin+FE-User: brand-accent polish x2 app - stripe dinh app + logo zone tint + PageHeader accent bar + thead brand (S58, anh yeu cau trang tri ro hon)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
2026-06-11 14:10:00 +07:00
e959f72916 [CLAUDE] FE-User: redesign density-first theo UI/UX guide AI_INFRA — giữ brand SOLUTION (S58)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
Anh yêu cầu sau /check-email ai_infra (guide canonical 13 mục "Surgical
Precision Minimalism", anh-approved 06-11): chỉnh giao diện eoffice giống
guide, GIỮ nhận dạng thương hiệu SOLUTION.

14 file fe-user, visual-only (mirror design system fe-admin S55 + đối chiếu
guide; fe-admin/BE untouched):
- index.css: heading ladder semibold (bỏ font-bold) + .label-eyebrow uppercase
  + tnum note. 6 ui primitives (Button/Input/Label/Select/Textarea/Dialog):
  text-xs font-semibold, control h28-40, rounded-lg, focus ring brand-500,
  bỏ shadow trang trí — variant/size keys + props/forwardRef STABLE.
- 6 shell: DataTable (thead sticky + density px-3 py-2 + tnum + RowActions/
  RowActionButton ADDITIVE luôn-hiện không opacity-hover) / Layout (active
  leaf brand left-rail, logic nav/permission nguyên) / TopBar / PageHeader /
  PhaseBadge (ring-current/15) / EmptyState. + LoginPage polish nhẹ.
- BRAND GIỮ: #1F7DC1 (brand-*) + Be Vietnam Pro + neutral slate (guide cho
  plug hue riêng — chia sẻ grammar, không chia sẻ vocabulary-màu).

Verify: npm build ×2 PASS 0 TS err (fe-user 443ms + fe-admin 8.9s untouched-
confirm). Diff-review từng file: functionality keys stable, additive-only.
frontend-designer return-truncated gotcha #53 giữa FD2 screenshot → em main
disk-recover + self-gate (precedent S55); visual live-check sau deploy.

Email AI_INFRA 2026-06-11-ui-ux-design-guide: inbox copy verified hash ✓✓
(whole-file + body), processed sau commit này.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:51:10 +07:00
dd117b749c [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
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m24s
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
69cb3937bb [CLAUDE] Master: nạp master data thật từ Excel (62 dự án + 71 hạng mục + 3 NCC) + Project +4 cột (Mig 48)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m33s
Nạp master data công ty từ file Excel 'HẠNG MỤC CÔNG VIỆC DỰ ÁN':
- 62 Projects (Mã + Năm; tên/CĐT/địa điểm/gói thầu cho ~6 dự án có chi tiết)
- 71 WorkItems: Vật tư 16 · Thầu phụ 30 · MEP 9 · Thiết bị 16
- 3 Suppliers (TRUONGGIANG/TANPHU/TGN)

Mig 48 AddProjectMasterFields: Project +4 cột nullable (Year/Investor/Location/Package) + ProjectFeatures DTO/Create/Update + ProjectsPage form ×2 app (SHA256 mirror).
SeedRealMasterDataAsync per-code idempotent, UNGATED → reaches prod (coexist demo). FLOCK01 collision → skip (demo wins).

Verify: build 0-err · test 216 PASS · runtime Dev proof (data landed, Investor col populates). Provenance: scripts/master-import-data.generated.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 09:27:04 +07:00
ca4b60277b [CLAUDE] Office: IT staff tự reassign ticket — authz Admin-OR-IT + capability endpoint (S54)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
- BE: GetAssignableItStaffQuery {canReassign,staff} capability endpoint + AssignItTicketHandler authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict); controller /assign hạ [Authorize(Roles=Admin)]→[Authorize] (handler enforce fine-grained data-driven)
- FE: fe-admin + fe-user ItTicketsPage SHA256-identical (reverse S53 divergence), nút gate by canReassign, dropdown từ /assignable-staff (không /users)
- Test: +13 authz guard (203→216 PASS), reviewer PASS (role-string Admin chain-verified real)
- No migration (DepartmentId reuse), no menu change

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:12:14 +07:00
dcf76f8a9f [CLAUDE] Office: P11-D ItTicket auto-assign round-robin + SLA timer (Wave 2, Mig 46)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
Mig 46 AddSlaFieldsToItTicket (SlaDueAt/SlaWarnedSent/SlaBreached). CreateItTicketHandler: round-robin least-loaded assign cho IT staff (dept Code=IT, tie-break Id) + SlaDueAt theo Priority (Urgent 4h/High 8h/Medium 24h/Low 72h). ItTicketSlaJob background (breach+warning notify, KHONG auto-transition). PUT /{id}/assign admin override. DbInitializer seed dept IT + 2 sample staff (nv.cao/nv.truong). FE ItTicketsPage +MaTicket+assignee+SLA badge (2 app SHA256 mirror). +9 test (191->200). Self-review PASS (seed<->query dept-code verified; em main solo review do session-limit kill reviewer-spawn).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 13:23:45 +07:00
30a99aa03f [CLAUDE] Hrm: P11-C Vehicle+Driver catalogs (Mig 44) + gotcha #57 filtered-unique 3 HRM catalog (Mig 45)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m18s
P11-C: extend HrmConfigs +2 kind (Vehicle/Driver) declarative. Mig 44 AddVehicleAndDriverCatalogs (2 table filtered-unique Code, tables 91->93). Domain entity + EF config (filtered day-1) + 2 DbSet + HrmConfigFeatures Region5/6 CRUD + Controller +2 route-group (GET public / write Roles=Admin) + MenuKeys +2 +All (auto Admin perm) + DbInitializer 2 menu leaf + idempotent seed 2 veh/2 drv. FE declarative KIND_CONFIG +2 kind x2 app (SHA256 mirror) + 4-place (types/page/menuKeys/Layout staticMap), :kind-driven no new route.

gotcha #57 (bundled; OtPolicy missed in backlog, caught via grep) - Mig 45 FilterHrmCatalogUniqueIndexesByIsDeleted: LeaveType+ShiftPattern+OtPolicy bare .IsUnique() -> .HasFilter([IsDeleted]=0) (recreate-on-soft-deleted-slot 500 fix, mirror Holiday Mig 43). Tests +5 HrmConfigFilteredUniqueTests (181->186 PASS) test-before RED->GREEN. Reviewer caught FE<->BE Driver required-field mismatch -> fixed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:32:28 +07:00
350b2bfb28 [CLAUDE] FE-Admin/FE-User: login subtitle contrast a11y fix (slate-500 -> 600)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m12s
FD2 spawn-test outcome — login subtitle contrast ~4.6 -> ~7.5:1 over translucent
card (FD5 WCAG-AA floor). On-scale token, no layout shift. Mirror x2 app.
Build x2 PASS, 0 TS error. Test 181 unchanged (FE-only, no .cs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 00:06:18 +07:00
82d7fcff4d [CLAUDE] Workflow: LeaveBalance business logic — trừ phép khi duyệt + số dư (Phase 11 P11-B)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m8s
Số dư phép theo (User × LeaveType × Year) + trừ tự động khi đơn nghỉ duyệt cuối.
Policy: cho phép vượt số dư (âm) + cảnh báo (anh main chốt), tích hợp vào trang đơn nghỉ.

Schema (Mig 42 AddLeaveBalances — pure additive, 1 bảng):
- LeaveBalance: UserId + LeaveTypeId + Year + EntitledDays + UsedDays + AdjustmentDays.
  UNIQUE (UserId,LeaveTypeId,Year), FK LeaveType Restrict, decimal(5,2).
  Remaining = Entitled + Adjustment − Used (computed, không store).

Deduction hook (ApproveLeaveRequestHandler nhánh terminal DaDuyet — exactly-once):
- Upsert LeaveBalance(RequesterUserId, LeaveTypeId, StartDate.Year), auto-create từ
  LeaveType.DaysPerYear, UsedDays += NumDays. Guard Status!=DaGuiDuyet chặn re-approve.

FK invariant guard (em main thêm sau test reveal FK risk):
- Create + UpdateDraft validate LeaveTypeId tồn tại (AnyAsync) → ConflictException.
  Đóng cửa vào — bogus type không thể tới deduction FK insert (tránh 500 kẹt đơn).

CQRS LeaveBalanceFeatures.cs: GetMy (self, lazy merge active LeaveType) + GetUser (admin)
  + AdjustLeaveBalance (admin upsert carry-over). Controller [Authorize] + admin Roles=Admin.
Embed: GetLeaveRequestByIdHandler trả balance NGƯỜI TẠO (approver xem thấy đúng).
FE: WorkflowAppDetailPage ×2 — block "Số dư phép" + cảnh báo vượt khi kind=leave (SHA256 identical).

Tests (+11, 130→154 PASS): deduction single/multi-level/accumulate/negative-allowed/
  reject-return-no-deduct + lazy-merge + adjust upsert + Create guard bogus→Conflict.
  Cũng repair 2 test S42 terminal FK-fail (template BuildLeave +seed LeaveType).

Verify: build 0 error · 154 test · FE ×2 · reviewer Max PASS (deduction exactly-once +
  FK invariant fully closed, 2 minor concurrency/comment defer).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 11:10:44 +07:00
e47ef1d4ee [CLAUDE] FE-User: fix ProposalCreatePage workflow dropdown shape (latent S37 bug)
Follow-up cho bug flagged trong 75df04e. ProposalCreatePage (fe-admin + fe-user)
fetch /approval-workflows-v2 expect flat array, nhưng endpoint trả AwAdminOverviewDto
{types:[{applicableType, history:[...]}]} → workflows.data.map chạy .map trên object
→ TypeError/dropdown rỗng. Latent vì create-with-workflow chưa exercise UAT.

Fix: mirror pattern proven của ContractCreatePage + WorkflowAppDetailPage —
res.data.types.find(t=>t.applicableType===4)?.history.filter(isUserSelectable).
WorkflowDto +isUserSelectable. Render .map giữ nguyên (data giờ là array đúng).

Verify: tsc -b + vite build ×2 PASS (exit 0) · fe-admin/fe-user SHA256 identical
(91565D47...7697C771).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:19:17 +07:00
75df04ec82 [CLAUDE] Workflow: fix workflow picker 2 bug (P11-A Max re-review) + SetWorkflow endpoint
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m5s
Double-check chất lượng P11-A ở Max (agents trước chạy High + truncate 3×) →
phát hiện 2 bug THẬT trong workflow-picker FE của WorkflowAppDetailPage (core
approve/reject/return ĐÚNG, chỉ sub-flow chọn quy trình hỏng):

Bug #1 (HIGH) — pinWorkflow PUT /{id} chỉ gửi {approvalWorkflowId} → UpdateDraft
  validator (Reason NotEmpty, NumDays>0...) fail → 400. Nút "Lưu quy trình" vỡ.
Bug #2 (HIGH) — fetch workflow expect flat array nhưng endpoint trả
  AwAdminOverviewDto {types:[...]} → picker rỗng/crash. FE copy nhầm pattern hỏng
  của ProposalCreatePage thay vì PE/Contract proven.

Fix:
- BE: thêm endpoint chuyên dụng PUT /{id}/workflow + Set{Module}WorkflowCommand/Handler
  cho 4 module — chỉ set ApprovalWorkflowId trên draft Nhap/TraLai (verify ApplicableType
  per module), KHÔNG validate field khác. Single-responsibility, bulletproof.
- FE: sửa fetch mirror PE/Contract (data.types.find(t=>t.applicableType===X)?.history
  .filter(isUserSelectable)) + pin gọi endpoint mới. fe-admin+fe-user SHA256 identical.
- Test: +3 SetWorkflow (happy no-status-change / wrong ApplicableType Conflict / submitted
  guard) → 141→144 PASS.

Verify: BE build 0 error · 144 test PASS · FE build ×2 · SHA256 identical.
Bonus phát hiện: ProposalCreatePage (S37) có bug #2 có sẵn (latent, chưa exercise UAT)
  → flag spawn task riêng, KHÔNG fix trong commit này.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:14:34 +07:00
e7b66cd52b [CLAUDE] Workflow: wire ApproveV2 + LevelOpinions cho 4 WorkflowApps module (Phase 11 P11-A)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m6s
Wire full approval workflow V2 cho Leave/OT/Travel/Vehicle — cookie-cutter
mirror Proposal (Mig 38). Trước đây skeleton Phase 1 (Create+List), giờ
ApproveV2 advance-level + UPSERT LevelOpinion + atomic codegen.

Schema (Mig 41 WireWorkflowAppsApprovalV2 — 84→89 tables, pure additive):
- 4 bảng {Leave,Ot,Travel,Vehicle}LevelOpinions (UNIQUE composite + Cascade
  parent + Restrict Level — mirror ProposalLevelOpinion)
- 1 bảng WorkflowAppCodeSequences (shared atomic MaDonTu, Prefix-keyed)
- 4 cột RejectedFromStatus (smart return tracking)
- enum ApprovalWorkflowApplicableType.TravelRequest = 9

Application (LeaveOt + TravelVehicle ApprovalFeatures.cs — 30 handler):
- GetById detail (Include LevelOpinions + JOIN Step/Level) · UpdateDraft
- Submit (gen MaDonTu + DaGuiDuyet + level=1, verify ApplicableType per module)
- Approve (verify actor==ApproverUserId OR Admin, UPSERT opinion latest-write-wins,
  advance level OR terminal DaDuyet, empty comment → placeholder)
- Reject (→TuChoi) · Return (→TraLai + RejectedFromStatus)

Api: 4 controller +6 route mỗi cái (GET/{id}, PUT/{id}, submit/approve/reject/return)
Infra: DbInitializer seed 4 workflow V2 mẫu (QT-NP/OT/CT/XE-V2-001) → UAT test ngay
FE: WorkflowAppDetailPage.tsx declarative 4-kind (fe-admin+fe-user SHA256 identical)
  — workflow status + opinion timeline + action buttons; gỡ banner skeleton + row nav

Tests: +11 WorkflowAppApproveV2Tests (130→141 PASS) — state machine + UPSERT
  invariant + guards + codegen + forbidden + placeholder (Leave full + Ot smoke)

Verify: build 0 error · 141 test PASS · FE build ×2 · reviewer checklist
  (ApplicableType per-module + cross-module DbSet + [Authorize] — no copy-paste bug)
Known-minor (unreachable): Reject/Return actor-check skip nếu CurrentApprovalLevelOrder
  null — nhưng DaGuiDuyet luôn có set (defer hardening).
ItTicket KHÔNG đụng (kanban, no workflow V2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:44:00 +07:00
e54a22de0c [CLAUDE] Domain+App+Infra+Api+FE-Admin+FE-User: S38 G-O4+G-O5+G-O6+G-P1+G-H3 SKELETON full-stack
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m53s
Phase 10.3-10.4 SKELETON 5 plan combo finish — Mig 39+40 + BE skeleton 7 module +
FE 2 app SHA256 IDENTICAL + 11 menu key. UAT visible end-to-end.

⚠️ SKELETON Phase 1 trade-off rõ:
  - Status flat 5-state WorkflowAppStatus enum share Leave/OT/Travel/Vehicle
  - ApproveV2 workflow advance DEFER Phase 11 (Drafter Create OK, Approve flow chưa wire)
  - LevelOpinions per-module DEFER Phase 11
  - LeaveBalance calc + Auto-assign + SLA timer DEFER Phase 11
  - CodeGen atomic + MaDonTu/MaTicket gen DEFER Phase 11
  - Vehicle catalog + Driver catalog DEFER Phase 11 (free text VehicleLicense)
  - ItTicketComments thread DEFER Phase 11 (free text Resolution field)

Mig 39 (em main solo): 5 entity Workflow Apps schema
  - LeaveRequest (G-O4, FK LeaveType Hrm Mig 35, ApplicableType=5)
  - OtRequest (G-O4, FK OtPolicy optional, ApplicableType=6)
  - TravelRequest (G-O4, reuse ApplicableType=4 Proposal)
  - VehicleBooking (G-O5, free text vehicle, ApplicableType=7)
  - ItTicket (G-O6, NO workflow V2 — kanban status flow)

Mig 40 (em main solo): Attendance entity (G-P1)
  - GPS lat/long check-in/out + Source enum Web/Mobile/Device
  - UNIQUE composite (UserId, AttendanceDate)
  - WorkHours computed simple diff (NO OtPolicy multiplier yet)

BE CQRS (em main solo, single mega ~1100 LOC):
  - WorkflowAppsFeatures.cs 7 region (5 module Create+List + Attendance CheckIn/Out/GetMonth + HrDashboard)
  - 7 Controller: /api/leave-requests + /ot-requests + /travel-requests + /vehicle-bookings + /it-tickets + /attendances + /hr/dashboard
  - Class-level [Authorize] any authenticated
  - 13 endpoint total

FE 2 app (em main solo fallback gotcha #53 risk):
  - types/workflowApps.ts × 2 SHA256 IDENTICAL 77470e182a15de88 (all DTOs + Status badge)
  - WorkflowAppsListPage.tsx × 2 IDENTICAL 58139d0301a60ddf — generic declarative KIND_CONFIG handles 4 module (Leave/OT/Travel/Vehicle)
  - ItTicketsPage.tsx × 2 IDENTICAL d3062de2f54c794c — kanban 5 status column
  - MyAttendancePage.tsx × 2 IDENTICAL 86da48ae147db012 — GPS check-in/out + tháng calendar
  - HrmDashboardPage.tsx × 2 IDENTICAL d9c6c12a5a8694f8 — 4 KPI card + gender ratio + status breakdown
  - Pattern 16-bis 9× cumulative (App.tsx +4 routes + menuKeys +8 const + Layout staticMap +7 entry)
  - 7 amber banner "Skeleton Phase 1 — full feature Phase 11" rõ ràng UAT

Menu seed: +11 const + SeedMenuTreeAsync 8 row (Off_DonTu sub-group + 3 leaf + Off_DatXe + Off_ItTicket + Off_ChamCong + Hrm_Dashboard).
DbInitializer Sample workflow seed DEFER (workflows V2 already seeded từ S29+S37 reuse — admin clone tạo riêng per ApplicableType=5/6/7).

Verify:
- dotnet build PASS 0 error 2 pre-existing warning
- dotnet test 130/130 PASS baseline preserve
- npm build × 2 PASS clean
- SHA256 verify 5 file × 2 app all IDENTICAL

Plan G-* progress 11/11  (100% COMPLETE):
   G-H1 (S33) + G-O1 (S34) + G-H2 (S35) + G-O2 (S36) + G-O3 (S37) +
   G-O4 + G-O5 + G-O6 + G-P1 + G-H3 (S38 skeleton)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:19:42 +07:00
de1c378279 [CLAUDE] Domain+App+Infra+Api+FE-Admin+FE-User: S37 Mig 37 enum + Plan G-O3 Đề xuất full-stack
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m53s
Phase 10.3 G-O3 Đề xuất (Proposal) — Mig 37 enum extend +5 values + Mig 38
Proposal schema + BE CQRS 8 endpoint + FE 2 app SHA256 IDENTICAL.

Mig 37 (em main solo): extend ApprovalWorkflowApplicableType enum +5 values
  ProposalGeneral=4 / LeaveRequest=5 / OtRequest=6 / VehicleBooking=7 / ItTicket=8
  cookie-cutter Mig 22 pattern (Up/Down empty — enum mức Domain).

Mig 38 (em main solo): 4 entity Proposal (Code DX/YYYY/NNN) + ProposalAttachment
  + ProposalLevelOpinion (UNIQUE composite PEId+LevelId mirror PE Mig 26) +
  ProposalCodeSequence (Prefix PK atomic seq). 4 EF Config + 2 DbContext mod.

BE CQRS (em main solo ~700 LOC ProposalFeatures.cs sau Implementer truncate phase
exploration gotcha #53 5th + 529 Overload):
  - 4 Header handler (List paged + GetById detail + Create + UpdateDraft owner-OR-admin)
  - 4 Workflow handler (Submit gen MaDeXuat atomic + Approve UPSERT LevelOpinion advance + Reject + Return)
  - SERIALIZABLE transaction CodeGen
  - DTOs nested LevelOpinion với Step+Level metadata JOIN

ProposalsController 8 endpoint /api/proposals (List/GetById/Create/Update/Submit/Approve/Reject/Return)
class-level [Authorize] + handler-level owner-OR-admin guard.

DbInitializer: SeedSampleProposalWorkflowV2Async ~40 LOC seed QT-DX-V2-001 IsUserSelectable=true
NOT gated DemoSeed per gotcha #51. SeedMenuTreeAsync +4 row (Off_DeXuat sub-group + 3 leaf).

FE 2 app (em main solo + Implementer 529 fail fallback):
  - types/proposal.ts × 2 SHA256 IDENTICAL 95607052ff1138f2
  - ProposalsListPage.tsx × 2 IDENTICAL 603f0d9cf74cd09a — table 6 cột + Status badge + filter
  - ProposalCreatePage.tsx × 2 IDENTICAL 6aed3a76563dd576 — Form Header card
  - ProposalDetailPage.tsx × 2 IDENTICAL 3dc229ea8dcc9bc0 — 3 Section + WorkflowActions
  - Pattern 16-bis 8× cumulative (App.tsx + menuKeys + Layout staticMap 3 entry)

Verify:
- dotnet build PASS 0 error 2 warning pre-existing DocxRenderer
- dotnet test 130/130 PASS baseline preserve
- npm build × 2 PASS (fe-admin 14.72s + fe-user 6.40s)
- SHA256 verify 4 file × 2 app all IDENTICAL

Pattern reinforced cumulative S37:
- Pattern 12-bis cross-module mirror 11× (PE V2 → Proposal V2 ApproveV2)
- Pattern 16-bis 4-place mirror cross-app 8×
- gotcha #53 5th occurrence Implementer mid-exploration truncation + 529 Overload 1× — em main solo fallback proven

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:51:14 +07:00
f45090b654 [CLAUDE] Domain+App+Infra+Api+FE-Admin+FE-User: S36 Plan G-O2 Phòng họp Mig 36 + BE CRUD + FE 2 app
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m55s
Phase 10.2 G-O2 Phòng họp BookingCalendar — Mig 36 schema + BE CQRS + FE 2 app
mirror cookie-cutter G-H2 HrmConfig pattern. Standalone không depend workflow.

BE schema (Mig 36 — em main solo Step 4):
- 4 Domain new: MeetingRoom catalog + MeetingBooking header + MeetingBookingAttendee
  join table N-to-N (NOT JSON per Investigator verdict) + Enums (MeetingBookingStatus
  3-state: Confirmed/Cancelled/Completed)
- 3 EF Config: UNIQUE Code + composite index (RoomId, StartAt) range query + UNIQUE
  composite (BookingId, UserId) join
- FK strategy: Room→Restrict (preserve history) + Booking→Cascade attendees +
  User→Restrict (denorm FullName+Email tránh cascade wipe)
- Mig 36 3-file rule + ApplicationDbContextModelSnapshot updated + apply Dev+Design DB

BE CQRS (~584 LOC — Implementer Case 2):
- MeetingFeatures.cs 479 LOC 9 handler: 4 Room CRUD + 5 Booking (List + GetById +
  Create + Update + Cancel)
- SERIALIZABLE transaction overlap check via EXISTS query — throw 409 Conflict
  "Phòng đã được đặt trong khoảng thời gian này"
- MeetingRoomsController 49 LOC + MeetingBookingsController 56 LOC — class-level
  [Authorize] + Roles="Admin" for write
- Application.csproj +Microsoft.EntityFrameworkCore.Relational package (em main fix
  IsolationLevel overload — Implementer gotcha #53 4th truncation diagnose mid-task)
- MenuKeys.cs +4 const (Off_PhongHop sub-group + View/Manage/Book leaf)
- DbInitializer +SeedMeetingRoomsAsync 4 sample (PH-A Phòng họp lớn cap=20 + PH-B
  cap=8 + PHG-501 Giám đốc cap=6 + ONL-1 Online Zoom cap=50) — NOT gated DemoSeed
  per gotcha #51 INFRASTRUCTURE seed

FE 2 app (~1770 LOC × 2 — Implementer Case 2):
- types/meeting.ts × 2 SHA256 IDENTICAL (ce0ad9c6d017cde2) — DTO interface mirror
- MeetingCalendarPage.tsx × 2 SHA256 IDENTICAL (d6d160ae1e4f2285) ~530 LOC — custom
  HTML 7-day grid 8h-20h slot, NO FullCalendar dep (~80 KB bundle saved per
  Investigator verdict alternative)
- MeetingRoomsPage.tsx × 2 SHA256 IDENTICAL (ba35a7ef379a5e9c) ~270 LOC — admin
  catalog CRUD table + Dialog
- 4-place mirror Pattern 16-bis 7× cumulative: types + page + App.tsx route +
  menuKeys + Layout staticMap 3 entry (gotcha #50 silent sidebar drop prevention)

Verify:
- dotnet build SolutionErp.slnx PASS 0 error 2 pre-existing DocxRenderer warning
- dotnet test 130/130 PASS baseline preserve (58 Domain + 72 Infra)
- npm build × 2 app PASS 0 TS error (fe-admin 16.91s bundle 1490 KB / fe-user 8.56s
  bundle 1404 KB, +23 KB gzip both)

Pattern reinforced cumulative S36:
- Pattern 12-bis cross-module mirror 10× (PE → Contract V2 → Hrm → Office)
- Pattern 16-bis 4-place mirror cross-app 7×
- Smart Friend Implementer truncation gotcha #53 4th — mitigation tight brief WORK
  (FE 2 app no truncation, BE truncate diagnose mid only)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:06:12 +07:00
021674a66a [CLAUDE] FE-Admin+FE-User: S35 Plan G-H2 Task 4 — HrmConfigsPage declarative 4 catalog × 2 app
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m37s
Pattern 12-bis × 16-bis cookie-cutter cumulative 9× (Smart Friend Implementer catch).
Single page declarative KIND_CONFIG Record + URL `:kind` param + 4 sub-tab mirror
Master/Catalogs/CatalogsPage.tsx 321 LOC pattern. 4 catalog HRM (LeaveTypes/Holidays/
Shifts/OtPolicies) wire BE 16 endpoint /api/hrm-configs/{kind} từ commit `909655c`.

## Scope (Implementer Case 2 ~25K spawn)
- types/hrm-config.ts (NEW 98 LOC × 2 app SHA256 IDENTICAL `228917e5fac2cdc6`)
- HrmConfigsPage.tsx (NEW ~470 LOC × 2 app SHA256 IDENTICAL `6378fbc71ff90260`)
- App.tsx +3 LOC × 2 app (route + Navigate redirect default `/hrm/configs` → `leave-types`)
- Layout.tsx staticMap +6 LOC × 2 app — Pattern 16-bis 4-place enforcement
  (em main spec line 24 GAP — Smart Friend Implementer caught + fixed proactive)

## 4 kind FieldDef declarative
- leave-types: code/name/daysPerYear/isPaid/requiresAttachment/description
- holidays: year/date/name/isRecurring/isPaid/description
- shifts: code/name/startTime/endTime/breakMinutes/workDays(multiselect-weekday)/description
- ot-policies: code/name/multiplier×3/maxHours×3/description

## Pattern 16-bis 4-place mirror Pattern 16-bis 6× cumulative
- types/hrm-config.ts (place 1)
- pages/hrm/HrmConfigsPage.tsx (place 2)
- App.tsx routes (place 3)
- Layout.tsx staticMap (place 4 — em main MISS, Implementer caught via gotcha #50 prior knowledge)

## Verify
- npm build × 2 PASS (fe-admin 14.33s + fe-user 744ms, 0 TS error)
- SHA256 IDENTICAL × 2 NEW pair (types + page)
- Reviewer pre-commit PASS Cat A-D clean (5K token tight scope no truncation)
- gotcha #50 silent sidebar drop prevention — Pattern 16-bis discipline reinforced
- Smart Friend 9× clean cumulative S22+S25+S29×2+S33×2+S35×3

## Multi-agent ROI S35 chunk 3 ~30K
- Implementer Case 2 declarative single-page mega + spec gap catch
- Reviewer tight 5K verdict Cat A-D PASS

## State delta S35 cumulative
- 0 mig add (Mig 35 schema S34)
- 0 BE endpoint add (16 endpoint commit `909655c`)
- +1 FE page (HrmConfigsPage) × 2 app routes
- Pattern 12-bis cumulative 3× + Pattern 16-bis 6× + Pattern 12-ter 6× (FE forms)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:01:43 +07:00
c3cd343bae [CLAUDE] FE-Admin+FE-User: S35 Phase 1.5 Item 3-FE — inline forms 5 satellite cookie-cutter
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m51s
Pattern 12-ter (within-module N-satellite) × Pattern 16-bis (cross-app mirror) cumulative
6×. FE inline expandable form Add/Edit/Delete cho 5 satellite EmployeeProfile (WorkHistory
+ Education + FamilyRelation + Skill + Document) — close Phase 1.5 backlog Item 3 FE side.

## Scope (Implementer Case 2 ~30K spawn)
- Section component extend optional `actions?` prop (backward-compat 100%)
- 5 inline form components per app: WorkHistory/Education/FamilyRelation/Skill/Document
- 3 DRY helpers: FormField + FormFooter + RowActions (45 usage site)
- DRY helper `invalidate()` line 268 — 15 mutations × 1 shared = clean
- 5 Input types append types/employee.ts (CreateEmployeeWorkHistoryInput + 4 more)
- 15 useMutation per app (5 sat × 3 verb) = 30 total cross-app
- Wire BE 15 endpoint S34 ready: POST/PUT/DELETE /api/employees/{id}/{satellite-path}
- gotcha #44 mitigation ACTIVE: per-action policy Hrm_HoSo.{Create|Update|Delete}

## Stats
- fe-admin EmployeesListPage.tsx 573 → 1200 LOC (+627, +110%)
- fe-user EmployeesListPage.tsx mirror SHA256 IDENTICAL `802d01fd1ee79925`
- 2 types file +53 LOC each, SHA256 IDENTICAL `db29156a61af76e9`
- npm build × 2 PASS (fe-admin 31.57s + fe-user 23.39s, 0 TS error)
- BE files NOT touched (15 endpoint scaffold S34 ready)
- Test gate 130 PASS baseline preserve (FE-only)

## Multi-agent ROI S35 ~70K
- Implementer Case 2 ~30K (FE cookie-cutter scaffold)
- Investigator ~8K (G-H2 BE CRUD pre-flight, defer Plan G-H2 next chunk)
- Reviewer pre-commit ~15K Cat 1 wire BE PERFECT + em main verify Cat 2-6 PASS
- CICD warm-up ~15K (Run #241 baseline verified + standby S35 push)

Smart Friend 7× clean cumulative S22+S25+S29×2+S33×2+S35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:38:56 +07:00
07b3f3b284 [CLAUDE] Domain+App+Infra+FE-Admin+FE-User: S34 Plan 4 G-H2 Mig 35 schema foundation
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m30s
Phase 10.2 G-H2 Cấu hình HRM — 4 catalog lookup foundation deploy (BE CRUD +
FE forms DEFER S35 cho clean handoff).

Mig 35 `AddHrmConfigs` — 4 table mới:
- LeaveTypes (Code unique + Name + DaysPerYear decimal(5,2) + IsPaid +
  RequiresAttachment) — 5 sample seed (ANNUAL 12d + SICK 30d + MATERNITY 180d
  + COMPASSIONATE 3d + UNPAID 0d)
- Holidays (Year + Date UNIQUE composite + Name + IsRecurring + IsPaid) —
  10 sample VN 2026 (Tết Dương + 5 Tết Nguyên đán placeholder + Giỗ tổ +
  30/4 + 1/5 + 2/9 + Quốc khánh)
- ShiftPatterns (Code unique + Name + StartTime/EndTime TimeOnly + BreakMinutes +
  WorkDays comma string) — 3 sample (HC 8-17 T2-T6 + CA1 6-14 T2-T7 + CA2 14-22)
- OtPolicies (Code unique + 3 Multiplier decimal(4,2) + 3 MaxHours int) —
  1 sample STANDARD (1.5x/2.0x/3.0x weekday/weekend/holiday + 4h/40h/200h cap
  Luật Lao động VN 2019)

Files:
- Domain/Hrm/{LeaveType,Holiday,ShiftPattern,OtPolicy}.cs (4 entity AuditableEntity)
- Infrastructure/Persistence/Configurations/{LeaveType,Holiday,ShiftPattern,OtPolicy}Configuration.cs (4 EF Config UNIQUE indexes)
- IApplicationDbContext + ApplicationDbContext +4 DbSet
- Migrations/20260527075940_AddHrmConfigs.{cs,Designer.cs} + Snapshot updated (3-file rule)
- DbInitializer.SeedHrmConfigsAsync ~120 LOC seed sample (NOT gated DemoSeed per gotcha #51)
- MenuKeys.cs +HrmConfig sub-group + 4 leaf (LeaveTypes/Holidays/Shifts/OtPolicies) Order=2 dưới Hrm
- DbInitializer.SeedMenuTreeAsync +5 entry (sub-group + 4 leaf)
- fe-admin + fe-user menuKeys.ts +5 const mirror BE (Pattern 16-bis sync)

Verify:
- dotnet build PASS (2 warn DocxRenderer baseline, 0 error)
- dotnet test 130/130 PASS baseline preserve
- Mig 35 applied LocalDB SolutionErp_Dev — verified via dotnet ef database update
- 4 catalog table created + 5+10+3+1 = 19 sample row seed

Defer S35:
- Task 2 BE CQRS 4 catalog CRUD (16 endpoint) — Implementer Case 2 cookie-cutter
- Task 4 FE 2 app 4 catalog page (list/create/edit dialog) — Implementer Case 2

Cumulative S34 mig: 34 → 35 (+1). Tables 67 → 71 (+4). Menu keys 64 → 69 (+5).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:04:10 +07:00
61e9ce5b3b [CLAUDE] Domain+App+Api+Tests+FE-Admin+FE-User: S34 Plan 3 Phase 1.5 batch 4 item
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m48s
Phase 1.5 backlog G-H1 EmployeeProfile hardening batch (Items 6+2+1+4 of 6).

Item 6 — menuKeys FE drift sync × 2 app:
- fe-admin add: Catalogs + 4 Catalog leaves + Workflows + Budgets + Bg_List/Create/Pending (10 key)
- fe-user add: Budgets + Bg_List/Create/Pending + ApprovalWorkflowsV2 + 2 AwV2 leaf + MenuVisibility + Workflows (8 key)
- Cả 2 file giờ identical mirror BE MenuKeys.cs (28 key cumulative)

Item 2 — UpdateEmployeeProfileCommand bool→bool? safe partial update:
- 3 field IsCommunistParty/IsYouthUnion/IsTradeUnion → bool?
- Handler: HasValue check, null = giữ giá trị cũ (Reviewer minor #(b) S33 fixed)
- FE không bắt buộc gửi 3 field every PUT — tránh accidental reset

Item 1 — EmployeesController per-action policy (gotcha #44 mitigation):
- Class-level [Authorize(Policy = "Hrm_HoSo.Read")] — non-admin thiếu Read → 403
- POST [Authorize(Policy = "Hrm_HoSo.Create")]
- PUT  [Authorize(Policy = "Hrm_HoSo.Update")]
- DELETE [Authorize(Policy = "Hrm_HoSo.Delete")]

Item 4 — Test bundle Phase 1.5 (+10 [Fact], baseline 120 → 130/130 PASS):
- EmployeeCodeGeneratorTests (3 [Fact]) — atomic SERIALIZABLE NV/YYYY/NNNN
  + first call + sequential increment + year boundary preserve old year
- CreateEmployeeProfileCommandTests (4 [Fact]) — Create handler edge case
  + first profile + duplicate UserId Conflict + soft-deleted Conflict-restore
  + UserNotFound NotFoundException
- ListEmployeesQueryTests (3 [Fact]) — filter + paging logic
  + status filter + departmentId filter + search by EmployeeCode partial

Implementer Case 3 test gen caught spec mismatch (allow new after soft-delete
vs throws Conflict-restore) — chose CODE source of truth + renamed test
documenting discriminator message branch. Em main verify behavior correct
(admin UX khôi phục thay vì tạo mới — explicit flow defer Phase 1.5+).

Verify:
- dotnet build PASS (2 warn DocxRenderer baseline, 0 error)
- dotnet test 130/130 PASS (58 Domain + 72 Infra = +10)
- 4 endpoint /api/employees policy wired (gotcha #44 active mitigation)
- 4 MEMORY agent updated post-spawn (CICD Run #238 + Implementer test bundle)

Deferred Phase 1.5 next batch:
- Item 3 Satellite CRUD endpoints (WorkHistory/Education/FamilyRelation/Skill/
  Document) + FE inline edit forms — heavy ~2-3h
- Item 5 UAT smoke non-admin role verify silent 403 catch — defer post-deploy

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 13:57:08 +07:00
ea440da990 [CLAUDE] Domain+App+Api+Infra+FE-Admin+FE-User: S34 Plan 2 G-O1 Danh bạ nội bộ
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m46s
Phase 10.2 Văn phòng số — Internal Directory (1 endpoint reuse Users +
EmployeeProfiles + Departments, FE card grid avatar/dept/email/phone/Ext).

BE Task 1+2 (em main solo):
- Application/Office/DirectoryFeatures.cs — GetDirectoryQuery + DirectoryItemDto
  12 field LEFT JOIN Users.IsActive + Departments + EmployeeProfiles
- Api/Controllers/DirectoryController.cs — GET /api/directory?search=&departmentId=
  class-level [Authorize] (mọi authenticated NV tra cứu danh bạ nội bộ)
- MenuKeys.cs +Off+OffDanhBa const + All[] update
- DbInitializer.SeedMenuTreeAsync Off Order=29 + OffDanhBa Order=1 dưới Off

FE Task 3 (Implementer Case 2 Pattern 16-bis 4-place mirror cross-app — 5×):
- types/directory.ts SHA256 7349d9f64e78 × 2 app IDENTICAL
- pages/office/InternalDirectoryPage.tsx SHA256 2aa7e0eed2c8 × 2 app IDENTICAL
  Card grid responsive 1/2/3/4 col + filter dept dropdown + search input
  Avatar 14×14 initials gradient PALETTE 6 màu (Pattern 14 Tailwind JIT)
  EmployeeCode badge + Department emerald badge + email mailto + phone tel
  Internal phone Ext: amber badge + empty/loading state Vietnamese 100%
- App.tsx route /directory × 2 app
- lib/menuKeys.ts Off+OffDanhBa const × 2 app
- components/Layout.tsx resolvePath staticMap Off_DanhBa:/directory × 2 app
  (gotcha #50 — 5 places mirror crossapp DON'T MISS)

Verify:
- dotnet build PASS (2 warn DocxRenderer existing, 0 error)
- dotnet test 120/120 PASS (58 Domain + 62 Infra baseline preserve)
- npm build × 2 app PASS 0 TS err (fe-admin 1436KB / fe-user 1350KB)

Implementer MEMORY Pattern 16-bis reinforced 5× cumulative (S29 Plan CA HF1 +
S29 Plan B Chunk D + S33 Plan B G-H1 Task 5 + S34 Plan G-O1 Task 3).

Endpoint smoke pending CICD post-deploy Stage 4 (Run #XXX expected ~3m30s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 13:39:10 +07:00
9616ae219c [CLAUDE] FE-Admin+FE-User: Plan B G-H1 Task 5 — EmployeesPage 2-panel + EmployeeCreatePage cookie-cutter mirror
Phase 10.1 G-H1 Phase 2 Task 5 — FE 2 app cookie-cutter mirror PE pattern.
Phase 1 ULTRA-MINIMAL scope (Implementer afdc812 scaffold):
- 2-panel ListPage (filter left + list+detail right, KHÔNG 3-panel vì Hrm
  no workflow)
- 6-section inline collapsible detail (Cơ bản/Công tác/Đào tạo/Thân nhân/
  Kỹ năng/Hồ sơ) — NO separate DetailTabs component file
- CreatePage Header form minimal (UserId picker + Status + DateOfBirth +
  Gender + Phone + HireDate + Nationality)
- Display read-only Phase 1 satellite (no inline edit — defer Phase 1.5)

## Files (6 new + 6 modified × 2 app = 12)

### NEW (3 × 2 app, SHA256 IDENTICAL cross-app mirror)

| File | LOC | SHA256 prefix |
|------|----:|---|
| `fe-{admin,user}/src/types/employee.ts` | 283 | CCFC70666568 |
| `fe-{admin,user}/src/pages/hrm/EmployeesListPage.tsx` | 417 | DC859C897C5C |
| `fe-{admin,user}/src/pages/hrm/EmployeeCreatePage.tsx` | 178 | C796F25D01AC |

10 const-object enum mirror BE Domain.Hrm.Enums + DTOs:
- EmployeeStatus/Gender/MaritalStatus/EmployeeType/DegreeLevel/
  EducationMode/GradeLevel/FamilyRelationKind/SkillKind/EmployeeDocumentType
- EmployeeListItem + EmployeeDetail + 5 satellite DTO type

### MODIFIED (3 × 2 app)

- `fe-{admin,user}/src/lib/menuKeys.ts` — +Hrm + HrmHoSo const
- `fe-{admin,user}/src/components/Layout.tsx` — +Hrm_HoSo:'/employees' staticMap
  (LESSON Plan CA Hotfix 1 gotcha #50: page route mới phải thêm staticMap
  entry cùng commit, else silent sidebar drop)
- `fe-{admin,user}/src/App.tsx` — +2 route /employees + /employees/new

## Pattern reinforcement

- **Pattern 16-bis 4-place mirror cross-app** reinforced 4× cumulative (S29
  Plan CA HF1 + S29 Plan B Chunk D + S33 Task 5 admin + S33 Task 5 user).
  Comment header trong Layout.tsx ghi explicit Plan CA Hotfix 1 #50 lesson.
- **Pattern 12-bis cross-module entity FE port PE → Hrm** reinforced 4× (Plan
  B Chunk C Mig 33 + G-H1 Task 4 BE + Task 5 FE types mirror PE types/page
  structure mirror PE 2-panel scope-down 3→2 panel).

## Reviewer ae752c0 verdict: PASS (commit 0e191de earlier)

- Smart Friend 6× cumulative clean (em main + Implementer quality genuine)
- gotcha #50 Layout staticMap mirror ✓ (cả fe-admin + fe-user)
- menuKeys.ts FE drift pre-existing intentional (fe-admin minimal vs fe-user
  expanded Catalogs/Suppliers/Projects/Departments) — NOT blocking, follow-up
  task add Budgets/Catalogs to fe-admin OR document intentional minimal scope.

## Verify

- fe-admin npm build: PASS 21.4s · 0 TS6 err · 1,431 KB bundle
- fe-user npm build: PASS 9.2s · 0 TS6 err · 1,345 KB bundle
- dotnet build: PASS 1.59s · 0 warn 0 err (no BE change)
- dotnet test: 120/120 PASS baseline preserved

## Defer Phase 1.5 (per Reviewer recommend)

1. PermissionGuard wrapper menuKey HrmHoSo + per-action Hrm_HoSo_View/Create
2. Convert 3 bool field UpdateCommand thành bool? safe partial update
3. Satellite CRUD endpoint + form (WorkHistory/Education/FamilyRelation/
   Skill/Document)
4. Test bundle (Create UNIQUE conflict + List filter + codeGen race)
5. Add Bg_*/Catalog* to fe-admin menuKeys.ts sync với fe-user

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 20:27:25 +07:00
14feb6955d [CLAUDE] FE-Admin+FE-User: Plan B Chunk E3 — ContractDetailPage Section 5 LevelOpinionsV2 dynamic
Em main solo sau Implementer E3 stuck mid-task. Minimum viable mirror PE
Section 5 LevelOpinionsSectionV2 pattern. V2 contract pin ApprovalWorkflowId
→ render dynamic Section 5 với opinion data UPSERT từ Service ApproveV2Async
(Plan B Chunk B2 1f199b0).

Changes × 2 app:

types/contracts.ts (×2):
- ContractDetail +3 fields V2 (default null backward compat):
  - approvalWorkflowId: string | null
  - currentApprovalLevelOrder: number | null
  - levelOpinions: ContractLevelOpinion[] | null
- NEW type ContractLevelOpinion (12 fields mirror BE DTO)

components/contracts/ContractDetailContent.tsx (×2):
- Add Section 5 sau "Chi tiết HĐ" section
- Conditional render: chỉ khi c.approvalWorkflowId (V2 mode)
- Empty placeholder "Chưa có ý kiến" khi workflow vừa start
- forEach opinion render card:
  - Title: Bước X (StepName) — Cấp Y (LevelName)
  - Comment + signedAt vi-VN format
  - NV duyệt: approverFullName
  - Banner " Admin duyệt thay" khi signedByUserId !== approverUserId
- Style: emerald palette mirror PE Section 5

V1 contract: 3 fields null → Section 5 KHÔNG render (backward compat).

Verify:
- npm run build × 2 app PASS 0 TS err
- Mirror 2 app §3.9 byte-similar (4 file edit cùng pattern)
- BE wire OK: E2 commit 48f6d22 expose approvalWorkflowId + levelOpinions

Plan B COMPLETE 9/9 chunks LOCAL:
- A1 58898e8  Entity +2 fields
- A2 a85e437  Mig 32 + Config + Seed
- B 138469d  Service ApproveV2Async branch
- C 26c98d3  Mig 33 LevelOpinions
- B2 1f199b0  UPSERT block
- E1 ef23308  CreateContractCommand +V2
- D 62b50d1  FE Workspace V2
- E2 48f6d22  ContractDetailDto + populate
- E3 (this)  FE Section 5 LevelOpinionsV2

Implementer E3 spawn stopped mid-task ("check ContractDetail type" judgment
call) → em main solo finish. Pattern lesson: complex FE feature mirror với
type extend + new component → em main solo more reliable than Implementer.

Pending: Reviewer pre-commit Plan B cumulative + push remote + CICD verify
+ docs/STATUS update.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:45:33 +07:00
62b50d112b [CLAUDE] FE-Admin+FE-User: Plan B Chunk D — ContractCreatePage Workspace V2 Select dropdown
Mirror PE PeWorkspaceCreateView Workspace pattern. Drafter pick V2
workflow IsUserSelectable=true filter ApplicableType=Contract(3).

Changes × 2 app:
- Add useQuery fetch /api/approval-workflows-v2?applicableType=3 + filter
  client-side isUserSelectable=true (mirror PE Mig 25 pattern)
- Add Select dropdown "Quy trình duyệt V2 (tùy chọn)" trong
  ContractHeaderForm (create mode panel 2)
- Wire approvalWorkflowId vào CreateContractCommand POST body
- Conditional UI: blank = V1 fallback auto pick (7 prod contract behavior
  giữ nguyên); user pick V2 → pin ApprovalWorkflowId Mig 32 schema
- Hint khi 0 workflows V2 admin ghim → message rõ V1 fallback

Verify:
- npm run build × 2 app PASS 0 TS err (1.32MB fe-user, 1.40MB fe-admin)
- Mirror 2 app §3.9: +44 LOC mỗi file = +88 LOC total byte-similar
- API endpoint /api/approval-workflows-v2 existing (Mig 25 Plan AA S24)
- BE CreateContractCommand.ApprovalWorkflowId field đã add Chunk E1
  (em main commit prior) — FE wire safe
- Backward compat: V1 contract path unchanged khi user bỏ trống dropdown

Plan B chain (6 chunks):
- A1 58898e8  Entity ApprovalWorkflowId + CurrentApprovalLevelOrder
- A2 a85e437  Mig 32 + Seed sample V2 Contract workflow
- B 138469d  Service ApproveV2 branch (PE pattern mirror)
- C 26c98d3  Mig 33 ContractLevelOpinions
- B2 1f199b0  UPSERT LevelOpinion block (PE Mig 26 mirror)
- D (this)  FE Workspace V2 dropdown
- E FE Section 5 V2 (em main + Implementer split E1+E2 sau)

Pattern 16-bis 4-place mirror check:
- Page file × 2 app: edited (insertion mirror byte-similar)
- App.tsx Routes: N/A (enhance existing /contracts/new route)
- menuKeys.ts: N/A (không thêm menu key mới)
- Layout staticMap: N/A (route unchanged)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:34:00 +07:00
e55d96b856 [CLAUDE] FE-User: Plan CA Hotfix 1 — Add 7 master/catalog leaf routes vào resolvePath staticMap
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m24s
Bug UAT bro screenshot 2026-05-22: eoffice sidebar group "DANH MỤC" expand
chỉ thấy "Danh mục chi tiết" (Catalogs sub-group), 3 leaf Suppliers/Projects/
Departments + 4 sub-catalog leaves KHÔNG render.

Root cause: fe-user/src/components/Layout.tsx:238 `MenuLeaf` component
`if (!path) return null` → silent drop khi resolvePath(key) trả null.
Implementer Chunk B (06a441c) thêm Routes vào App.tsx + 4 page + menuKeys.ts
NHƯNG QUÊN mirror staticMap resolvePath (line 55-94) — fe-admin có sẵn
7 entries nhưng fe-user chỉ có 7 entries Dashboard/Contracts/PE/Budget.

Fix: thêm 7 entries vào fe-user staticMap mirror fe-admin EXACT route:
- Suppliers: '/master/suppliers'
- Projects: '/master/projects'
- Departments: '/master/departments'
- CatalogUnits: '/master/catalogs/units'
- CatalogMaterials: '/master/catalogs/materials'
- CatalogServices: '/master/catalogs/services'
- CatalogWorkItems: '/master/catalogs/work-items'

Verify:
- npm run build PASS 9.68s 0 TS err
- BE /api/menus/me admin token return CORRECT tree (Master + 4 children +
  Catalogs sub-tree 4 children) — verified curl pre-fix
- Permissions OK: Admin 9/9 CRUD + CatalogManager 9/9 CRUD (verified sqlcmd)
- fe-admin parity already correct (Layout.tsx:33-47 staticMap có 7 entries
  từ trước Plan CA)

Pattern reusable: Khi Implementer Case 2 cookie-cutter mirror page move
cross-app, MUST also mirror Layout.tsx resolvePath staticMap entries —
KHÔNG chỉ Routes + menuKeys.ts. Gotcha discovery thêm vào MEMORY post-deploy.

Plan CA chain (6 commits cumulative):
- A 80d39a0 BE Role + Seed
- B 06a441c FE move 4 master pages (missed resolvePath mirror)
- C c995f42 Sidebar filter 2 app
- D 4a592cf Seed demo user
- D2 68bcedd Password ≥12 chars hotfix
- HF1 (this) Mirror resolvePath staticMap 7 entries

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 11:38:10 +07:00
c995f42e0d [CLAUDE] FE-Admin+FE-User: Plan CA Chunk C — Sidebar filter 2 app (admin HIDE + user SHOW)
fe-admin/src/components/Layout.tsx:
- Add ADMIN_HIDDEN_MASTER_KEYS Set với 9 menu key danh mục
- Extend isAdminHidden predicate: hide Ct_* + ADMIN_HIDDEN_MASTER_KEYS
- Master/Suppliers/Projects/Departments/Catalogs/4 sub-catalogs giờ ẩn khỏi admin sidebar

fe-user/src/components/Layout.tsx:
- Remove `Master, Suppliers, Projects, Departments` khỏi USER_HIDDEN_KEYS
- Catalogs (root + 4 leaf) auto-visible qua tree-inherit từ Master
- Giữ ẩn `System, Users, Roles, Permissions, Forms, Reports` (admin tools)

Verify:
- npm run build × 2 app PASS 0 TS err
- fe-admin bundle `index-BQidGwKU.js` 1,404 KB gz 357 KB (rotate)
- fe-user bundle `index-Co8LTtad.js` 1,317 KB gz 342 KB (rotate)
- Pattern 5 (mirror 2 app §3.9) applied — cùng 1 plan touch 2 file Layout

Plan CA chain:
- Chunk A 80d39a0 BE Role + Seed (em main solo)
- Chunk B 06a441c FE move 4 pages (Implementer Case 2)
- Chunk C (this) sidebar filter (em main solo)
- Pending Chunk D: smoke verify + tạo demo user catalog.manager@solutions.com.vn

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