---
name: s62-pe-budget-soft-warning
description: S62 review PASS — PE "vượt ngân sách" hard-block→soft-warning; validator drop ExpectedRemaining>=0, FE amber banner + allowNegative row8
metadata:
  type: project
---

# S62 — PE budget over-spend: hard-block → soft-warning (PASS)

Reviewed 2026-06-13. Anh Kiệt FDC directive: phiếu PE khi giá trị NCC vượt ngân sách → ô "Giá trị thực hiện dự kiến còn lại" (row8) ra âm → bị chặn lưu. Chốt: cho lưu, chỉ cảnh báo mềm.

**Why:** Adversarial review of a small (4-file, ~20 LOC) validation-relaxation change. Verdict PASS.

**How to apply:** When a future change touches PE budget validation or `ExpectedRemainingAmount`, recall these verification anchors:
- BE submit guard `PurchaseEvaluationWorkflowService.cs:198` = `BudgetPeriodAmount is null || <= 0` → adds "chưa nhập Ngân sách kỳ này". This is the budget>0 enforcement; must NOT be loosened when relaxing row8.
- FE mirror of that guard: `PeDetailTabs.tsx:178` (`budgetPeriodAmount == null || <= 0`). BE+FE predicate kept in sync (S61 lineage).
- Validator `AdjustPurchaseEvaluationBudgetCommandValidator` keeps `BudgetPeriodAmount.GreaterThan(0)`, drops `ExpectedRemainingAmount.GreaterThanOrEqualTo(0)`.

**Negative-safety chain (row8 can now be negative — verified no break):** `row8 = expectedRemainingAmount ?? row7`; `row9 = row4 + row8`; `cmpFull = full - row9`; `cmpPeriod = row3 - row4`. All pure additive — no division by row8, no sqrt, no unsigned cast. BE projection (PurchaseEvaluationFeatures.cs:1038) + CreateContractFromEvaluation clone (line 155) pass the value through with zero arithmetic.

**Precedent:** mirrors LeaveBalance allowing negative balance (cited in code comment as the in-repo precedent for a domain quantity going negative).
