[CLAUDE] App: Chunk B — Lock edit guards (Phase != DangSoanThao) cho 17 handler
Ràng buộc 1 (Phase 9): khi đã trình duyệt → KHÔNG sửa được Header + Detail + Quote nữa. Phải reject để Drafter sửa lại. Pattern dùng: extend helper EnsureContractType + tạo helper PurchaseEvaluationDraftGuard mới cho PE + inline guard cho Budget. Single source of truth cho mỗi module. Handlers added Phase guard (17 total): Contract module (15) — qua EnsureContractType helper: - 7 Add*DetailHandler (ThauPhu/GiaoKhoan/NhaCungCap/DichVu/MuaBan/NguyenTacNcc/NguyenTacDv) - 7 Update*DetailHandler (cùng 7 type) - DeleteContractDetailHandler (inline guard) PE module (5) — qua PurchaseEvaluationDraftGuard helper mới: - AddPurchaseEvaluationDetail - UpdatePurchaseEvaluationDetail - DeletePurchaseEvaluationDetail - UpsertPurchaseEvaluationQuote - DeletePurchaseEvaluationQuote Budget module (3) — inline guard: - AddBudgetDetail - UpdateBudgetDetail (refactor: load Budget thay vì FirstOrDefault sau Detail load → bỏ null check không cần) - DeleteBudgetDetail (refactor: tương tự) KHÔNG lock (intentional): - ContractComment (cần được trong DangGopY phase 3) - ContractAttachment Upload/Delete (Drafter scan ký ở DangInKy phase 5) - PE OpinionUpsert (Ý kiến 4 PB là sign-off, có thể nhập sau khi trình) - PE Attachment (báo giá NCC upload xuyên suốt workflow) Verify: - Build pass (2 warning DocxRenderer cũ) - 77 unit test pass (54 Domain + 23 Infra) — domain policy không đổi Smart reject (ràng buộc 2) + 2-stage dept approval (ràng buộc 3) làm ở Chunk C + D. WorkflowService transition guard chưa update. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -424,6 +424,9 @@ public class DeleteContractDetailHandler(IApplicationDbContext db, IChangelogSer
|
||||
{
|
||||
var contract = await db.Contracts.AsNoTracking().FirstOrDefaultAsync(c => c.Id == cmd.ContractId, ct)
|
||||
?? throw new NotFoundException("Contract", cmd.ContractId);
|
||||
// Lock edit guard (Phase 9 — Migration 16): chỉ Phase=DangSoanThao xóa được.
|
||||
if (contract.Phase != ContractPhase.DangSoanThao)
|
||||
throw new ConflictException($"HĐ đã trình duyệt (Phase={contract.Phase}), không thể xóa chi tiết. Phải reject để Drafter sửa lại.");
|
||||
|
||||
// Dispatch xóa theo Type — tránh load tất cả 7 DbSet
|
||||
bool removed = false;
|
||||
@ -477,6 +480,10 @@ internal static class ContractDetailsHelpers
|
||||
?? throw new NotFoundException("Contract", contractId);
|
||||
if (contract.Type != expectedType)
|
||||
throw new ConflictException($"HĐ này thuộc loại {contract.Type}, không thể thêm chi tiết loại {expectedType}.");
|
||||
// Lock edit guard (Phase 9 — Migration 16): chỉ Phase=DangSoanThao mới
|
||||
// được CRUD chi tiết. Đã trình duyệt → KHÔNG sửa được thông tin nữa.
|
||||
if (contract.Phase != ContractPhase.DangSoanThao)
|
||||
throw new ConflictException($"HĐ đã trình duyệt (Phase={contract.Phase}), không thể chỉnh sửa chi tiết. Phải reject để Drafter sửa lại.");
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user