UAT anh Kiet FDC 07-28 "cho nay lay dia chi len luon giup anh". Do lai: co-che
auto-fill Dia diem tu Project.Location DA WIRE tu S59 va van chay dung (BE
ProjectFeatures.cs:51 project Location -> FE types master.ts:97 -> onChange
SearchableSelect). O trong vi DU AN THIEU DU LIEU: prod 57/62 du an co
Location NULL, gom ca BVN01 trong anh chup. Chi 5 du an co dia chi (CAL01,
MIDEA01, SAM01, TLB01, ZOTE01) - dung 5 dong co dia chi trong Excel S55.
=> Khong sua co-che (khong hong). Them dong canh bao amber khi da chon du an
ma du an do khong co Location: noi thang ly do + tro cho bo sung (Danh muc Du
an -> Dia diem), thay vi de o trong im lang trong nhu he thong hong.
4 file, SHA256 mirror fe-user/fe-admin giu IDENTICAL. npm build 2/2 PASS.
Backfill 57 dia chi con lai = can du lieu tu anh/FDC.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anh chốt "không chọn quy trình thì không cho tạo phiếu, ràng mấy cái rủi ro lại hết":
- Form TẠO: nút "Tạo phiếu" disabled khi thiếu (Quy trình duyệt / Hạng mục / Dự án) + hint
ĐỎ liệt kê rõ còn thiếu gì (✓ xanh khi đủ). Defense-in-depth với BE validator NotEmpty (S83).
- Detail (D4): checklist xanh ✓ "đã khai" / đỏ ✗ "chưa khai" cho 4 trường bắt buộc gửi duyệt
(NCC winner · giá>0 · ngân sách · bảng so sánh) hiện phía trên nút "Lưu & Gửi Duyệt"
(mirror missingForApproval predicate, khớp annotation anh Kiệt "xanh=đã khai, đỏ=chưa khai").
FE-only 2 component × 2 app SHA-identical. Both build PASS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
- 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>
- 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.
User Session 20 turn 6 screenshot: chế độ "Nhập tay (không link)" Section 2
b. Ngân sách vẫn còn input "Tên (vd Tạm tính T11/2025)" cùng số tiền. User
chỉ cần nhập số tiền — bỏ Tên + áp VND format consistent.
3 file × 2 app = 6 file FE update:
- PeDetailTabs.tsx BudgetFieldRow (Section 2 detail editor)
- PeWorkspaceCreateView.tsx (workspace mode "new")
- PeHeaderForm.tsx (Create/Edit header page)
Mỗi file:
- Drop Input "Tên ngân sách" UI khỏi manual mode (state field giữ '' để
backward compat — BE save luôn null)
- Manual mode UI giờ chỉ 1 input số tiền (max-w-xs):
* type="text" inputMode="numeric" + value={formatVndInput(amount)}
* onChange={parseVnd} strip non-digit → number
* Suffix "đ" tuyệt đối inset-y-0 right-3
* Hint "VND — nhập số, tự format dấu chấm ngàn (vd 1.000.000)"
- Helpers parseVnd + formatVndInput inline mỗi file (mirror PeDetailTabs)
PeDetailTabs BudgetFieldRow cleanup:
- Drop state manualName + setManualName
- Drop manualName từ dirty check
- Save payload: budgetManualName: null luôn (không phụ thuộc state)
- Hủy thay đổi: drop reset manualName line
Read-only display (legacy data) giữ ev.budgetManualName nếu data cũ có tên
(đoạn render khi !canEdit) — không xóa hiển thị, chỉ ẩn input UI.
BE schema KHÔNG đụng — endpoint PUT /pe/:id vẫn nhận budgetManualName field,
chỉ FE luôn gửi null.
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>
Hai yêu cầu UAT 2026-05-08:
1. Bỏ "(clone)" auto-append khi clone version mới — version đã đủ phân biệt.
2. Thêm pin toggle để admin chọn workflows nào cho user pick lúc tạo phiếu.
Migration 25 AddIsUserSelectableToApprovalWorkflows:
- ALTER ApprovalWorkflows ADD IsUserSelectable bit NOT NULL DEFAULT 0
- UPDATE backfill SET IsUserSelectable=1 WHERE IsActive=1 (giữ behavior cũ
cho active versions, archived = false default — admin tự pin nếu cần)
BE:
- Domain ApprovalWorkflow +property IsUserSelectable
- DTO AwDefinitionDto +field
- CreateAwDefinitionCommandHandler set default true cho version mới
- New SetAwUserSelectableCommand + Handler
- API PATCH /api/approval-workflows-v2/{id}/user-selectable (Workflows.Create policy)
- DbInitializer SeedSampleApprovalWorkflowsV2Async set IsUserSelectable=true
FE Designer (fe-admin):
- DefinitionDto +isUserSelectable
- Badge amber "Pin Cho user chọn" khi true (cạnh Đang áp dụng/Archived)
- Button "Pin/PinOff Ghim cho user / Bỏ ghim" trong action group + mutation toggle
- Auto-fill name khi clone: bỏ "(clone)" suffix → giữ nguyên name
FE Workspace (fe-admin + fe-user):
- approvalWorkflows query filter w.isUserSelectable === true
- User dropdown chỉ thấy workflows admin đã pin
Verify: dotnet build pass · 81 test pass · npm build × 2 pass · Mig 25 apply LocalDB OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User feedback: thay field "Loại quy trình (theo menu — khóa)" disabled
→ Select dropdown cho User pick quy trình ApprovalWorkflowsV2 (Mig 22)
ngay từ workspace tạo mới. Hiển thị "Mã + Tên + Version".
BE Domain:
- PurchaseEvaluation +ApprovalWorkflowId Guid? (nullable, FK Restrict)
- EF Configuration: Index + FK Restrict to ApprovalWorkflows
- Migration 23 `AddApprovalWorkflowIdToPurchaseEvaluation` (1 ALTER +
1 IX + 1 FK), applied cả _Design + _Dev LocalDB
- Field WorkflowDefinitionId (Mig 21 legacy) giữ song song để Service
PE chạy logic cũ tới khi Session sau wire qua schema mới
BE Application:
- CreatePurchaseEvaluationCommand +ApprovalWorkflowId? Guid? optional
param (default null)
- Validate: nếu set, phải tồn tại + ApplicableType khớp PE.Type
(DuyetNcc=1 → ApprovalWorkflowApplicableType.DuyetNcc, etc)
- Handler set entity.ApprovalWorkflowId từ request
- UpdatePurchaseEvaluationDraftCommand mirror — cho User đổi quy trình
khi sửa Nháp/Trả lại (validate same)
- PurchaseEvaluationDetailBundleDto +ApprovalWorkflowId/Code/Name/Version
- GetPurchaseEvaluationByIdQuery handler load workflow info join
- Update Phase guard: cho sửa cả DangSoanThao + TraLai (Trả lại =
editable per Session 17 spec)
FE (cả 2 app mirror):
- types/purchaseEvaluation.ts: PeDetail +approvalWorkflowId/Code/Name/Version
- PeWorkspaceCreateView.tsx:
- Replace field disabled "Loại quy trình" → Select bắt buộc
- useQuery `/api/approval-workflows-v2?applicableType=N` filter theo
defaultType (1=DuyetNcc / 2=DuyetNccPhuongAn)
- Display option: "QT-DN-V2-001 v01 — Quy trình Duyệt NCC (đang áp dụng)"
- List cả version active + archived (UAT cần test compare)
- Empty state hint amber "Chưa có quy trình, vào /system/approval-workflows-v2"
- canSubmit require approvalWorkflowId set
- POST payload include approvalWorkflowId
Verify: dotnet build OK · 81 test pass · npm build × 2 OK · Mig 23 applied
cả 2 LocalDB.
Logic Service PE chưa wire qua ApprovalWorkflowId — vẫn pin
WorkflowDefinitionId Mig 21 legacy chạy. Session sau wire Service iterate
ApprovalWorkflowSteps + match approver theo schema V2 + drop legacy.
CI run #125 + #126 fail (red ❌ Gitea Actions) do TS compile errors trong commit
`18ebfa1` + `0c5db13` không catch local (UAT skip-verify rule). Errors:
PeListPanel.tsx:41 — Property 'forcedPhase' does not exist (renamed to
editableOnly nhưng quên xóa khỏi destructuring args list)
PeListPanel.tsx:81,106 — Cannot find name 'editableOnly' (do destructuring
vẫn dùng forcedPhase cũ → editableOnly không được declare ở scope)
PeWorkspaceCreateView.tsx:20 — 'PurchaseEvaluationType' declared but never
read (sau khi đổi <Select> Loại quy trình → <Input disabled> chỉ dùng
PurchaseEvaluationTypeLabel, không cần enum value nữa)
Fix:
~ PeListPanel × 2 app: destructuring `forcedPhase,` → `editableOnly = false,`
~ PeWorkspaceCreateView × 2 app: bỏ `PurchaseEvaluationType` khỏi import
Verify: npm run build fe-admin + fe-user pass · 0 TS error · dotnet test 83
vẫn pass (Migration 17 + TraLai phase enum đã verify trước).
UAT mode rule: vẫn skip verify cho task FE-only nhỏ — nhưng phát hiện
multi-rename refactor + bỏ import nên check `npm run build` 1 lần trước commit.
TODO update memory feedback_uat_skip_verify.md thêm exception khi prop rename
hoặc remove unused import.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User feedback 2026-05-07 (annotation screenshot):
1. "Gán cứng Duyệt NCC hoặc Duyệt NCC và Giải pháp theo đúng Menu" — Loại quy
trình lock theo URL ?type=N (user vào menu nào → loại đó, không chọn lại).
2. "Chỗ này vẫn hiểu code sửa lại thành select" — Điều khoản thanh toán đổi từ
Textarea (JSON code-style placeholder) → Select preset options + "Khác".
Implementation:
~ PeWorkspaceCreateView.tsx (× 2 app)
- Loại quy trình: <Select> editable → <Input disabled> hiển thị
PurchaseEvaluationTypeLabel[type] với bg-slate-100. Label đổi sang
"Loại quy trình (theo menu — khóa)" rõ ý đồ.
- Điều khoản thanh toán: <Textarea> JSON → <Select> với 8 preset:
"100% sau khi nghiệm thu" / "Tạm ứng 30% / 70%" / "Tạm ứng 50% / 50%" /
"TGN-30 ngày" / "TGN-45" / "TGN-60" / "Tiến độ theo đợt" / "Bảo hành 5%"
+ last option "Khác (nhập tay)" → khi chọn show Input text custom.
- Bỏ import Textarea (không dùng nữa).
- paymentMode local state điều khiển select; form.paymentTerms vẫn save text.
UAT mode: skip verify, push ngay.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>