wal: flush 20260714T1100
This commit is contained in:
@ -0,0 +1,38 @@
|
||||
# Spec — PE duyệt cấp cuối: chọn CẢ Min và Max (duyệt theo khoảng)
|
||||
|
||||
> `/fable-real investigator-codebase` engine-đắt deep-pass — run 2026-07-14 (S117 task 2). Model lane: fable (0-garble, clean verdict). Lead verify: HĐ-gen linchpin CONFIRMED độc-lập (`CreateContractFromEvaluationFeatures.cs:88-90` GiaTri=SUM selected NCC quotes, grep ApprovedPrice=0-match). Owner: "làm theo hướng dẫn của nó luôn".
|
||||
|
||||
## ① Tính-năng / đề-bài
|
||||
anh Kiệt FDC: ô "CHỌN GIÁ CHỐT (DUYỆT THEO GIÁ ĐỀ XUẤT)" khi duyệt cấp cuối hiện radio Ncc/ProMin/ProMax/Ccm — chọn ĐÚNG 1. Yêu cầu: **khi PRO có cả Min & Max → cho chọn CẢ HAI (duyệt theo khoảng [Min,Max])**. "Chọn cả 2 min và max."
|
||||
|
||||
## ② Cách implement — MODEL A (investigator khuyến nghị, verify OK)
|
||||
Thêm nullable `ApprovedPriceMaxAmount` + source token `"ProMinMax"` làm **radio thứ 5** (chỉ hiện khi PRO có CẢ Min+Max). Bất-biến: `ApprovedPriceMaxAmount != null ⟺ ApprovedPriceSource == "ProMinMax"` (Amount=Min, Max=Max). Source đơn giữ nguyên (Max=null). **1 migration AddColumn nullable, no new table, NO backfill** (phiếu cũ nguyên vẹn). **HĐ.GiaTri KHÔNG đổi** (không đọc giá chốt) — range thuần record-of-decision hiển thị.
|
||||
|
||||
**BE:**
|
||||
- Entity `PurchaseEvaluation.cs:97-98` +`decimal? ApprovedPriceMaxAmount`.
|
||||
- Config `PurchaseEvaluationConfiguration.cs` +`HasPrecision(18,2)`.
|
||||
- Migration `AddPeApprovedPriceRange` (Mig 66) 3-file.
|
||||
- Service `PurchaseEvaluationWorkflowService.cs`: `ValidApprovedPriceSources:950` +`"ProMinMax"`; `ApplyApprovedPriceOnFinalize:951-966` +param `decimal? maxAmount` (ProMinMax⇒require maxAmount≠null && amount≤maxAmount; source-đơn+maxAmount≠null⇒Conflict wire-bug; isSystem+null giữ); 3 call-site :858/:896/:928 + `ApproveV2Async:650-661` sig + `TransitionAsync:47-50` sig + pass-through :291.
|
||||
- Interface `IPurchaseEvaluationWorkflowService.cs:33-34` +`approvedPriceMaxAmount=null`.
|
||||
- `PurchaseEvaluationFeatures.cs`: Command +field; Validator (+ProMinMax vào Must; +Max≥0; +cross-rule Max⟺ProMinMax; Min≤Max); Handler pass; projection GetDetail +`e.ApprovedPriceMaxAmount`.
|
||||
- Controller `PurchaseEvaluationsController.cs`: `TransitionPeBody` +field; Send +field.
|
||||
- DTO `PurchaseEvaluationDtos.cs:285` +`ApprovedPriceMaxAmount`.
|
||||
|
||||
**FE (2-app):**
|
||||
- `types/purchaseEvaluation.ts` (⚠️ 2 app KHÔNG identical — sửa riêng) +`approvedPriceMaxAmount`.
|
||||
- `PeWorkflowPanel.tsx:134-141`: +candidate `{source:'ProMinMax', label:'PRO — cả Min và Max (duyệt theo khoảng)', amount:min, amountMax:max}` chỉ khi cả 2≠null; GIỮ radio; +`selectedPriceAmountMax`; submit +`approvedPriceMaxAmount`; render "min – max".
|
||||
- `PeDetailTabs.tsx:1661-1666` +`ProMinMax:'PRO Min–Max'`; :1850-1863 khi Max≠null render `min – max`.
|
||||
|
||||
## ③ Checklist (financial-critical → test-before merge, rules §7)
|
||||
- [ ] Entity + config + migration 3-file → ef update Dev.
|
||||
- [ ] Service allow-list + helper +param + 3 call-site + 2 sig + interface.
|
||||
- [ ] Command/Validator/Handler + Controller body + DTO + projection.
|
||||
- [ ] Tests (`PeApprovedPriceFinalizeTests` mirror): (a) ProMinMax happy set 2 field; (b) thiếu maxAmount→Conflict not-finalized; (c) min>max→Conflict; (d) source-đơn+maxAmount→Conflict; (e) 4 source đơn regression pass. `dotnet test`.
|
||||
- [ ] FE types ×2 → Panel ×2 mirror → DetailTabs ×2 mirror → npm build ×2 + SHA-check Panel/Tabs.
|
||||
- [ ] Smoke: duyệt cuối chọn range → detail "min – max"; phiếu cũ nguyên.
|
||||
|
||||
## Product-notes (resolved theo owner "làm theo hướng dẫn")
|
||||
- HĐ.GiaTri khi range = GIỮ NGUYÊN (SUM NCC quotes, không đọc giá chốt). Cảnh-báo-mềm GiaTri ngoài [Min,Max] = **out-of-scope** (feature riêng, flag cho anh Kiệt).
|
||||
- Range dùng chung 3 finalize path (level-finalize/ccm-delegation/all-steps) — tự có vì chung helper, OK.
|
||||
- UI = 1 radio "cả Min và Max" (khớp "chọn cả 2 min và max"), KHÔNG checkbox combo.
|
||||
- Latent (pre-existing, ghi nhận không sửa): winnerQuoteTotal âm S116 → validator ApprovedPriceAmount≥0 reject — ngoài scope.
|
||||
Reference in New Issue
Block a user