[CLAUDE] PE-Workflow: S21 t5 Chunk A — Mig 29 refactor Allow* sang per-NV (per-Level + per-Drafter)
Refactor 6 Allow* options từ workflow-level (Mig 28 S21 t4) sang per-NV scope: - F1 (4 mode Trả lại) + F3 (Edit Section 2) → 5 flag MOVE xuống `ApprovalWorkflowLevels` (per slot Approver, cùng table với ApproverUserId). - F2 (AllowDrafterSkipToFinal) → MOVE xuống `Users` (per-Drafter user, User Mgmt). Mig 29 `RefactorAdvancedOptionsToPerLevelAndDrafterUser` — 4-stage migration (EF auto-generated drop-then-add đã được REORDER manual): 1. ADD 5 column trên `ApprovalWorkflowLevels` (AllowReturnOneLevel/OneStep/ ToAssignee/ToDrafter[default true]/AllowApproverEditDetails) 2. ADD 1 column trên `Users` (AllowDrafterSkipToFinal default false) 3. BACKFILL bulk SQL (preserve admin config Mig 28): - Levels: copy workflow.Allow* → all Levels của workflow (JOIN Steps) - Users: SET TRUE cho user nào từng Drafter PE link workflow Allow=true 4. DROP 6 column workflow-level (Mig 28 cleanup) 3-file rule complete. Apply LocalDB Dev + Design success. Domain entity refactor: - `ApprovalWorkflow.cs` — REMOVE 6 Allow* field (S21 t4 Mig 28 cũ) - `ApprovalWorkflowLevel.cs` — ADD 5 Allow* field (F1 + F3) - `User.cs` — ADD 1 Allow* field (F2 AllowDrafterSkipToFinal) EF config update: - `ApprovalWorkflowConfiguration.cs` — remove 6 HasDefaultValue workflow-level, add 5 HasDefaultValue per-Level (4 false + 1 AllowReturnToDrafter true S17) Service refactor `ApplyReturnModeAsync` (`PurchaseEvaluationWorkflowService.cs`): - Resolve currentLevel slot (CurrentWorkflowStepIndex + CurrentApprovalLevelOrder) - Read 5 Allow* từ `currentLevel.AllowXxx` thay vì workflow.Allow* - Admin bypass per-Level flag check (unchanged behavior) - Drafter mode đặc biệt: check AllowReturnToDrafter của currentLevel (vẫn validate) - V1 legacy (no V2 schema) → fallback Drafter behavior tự động DRAFTER trình refactor (`TransitionAsync` skipToFinal branch): - Permission check moved from workflow-level → `drafterUser.AllowDrafterSkipToFinal` - Use `userManager.FindByIdAsync(actorUserId)` để get current Drafter user entity - Admin bypass user flag check (unchanged) Helper `EnsureEditableForDetailsAsync` refactor: - Read `level.AllowApproverEditDetails` thay vì workflow.AllowApproverEditDetails - Error message rõ "Cấp Approver hiện tại (Bước X / Cấp Y)" thay vì "Workflow" DTO refactor: - `AwLevelDto` ADD 5 Allow* field (admin Designer GET per-Level) - `AwDefinitionDto` REMOVE 6 Allow* (no longer workflow-level) - `CreateAwLevelInput` ADD 5 Allow* param (admin Designer POST per-Level) - `CreateAwDefinitionCommand` REMOVE 6 Allow* (Steps[].Levels[] now has them) - `ApprovalWorkflowOptionsDto` chỉ còn 5 flag (F2 removed — separate field) - `PurchaseEvaluationDetailBundleDto`: - rename `WorkflowOptions` → `CurrentLevelOptions` (clearer semantic per-slot) - ADD `DrafterAllowSkipToFinal bool` (resolve từ DrafterUserId → User entity) GetPurchaseEvaluationQueryHandler populate: - `currentLevelOptions` = 5 Allow* của Cấp hiện tại (null nếu V1 legacy / no pointer) - `drafterAllowSkipToFinal` = User.AllowDrafterSkipToFinal lookup từ DrafterUserId Backward compat verified: - Mig 29 backfill preserve admin config S21 t4 — workflow cũ vẫn chạy đúng sau deploy. User chưa từng làm Drafter F2 phải opt-in lần đầu (no auto-set). - 84 test PASS (58 Domain + 26 Infra unchanged, 3 gotcha #45 guard test backward compat signature). Pending Chunk B/C: FE Admin Designer move 5 checkbox xuống per-Level slot + FE eOffice read currentLevelOptions + drafterAllowSkipToFinal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -26,7 +26,14 @@ public record AwLevelDto(
|
||||
string? Name,
|
||||
Guid ApproverUserId,
|
||||
string? ApproverUserName,
|
||||
string? ApproverEmail);
|
||||
string? ApproverEmail,
|
||||
// Mig 29 (S21 t5) — 5 advanced options per slot Approver (F1 mode Trả lại
|
||||
// + F3 Edit Section 2). Mỗi NV trong workflow có quyền riêng.
|
||||
bool AllowReturnOneLevel,
|
||||
bool AllowReturnOneStep,
|
||||
bool AllowReturnToAssignee,
|
||||
bool AllowReturnToDrafter,
|
||||
bool AllowApproverEditDetails);
|
||||
|
||||
public record AwStepDto(
|
||||
Guid Id,
|
||||
@ -46,15 +53,9 @@ public record AwDefinitionDto(
|
||||
string? Description,
|
||||
bool IsActive,
|
||||
bool IsUserSelectable,
|
||||
// Mig 28 (S21 t4) — 6 advanced options của workflow per version. Admin
|
||||
// Designer tick stick → checkbox. FE eOffice render dropdown / Skip / Edit
|
||||
// conditional theo flag tương ứng.
|
||||
bool AllowReturnOneLevel,
|
||||
bool AllowReturnOneStep,
|
||||
bool AllowReturnToAssignee,
|
||||
bool AllowReturnToDrafter,
|
||||
bool AllowDrafterSkipToFinal,
|
||||
bool AllowApproverEditDetails,
|
||||
// Mig 29 (S21 t5) — 6 advanced options đã MOVE per-NV: 5 flag (F1+F3) xuống
|
||||
// AwLevelDto (per slot Approver), F2 AllowDrafterSkipToFinal xuống User table
|
||||
// (per-Drafter user). Workflow-level Mig 28 dropped.
|
||||
DateTime? ActivatedAt,
|
||||
DateTime CreatedAt,
|
||||
List<AwStepDto> Steps);
|
||||
@ -137,13 +138,6 @@ public class GetAwAdminOverviewQueryHandler(
|
||||
d.Description,
|
||||
d.IsActive,
|
||||
d.IsUserSelectable,
|
||||
// Mig 28 — 6 Allow* flag
|
||||
d.AllowReturnOneLevel,
|
||||
d.AllowReturnOneStep,
|
||||
d.AllowReturnToAssignee,
|
||||
d.AllowReturnToDrafter,
|
||||
d.AllowDrafterSkipToFinal,
|
||||
d.AllowApproverEditDetails,
|
||||
d.ActivatedAt,
|
||||
d.CreatedAt,
|
||||
d.Steps.OrderBy(s => s.Order).Select(s => new AwStepDto(
|
||||
@ -155,7 +149,10 @@ public class GetAwAdminOverviewQueryHandler(
|
||||
s.Levels.OrderBy(l => l.Order).Select(l =>
|
||||
{
|
||||
users.TryGetValue(l.ApproverUserId, out var info);
|
||||
return new AwLevelDto(l.Id, l.Order, l.Name, l.ApproverUserId, info.FullName, info.Email);
|
||||
// Mig 29 (S21 t5) — 5 Allow* flag per slot Level
|
||||
return new AwLevelDto(l.Id, l.Order, l.Name, l.ApproverUserId, info.FullName, info.Email,
|
||||
l.AllowReturnOneLevel, l.AllowReturnOneStep, l.AllowReturnToAssignee,
|
||||
l.AllowReturnToDrafter, l.AllowApproverEditDetails);
|
||||
}).ToList()
|
||||
)).ToList());
|
||||
|
||||
@ -181,7 +178,18 @@ public class GetAwAdminOverviewQueryHandler(
|
||||
|
||||
// ========== POST new version ==========
|
||||
|
||||
public record CreateAwLevelInput(int Order, string? Name, Guid ApproverUserId);
|
||||
public record CreateAwLevelInput(
|
||||
int Order,
|
||||
string? Name,
|
||||
Guid ApproverUserId,
|
||||
// Mig 29 (S21 t5) — 5 Allow* options per slot. Admin Designer tick per
|
||||
// Level row. Default backward compat: AllowReturnToDrafter=true, 4 còn lại
|
||||
// false (admin opt-in từng slot).
|
||||
bool AllowReturnOneLevel = false,
|
||||
bool AllowReturnOneStep = false,
|
||||
bool AllowReturnToAssignee = false,
|
||||
bool AllowReturnToDrafter = true,
|
||||
bool AllowApproverEditDetails = false);
|
||||
|
||||
public record CreateAwStepInput(
|
||||
int Order,
|
||||
@ -194,15 +202,7 @@ public record CreateAwDefinitionCommand(
|
||||
string Code,
|
||||
string Name,
|
||||
string? Description,
|
||||
List<CreateAwStepInput> Steps,
|
||||
// Mig 28 (S21 t4) — 6 Allow* options. Default = backward compat S17
|
||||
// (chỉ Trả về Drafter enabled). Admin tick stick để mở mode khác.
|
||||
bool AllowReturnOneLevel = false,
|
||||
bool AllowReturnOneStep = false,
|
||||
bool AllowReturnToAssignee = false,
|
||||
bool AllowReturnToDrafter = true,
|
||||
bool AllowDrafterSkipToFinal = false,
|
||||
bool AllowApproverEditDetails = false) : IRequest<Guid>;
|
||||
List<CreateAwStepInput> Steps) : IRequest<Guid>;
|
||||
|
||||
public class CreateAwDefinitionCommandValidator : AbstractValidator<CreateAwDefinitionCommand>
|
||||
{
|
||||
@ -295,13 +295,7 @@ public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
Description = request.Description,
|
||||
IsActive = true,
|
||||
IsUserSelectable = true, // Mig 25 — version mới mặc định cho user pick
|
||||
// Mig 28 (S21 t4) — 6 Allow* options
|
||||
AllowReturnOneLevel = request.AllowReturnOneLevel,
|
||||
AllowReturnOneStep = request.AllowReturnOneStep,
|
||||
AllowReturnToAssignee = request.AllowReturnToAssignee,
|
||||
AllowReturnToDrafter = request.AllowReturnToDrafter,
|
||||
AllowDrafterSkipToFinal = request.AllowDrafterSkipToFinal,
|
||||
AllowApproverEditDetails = request.AllowApproverEditDetails,
|
||||
// Mig 29 (S21 t5) — Allow* options đã move xuống Level slot (per-NV)
|
||||
ActivatedAt = DateTime.UtcNow,
|
||||
Steps = request.Steps.OrderBy(s => s.Order)
|
||||
.Select(s => new ApprovalWorkflowStep
|
||||
@ -315,6 +309,12 @@ public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
Order = l.Order,
|
||||
Name = l.Name,
|
||||
ApproverUserId = l.ApproverUserId,
|
||||
// Mig 29 (S21 t5) — 5 Allow* per slot
|
||||
AllowReturnOneLevel = l.AllowReturnOneLevel,
|
||||
AllowReturnOneStep = l.AllowReturnOneStep,
|
||||
AllowReturnToAssignee = l.AllowReturnToAssignee,
|
||||
AllowReturnToDrafter = l.AllowReturnToDrafter,
|
||||
AllowApproverEditDetails = l.AllowApproverEditDetails,
|
||||
}).ToList(),
|
||||
})
|
||||
.ToList(),
|
||||
|
||||
Reference in New Issue
Block a user