[CLAUDE] PurchaseEvaluation: Mig 54 giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m22s

Theo note anh Kiệt FDC (go-live so-sánh-giá thứ Hai):
- (1) Giá chào thầu thêm giá đề xuất NGOÀI giá NCC: PRO nhập dải Min/Max +
  CCM nhập 1 giá (2 lệnh role-gate Procurement/CostControl, fail-closed).
  Khi duyệt cấp cuối, người duyệt CHỌN 1 giá chốt (Ncc/ProMin/ProMax/Ccm)
  -> luu ApprovedPriceAmount/Source (bind tai moi nhanh DaDuyet, bat buoc
  chon; auto-approve he thong mien).
- (3) CCM duyet-done mien CEO: DOI tu AUTO-threshold (S69) sang O-TICH-TAY
  (finalizeByCcmDelegation) -- CCM chu dong tich, fail-closed theo nguong
  + role + gia goi. An toan hon (khong vo tinh bo CEO).
- Mig 54 additive-nullable (5 cot PE) - FE 2 app SHA-mirror - test 306->334
  (+28: opt-in 6->11, +10 gia chot, +13 setter authz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-06-18 15:51:39 +07:00
parent 77ad219361
commit 1d86abcdc5
20 changed files with 7931 additions and 101 deletions

View File

@ -96,6 +96,25 @@ public class PurchaseEvaluationsController(IMediator mediator) : ControllerBase
}
public record SetUrgentBody(bool IsUrgent);
// [Mig 54 2026-06-18 — anh Kiệt FDC] Nhập GIÁ ĐỀ XUẤT tại "c. Giá chào thầu" theo
// role. Class [Authorize] any-auth; handler fine-grained Forbidden (PRO=Procurement
// Min/Max, CCM=CostControl 1 giá, Admin cả 2). Set per-phiếu. Absolute-set (null=clear).
[HttpPut("{id:guid}/suggested-price/pro")]
public async Task<IActionResult> SetSuggestedPricePro(Guid id, [FromBody] SuggestedPriceProBody body, CancellationToken ct)
{
await mediator.Send(new UpdatePeSuggestedPriceProCommand(id, body.MinPrice, body.MaxPrice), ct);
return NoContent();
}
public record SuggestedPriceProBody(decimal? MinPrice, decimal? MaxPrice);
[HttpPut("{id:guid}/suggested-price/ccm")]
public async Task<IActionResult> SetSuggestedPriceCcm(Guid id, [FromBody] SuggestedPriceCcmBody body, CancellationToken ct)
{
await mediator.Send(new UpdatePeSuggestedPriceCcmCommand(id, body.CcmPrice), ct);
return NoContent();
}
public record SuggestedPriceCcmBody(decimal? CcmPrice);
[HttpPost("{id:guid}/transitions")]
public async Task<IActionResult> Transition(Guid id, [FromBody] TransitionPeBody body, CancellationToken ct)
{
@ -106,7 +125,8 @@ public class PurchaseEvaluationsController(IMediator mediator) : ControllerBase
// Root cause bro UAT 2026-05-15 "Trả lại Người chỉ định fail".
await mediator.Send(new TransitionPurchaseEvaluationCommand(
id, body.TargetPhase, body.Decision, body.Comment,
body.ReturnMode, body.ReturnTargetUserId, body.SkipToFinal), ct);
body.ReturnMode, body.ReturnTargetUserId, body.SkipToFinal,
body.FinalizeByCcmDelegation, body.ApprovedPriceAmount, body.ApprovedPriceSource), ct);
return NoContent();
}
@ -314,7 +334,11 @@ public record TransitionPeBody(
string? Comment,
WorkflowReturnMode? ReturnMode = null, // F1 mode Trả lại
Guid? ReturnTargetUserId = null, // F1 Assignee target
bool SkipToFinal = false); // F2 duyệt thẳng Cấp cuối
bool SkipToFinal = false, // F2 duyệt thẳng Cấp cuối
// [Mig 54 2026-06-18 — anh Kiệt FDC] ③ CCM duyệt done miễn CEO + ① giá chốt.
bool FinalizeByCcmDelegation = false,
decimal? ApprovedPriceAmount = null,
string? ApprovedPriceSource = null);
public record AddSupplierBody(
Guid SupplierId,