[CLAUDE] Domain+Infra: Migration 17 — manual budget fields cho PE + HĐ

Chunk 1/5 — DB schema + Domain layer cho fallback "user nhập số tiền ngân sách
tay khi chưa link Budget entity" (UAT request 2026-05-07). Áp cho cả PE + HĐ
(mirror logic per user Q3 chốt).

Migration 17 `AddManualBudgetFieldsToPeAndContract` — 4 ALTER:
  - PurchaseEvaluations.BudgetManualName  nvarchar(200) NULL
  - PurchaseEvaluations.BudgetManualAmount decimal(18,2) NULL
  - Contracts.BudgetManualName            nvarchar(200) NULL
  - Contracts.BudgetManualAmount          decimal(18,2) NULL

Validation Q2: cả 2 cùng null OK (PE/HĐ chưa có ngân sách gì cả). KHÔNG XOR
với BudgetId — tạm thời cho phép cả 2 cùng có (BE prefer BudgetId nếu set vì
có Phase=DaDuyet guarantee, manual chỉ là fallback hiển thị/note).

Files:
  ~ Domain/PurchaseEvaluations/PurchaseEvaluation.cs — 2 property mới
  ~ Domain/Contracts/Contract.cs — 2 property mới
  ~ Infrastructure/Persistence/Configurations/PurchaseEvaluationConfiguration.cs
    — HasMaxLength(200) + HasPrecision(18,2)
  ~ Infrastructure/Persistence/Configurations/ContractConfiguration.cs — same
  + Migration 17 .cs + .Designer.cs (3-file rule per ef-core-migration skill)
  ~ ApplicationDbContextModelSnapshot.cs (auto-overwrite)

Verify:
  - dotnet ef migrations add → 3 file gen sạch (4 AddColumn Up + 4 DropColumn Down)
  - dotnet ef database update → applied LocalDB OK
  - dotnet test SolutionErp.slnx → 83 pass (54 Domain + 29 Infra) — không regression

Next: Chunk 2 App CQRS Create/Update commands + DTO + AutoMapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-07 12:30:59 +07:00
parent d04bd88fbe
commit ecd5f7e9d9
7 changed files with 3674 additions and 0 deletions

View File

@ -25,6 +25,11 @@ public class Contract : AuditableEntity
public bool SlaWarningSent { get; set; } // Flag để không gửi warning 2 lần
public Guid? BudgetId { get; set; } // Reference Budget (Phase 7) — đối chiếu chi phí HĐ vs ngân sách
// Manual budget fields (Phase 9 — Migration 17 mirror PE): user nhập tay khi
// KHÔNG link Budget entity. Cả 2 cùng null OK. KHÔNG XOR validate với BudgetId.
public string? BudgetManualName { get; set; } // Tên tham chiếu
public decimal? BudgetManualAmount { get; set; } // Tổng số tiền nhập tay (đ)
// Smart reject (Phase 9 — Migration 16): Phase nguồn khi reject. Drafter
// sửa lại + trình lại → quay về RejectedFromPhase thay vì DangSoanThao
// tuần tự lại từ đầu. Null khi chưa từng reject hoặc đã trình lại xong.

View File

@ -28,6 +28,14 @@ public class PurchaseEvaluation : AuditableEntity
public Guid? ContractId { get; set; } // FK Contracts — set khi user gen HĐ từ phiếu
public Guid? BudgetId { get; set; } // FK Budget (Phase 7) — đối chiếu báo giá vs ngân sách gói thầu
// Manual budget fields (Phase 9 — Migration 17): user nhập tay khi KHÔNG link
// Budget entity (vd ngân sách chưa approve hoặc gói nhỏ ko cần workflow ngân
// sách riêng). Cả 2 cùng null OK (PE chưa có ngân sách gì cả). KHÔNG validate
// XOR với BudgetId — tạm thời cho phép cả 2 cùng có (BE prefer BudgetId nếu
// set vì có Phase=DaDuyet guarantee, manual chỉ là fallback hiển thị).
public string? BudgetManualName { get; set; } // Tên tham chiếu vd "Tạm tính dự toán T11/2025"
public decimal? BudgetManualAmount { get; set; } // Tổng số tiền nhập tay (đ)
// Smart reject (Phase 9 — Migration 16): Phase nguồn khi reject. Drafter
// sửa lại + trình lại → quay về RejectedFromPhase thay vì đi tuần tự.
public PurchaseEvaluationPhase? RejectedFromPhase { get; set; }