[CLAUDE] PE-Workflow: S22+5 Chunk A — Mig 30 +AllowApproverEditBudget per-Level slot
Bro clarify spec S22+4: - KHÔNG đổi logic edit ngân sách (Drafter Nháp/TraLai vẫn duy nhất default) - Thêm flag per-NV slot trong Designer: "Cho phép NV này edit Section ngân sách lúc đang duyệt" (mirror pattern F3 AllowApproverEditDetails Mig 29) Mig 30 `AddAllowApproverEditBudgetToLevels`: - ALTER ApprovalWorkflowLevels +AllowApproverEditBudget bit NOT NULL DEFAULT 0 - 3-file rule (mig.cs + Designer.cs + Snapshot.cs) - Apply LocalDB Dev + Design Domain entity ApprovalWorkflowLevel +AllowApproverEditBudget (default false). EF config HasDefaultValue(false). DTO AwLevelDto + ApprovalWorkflowOptionsDto + CreateAwLevelInput all extend +AllowApproverEditBudget. PE GET handler populate currentLevelOptions thêm AllowApproverEditBudget từ curLevel slot. Admin Designer GET/POST handler propagate flag. AdjustBudgetCommand handler refactor ChoDuyet branch: - Trước: check actor match level.ApproverUserId (cho phép mặc định) - Sau: check level.AllowApproverEditBudget=true AND actor match ApproverUserId → throw ConflictException nếu slot chưa được cấp quyền Verify: - dotnet build SolutionErp.slnx — 0 err, 2 warn DocxRenderer pre-existing - Mig 30 applied Dev + Design DB Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -28,12 +28,14 @@ public record AwLevelDto(
|
||||
string? ApproverUserName,
|
||||
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.
|
||||
// + F3 Edit Section 2). Mig 30 (S22+5) — F4 +AllowApproverEditBudget.
|
||||
// Mỗi NV trong workflow có quyền riêng.
|
||||
bool AllowReturnOneLevel,
|
||||
bool AllowReturnOneStep,
|
||||
bool AllowReturnToAssignee,
|
||||
bool AllowReturnToDrafter,
|
||||
bool AllowApproverEditDetails);
|
||||
bool AllowApproverEditDetails,
|
||||
bool AllowApproverEditBudget);
|
||||
|
||||
public record AwStepDto(
|
||||
Guid Id,
|
||||
@ -152,7 +154,7 @@ public class GetAwAdminOverviewQueryHandler(
|
||||
// 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);
|
||||
l.AllowReturnToDrafter, l.AllowApproverEditDetails, l.AllowApproverEditBudget);
|
||||
}).ToList()
|
||||
)).ToList());
|
||||
|
||||
@ -184,12 +186,13 @@ public record CreateAwLevelInput(
|
||||
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).
|
||||
// false (admin opt-in từng slot). Mig 30 (S22+5) — F4 AllowApproverEditBudget.
|
||||
bool AllowReturnOneLevel = false,
|
||||
bool AllowReturnOneStep = false,
|
||||
bool AllowReturnToAssignee = false,
|
||||
bool AllowReturnToDrafter = true,
|
||||
bool AllowApproverEditDetails = false);
|
||||
bool AllowApproverEditDetails = false,
|
||||
bool AllowApproverEditBudget = false);
|
||||
|
||||
public record CreateAwStepInput(
|
||||
int Order,
|
||||
@ -315,6 +318,7 @@ public class CreateAwDefinitionCommandHandler(IApplicationDbContext db)
|
||||
AllowReturnToAssignee = l.AllowReturnToAssignee,
|
||||
AllowReturnToDrafter = l.AllowReturnToDrafter,
|
||||
AllowApproverEditDetails = l.AllowApproverEditDetails,
|
||||
AllowApproverEditBudget = l.AllowApproverEditBudget,
|
||||
}).ToList(),
|
||||
})
|
||||
.ToList(),
|
||||
|
||||
@ -82,12 +82,14 @@ public record PurchaseEvaluationChangelogDto(
|
||||
// FE eOffice filter Trả lại dropdown + Edit Section 2 enabled theo flag của
|
||||
// Cấp hiện tại NV đang duyệt. Null nếu phiếu V1 legacy hoặc không ChoDuyet.
|
||||
// F2 (Drafter skip) đã move sang `PeDetailBundleDto.DrafterAllowSkipToFinal`.
|
||||
// Mig 30 (S22+5) — F4 +AllowApproverEditBudget cho Section "Điều chỉnh ngân sách".
|
||||
public record ApprovalWorkflowOptionsDto(
|
||||
bool AllowReturnOneLevel,
|
||||
bool AllowReturnOneStep,
|
||||
bool AllowReturnToAssignee,
|
||||
bool AllowReturnToDrafter,
|
||||
bool AllowApproverEditDetails);
|
||||
bool AllowApproverEditDetails,
|
||||
bool AllowApproverEditBudget);
|
||||
|
||||
public record PurchaseEvaluationWorkflowSummaryDto(
|
||||
string PolicyName,
|
||||
|
||||
@ -290,7 +290,9 @@ public class AdjustPurchaseEvaluationBudgetCommandHandler(
|
||||
}
|
||||
else if (entity.Phase == PurchaseEvaluationPhase.ChoDuyet)
|
||||
{
|
||||
// Approver scope — actor phải là ApproverUserId của currentLevel
|
||||
// F4 (Mig 30 — S22+5) — Approver scope chỉ accept khi
|
||||
// currentLevel.AllowApproverEditBudget=true (admin Designer tick
|
||||
// per slot) AND actor match ApproverUserId.
|
||||
if (entity.ApprovalWorkflowId is not Guid awId)
|
||||
throw new ConflictException("Phiếu V1 legacy không hỗ trợ điều chỉnh ngân sách lúc đang duyệt.");
|
||||
if (entity.CurrentWorkflowStepIndex is not int csi || entity.CurrentApprovalLevelOrder is not int curLvl)
|
||||
@ -307,7 +309,14 @@ public class AdjustPurchaseEvaluationBudgetCommandHandler(
|
||||
throw new ConflictException("Pointer step out of range — schema lỗi.");
|
||||
var step = stepsOrdered[csi];
|
||||
var level = step.Levels.FirstOrDefault(l => l.Order == curLvl);
|
||||
if (level?.ApproverUserId != actorId)
|
||||
if (level is null)
|
||||
throw new ConflictException("Cấp duyệt không tìm thấy — schema lỗi.");
|
||||
if (!level.AllowApproverEditBudget)
|
||||
throw new ConflictException(
|
||||
$"Cấp Approver hiện tại (Bước {step.Order} / Cấp {curLvl}) " +
|
||||
"không được cấp quyền chỉnh sửa Section ngân sách. " +
|
||||
"Liên hệ Admin Designer cấp quyền slot.");
|
||||
if (level.ApproverUserId != actorId)
|
||||
throw new ForbiddenException(
|
||||
$"Chỉ NV phụ trách Bước {step.Order} / Cấp {curLvl} mới được điều chỉnh ngân sách lúc đang duyệt.");
|
||||
actorTag = $"[Approver Bước {step.Order}/Cấp {curLvl}]";
|
||||
@ -761,7 +770,8 @@ public class GetPurchaseEvaluationQueryHandler(
|
||||
curLevel.AllowReturnOneStep,
|
||||
curLevel.AllowReturnToAssignee,
|
||||
curLevel.AllowReturnToDrafter,
|
||||
curLevel.AllowApproverEditDetails);
|
||||
curLevel.AllowApproverEditDetails,
|
||||
curLevel.AllowApproverEditBudget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user