[CLAUDE] PurchaseEvaluation: CV PRO refinement batch (anh Kiệt FDC) — live budget recompute + clear winner + fullscreen preview + hide create c/d
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m59s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m59s
C1 ẩn "c. Giá chào thầu" + "d. Bảng so sánh giá" khỏi form TẠO (vẫn hiện ở Detail tabs) C3 ô 8 "Giá trị TH dự kiến còn lại" pre-fill từ dòng 7 (Ngân sách còn lại) C4a live-recompute: VndInlineEdit +onLiveChange, PeBudgetSummaryTable draftRow3/8 → dòng 5/6/7/9 + So sánh + % nhảy NGAY khi gõ ô 3/8 (chưa cần Lưu) C4b So sánh = 0 → "Bằng ngân sách" / "—" thay "0 đ" (chỉ khi base>0) C5 hủy/đổi NCC winner: BE SelectWinnerBody(Guid?) + Command/Handler 2 nhánh (null=clear bỏ-qua-validate-list / non-null=giữ logic cũ); FE dropdown ""→clear + nút ✓ toggle. KHÔNG migration (SelectedSupplierId đã Guid?) C7 nút "Toàn màn hình" preview file báo giá (overlay inset-0 + Esc thoát) BE 2 file (Api controller record + Application command/handler). FE 3 file × 2 app SHA-identical. Test +10 PeSelectWinnerClearTests (4 clear + 4 select-regression + 2 PE-existence) → 366 PASS. Both FE build PASS, slnx build 0 err. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -345,7 +345,7 @@ public record AddSupplierBody(
|
||||
string? DisplayName, string? ContactName, string? ContactEmail, string? ContactPhone,
|
||||
string? PaymentTermText, string? Note);
|
||||
|
||||
public record SelectWinnerBody(Guid SupplierId);
|
||||
public record SelectWinnerBody(Guid? SupplierId); // null = bỏ chọn NCC (cho phép xóa + điền lại — anh Kiệt FDC C5)
|
||||
|
||||
public record DetailBody(
|
||||
string GroupCode, string GroupName, string? ItemCode, string NoiDung, string? DonViTinh,
|
||||
|
||||
@ -387,7 +387,9 @@ public class DeletePurchaseEvaluationQuoteCommandHandler(
|
||||
|
||||
// ========== Select winner (NCC được chọn tổng thể) ==========
|
||||
|
||||
public record SelectPurchaseEvaluationWinnerCommand(Guid PurchaseEvaluationId, Guid SupplierId) : IRequest;
|
||||
// SupplierId nullable [anh Kiệt FDC C5]: null = BỎ CHỌN (xóa đơn vị đã chọn, điền
|
||||
// lại) — un-select winner về none; có giá trị = chọn/đổi NCC (logic cũ giữ 100%).
|
||||
public record SelectPurchaseEvaluationWinnerCommand(Guid PurchaseEvaluationId, Guid? SupplierId) : IRequest;
|
||||
|
||||
public class SelectPurchaseEvaluationWinnerCommandHandler(
|
||||
IApplicationDbContext db,
|
||||
@ -398,15 +400,27 @@ public class SelectPurchaseEvaluationWinnerCommandHandler(
|
||||
var entity = await db.PurchaseEvaluations.FirstOrDefaultAsync(x => x.Id == request.PurchaseEvaluationId, ct)
|
||||
?? throw new NotFoundException("PurchaseEvaluation", request.PurchaseEvaluationId);
|
||||
|
||||
_ = await db.Suppliers.FirstOrDefaultAsync(s => s.Id == request.SupplierId, ct)
|
||||
?? throw new NotFoundException("Supplier", request.SupplierId);
|
||||
if (request.SupplierId is Guid supplierId)
|
||||
{
|
||||
// ── Chọn / đổi NCC trúng thầu (logic cũ giữ nguyên 100%) ──
|
||||
_ = await db.Suppliers.FirstOrDefaultAsync(s => s.Id == supplierId, ct)
|
||||
?? throw new NotFoundException("Supplier", supplierId);
|
||||
|
||||
// Verify supplier nằm trong danh sách phiếu
|
||||
var hasSupplier = await db.PurchaseEvaluationSuppliers
|
||||
.AnyAsync(s => s.PurchaseEvaluationId == request.PurchaseEvaluationId && s.SupplierId == request.SupplierId, ct);
|
||||
if (!hasSupplier) throw new ConflictException("NCC chưa được thêm vào phiếu đánh giá.");
|
||||
// Verify supplier nằm trong danh sách phiếu
|
||||
var hasSupplier = await db.PurchaseEvaluationSuppliers
|
||||
.AnyAsync(s => s.PurchaseEvaluationId == request.PurchaseEvaluationId && s.SupplierId == supplierId, ct);
|
||||
if (!hasSupplier) throw new ConflictException("NCC chưa được thêm vào phiếu đánh giá.");
|
||||
|
||||
entity.SelectedSupplierId = request.SupplierId;
|
||||
entity.SelectedSupplierId = supplierId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ── Bỏ chọn (clear về none) — KHÔNG validate participating list ──
|
||||
// Row 4 "Giá trị kỳ này" + winnerQuoteTotal tính-khi-đọc theo
|
||||
// SelectedSupplierId (PurchaseEvaluationFeatures GetDetail) → tự về 0.
|
||||
// ApprovedPriceAmount/Source là cột chốt giai-đoạn DaDuyet, KHÔNG đụng ở đây.
|
||||
entity.SelectedSupplierId = null;
|
||||
}
|
||||
|
||||
db.PurchaseEvaluationChangelogs.Add(new PurchaseEvaluationChangelog
|
||||
{
|
||||
@ -416,7 +430,7 @@ public class SelectPurchaseEvaluationWinnerCommandHandler(
|
||||
PhaseAtChange = entity.Phase,
|
||||
UserId = currentUser.UserId,
|
||||
UserName = currentUser.FullName ?? currentUser.Email,
|
||||
Summary = "Chọn NCC trúng thầu",
|
||||
Summary = request.SupplierId is null ? "Bỏ chọn NCC trúng thầu" : "Chọn NCC trúng thầu",
|
||||
});
|
||||
|
||||
await db.SaveChangesAsync(ct);
|
||||
|
||||
Reference in New Issue
Block a user