[CLAUDE] FE-PE: S22+5 Chunk B — Designer checkbox +AllowApproverEditBudget per slot + Section read flag (mirror 2 app)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m23s

FE Admin Designer (ApprovalWorkflowsV2Page.tsx):
- LevelDto + EditLevelEntry +allowApproverEditBudget
- copyFromDefinition + makeDefaultLevelEntry propagate default false
- POST body include allowApproverEditBudget cho mỗi Level slot
- NEW checkbox UI per Level inline panel:
  "Cho phép chỉnh sửa Section ngân sách lúc đang duyệt"
  (col-span-2, mirror pattern allowApproverEditDetails Mig 29)

FE Types mirror 2 app:
- fe-admin + fe-user `ApprovalWorkflowOptions` +allowApproverEditBudget

FE BudgetAdjustSection refactor (mirror 2 app):
- Trước: isApproverChoDuyet = phase ChoDuyet + actor in approvers
- Sau: isApproverChoDuyet = phase ChoDuyet + actor in approvers
  + currentLevelOptions.allowApproverEditBudget=true (per slot opt-in)
- Drafter scope Nháp/Trả lại unchanged
- Admin bypass unchanged

UX impact:
- Admin Designer phải tick checkbox cho NV slot mới được edit ngân sách lúc duyệt
- Nếu KHÔNG tick → button "Điều chỉnh" trong Section 5 KHÔNG hiện cho approver
- Drafter vẫn edit bình thường khi phiếu Nháp/Trả lại

Verify:
- npm run build fe-admin — 569ms pass
- npm run build fe-user — 528ms pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-13 23:12:43 +07:00
parent b079b27343
commit b04a11a62f
5 changed files with 29 additions and 3 deletions

View File

@ -42,11 +42,13 @@ type LevelDto = {
approverUserName: string | null
approverEmail: string | null
// Mig 29 (S21 t5) — 5 Allow* options per slot Approver
// Mig 30 (S22+5) — +AllowApproverEditBudget cho Section ngân sách
allowReturnOneLevel: boolean
allowReturnOneStep: boolean
allowReturnToAssignee: boolean
allowReturnToDrafter: boolean
allowApproverEditDetails: boolean
allowApproverEditBudget: boolean
}
type StepDto = {
id: string
@ -86,11 +88,13 @@ type EditLevelEntry = {
approverUserId: string
// Mig 29 (S21 t5) — 5 Allow* per slot (default backward compat S17: chỉ
// AllowReturnToDrafter=true, 4 còn lại false).
// Mig 30 (S22+5) — +AllowApproverEditBudget cho Section ngân sách (default false).
allowReturnOneLevel: boolean
allowReturnOneStep: boolean
allowReturnToAssignee: boolean
allowReturnToDrafter: boolean
allowApproverEditDetails: boolean
allowApproverEditBudget: boolean
}
type EditStep = { name: string; departmentId: string | null; levelEntries: EditLevelEntry[] }
@ -137,6 +141,7 @@ function copyFromDefinition(d: DefinitionDto): EditStep[] {
allowReturnToAssignee: l.allowReturnToAssignee ?? false,
allowReturnToDrafter: l.allowReturnToDrafter ?? true,
allowApproverEditDetails: l.allowApproverEditDetails ?? false,
allowApproverEditBudget: l.allowApproverEditBudget ?? false,
})),
}))
}
@ -152,6 +157,7 @@ function makeDefaultLevelEntry(order: LevelOrder, approverUserId: string): EditL
allowReturnToAssignee: false,
allowReturnToDrafter: true,
allowApproverEditDetails: false,
allowApproverEditBudget: false,
}
}
@ -553,6 +559,7 @@ function Designer({
allowReturnToAssignee: e.allowReturnToAssignee,
allowReturnToDrafter: e.allowReturnToDrafter,
allowApproverEditDetails: e.allowApproverEditDetails,
allowApproverEditBudget: e.allowApproverEditBudget,
})),
})),
})
@ -911,6 +918,15 @@ function Designer({
/>
<span>Cho phép chỉnh sửa Section 2 (Hạng mục/NCC/Báo giá) lúc đang duyệt</span>
</label>
<label className="col-span-2 flex items-center gap-1 text-[11px] text-slate-700">
<input
type="checkbox"
className="h-3 w-3"
checked={entry.allowApproverEditBudget}
onChange={e => updateField('allowApproverEditBudget', e.target.checked)}
/>
<span>Cho phép chỉnh sửa Section ngân sách lúc đang duyệt</span>
</label>
</div>
</div>
)