# sub-implementer-backend-0 — IMPL-A BE lũy kế TẠM TÍNH (S134)

> Ghi-đĩa-trong-lúc-làm (chống #53). Append từng bước. 4 file code + build verify.

## Scope (KHÔNG ĐỤNG)
ComputeAsync thân · snapshot 11 cột ApprovedBudget* · Mig 67/Migrations/ModelSnapshot · frozen số cũ · submit-guard :206 · fe-*/** · tests/** · KHÔNG commit/push/git-add.

## Baseline (đo trước khi sửa)
- `git status --porcelain` = CLEAN (branch main).
- DTO namespace = `SolutionErp.Application.PurchaseEvaluations.Dtos` (:4) ; accumulator namespace = `SolutionErp.Application.PurchaseEvaluations` → CẦN thêm `using ...Dtos;` vào accumulator.
- `PurchaseEvaluation.MaPhieu` = `string?` (:10) → DTO PePendingPriorPeDto MaPhieu nullable ✓ (khớp reviewer N2).
- Phase enum: DangSoanThao=1 · legacy 2-6 (ChoPurchasing/ChoDuAn/ChoCCM/ChoCEODuyetPA/ChoCEODuyetNCC) · DaDuyet=7 · ChoDuyet=10 · TraLai=98 · TuChoi=99.
- Changelog entity fields: PurchaseEvaluationId/EntityType/EntityId?/Action/PhaseAtChange?/UserId?/UserName?/Summary?/FieldChangesJson?/ContextNote?. EntityType.Workflow=5, ChangelogAction.Update=2 (ContractChangelog.cs:41). LogTransitionAsync (:1128-1155) dùng `.Add(...)` sync + Action=Transition.
- Reviewer GO_WITH_FIXES: M1 (changelog shape) + N1 (.Add not AddAsync) + N2 (MaPhieu nullable) đã incorporate vào task spec item 4 — tôi follow.
- 2 construction site verified: Features.cs:946 (frozen) + :975 (live). Helper 5 call-site :311/:865/:904/:937/:1112 — KHÔNG đổi signature.

## Tiến độ
- [x] Chunk 1: PeBudgetAccumulator.cs — +using Dtos (:3); +PePendingAccumulation record struct (5-field, sau PeBudgetAccumulation); +ComputePendingAsync (window Y HỆT ComputeAsync; PendingSubmitted loại {1,7,10,99}; PendingSelected loại {1,7,99}+winner mirror join :50-60; PriorPes loại {7,99} order CreatedAt Select PePendingPriorPeDto). CHỈ đọc AsNoTracking, KHÔNG mutate. ComputeAsync thân KHÔNG đổi.
- [x] Chunk 2: PurchaseEvaluationDtos.cs — +PePendingPriorPeDto(Guid Id, string? MaPhieu, int Phase) trước PeBudgetSummaryDto; extend PeBudgetSummaryDto append-CUỐI sau BudgetFrozen: +PendingSubmittedTotal=0/Count=0/SelectedTotal=0/Count=0/PendingPriorPes=null.
- [x] Chunk 3: PurchaseEvaluationFeatures.cs — live-branch insert ComputePendingAsync sau ComputeAsync; live construction (:975) fill 5 field từ pending; frozen construction (:946) thêm 5 default 0m/0/0m/0/null (BudgetFrozen: true GIỮ). ComputeAsync call-site KHÔNG đổi (chỉ THÊM call ComputePendingAsync sau nó).
- [x] Chunk 4: PurchaseEvaluationWorkflowService.cs — D4 trong ApplyBudgetSnapshotOnFinalizeAsync nhánh wiKey SAU set 4 lũy kế; gọi ComputePendingAsync 1 lần; PriorPes.Count>0 → .Add(changelog Action=Update, EntityType=Workflow, PhaseAtChange=DaDuyet, UserId=null, UserName="Hệ thống"); local switch PendingPhaseLabel (1→Nháp,10→Đã gửi duyệt,98→Trả lại,_→Đang duyệt); KHÔNG đổi signature, KHÔNG SaveChanges.
- [x] Build slnx: **Build succeeded. 0 Warning(s) 0 Error(s)** (58.84s).
- [x] git status verify: Migrations/ + ModelSnapshot = **NONE changed (PASS)**. 4 BE file mine đổi. 4 FE file (fe-admin/fe-user PeDetailTabs+types) + sub-implementer-frontend-1.md = của agent implementer-frontend-1 CHẠY SONG SONG (INV-2 A‖B) — KHÔNG phải tôi.

## Verify acceptance (đo được)
- **A1 (ComputeAsync thân = 0 đổi):** PeBudgetAccumulator.cs diff = `68 insertions(+), 0 deletions`. `grep '^-'` = NO REMOVED LINES → ComputeAsync body byte-nguyên. PASS.
- **A6 (5 call-site helper = 0 đổi):** WorkflowService.cs diff = `30 insertions(+), 0 deletions` (insertion-only). 5 call-site giữ signature `(evaluation, ct)` tại :311/:865/:904/:937/:1142 (site cuối dịch :1112→:1142 = +30 do CHÈN trong THÂN helper, nội-dung call bất động). Signature helper :998 KHÔNG đổi. PASS.
- **A2 (đúng 2 construction site):** `grep 'new PeBudgetSummaryDto' src/Backend/` = ĐÚNG 2 (Features.cs:946 frozen + :985 live; :985 = :975 cũ dịch +10 do frozen+4 & live-insert+6). PASS.
- **Frozen số cũ bất động:** Features.cs diff — nhánh frozen chỉ THÊM 5 default (`0m,0,0m,0,null`) vào construction :946; các dòng `e.ApprovedBudget*` = context KHÔNG đổi. 2 dòng "removed" = `BudgetFrozen: true);`/`false);` chỉ là đóng-ngoặc mở-rộng (giá-trị BudgetFrozen giữ). PASS.
- **submit-guard :206:** KHÔNG trong diff (grep `selectedThanhTien`/`.All(x=>x==0)` trong diff = rỗng). PASS.
- **DTO append-CUỐI:** DTOs.cs diff `14 insertions, 1 deletion` (deletion = mở-rộng `bool BudgetFrozen = false);` → +5 field). Pure-append. PASS.

## Note (bàn giao FE / risk)
- Contract JSON: `PendingPriorPes` = **null** (nhánh frozen / không-cặp) hoặc list (live) → FE PHẢI null-guard `?? []` (reviewer N2/N9 — plain text mã + fallback "(chưa có mã)", KHÔNG render link). FE = implementer-frontend-1 lo.
- `(int)p.Phase` projection EF-translate: spec-pinned + reviewer trục-4 validated; enum→int underlying = EF standard. Runtime chưa chạy được vì Dev DB 0 multi-pair (reviewer N5) — build compile PASS, logic mirror ComputeAsync đã proven.
