[CLAUDE] FE-PE: S21 t5 Chunk C — eOffice read currentLevelOptions + drafterAllowSkipToFinal (per-NV) mirror 2 app
Types refactor `fe-{admin,user}/src/types/purchaseEvaluation.ts`:
- `ApprovalWorkflowOptions` REMOVE allowDrafterSkipToFinal (F2 đã move per-User).
Còn 5 flag (F1 4 mode + F3 EditDetails).
- `PeDetailBundle`:
- RENAME `workflowOptions` → `currentLevelOptions` (clearer semantic per-slot)
- ADD `drafterAllowSkipToFinal: boolean` (BE resolve từ DrafterUserId → User entity)
PeWorkflowPanel.tsx (mirror 2 app):
- RENAME local var `wfOptions` → `levelOptions`
- READ `evaluation.currentLevelOptions` (Cấp hiện tại)
- 4 mode radio render conditional theo levelOptions.allowReturnXxx (unchanged
logic, just rename source)
PeDetailTabs.tsx (mirror 2 app):
- F3 approverEditMode: READ `evaluation.currentLevelOptions?.allowApproverEditDetails`
thay vì workflowOptions.allowApproverEditDetails (semantic per-NV slot)
- F2 allowSkipToFinal: READ `evaluation.drafterAllowSkipToFinal` thay vì
workflowOptions.allowDrafterSkipToFinal (semantic per-Drafter user)
Backward compat verified:
- Phiếu cũ trước Mig 29 vẫn return currentLevelOptions populated (BE backfill
Mig 29 đã copy 5 Allow* per Level)
- drafterAllowSkipToFinal: BE backfill chỉ TRUE cho user từng Drafter PE link
workflow.AllowDrafterSkipToFinal=true (preserve admin config S21 t4)
- Phiếu V1 legacy: currentLevelOptions=null → FE fallback chỉ Drafter mode
Verify:
- npm run build × 2 app pass (fe-user 450ms + fe-admin 439ms, cache hot)
- 0 TS6 err, warning chunk size pre-existing
Pending Chunk D: Docs (schema-diagram §14 update + STATUS + HANDOFF + session log).
Note: User Management page chưa có F2 checkbox UX (defer commit sau khi admin
UAT request — BE field đã có, FE chỉ cần thêm 1 toggle vào UserEdit dialog).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -41,8 +41,9 @@ export function PeWorkflowPanel({
|
||||
const { user: currentUser } = useAuth()
|
||||
const isAdmin = currentUser?.roles?.includes('Admin') ?? false
|
||||
|
||||
// Mig 28 — F1 workflow options. Null nếu V1 legacy → fallback chỉ "Trả về Drafter".
|
||||
const wfOptions = evaluation.workflowOptions
|
||||
// Mig 29 (S21 t5) — F1 options per-Level (Cấp Approver hiện tại). Null nếu
|
||||
// V1 legacy hoặc pointer chưa init → fallback chỉ "Trả về Drafter".
|
||||
const levelOptions = evaluation.currentLevelOptions
|
||||
// List approvers đã ký (cho mode Assignee dropdown pick)
|
||||
const signedApprovers = (evaluation.levelOpinions ?? [])
|
||||
.map(o => ({ userId: o.approverUserId, fullName: o.approverFullName ?? 'NV' }))
|
||||
@ -302,15 +303,15 @@ export function PeWorkflowPanel({
|
||||
<>
|
||||
{/* Mig 28 (S21 t4) — F1 mode picker khi Trả lại. Show modes
|
||||
enabled per workflow.options. Default Drafter (S17 fallback). */}
|
||||
{(wfOptions?.allowReturnOneLevel
|
||||
|| wfOptions?.allowReturnOneStep
|
||||
|| wfOptions?.allowReturnToAssignee
|
||||
|| wfOptions?.allowReturnToDrafter
|
||||
|| !wfOptions) && (
|
||||
{(levelOptions?.allowReturnOneLevel
|
||||
|| levelOptions?.allowReturnOneStep
|
||||
|| levelOptions?.allowReturnToAssignee
|
||||
|| levelOptions?.allowReturnToDrafter
|
||||
|| !levelOptions) && (
|
||||
<div className="mb-3 space-y-1.5">
|
||||
<Label className="text-[12px]">Chọn cách Trả lại</Label>
|
||||
<div className="space-y-1">
|
||||
{(wfOptions?.allowReturnOneLevel) && (
|
||||
{(levelOptions?.allowReturnOneLevel) && (
|
||||
<label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
|
||||
<input
|
||||
type="radio"
|
||||
@ -324,7 +325,7 @@ export function PeWorkflowPanel({
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
{(wfOptions?.allowReturnOneStep) && (
|
||||
{(levelOptions?.allowReturnOneStep) && (
|
||||
<label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
|
||||
<input
|
||||
type="radio"
|
||||
@ -338,7 +339,7 @@ export function PeWorkflowPanel({
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
{(wfOptions?.allowReturnToAssignee) && (
|
||||
{(levelOptions?.allowReturnToAssignee) && (
|
||||
<label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
|
||||
<input
|
||||
type="radio"
|
||||
@ -364,7 +365,7 @@ export function PeWorkflowPanel({
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
{(wfOptions?.allowReturnToDrafter !== false) && (
|
||||
{(levelOptions?.allowReturnToDrafter !== false) && (
|
||||
<label className="flex items-start gap-2 rounded border border-amber-200 bg-white px-2 py-1.5 text-[12px] hover:bg-amber-50/40">
|
||||
<input
|
||||
type="radio"
|
||||
|
||||
Reference in New Issue
Block a user