Commit Graph

93 Commits

Author SHA1 Message Date
7886fd03dd [CLAUDE] PurchaseEvaluation: nguoi duyet dinh kem file khi DUYET (reuse attachment Purpose=ApprovalAttachment, no migration)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m56s
Modal Duyet them picker multi-file -> upload TRUOC khi chuyen phase (file loi/>20MB = throw, khong duyet). File hien o muc 'File dinh kem khi duyet' (download/preview) trong Panel quy trinh, gan ten nguoi tai + thoi gian. Fix 2 filter dung supplierId=null lam proxy Bang-so-sanh (banSoSanhAttachments + submit-guard) loai purpose=5 tranh lan section + false-pass. FE 2 app SHA-identical. authz: approver upload duoc (handler khong guard drafter-only). Test 354 PASS, no migration. UAT Tra Sol / 5 tester.
2026-06-19 16:46:37 +07:00
e823694202 [CLAUDE] FE: PE phieu Tra lai them banner huong dan gui duyet lai (che do Xem)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m50s
Bich Phuong hoi 'chi Tra tra ve thi bam nop lan 2 cho nao'. Phieu Tra lai o che do XEM (readOnly) khong co nut 'Luu & Gui Duyet' (nut do chi hien khi Sua) -> NV khong biet gui lai. Them banner amber khi phase==TraLai && readOnly: huong dan ra danh sach -> ✏️ Sua (but chi) -> dieu chinh -> 'Luu & Gui Duyet ->' o cuoi phieu; ly do tra lai xem o Lich su. Khop dung cau tra loi cua anh cho Bich Phuong. FE-only, 2 app SHA256-identical PeDetailTabs. Build PASS x2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:38:15 +07:00
b5aa72d005 [CLAUDE] PurchaseEvaluation: co gap GAN=NV chuc nang / GO=chi Truong phong (DeptManager) bat doi xung
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m48s
Tra Sol + anh Kiet (Zalo chot 14:25): tranh NV khac lo tay go co cua nguoi da gan. Handler SetPurchaseEvaluationUrgent gate BAT DOI XUNG theo IsUrgent: GAN (true) = role chuc nang (Procurement->do / CostControl->xanh / Admin->ca 2); GO (false) = role chuc nang + DeptManager (Truong phong) hoac Admin. FE PeDetailTabs nut toggle gate theo trang thai hien tai (da gap->can quyen GO; chua gap->can quyen GAN) → an nut GO voi NV thuong. Test PeUrgentToggleAuthzTests rewrite asymmetric (354 PASS 0 fail). FE 2 app SHA256-identical. Build slnx 0-err.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:42:08 +07:00
e29391ec9e [CLAUDE] FE: PE bang ngan sach muc con thut dong + gach dau dong (phan biet muc co so / khong so)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m39s
Tra Sol + anh Kiet (Zalo, annotate anh do): muc con (khong co so) thut vao + gach dau dong '–' de phan biet voi muc cha co so (1-9). BudgetRow +indent prop (pl-5 + dash span). Ap dung: Block A '– Ngan sach Ban hanh lan dau' + '– Ngan sach V0/hieu chinh tang giam' (con cua Ngan sach full); Block B '– Gia tri ky nay' + '– So sanh voi ngan sach ky nay' + '– So voi NS' + '– So sanh voi Ngan sach full'. Muc 1-9 giu cap cha. FE-only, 2 app SHA256-identical PeDetailTabs. Build PASS x2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:24:48 +07:00
e42d103694 [CLAUDE] FE: PE bang ngan sach so am -> do + ngoac (...) hang 7/8/9 dong bo hang so sanh
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m45s
Tra Sol (Zalo): cai nao la so am thi ngoac + mau do. Hang 7 (Ngan sach con lai) / 8 (Gia tri thuc hien du kien con lai) / 9 (Gia tri tong thuc hien du kien) dang dung fmtVnd (dau tru, mau mac dinh) -> chuyen sang fmtVndSigned (ngoac '(abs) d' cho so am, da co san) + span text-red-600 khi <0; dong bo voi cac hang 'So sanh' (cmpPeriod/cmp56/cmpFull da do+ngoac tu truoc). FE-only, 2 app SHA256-identical PeDetailTabs. Build PASS x2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:17:19 +07:00
94e0e12f77 [CLAUDE] PurchaseEvaluation: Mig 57 ghi chu gia de xuat PRO/CCM + so phan cach VND + sua chinh ta + guard #70
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m52s
Theo Tra Sol + anh Kiet FDC (Zalo): A) o nhap tien VndInlineEdit + BudgetCell nhay phan cach vi-VN (300.000.000) on-keystroke (o dialog da co san). B) them o ghi chu PRO + CCM canh nut Luu trong khoi Gia de xuat (giai thich vi sao chon Min/Max) — Mig 57 AddPeSuggestedPriceNotes (+ProSuggestedPriceNote +CcmSuggestedPriceNote nvarchar(1000) null, additive no-backfill no-table); 2 setter command +Note absolute-set rides role-gate PRO/CCM/Admin; DTO +2 field; controller body +note. C) sua chinh ta 'd. Ban so sanh' -> 'd. Bang so sanh gia' (2 app). GUARD gotcha #70: o gia + ghi chu echo nhau absolute-set -> them peFetching khoa nut Luu toi khi pe-detail refetch land, tranh stale-echo mat du lieu (mirror bang ngan sach S76; em-main review bat impl-frontend sot guard). BE slnx 0-warn 0-err; FE build PASS x2; test 344->351 (+7); PeDetailTabs/PeWorkspaceCreateView 2 app SHA256-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:08:45 +07:00
398b01d0a6 [CLAUDE] FE: PE che do tap trung duyet phieu (overlay truot phai, an menu+list) + responsive laptop nho
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m40s
Bam phieu -> focus overlay (fixed inset-0 z-50) truot tu phai, che menu+TopBar+list rail; phieu full-width tu cuon + panel duyet ben canh (stack xuong duoi tren man nho). Thu gon/Esc/backdrop HOAC Duyet (chi forward-approve; Tra lai/Tu choi giu overlay) -> dong ve danh sach. List state = panel giua mx-auto max-w-5xl, giu cay 4 tang + PeUrgentChips + search/filter/SLA. Responsive lg-pivot (flex-col stack <lg, flex-row >=lg), compact laptop nho, KHONG dong cham man hinh to (anh: 'man to OK roi'). PeWorkflowPanel +onApproved (wasReject byte-mirror isReject). 2 app SHA256-identical. a11y role=dialog/Esc/focus-trap/scroll-lock/reduced-motion. FE-only, 0 BE, 0 migration. Build PASS x2. Note: backend down luc design -> live authed verify sau deploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:28:26 +07:00
8e68ed1892 [CLAUDE] FE: PE co gap PILL (do PRO / xanh CCM) dong bo moi danh sach + inbox
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m46s
Surface co gap GAP tren MOI danh sach phieu de CEO/nguoi duyet thay urgency ngay tren danh sach khong can mo phieu (anh Kiet FDC). Cay danh sach: emoji -> pill labeled. Khung 'Danh sach phieu' cho duyet (Workspace + picker) + inbox 'phieu cho toi duyet': them pill (truoc day thieu). NEW PeUrgentChips.tsx single-source-of-truth (style khop badge detail S69) x2 app. FE-only, 0 BE, 0 migration — DTO da co IsUrgentByPro/Ccm tu S69 Mig 53. Build PASS x2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 12:31:08 +07:00
21d1f4ec43 [CLAUDE] FE: PE ngan sach Block A -> bang luoi <table> vien o giong Excel (anh phan hoi)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m46s
Anh: "giao dien van chua chia cot dung, muon giong file Excel". Block A dang dung
flex + spacing (khong co vien doc chia cot) -> chuyen sang <table border-collapse>
vien o day du: header [Khoan muc | Du an | PRO | CCM] + 5 hang (full / ban hanh /
hieu chinh / ghi chu PRO / ghi chu CCM). BudgetCell xep doc (input full o + nut Luu
duoi) cho vua cot. BudgetNoteRow -> BudgetNoteCell (td colSpan=3). Mirror
fe-user/fe-admin identical. FE-only, build 2 app PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:28:18 +07:00
e33481efb6 [CLAUDE] PurchaseEvaluation: Mig 56 ngan sach MA TRAN 3 cot (Du an|PRO|CCM) + badge quyen NS theo role
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m57s
S76 (anh Kiet FDC + chi Tra Sol) — form ngan sach + hien thi quyen nhap NS trong flow:
- Part 1: form ngan sach -> MA TRAN 3 cot, moi phong nhap+dieu chinh cot minh
  (PRO canEditPro / CCM canEditCcm / Du an FE hien-thi-only). Mig 56
  +ProInitialAmount/ProAdjustmentAmount (additive-nullable + data-migrate
  ProEstimate->ProInitial). full moi cot = ban hanh + hieu chinh.
- Part 2: Workflow Designer (fe-admin) +badge "NS PRO/CCM" canh approver
  (suy tu role Admin|Procurement / Admin|CostControl, hien-thi-only no-authz).
- Part 3: flow quy trinh fe-user/fe-admin (Duyet NCC) +badge tuong tu.
- Fix race mat-du-lieu Part 1 (useIsFetching khoa Luu khi refetch — dong
  cua-so stale-echo, reviewer Part2/3 bat).
- Test 339->344 (+5). 2 workflow review (Part 1 PASS + Part 2/3 PASS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:02:47 +07:00
8655ebf1ba [CLAUDE] PurchaseEvaluation: Mig 55 ô "Ghi chú từ CCM" ngân sách gói thầu — CCM nhập số + ghi lý do giống PRO
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m54s
- Entity PeWorkItemBudget +CcmNote (mirror ProNote, nvarchar 1000) + Mig 55 additive-nullable
- UpdatePeBudgetCcmCommand +CcmNote absolute-set, role-gate CostControl/Admin fail-closed
- DTO PeBudgetSummaryDto +CcmNote + controller BudgetCcmBody + GET mapping
- FE 2 app SHA-mirror: dòng "Ghi chú từ CCM" gate canEditCcm (sau V0/hiệu chỉnh), absolute-set đủ 3 field
- Test +5 (set CCM/Admin, null-clear, non-priv Forbidden, all-3-persist) -> 339 pass

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:05:10 +07:00
6aa4dcb525 [CLAUDE] FE-User: PE khoa nut Xac nhan khi phai chon gia ma chua co gia nao (Mig 54 fix)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m12s
Empty-candidates edge: neu duyet cap cuoi ma priceCandidates rong, nut Xac
nhan van mo -> bam -> BE Conflict kho hieu. Khoa nut + giu message ro rang.
Phong-thu thuan (double-check xac nhan edge UNREACHABLE qua submit-guard
winnerQuoteTotal>0 :194) + sua mau thuan UX cu. fe-user/fe-admin SHA-identical
(4d6c89d9). 2 workflow review (Round1 schema 1/4 + Round2 free-text 2/3 PASS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:21:31 +07:00
1d86abcdc5 [CLAUDE] PurchaseEvaluation: Mig 54 giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m22s
Theo note anh Kiệt FDC (go-live so-sánh-giá thứ Hai):
- (1) Giá chào thầu thêm giá đề xuất NGOÀI giá NCC: PRO nhập dải Min/Max +
  CCM nhập 1 giá (2 lệnh role-gate Procurement/CostControl, fail-closed).
  Khi duyệt cấp cuối, người duyệt CHỌN 1 giá chốt (Ncc/ProMin/ProMax/Ccm)
  -> luu ApprovedPriceAmount/Source (bind tai moi nhanh DaDuyet, bat buoc
  chon; auto-approve he thong mien).
- (3) CCM duyet-done mien CEO: DOI tu AUTO-threshold (S69) sang O-TICH-TAY
  (finalizeByCcmDelegation) -- CCM chu dong tich, fail-closed theo nguong
  + role + gia goi. An toan hon (khong vo tinh bo CEO).
- Mig 54 additive-nullable (5 cot PE) - FE 2 app SHA-mirror - test 306->334
  (+28: opt-in 6->11, +10 gia chot, +13 setter authz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:51:39 +07:00
ebd7e1c42f [CLAUDE] PurchaseEvaluation: cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị (Mig 53) + 14 test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m41s
Yêu cầu anh Kiệt FDC (sau họp sếp). Mig 53 AddPeUrgentAndCeoApprovalThreshold — 3 AddColumn, no new table (Mig 52→53). Rollout an toàn: cột nullable, ngưỡng null = giữ luồng duyệt cũ 100% cho tới khi admin set.

B — CCM duyệt-final theo NGƯỠNG GIÁ TRỊ ("gói CEO phân quyền theo giá trị"):
- ApprovalWorkflow += CeoApprovalThreshold (decimal?, admin nhập trong Workflow Designer).
- ApproveV2Async: actor role CostControl (CCM) + winnerQuoteTotal (tổng giá NCC được chọn) < ngưỡng → DaDuyet luôn (bỏ CEO); ≥ ngưỡng → đẩy lên CEO như cũ. Ngưỡng null = luồng tuyến tính cũ. Q4 chốt nhận diện theo ROLE người duyệt.
- reviewer PASS 0 blocker: cascade-safe (Off/role không lan), tested load-bearing (CCM dưới ngưỡng → DaDuyet skip CEO).

A — cờ gấp per-vai (visibility-only, Q3 KHÔNG đổi luồng):
- PE += IsUrgentByPro (PRO đỏ) / IsUrgentByCcm (CCM xanh).
- Endpoint PUT /purchase-evaluations/{id}/urgent role-gated (Procurement→ByPro, CostControl→ByCcm, Admin→cả 2, khác→Forbidden) + notify CEO (Director) khi MỚI bật (best-effort).

FE ×2 app: Workflow Designer ô "Ngưỡng giá trị gói CEO" (fe-admin) + PE detail nút bật/tắt cờ gấp đỏ/xanh theo role + badge GẤP + hint "giá trị gói vs ngưỡng → CCM duyệt-final/cần CEO" + PE list badge gấp.
DTO: PE detail += isUrgentByPro/Ccm + winnerQuoteTotal + ceoApprovalThreshold; list += isUrgentByPro/Ccm; workflow V2 += ceoApprovalThreshold.

+14 test (292→306): PeCcmThresholdFinalizeTests 5 (B routing) + PeUrgentToggleAuthzTests 9 (A authz). Build slnx 0/0 · npm build ×2 0 err · dotnet test 306 PASS.

C (sau duyệt xong chuyển phiếu đến dự án) — chờ anh Kiệt làm chi tiết form, CHƯA làm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:27:50 +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
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
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
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
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
506cada86b [CLAUDE] FE-User FE-Admin: Plan AF — userMap fallback resolve historical entries pre-Plan AE
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m23s
Bro UAT 2026-05-19 post-Plan AE: phiếu cũ entries vẫn show "Hệ thống" thay
vì user name. Plan AE chỉ forward fix — entries CŨ pre-deploy có
userName="" empty, FE fallback "Hệ thống".

Fix Plan AF — Option A bro chốt (FE fallback lookup, no DB write):

ApprovalsTab + HistoryTab build userMap useMemo từ PeDetailBundle data
có sẵn (KHÔNG cần extra fetch /api/users admin permission):
- ev.drafterUserId + ev.drafterName
- ev.approvals[].approverUserId + approverName
- ev.approvalFlow.steps[].levels[].approvers[].userId + fullName
- ev.levelOpinions[].signedByUserId + signedByFullName
- ev.departmentOpinions[].userId + userName

resolveUserName / resolveActorName helper:
1. Trust entry.userName nếu non-empty
2. Lookup userMap qua entry.userId
3. Fallback 'Hệ thống' nếu không match

Cover gần hết users tham gia phiếu (drafter + approver + signer). Edge
case: user edit phiếu nhưng KHÔNG xuất hiện trong workflow → vẫn fallback.

Pattern reusable: synthetic data recovery cho audit trail từ embedded
domain data sources, no extra API contract change.

Mirror 2 app §3.9 identical logic.

Verify:
- npm build × fe-user PASS 0 TS err (9.12s)
- npm build × fe-admin PASS 0 TS err (8.91s)
- BE unchanged from 9ea62be

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:04:59 +07:00
0aaf2df04a [CLAUDE] FE-User FE-Admin: Plan AD — Lịch sử duyệt redesign drop phase badges + next-target hint
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m24s
Bro UAT 2026-05-19 post-Plan AC2 deploy: phase badges "Đã gửi duyệt →
Đã gửi duyệt" gây nhầm (Reject event nhìn giống Approve, không rõ gửi
duyệt cho ai).

Fix Plan AD — Option A bro chốt:

1. DROP fromPhase→toPhase badges entirely khỏi ApprovalsTab — redundant
   visual noise khi 3/4 mode return giữ Phase=ChoDuyet, và misleading cho
   user thấy "Đã gửi duyệt → Đã gửi duyệt" lặp lại.

2. ADD next-target hint parse từ comment via helper extractNextTargetHint():
   Approve patterns:
     - Comment "sang Cấp X" → "→ Cấp X"
     - Comment "sang Bước X" → "→ Bước X (Cấp 1)"
     - Comment "[Duyệt vượt cấp tới Cấp cuối]" → "→ Vượt cấp tới Cấp cuối"
     - toPhase=DaDuyet(20) → "→ Đã duyệt hoàn tất"
   Reject patterns:
     - Comment "không lùi được" → "→ Không lùi được"
     - Comment "Người chỉ định" + Bước/Cấp → "→ Trả về Người chỉ định (Bước X Cấp Y)"
     - Comment "Người soạn thảo"/"Drafter" → "→ Trả về Người soạn thảo"
     - Comment "Trả về 1 Cấp"/"Trả về Cấp X" → "→ Lùi về Cấp X" / "→ Lùi 1 Cấp"
     - Comment "Trả về 1 Bước"/"Trả về Bước X" → "→ Lùi về Bước X" / "→ Lùi 1 Bước"
     - toPhase=TuChoi(99) → "→ Từ chối hoàn toàn"

3. Layout cleaner: [Decision badge] [Next-target hint] flex-wrap min-w-0 +
   timestamp shrink-0 right. Comment + actor stays below.

4. Cleanup import: drop unused PurchaseEvaluationPhaseColor (no longer
   needed after dropping phase badges). Keep PurchaseEvaluationPhaseLabel
   (still used at line 157+ for InfoTab phase label).

Mirror 2 app §3.9 identical logic.

Verify:
- npm build × fe-user + fe-admin PASS 0 TS err
- BE/test unchanged from 25837b6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:19:43 +07:00
25837b6220 [CLAUDE] FE-User FE-Admin: Plan AC2 — FE merge view recover historical Reject events PE cũ
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m22s
Bro UAT 2026-05-19 phản hồi sau Plan AC deploy: phiếu cũ PE/2026/A/032 vẫn KHÔNG
show events Trả lại pre-deploy (Bro test trả lại Phan Văn Chương → Trà từ TRƯỚC
cdfd542 không có trong Lịch sử duyệt).

Root cause: Plan AC chỉ add Approval row cho events POST-deploy. Events
pre-deploy chỉ có Changelog (LogTransitionAsync) — Approval table miss.

Fix Plan AC2 — FE merge view (Option 2A bro chọn):

ApprovalsTab fetch BOTH approvals + changelogs (cùng endpoint HistoryTab dùng):
- Reconstruct synthetic PeApproval rows từ Changelog Workflow+Reject events:
  - Filter: entityType=Workflow(5) + summary "→ TraLai"/"→ TuChoi" OR
    contextNote chứa "Trả về"/"không lùi được" (3 mode OneLevel/OneStep/Assignee
    giữ ChoDuyet → distinguish qua ContextNote keywords)
  - Parse fromPhase/toPhase từ summary regex "Chuyển phase X → Y"
  - id prefix "syn-" để distinct vs real Approval rows
- Dedupe synthetic vs real Reject Approval (post-Plan AC) qua
  approverUserId + timestamp 5s bucket key
- Merge approvals + dedupedSynthetic → sort by approvedAt → render

Reversible: KHÔNG touch DB, KHÔNG migration. FE-only fix recover history
cho mọi PE cũ trước deploy.

Mirror 2 app §3.9 identical logic.

Verify:
- npm build × fe-user + fe-admin PASS 0 TS err
- BE/test unchanged from a734bf2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:00:05 +07:00
a734bf2b8b [CLAUDE] PurchaseEvaluation: Plan AC — fix Lịch sử duyệt panel show Trả lại + Duyệt vượt cấp
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m27s
Bro UAT 2026-05-19 screenshot: panel "Lịch sử duyệt" KHÔNG show Return mode
events (Bro Trả lại từ Phan Văn Chương → Trà missing) + KHÔNG distinct
event Duyệt vượt cấp (skipToFinal F2).

Root cause:
- PurchaseEvaluationApprovals.Add() chỉ ở Approve branch (line 472 V2 + 660 V1)
- Reject branch line 75-103 NEVER adds Approval row — chỉ log Changelog
- skipToFinal advance branch line 532-572 dùng existing line 472 row nhưng
  comment KHÔNG distinct "vượt cấp" semantic vs approve thường

Fix Plan AC:

1. BE Service.cs Reject branch (line 75-103): capture pre-call Step/Level
   trước ApplyReturnModeAsync mutate pointer, add Approval row sau khi mutate:
   Decision=Reject + FromPhase + ToPhase=evaluation.Phase + Comment carry
   from-position + mode summary. Cover cả Trả lại (TraLai+pointer-mode) +
   Từ chối (TuChoi terminal).

2. BE Service.cs line 472 Approve branch: enrich Comment với prefix
   "[Duyệt vượt cấp tới Cấp cuối]" khi skipToFinal=true để Lịch sử duyệt
   distinguish vượt cấp với approve thường.

3. FE PeDetailTabs.tsx × 2 app ApprovalsTab: add Decision badge phân biệt
   Approve (emerald) / Trả lại (amber) / Từ chối (rose). Vì 3/4 mode Trả
   lại (OneLevel/OneStep/Assignee) giữ Phase=ChoDuyet → fromPhase→toPhase
   badge giống Approve. Decision badge bù visual phân biệt.

Verify:
- dotnet build clean 0 err 2 warn (pre-existing DocxRenderer)
- dotnet test 111/111 PASS
- npm build × fe-user + fe-admin PASS 0 TS err

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:45:25 +07:00
cdfd54212c [CLAUDE] PurchaseEvaluation: Plan AB Chunk A — fix Changelog visibility Bug 1 Budget Adjust + Bug 2 Return Mode
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 1m6s
- BE ApplyReturnModeAsync 4 mode add Changelog.Add() common path (refactor Drafter early return)
- FE PeDetailTabs.tsx HistoryTab filter extend cover Header+ngân sách (B1) + Workflow+Trả lại (B2)
- FE empty placeholder + comment update reflect new filter scope
- Mirror 2 app §3.9

Bug 1: Budget Adjust handler đã log (Header+Update) nhưng FE filter strict TraLai-only
Bug 2: Return mode Service không log Changelog — chỉ approval phase transition

Verify:
- Build clean 0 err
- npm build × 2 app pass 0 TS err
- 111 test baseline preserve (UAT skip test-after defer)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:07:44 +07:00
108268a2e2 [CLAUDE] FE-Admin FE-User: Chunk Q — Fix layout banner F3 violet mx-5 inset gap khiến button "+ Thêm hạng mục" lệch
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m15s
Bro UAT screenshot 2026-05-15 sau Plan O+P deploy: PE/2026/A/025 Phase=ChoDuyet
actor NV Test có F3 AllowApproverEditDetails=TRUE — banner violet "Bạn được
phép chỉnh sửa Hạng mục / NCC / Báo giá" render ĐÚNG nhưng layout:

```
[Section padding px-5 = 20px]
   [Banner mx-5 inset 20px both sides]  ← gap 20px right edge
[ItemsTab header flex justify-between]
   [text "1 hạng mục..."]    [Button "+ Thêm hạng mục"]
```

Banner mx-5 đẩy inset 20px khỏi Section padding x-5 → tạo gap visual 20px
bên phải banner. Phía dưới gap đó là button right-aligned (full Section
width) → trông button "lệch" so với banner end + có khoảng trắng phía trên.

Fix mirror 2 app (rule §3.9):

```diff
-     <div className="mx-5 mt-2 rounded border border-violet-200 bg-violet-50 px-3 py-2 text-[11px] text-violet-800">
+     <div className="mb-3 rounded border border-violet-200 bg-violet-50 px-3 py-2 text-[11px] text-violet-800">
```

- `mx-5` → drop (banner full Section padding width)
- `mt-2` → `mb-3` (consistent spacing với ItemsTab header `mb-3` style)

Visual sau fix:
```
[Section padding px-5]
   [Banner full width]
   [ItemsTab header: text + button align Section right edge]
```

Button "+ Thêm hạng mục" align cùng phải edge với banner. KHÔNG còn gap visual.

Files (2 mirror):
- fe-user/src/components/pe/PeDetailTabs.tsx:218-223
- fe-admin/src/components/pe/PeDetailTabs.tsx:213-218

Verify:
- npm run build fe-user PASS clean (0 TS err, 7.67s)
- npm run build fe-admin PASS clean (0 TS err, 7.50s)

KHÔNG đụng BE. KHÔNG đụng logic. CSS layout polish only.

Pending: bro UAT verify layout fix + Plan P CICD Monitor verify F1+F2 wire
(spawn earlier, vẫn running).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:38:34 +07:00
508b17a43c [CLAUDE] FE-Admin FE-User: Chunk M3 — Rename Phase=TraLai display label "Trả lại" → "Cần chỉnh sửa lại"
Plan M Chunk M3 — UAT disconnect fix: bro UAT phát hiện label "Trả lại" + "Bản
nháp" không phân biệt rõ với end-user → rename Phase=TraLai (98) display label
sang "Cần chỉnh sửa lại" để self-descriptive.

Scope HẸP — chỉ status display reference (KHÔNG đụng action verb):
- types/purchaseEvaluation.ts × 2 app: PurchaseEvaluationPhaseLabel[98] +
  PeDisplayStatusLabel.TraLai = 2 const map rename
- components/pe/PeWorkflowPanel.tsx × 2 app: 2 inline literal hardcode trong
  F1 dialog tooltip `Phase → "..."` + confirm message `Phiếu sẽ về "..."` —
  status reference, KHÔNG phải action verb

KHÔNG đụng:
- Action button label `← Trả lại` (verb, giữ nguyên)
- F1 mode picker label `Trả về Người soạn thảo` (4 mode action, giữ nguyên)
- Comments narrative giữ rationale dev (rule §6.5)
- types/contracts.ts + types/budget.ts Phase 98 'Trả lại' — module Contract +
  Budget khác PE, ngoài scope M3

Mirror 2 app rule §3.9 strict applied.

Verify:
- npm run build fe-admin PASS clean (0 TS err, 9.40s)
- npm run build fe-user PASS clean (0 TS err, 6.92s)

Diff: +4/-4 LOC × 4 file = 8 LOC total

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:15:01 +07:00
f212f04365 [CLAUDE] FE-Admin FE-User: Chunk L3 — Fix Trả lại dialog default mode = first available F1 (mode đang gửi duyệt)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 48s
Bro UAT S23 t2 catch screenshot: tick AllowReturnToAssignee + untick AllowReturnToDrafter
cho slot Approver → user click "Trả lại" → dialog mở với default state `returnMode=Drafter`
(S17 backward compat fallback). Radio Drafter HIDDEN vì allowReturnToDrafter=false
→ user thấy radio Assignee đã pick + Bùi Lê Thủy Trà từ dropdown → click Xác nhận →
BE receive `returnMode: 4` (Drafter từ initial state) → throw "Cấp Approver hiện tại
không bật mode 'Drafter'. Liên hệ Admin Designer".

Bro intent: "cho duyệt trong muốn cho trả lại trong mode đang gửi duyệt chứ ko phải
draft, draft chỉ khi trả lại cho người soạn thôi" — 3 F1 modes (OneLevel/OneStep/
Assignee) là "trả lại trong mode đang gửi duyệt" (Phase=ChoDuyet lùi pointer);
Drafter mode = trả về Người soạn (Phase=TraLai), CHỈ default khi không có F1 nào.

Fix FE × 2 app PeWorkflowPanel.tsx (mirror rule §3.9):
- Import useEffect
- useEffect khi target=TraLai → compute first available F1 mode:
  - allowReturnOneLevel ? OneLevel
  - : allowReturnOneStep ? OneStep
  - : allowReturnToAssignee ? Assignee
  - : Drafter (fallback)
- setReturnMode(firstAvailable)

→ Dialog mở với mode đúng selected → user click Xác nhận → BE receive correct
mode → ApplyReturnModeAsync check correct flag → PASS.

Pattern lesson saved: dialog initial state phải compute từ permission flags
KHÔNG hardcode default — admin có thể disable mọi mode khác Drafter, hoặc
ngược lại enable F1 only.

Verify:
- npm run build × 2 app pass (0 TS err)
- Bundle hash rotate × 2 app

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:44:05 +07:00
10ddc8761b [CLAUDE] FE-Admin FE-User: Chunk L2 — Fix F4 BudgetAdjustSection bypass readOnly khi Approver scope (menu Duyệt)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Failing after 1m1s
Bro UAT S23 t2 catch: "Đã stick cho edit trong luồng duyệt nhưng trong menu
duyệt -> vẫn không edit đc ngân sách". Investigator audit root cause:
- BudgetAdjustSection canAdjust = !readOnly && (...) — `!readOnly` short-circuit
  block F4 logic
- Menu Duyệt route truyền readOnly=true xuống PeDetailTabs → button "Điều chỉnh"
  hidden dù admin đã tick AllowApproverEditBudget cho slot + actor match
- F3 wire ItemsTab ĐÚNG via `itemsReadOnly = readOnly && !approverEditMode`
  pattern bypass — F4 không follow same pattern

Refactor canAdjust × 2 app (rule §3.9 mirror):
```
- canAdjust = !readOnly && (isAdmin || (isDrafter && isDrafterPhase) || isApproverChoDuyet)
+ canAdjust = isAdmin
+   || (!readOnly && isDrafter && isDrafterPhase)
+   || isApproverChoDuyet
```

→ F4 Approver scope (Mig 30) BYPASS readOnly:
- Admin: bypass readOnly (full quyền)
- Drafter (Nháp/TraLai): chỉ Workspace (readOnly=false)
- Approver ChoDuyet + flag tick + actor match: bypass readOnly → button "Điều chỉnh"
  visible trong menu Duyệt

Mirror F3 pattern (itemsReadOnly line 118). F4 wire S22+5 ban đầu miss BYPASS
pattern — fixed S23 t2.

Verify:
- npm run build × 2 app pass (0 TS err, bundle hash rotated)
- Bro UAT verify: tick F4 → vào menu Duyệt → click "Điều chỉnh ngân sách"
  → modal open editable

Pattern lesson saved memory: per-NV admin opt-in flag wire RULE — FE bypass
readOnly khi flag tick + actor match + phase match (mirror F3 itemsReadOnly).
F4 BudgetAdjustSection retroactive fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:39:21 +07:00
f3db9e6cc0 [CLAUDE] PurchaseEvaluation: Chunk L1 — Fix F2 skipToFinal semantic: skip pointer tới NV cuối (KHÔNG terminate DaDuyet)
Bro UAT S23 t2 catch: Plan K K2 implement F2 SAI semantic — set
Phase=DaDuyet terminal auto-approve. Bro intent: "Duyệt thẳng đến CEO,
bỏ qua các bước khác chứ ko phải chuyển sang đã duyệt."

Refactor Service.cs ApproveV2Async F2 branch:
- Resolve lastStepIdx = steps.Count - 1, lastLevelMaxOrder = max(LevelOrder)
  trong Step cuối
- Advance pointer: CurrentWorkflowStepIndex = lastStepIdx + CurrentApprovalLevelOrder = lastLevelMaxOrder
- Phase GIỮ NGUYÊN ChoDuyet — NV cuối (CEO/last approver) vẫn cần ký thật
  để tiến DaDuyet
- Audit log "Approver skip thẳng tới Bước X Cấp Y (NV cuối) — bỏ qua các Bước/Cấp trung gian"
- Guard no-op: actor đã ở slot cuối → fall through advance logic (normal → DaDuyet)
  (KHÔNG double-advance khi skipToFinal=true ngay slot cuối)
- Reset SLA 7d cho NV cuối nhận lại

FE × 2 app PeWorkflowPanel.tsx (mirror rule §3.9):
- Description text update: "Phiếu sẽ skip tới NV cuối (CEO/cấp ký cuối) —
  NV cuối vẫn cần duyệt thật để hoàn tất."
- Amber warning update: "Bỏ qua mọi Cấp/Bước trung gian, phiếu chuyển thẳng
  tới NV cuối. NV cuối vẫn phải ký duyệt thật để phiếu thành 'Đã duyệt'."

Verify:
- dotnet build production projects clean (0 err, 2 pre-existing warn)
- npm run build × 2 app pass

Pattern lesson saved memory: Service skipToFinal semantic = advance pointer
NOT terminate. K7 tests TODO update: 3 Approver F2 tests assert pointer
moved to last slot, NOT Phase=DaDuyet. Defer test fix sau UAT confirm UX.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:39:03 +07:00
ebe2469470 [CLAUDE] FE-Admin FE-User: Chunk E — K6 Workspace DROP Drafter checkbox + ADD Approver toggle (Mig 31 F2 refactor)
Plan K Chunk E mirror 2 app rule §3.9. Refactor F2 UX flow:

DROP fe-admin + fe-user Workspace Drafter checkbox:
- PeDetailTabs.tsx Workspace action bar: REMOVE "Gửi thẳng Cấp cuối (skip trung gian)"
  violet label + state skipToFinal + allowSkipToFinal lookup + skipToFinal payload
- submitForApproval mutation signature simplify: opts: { skipToFinal: boolean } → void
- Confirm dialog text + button label drop skipToFinal conditional

ADD fe-admin + fe-user Approver toggle trong PeWorkflowPanel dialog:
- State skipToFinalApprover default false
- Visible khi Approve forward (NOT Cancel + NOT SendBack) + currentLevelOptions?.allowApproverSkipToFinal
- Checkbox violet panel với description "Phiếu sẽ tiến thẳng tới Đã duyệt (terminal)"
- Amber warning khi checked: "Hành động KHÔNG quay lại được"
- Mutation payload +skipToFinal: !isReject && skipToFinalApprover
- onSuccess reset state

Type ApprovalWorkflowOptions × 2 app: +allowApproverSkipToFinal: boolean (7th)
Type PeDetailBundle × 2 app: REMOVE drafterAllowSkipToFinal field + comment Mig 29+30+31

UX design Dialog approach (consistent với Trả lại Mode picker pattern):
- Skip thẳng Cấp cuối = destructive action → confirm dialog amber warning
- Mirror Mig 28 Trả lại 4 mode picker UX consistency
- Em main solo K6 per UX flow decision criteria

Per bro decision Plan K S23 t1: "Chỗ cấu hình cho phép skip → duyệt thẳng cho phép
trong trạng thái đang duyệt" + "Tất cả đều cấu hình ngay trong chỗ setup quy trình duyệt".

Verify:
- npm run build × 2 app pass clean (0 TS err)
- Pre-existing warnings unchanged (chunk size + INEFFECTIVE_DYNAMIC_IMPORT)
- Bundle hash rotated × 2 app

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 23:34:39 +07:00
b04a11a62f [CLAUDE] FE-PE: S22+5 Chunk B — Designer checkbox +AllowApproverEditBudget per slot + Section read flag (mirror 2 app)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m23s
FE Admin Designer (ApprovalWorkflowsV2Page.tsx):
- LevelDto + EditLevelEntry +allowApproverEditBudget
- copyFromDefinition + makeDefaultLevelEntry propagate default false
- POST body include allowApproverEditBudget cho mỗi Level slot
- NEW checkbox UI per Level inline panel:
  "Cho phép chỉnh sửa Section ngân sách lúc đang duyệt"
  (col-span-2, mirror pattern allowApproverEditDetails Mig 29)

FE Types mirror 2 app:
- fe-admin + fe-user `ApprovalWorkflowOptions` +allowApproverEditBudget

FE BudgetAdjustSection refactor (mirror 2 app):
- Trước: isApproverChoDuyet = phase ChoDuyet + actor in approvers
- Sau: isApproverChoDuyet = phase ChoDuyet + actor in approvers
  + currentLevelOptions.allowApproverEditBudget=true (per slot opt-in)
- Drafter scope Nháp/Trả lại unchanged
- Admin bypass unchanged

UX impact:
- Admin Designer phải tick checkbox cho NV slot mới được edit ngân sách lúc duyệt
- Nếu KHÔNG tick → button "Điều chỉnh" trong Section 5 KHÔNG hiện cho approver
- Drafter vẫn edit bình thường khi phiếu Nháp/Trả lại

Verify:
- npm run build fe-admin — 569ms pass
- npm run build fe-user — 528ms pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 23:12:43 +07:00
30d51c89bb [CLAUDE] FE-PE: S22+4 Chunk B — Attachment preview dialog + View button + Section "Điều chỉnh ngân sách" (mirror 2 app)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m26s
Feature 1 (FE attachment preview):
- NEW component `AttachmentPreviewDialog.tsx` (shared 2 app):
  * Fetch BE `/view` endpoint as blob → object URL (bearer auth qua axios)
  * Render iframe (PDF) hoặc img (image) trong Dialog size=lg
  * Helper `isPreviewable(fileName)` check ext PDF/PNG/JPG/JPEG/WEBP/GIF
- Update `SupplierAttachmentsCell` (per-NCC quote files):
  * Click filename KHÔNG còn trigger download — chuyển sang explicit buttons
  * Eye violet button "Xem trước" khi previewable
  * Download brand button cạnh bên (always visible)
- Update `GeneralAttachmentsSection` (bảng so sánh general):
  * Same pattern: Eye + Download split buttons
- Word/Excel (.doc/.docx/.xls/.xlsx) → download-only (UAT users mở local Office)
- Mirror fe-admin + fe-user (rule §3.9)

Feature 2 (Section "Điều chỉnh ngân sách"):
- NEW component `BudgetAdjustSection` in PeDetailTabs (mirror 2 app)
- Section 5 cuối Detail view sau "4. Ý kiến cấp duyệt"
- canAdjust 3 scope:
  * Admin → bypass
  * Drafter của phiếu + Phase DangSoanThao/TraLai
  * Approver currentLevel (match approvalFlow.approvers) + Phase ChoDuyet
- 2 mode edit: Select Budget link OR Manual amount + name
- Banner amber khi Approver điều chỉnh trong duyệt (audit notice)
- Save → PATCH /api/purchase-evaluations/{id}/budget-adjust (Chunk A BE)
- History display defer S22+5 (changelogs fetch separate endpoint, không có
  trong PeDetailBundle — UAT user xem Panel 3 "Lịch sử thay đổi")

Verify:
- npm run build fe-admin — 577ms pass
- npm run build fe-user — 550ms pass
- dotnet test SolutionErp.slnx — 104/104 PASS regression-free

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 22:32:56 +07:00
40f64c6b32 [CLAUDE] PE-Workflow: UAT S22+1 — disable cả 3 button khi không quyền + BE guard
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m29s
User UAT feedback: "Nếu đã không được quyền thao tác thì ko được quyền thao tác
hết tất cả các hành động" — trước đây chỉ "Duyệt" disabled, "Trả lại" + "Từ chối"
vẫn enabled (design intent S17 cũ).

FE 2 app mirror (PeWorkflowPanel.tsx):
- `isDisabled = blockedByV2Level` (drop `isForwardApprove &&` qualifier)
- Tooltip update "mới thao tác được (Duyệt / Trả lại / Từ chối)"
- Comment refresh ghi UAT S22+1 spec + cross-ref BE EnsureCanRejectV2Async

BE defense-in-depth (PurchaseEvaluationWorkflowService.cs):
- Helper mới `EnsureCanRejectV2Async` mirror FE actorInV2Level logic:
  Skip silent khi admin/V1/non-ChoDuyet/no actor/no pointer. Throw
  ForbiddenException khi V2 + ChoDuyet + actor != currentLevel.ApproverUserId.
- Invoke ở top Reject branch (cover cả TuChoi + Trả lại sub-branches).
- Chặn request forge: non-approver gọi PATCH /transitions direct sẽ 403.

Test (test-before §7 — security guard critical algorithm):
- ReturnMode tests existing 7/7 vẫn PASS (a2.Id = currentLevel approver, guard accept)
- +1 NEW test `Reject_NonApprover_V2_Throws_ForbiddenException` — outsider
  Drafter role gọi Reject phiếu V2 → throw + Phase không mutate

Verify:
- dotnet test SolutionErp.slnx — 104/104 PASS (+1 guard regression)
  Δ: 103 → 104
- npm run build × 2 app — pass (482ms + 583ms)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 21:46:51 +07:00
5ccb2a7057 [CLAUDE] FE-PE: S21 t5 Chunk C — eOffice read currentLevelOptions + drafterAllowSkipToFinal (per-NV) mirror 2 app
Types refactor `fe-{admin,user}/src/types/purchaseEvaluation.ts`:
- `ApprovalWorkflowOptions` REMOVE allowDrafterSkipToFinal (F2 đã move per-User).
  Còn 5 flag (F1 4 mode + F3 EditDetails).
- `PeDetailBundle`:
  - RENAME `workflowOptions` → `currentLevelOptions` (clearer semantic per-slot)
  - ADD `drafterAllowSkipToFinal: boolean` (BE resolve từ DrafterUserId → User entity)

PeWorkflowPanel.tsx (mirror 2 app):
- RENAME local var `wfOptions` → `levelOptions`
- READ `evaluation.currentLevelOptions` (Cấp hiện tại)
- 4 mode radio render conditional theo levelOptions.allowReturnXxx (unchanged
  logic, just rename source)

PeDetailTabs.tsx (mirror 2 app):
- F3 approverEditMode: READ `evaluation.currentLevelOptions?.allowApproverEditDetails`
  thay vì workflowOptions.allowApproverEditDetails (semantic per-NV slot)
- F2 allowSkipToFinal: READ `evaluation.drafterAllowSkipToFinal` thay vì
  workflowOptions.allowDrafterSkipToFinal (semantic per-Drafter user)

Backward compat verified:
- Phiếu cũ trước Mig 29 vẫn return currentLevelOptions populated (BE backfill
  Mig 29 đã copy 5 Allow* per Level)
- drafterAllowSkipToFinal: BE backfill chỉ TRUE cho user từng Drafter PE link
  workflow.AllowDrafterSkipToFinal=true (preserve admin config S21 t4)
- Phiếu V1 legacy: currentLevelOptions=null → FE fallback chỉ Drafter mode

Verify:
- npm run build × 2 app pass (fe-user 450ms + fe-admin 439ms, cache hot)
- 0 TS6 err, warning chunk size pre-existing

Pending Chunk D: Docs (schema-diagram §14 update + STATUS + HANDOFF + session log).
Note: User Management page chưa có F2 checkbox UX (defer commit sau khi admin
UAT request — BE field đã có, FE chỉ cần thêm 1 toggle vào UserEdit dialog).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 20:09:31 +07:00
d27caafcf5 [CLAUDE] FE-PE: Chunk D — eOffice Trả lại modes + Skip CEO + Approver edit Section 2 (F1+F2+F3) mirror 2 app
Types (fe-{admin,user}/src/types/purchaseEvaluation.ts):
- ApprovalWorkflowOptions type (6 boolean Allow* flag)
- WorkflowReturnMode const-object {OneLevel,OneStep,Assignee,Drafter}
- PeDetailBundle +workflowOptions field (null nếu V1 legacy)

PeWorkflowPanel.tsx F1 (mirror 2 app):
- State returnMode + returnTargetUserId thêm vào transition mutation payload
- Dialog Trả lại render radio list 1-4 mode enabled theo workflowOptions:
  • Trả về 1 Cấp trước (lùi pointer trong cùng Bước, peer review)
  • Trả về 1 Bước trước (Cấp cuối Bước trước nhận lại)
  • Trả về Người chỉ định (pick từ dropdown NV đã ký levelOpinions)
  • Trả về Người soạn thảo (default Drafter S17 fallback)
- Banner amber rounded box dưới radio list mô tả hành vi mode chọn
- onSuccess reset returnMode về Drafter + returnTargetUserId null

PeDetailTabs.tsx F2 (mirror 2 app):
- State skipToFinal + allowSkipToFinal (từ workflowOptions)
- submitForApproval mutationFn accept opts.skipToFinal → POST body
- Workspace action bar: thêm checkbox violet "Gửi thẳng Cấp cuối (skip trung gian)"
  hiển thị conditional theo allowSkipToFinal + canSubmitForApproval
- Confirm dialog message dynamic: "Gửi thẳng" warning vs default tuần tự
- Button label dynamic: "Lưu & Gửi thẳng CẤP CUỐI →" vs "Lưu & Gửi Duyệt →"

PeDetailTabs.tsx F3 (mirror 2 app):
- useAuth import + compute approverEditMode (phase=ChoDuyet +
  workflow.AllowApproverEditDetails + actor match currentApproval.approvers)
- itemsReadOnly = readOnly && !approverEditMode → ItemsTab nhận
- Banner violet "ⓘ Bạn được phép chỉnh sửa Hạng mục/NCC/Báo giá" khi
  approverEditMode + readOnly (Duyệt menu) — UX nhắc về quyền extended

InfoTab + NccSelectorRow + BudgetFieldRow GIỮ strict isEditablePhase (KHÔNG
trong F3 scope — Header section + Section 3 winner KHÔNG cho Approver edit).

Verify:
- npm run build × 2 app pass (fe-user 7.52s, fe-admin 499ms cached)
- 0 TS6 err, warning chunk size pre-existing
- BE Chunk B đã accept skipToFinal + returnMode + returnTargetUserId trong
  TransitionPurchaseEvaluationCommand → wire E2E complete

Pending Chunk E: Docs schema-diagram §14 update + STATUS + HANDOFF + session log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 19:08:08 +07:00
4b29d00716 [CLAUDE] FE-PE: Chunk B — Fix button "Trả lại" gửi decision=Approve thay vì Reject (gotcha #45) mirror 2 app
Bug pattern: button "← Trả lại" trong PeWorkflowPanel.tsx hiển thị đúng label
(L205-207 isSendBack include TraLai) NHƯNG payload `isReject` (L64-66) thiếu
nhánh TraLai → gửi decision=1 (Approve) thay vì 2 (Reject) khi target=TraLai
(98). BE Service vào APPROVE STEP → ApproveV2Async UPSERT opinion "đã duyệt"
+ advance Cấp tiếp theo. User UAT thấy: "Trả về nhưng hệ thống vẫn duyệt".

Inconsistency thứ 2: dialog `isSendBack` (L247-248) cũng thiếu nhánh TraLai
→ dialog title fallback `✓ Duyệt → Trả lại` + KHÔNG hiển thị amber warning.

Fix 3 chỗ × 2 app (fe-user + fe-admin, rule §3.9 mirror):
1. `isReject` payload — thêm nhánh `target=TraLai && phase!=TraLai`
2. dialog `isSendBack` — thêm nhánh TraLai + guard phase != TraLai
3. Comments document context bug + cross-ref BE guard Chunk A

Sync với BE guard (Chunk A `de00887` `PurchaseEvaluationWorkflowService.cs`):
- BE throw ConflictException khi target ∈ {TraLai, TuChoi} && decision != Reject
- 2 phía cùng đúng → no payload mismatch

Verify:
- npm run build × 2 app pass (fe-user 17.91s, fe-admin 6.71s, 0 TS6 err)
- Warning chunk size pre-existing (NOT introduced)

Pending Chunk C: docs gotcha #45 + STATUS + HANDOFF + session log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:43:20 +07:00
6e338f745e [CLAUDE] FE: Responsive cho laptop màn hình nhỏ — sidebar slim + Section/HangMucCard padding tighter + workspace 2-panel breakpoint
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m13s
User Session 20 turn 11: "giao diện hiện tại chưa đáp ứng tốt cho laptop màn
hình nhỏ -> Căn chỉnh lại nhé."

Pain points trên laptop 1280-1366px viewport (fe-user content panel
1280-288=992px hoặc fe-admin workspace 2-panel content còn ~672px):
- Sidebar 288px chiếm nhiều
- PE Workspace list panel 320px = thừa
- Section padding px-5 + HangMucCard p-3 cộng gộp tốn ~16-20px mỗi cell
- Inline NCC table 7 cột bị compressed

FE-only mirror fe-admin + fe-user. Targeted fixes (no breaking change):

### 1. Sidebar slim — w-60 (240px) lg/xl giảm xuống → bump xl:w-72
- fe-admin Layout aside: `w-72` → `w-60 xl:w-72`
- fe-user Layout aside: `w-72` → `w-60 xl:w-72`
- Trên màn ≥xl (1280px+) → giữ 288px như cũ
- Trên màn <xl (laptop nhỏ) → 240px, save 48px cho content

### 2. PE Workspace 2-panel list breakpoint
- `lg:grid-cols-[320px_1fr]` → `lg:grid-cols-[260px_1fr] xl:grid-cols-[320px_1fr]`
- Trên lg (1024-1279): list 260px (đủ pick) → content +60px
- Trên xl+ (1280+): list 320px như cũ
- Save total: ~60px cho NCC table render

### 3. Section + HangMucCard padding responsive
- Section component `<section className="px-5 py-4">`
  → `px-3 py-3 sm:px-5 sm:py-4` (xs/sm: tighter 12px each side, save 16px width)
- HangMucCard header `flex items-start gap-3 ... p-3`
  → `flex flex-wrap items-start gap-2 ... p-2 sm:gap-3 sm:p-3`
  → +flex-wrap: stat "Số tiền NS" wrap xuống dòng khi container hẹp
- HangMucCard expand panel `p-3` → `p-2 sm:p-3`

Net width gain trên laptop 1366px (typical):
- Sidebar slim: +48px
- Workspace list: +60px
- Section padding: +16px
- HangMucCard padding: +8px
Total ~+132px cho NCC table area render comfortable thêm 1-2 cột

KHÔNG đụng dialog widths, schema BE, hoặc semantic breakpoints lớn.

Verify:
- npm run build × fe-admin pass
- npm run build × fe-user pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:20:01 +07:00
66551db4d8 [CLAUDE] FE-PE: AddSupplierDialog auto-fill từ master khi chọn NCC
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m0s
User Session 20 turn 10: chọn NCC từ dropdown master → auto-load các field
đã có sẵn (contactPerson/phone/email/note) vào form, đỡ phải nhập tay lại.

FE-only mirror fe-admin + fe-user.

AddSupplierDialog dropdown "NCC (master)" onChange:
  - Lookup suppliers.data find(s => s.id === selectedId) → master row
  - setForm prev → ghi đè 4 field:
    * contactName ← picked.contactPerson ?? ''
    * contactPhone ← picked.phone ?? ''
    * contactEmail ← picked.email ?? ''
    * note ← picked.note ?? ''
  - KHÔNG đụng displayName / paymentTermText / thanhTien (manual cho user)
  - Hint "✓ Đã tự điền từ Master — bạn có thể sửa lại nếu cần." text-[10px]
    text-emerald-600 dưới dropdown khi đã chọn supplier

Mapping master Supplier → PE.Supplier fields (skip address vì không có
field tương ứng — có thể nhét vào note nếu user cần, manual).

User vẫn override các field auto-fill được sau đó (input bình thường).
Đổi supplier giữa lúc đã chỉnh tay → re-fill từ master mới (mặc định ghi đè).

Verify:
- npm run build × fe-admin pass
- npm run build × fe-user pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:03:33 +07:00
83aae8ea64 [CLAUDE] FE-PE: Winner NCC revert badge → icon ✓ đậm + hover transition
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m50s
User Session 20 turn 9: bỏ badge "🏆 Trúng thầu" emerald-600 rounded-full
text-white, revert về icon stick ✓ prefix như cũ nhưng:
- Đậm hơn: text-base font-bold text-emerald-700
- Tên NCC khi winner: text-emerald-900 đậm
- Row hover transition: hover:bg-emerald-200/70 (winner) +
  hover:bg-white/80 hover:shadow-sm (non-winner palette)
- Transition smooth qua `transition` class

NCC row visual khi winner:
  - border-l-emerald-500 (giữ)
  - bg-emerald-100/70 (giữ)
  - font-semibold + shadow-sm + ring-1 ring-inset ring-emerald-300 (giữ)
  - +hover:bg-emerald-200/70 (mới — sáng lên hover)
  - Prefix ✓ text-base font-bold emerald-700 (đậm hơn icon cũ)
  - Tên NCC text-emerald-900 (đậm hơn slate-900 mặc định)

NCC row non-winner:
  - palette cycle (blue/purple/sky/teal/pink) giữ
  - +hover:bg-white/80 hover:shadow-sm (mới — nổi nhẹ khi hover)

Mirror fe-admin + fe-user.

Verify:
- npm run build × fe-admin pass
- npm run build × fe-user pass

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