[CLAUDE] App: PE + Contract Create/Update commands + DTO add manual budget fields
Chunk 2/5 — wire 2 field mới (BudgetManualName + BudgetManualAmount) qua tất cả
CQRS commands + handlers + DTOs cho cả PE và HĐ. Mirror logic per Q3 user.
Files sửa:
~ Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs
- CreatePurchaseEvaluationCommand record +2 param
- Validator: MaximumLength(200) + GreaterThanOrEqualTo(0)
- Handler: wire entity
- UpdatePurchaseEvaluationDraftCommand record +2 param + handler wire
- GetPurchaseEvaluationQuery → DTO mapping +2 field
~ Application/PurchaseEvaluations/Dtos/PurchaseEvaluationDtos.cs
- PurchaseEvaluationDetailBundleDto +2 field (BudgetManualName/Amount)
~ Application/PurchaseEvaluations/CreateContractFromEvaluationFeatures.cs
- Carry forward pe.BudgetManualName/Amount → contract khi gen HĐ từ phiếu
~ Application/Contracts/ContractFeatures.cs
- CreateContractCommand record +2 param + Validator + Handler
- UpdateContractDraftCommand record +2 param + Handler (diff log thêm 2 field)
- ContractDetailDto mapping +2 field
~ Application/Contracts/Dtos/ContractDtos.cs
- ContractDetailDto +2 field
Validation Q2 chốt: cả 2 cùng null OK. Manual amount có thể null hoặc >= 0.
KHÔNG XOR với BudgetId (BE prefer link BudgetId nếu set, manual fallback only).
Controllers KHÔNG đụng (FromBody bind JSON → record record optional fields gen
auto null cho legacy callers — backward compat).
Verify: dotnet build pass · dotnet test SolutionErp.slnx 83 pass.
Next: Chunk 3 FE-Admin toggle + 2 fields PeHeaderForm + ContractHeaderForm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -25,7 +25,9 @@ public record CreateContractCommand(
|
||||
string? NoiDung,
|
||||
bool BypassProcurementAndCCM,
|
||||
string? DraftData,
|
||||
Guid? BudgetId) : IRequest<Guid>;
|
||||
Guid? BudgetId,
|
||||
string? BudgetManualName,
|
||||
decimal? BudgetManualAmount) : IRequest<Guid>;
|
||||
|
||||
public class CreateContractCommandValidator : AbstractValidator<CreateContractCommand>
|
||||
{
|
||||
@ -37,6 +39,8 @@ public class CreateContractCommandValidator : AbstractValidator<CreateContractCo
|
||||
RuleFor(x => x.GiaTri).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.TenHopDong).MaximumLength(500);
|
||||
RuleFor(x => x.NoiDung).MaximumLength(2000);
|
||||
RuleFor(x => x.BudgetManualName).MaximumLength(200);
|
||||
RuleFor(x => x.BudgetManualAmount).GreaterThanOrEqualTo(0).When(x => x.BudgetManualAmount.HasValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,6 +91,8 @@ public class CreateContractCommandHandler(
|
||||
BypassProcurementAndCCM = request.BypassProcurementAndCCM,
|
||||
DraftData = request.DraftData,
|
||||
BudgetId = request.BudgetId,
|
||||
BudgetManualName = request.BudgetManualName,
|
||||
BudgetManualAmount = request.BudgetManualAmount,
|
||||
WorkflowDefinitionId = activeWfId,
|
||||
SlaDeadline = DateTime.UtcNow.Add(workflow.GetPhaseSla(ContractPhase.DangSoanThao) ?? TimeSpan.FromDays(7)),
|
||||
};
|
||||
@ -121,7 +127,9 @@ public record UpdateContractDraftCommand(
|
||||
string? NoiDung,
|
||||
Guid? TemplateId,
|
||||
string? DraftData,
|
||||
Guid? BudgetId) : IRequest;
|
||||
Guid? BudgetId,
|
||||
string? BudgetManualName,
|
||||
decimal? BudgetManualAmount) : IRequest;
|
||||
|
||||
public class UpdateContractDraftCommandHandler(
|
||||
IApplicationDbContext db,
|
||||
@ -159,6 +167,10 @@ public class UpdateContractDraftCommandHandler(
|
||||
changes.Add(new { Field = "TemplateId", Old = entity.TemplateId, New = request.TemplateId });
|
||||
if (entity.BudgetId != request.BudgetId)
|
||||
changes.Add(new { Field = "BudgetId", Old = entity.BudgetId, New = request.BudgetId });
|
||||
if (entity.BudgetManualName != request.BudgetManualName)
|
||||
changes.Add(new { Field = "BudgetManualName", Old = entity.BudgetManualName, New = request.BudgetManualName });
|
||||
if (entity.BudgetManualAmount != request.BudgetManualAmount)
|
||||
changes.Add(new { Field = "BudgetManualAmount", Old = entity.BudgetManualAmount, New = request.BudgetManualAmount });
|
||||
|
||||
entity.GiaTri = request.GiaTri;
|
||||
entity.TenHopDong = request.TenHopDong;
|
||||
@ -166,6 +178,8 @@ public class UpdateContractDraftCommandHandler(
|
||||
entity.TemplateId = request.TemplateId;
|
||||
entity.DraftData = request.DraftData;
|
||||
entity.BudgetId = request.BudgetId;
|
||||
entity.BudgetManualName = request.BudgetManualName;
|
||||
entity.BudgetManualAmount = request.BudgetManualAmount;
|
||||
|
||||
if (changes.Count > 0)
|
||||
{
|
||||
@ -471,6 +485,7 @@ public class GetContractQueryHandler(
|
||||
c.TemplateId, c.GiaTri, c.BypassProcurementAndCCM, c.SlaDeadline, c.DraftData,
|
||||
c.CreatedAt, c.UpdatedAt,
|
||||
c.BudgetId, budgetSummary,
|
||||
c.BudgetManualName, c.BudgetManualAmount,
|
||||
c.Approvals
|
||||
.OrderBy(a => a.ApprovedAt)
|
||||
.Select(a => new ContractApprovalDto(
|
||||
|
||||
@ -41,6 +41,8 @@ public record ContractDetailDto(
|
||||
DateTime? UpdatedAt,
|
||||
Guid? BudgetId,
|
||||
BudgetSummaryDto? Budget,
|
||||
string? BudgetManualName,
|
||||
decimal? BudgetManualAmount,
|
||||
List<ContractApprovalDto> Approvals,
|
||||
List<ContractCommentDto> Comments,
|
||||
List<ContractAttachmentDto> Attachments,
|
||||
|
||||
Reference in New Issue
Block a user