[CLAUDE] App: Contract workflow inner steps DTO + designer mirror PE (Chunk B)
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
DTO + Validator + Handler mở rộng cho N-stage admin designer Contract (Mig 20). Mirror PE Mig 18 pattern (PeWorkflowAdminFeatures Chunk B). WorkflowAdminFeatures: - WorkflowStepInnerStepDto record (Id, Order, DeptId, DeptName, PositionLevel, Name, SlaDays, IsRequired) - WorkflowStepDto extend +InnerSteps List - GetWorkflowAdminOverviewQueryHandler — Include InnerSteps OrderBy + resolve DeptNames cho display - CreateWorkflowStepInnerStepInput record - CreateWorkflowStepInput extend +InnerSteps (nullable, default null — backward compat existing test code positional new()) - Validator child rules cho InnerSteps (Order ≥1, DeptId not empty, PositionLevel 1-3, SlaDays ≥0) - CreateWorkflowDefinitionCommandHandler — convert InnerSteps khi build entity (atomic batch insert qua nav collection) Verify: dotnet build 0 error, 89 test pass (no regression). Pending Chunk C: ContractWorkflowService.TransitionAsync N-stage logic + legacy 2-stage fallback mirror PE pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -17,6 +17,17 @@ public record WorkflowStepApproverDto(
|
||||
string AssignmentValue,
|
||||
string? DisplayName); // resolved role label or user fullName
|
||||
|
||||
// Mig 20 — N-stage approval inner step level con (mirror PE Mig 18)
|
||||
public record WorkflowStepInnerStepDto(
|
||||
Guid Id,
|
||||
int Order,
|
||||
Guid DepartmentId,
|
||||
string? DepartmentName,
|
||||
int PositionLevel, // 1=NV, 2=PP, 3=TP
|
||||
string? Name,
|
||||
int? SlaDays,
|
||||
bool IsRequired);
|
||||
|
||||
public record WorkflowStepDto(
|
||||
Guid Id,
|
||||
int Order,
|
||||
@ -24,7 +35,8 @@ public record WorkflowStepDto(
|
||||
string PhaseLabel,
|
||||
string Name,
|
||||
int? SlaDays,
|
||||
List<WorkflowStepApproverDto> Approvers);
|
||||
List<WorkflowStepApproverDto> Approvers,
|
||||
List<WorkflowStepInnerStepDto> InnerSteps);
|
||||
|
||||
public record WorkflowDefinitionDto(
|
||||
Guid Id,
|
||||
@ -84,9 +96,21 @@ public class GetWorkflowAdminOverviewQueryHandler(
|
||||
var definitions = await db.WorkflowDefinitions.AsNoTracking()
|
||||
.Include(d => d.Steps.OrderBy(s => s.Order))
|
||||
.ThenInclude(s => s.Approvers)
|
||||
.Include(d => d.Steps)
|
||||
.ThenInclude(s => s.InnerSteps.OrderBy(i => i.Order))
|
||||
.OrderByDescending(d => d.Version)
|
||||
.ToListAsync(ct);
|
||||
|
||||
// Resolve dept names cho InnerStep.DepartmentName display (Mig 20)
|
||||
var deptIds = definitions
|
||||
.SelectMany(d => d.Steps).SelectMany(s => s.InnerSteps)
|
||||
.Select(i => i.DepartmentId).Distinct().ToList();
|
||||
var deptNames = deptIds.Count == 0
|
||||
? new Dictionary<Guid, string>()
|
||||
: await db.Departments.AsNoTracking()
|
||||
.Where(d => deptIds.Contains(d.Id))
|
||||
.ToDictionaryAsync(d => d.Id, d => d.Name, ct);
|
||||
|
||||
// Resolve user names for User-kind approvers
|
||||
var userIds = definitions
|
||||
.SelectMany(d => d.Steps)
|
||||
@ -130,7 +154,16 @@ public class GetWorkflowAdminOverviewQueryHandler(
|
||||
s.Approvers.Select(a => new WorkflowStepApproverDto(
|
||||
(int)a.Kind,
|
||||
a.AssignmentValue,
|
||||
ResolveDisplay(a, userNames))).ToList()
|
||||
ResolveDisplay(a, userNames))).ToList(),
|
||||
s.InnerSteps.OrderBy(i => i.Order).Select(i => new WorkflowStepInnerStepDto(
|
||||
i.Id,
|
||||
i.Order,
|
||||
i.DepartmentId,
|
||||
deptNames.GetValueOrDefault(i.DepartmentId),
|
||||
(int)i.PositionLevel,
|
||||
i.Name,
|
||||
i.SlaDays,
|
||||
i.IsRequired)).ToList()
|
||||
)).ToList());
|
||||
|
||||
var types = Enum.GetValues<ContractType>()
|
||||
@ -160,12 +193,23 @@ public class GetWorkflowAdminOverviewQueryHandler(
|
||||
|
||||
public record CreateWorkflowStepApproverInput(int Kind, string AssignmentValue);
|
||||
|
||||
// Mig 20 — Inner step input cho designer N-stage. InnerSteps optional empty
|
||||
// list → service fallback 2-stage Review/Confirm logic legacy Mig 16.
|
||||
public record CreateWorkflowStepInnerStepInput(
|
||||
int Order,
|
||||
Guid DepartmentId,
|
||||
int PositionLevel, // 1=NV, 2=PP, 3=TP
|
||||
string? Name,
|
||||
int? SlaDays,
|
||||
bool IsRequired);
|
||||
|
||||
public record CreateWorkflowStepInput(
|
||||
int Order,
|
||||
int Phase,
|
||||
string Name,
|
||||
int? SlaDays,
|
||||
List<CreateWorkflowStepApproverInput> Approvers);
|
||||
List<CreateWorkflowStepApproverInput> Approvers,
|
||||
List<CreateWorkflowStepInnerStepInput>? InnerSteps = null);
|
||||
|
||||
public record CreateWorkflowDefinitionCommand(
|
||||
ContractType ContractType,
|
||||
@ -198,6 +242,16 @@ public class CreateWorkflowDefinitionCommandValidator : AbstractValidator<Create
|
||||
app.RuleFor(a => a.Kind).InclusiveBetween(1, 2);
|
||||
app.RuleFor(a => a.AssignmentValue).NotEmpty().MaximumLength(100);
|
||||
});
|
||||
step.RuleForEach(s => s.InnerSteps!).ChildRules(inner =>
|
||||
{
|
||||
inner.RuleFor(i => i.Order).GreaterThanOrEqualTo(1);
|
||||
inner.RuleFor(i => i.DepartmentId).NotEmpty();
|
||||
inner.RuleFor(i => i.PositionLevel).InclusiveBetween(1, 3)
|
||||
.WithMessage("PositionLevel: 1=NV, 2=PP, 3=TP.");
|
||||
inner.RuleFor(i => i.Name).MaximumLength(200);
|
||||
inner.RuleFor(i => i.SlaDays).GreaterThanOrEqualTo(0)
|
||||
.When(i => i.SlaDays != null);
|
||||
}).When(s => s.InnerSteps != null);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -242,6 +296,15 @@ public class CreateWorkflowDefinitionCommandHandler(IApplicationDbContext db)
|
||||
Kind = (WorkflowApproverKind)a.Kind,
|
||||
AssignmentValue = a.AssignmentValue,
|
||||
}).ToList(),
|
||||
InnerSteps = (s.InnerSteps ?? new()).OrderBy(i => i.Order).Select(i => new WorkflowStepInnerStep
|
||||
{
|
||||
Order = i.Order,
|
||||
DepartmentId = i.DepartmentId,
|
||||
PositionLevel = (PositionLevel)i.PositionLevel,
|
||||
Name = i.Name,
|
||||
SlaDays = i.SlaDays,
|
||||
IsRequired = i.IsRequired,
|
||||
}).ToList(),
|
||||
})
|
||||
.ToList(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user