2.7 KiB
2.7 KiB
sub-implementer-backend-0 — INV-B pe-budget-freeze-daduyet (S133)
Role: implementer-backend. Task: implement TOÀN BỘ BE theo SPEC ② bước 1-8. T0 test ĐÃ TỒN TẠI + RED → mục tiêu TỰ GREEN, KHÔNG sửa test.
Anchors verified (re-grep TRƯỚC edit — line trôi nhẹ)
- Domain
PurchaseEvaluation.cs: props end ~:112 (EndedByLevelFinalize). Append 11 ApprovedBudget* props. PurchaseEvaluationConfiguration.cs: precision block :24-44 (mirror ApprovedPrice*/note pattern). HasQueryFilter(!IsDeleted) :74.- DTO
PeBudgetSummaryDto:331-349 (17-field positional record) → appendbool BudgetFrozen = false. - Query handler
GetPurchaseEvaluationQueryHandler:853; budget block :905-973 (pairRec load :911-912; peers/lũy kế :917-943; currentProposal :947-951; fullAmount :957-962; DTO ctor :964-972). - Workflow service
PurchaseEvaluationWorkflowService.cs(ctorIApplicationDbContext db, IDateTime dateTime, ...). Finalize 4 site: :861 (AllowApproverFinalize) · :899 (CCM-threshold) · :931 (all-steps) · :1053 (V1 legacy — CHỈ budget-snapshot, KHÔNG ApplyApprovedPrice). ApplyApprovedPriceOnFinalize :955. - Guard 7a
SetPeCcmBudgetPeriodCommandHandlerPeWorkItemBudgetFeatures.cs:228 (sau load+NotFound :230-231). - Guard 7b
AdjustPurchaseEvaluationBudgetCommandHandlerPurchaseEvaluationFeatures.cs:358 (sau load+NotFound :360-361, TRƯỚC isAdmin block :363). - Enum: DaDuyet=7, ChoDuyet=10, TraLai=98, TuChoi=99.
- NAMING TRAP: PeWorkItemBudget.InitialAmount/AdjustmentAmount = CCM; ProInitialAmount/ProAdjustmentAmount = PRO.
Regression scan (tests trong acceptance filter)
- PeWorkItemBudgetTests: MỌI queried-PE ở non-terminal (DangSoanThao/ChoDuyet); DaDuyet chỉ là PEER lũy kế → frozen-gate KHÔNG kích cho queried PE → live(else) branch → behavior-preserving qua accumulator. AdjustBudget tests đều DangSoanThao → guard 7b không fire.
- PeCcmBudgetPeriodSetterAuthzTests: mọi seed Phase=ChoDuyet → guard 7a không fire. (Không trong filter nhưng verify để 0 regression FULL.)
- T0 PeBudgetFreezeTests: dùng UpdatePeBudgetPro/Ccm (KHÔNG guard) → snapshot chốt 100tr/200tr, live đổi 999/888, frozen branch đọc snapshot.
TransitionAsync KHÔNG SaveChanges nội-bộ (:537 "caller có downstream save")
→ Trong T0, snapshot flush qua UpdatePeBudgetPro/Ccm SaveChanges (shared context, pe tracked). Mirror ApprovedPrice pattern (đã proven).
Backfill pattern (mirror Mig 61/65)
- Plain
migrationBuilder.Sql()T-SQL, KHÔNG C# ActiveProvider guard (SQLite tests EnsureCreated no-replay = "guard" kiến-trúc). Idempotent WHERE. Down no-op cho backfill data (nhưng Down MUST DropColumn ×11 cho schema).
Progress log
(cập nhật trong lúc làm)