[CLAUDE] Workflow: fix workflow picker 2 bug (P11-A Max re-review) + SetWorkflow endpoint
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m5s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m5s
Double-check chất lượng P11-A ở Max (agents trước chạy High + truncate 3×) → phát hiện 2 bug THẬT trong workflow-picker FE của WorkflowAppDetailPage (core approve/reject/return ĐÚNG, chỉ sub-flow chọn quy trình hỏng): Bug #1 (HIGH) — pinWorkflow PUT /{id} chỉ gửi {approvalWorkflowId} → UpdateDraft validator (Reason NotEmpty, NumDays>0...) fail → 400. Nút "Lưu quy trình" vỡ. Bug #2 (HIGH) — fetch workflow expect flat array nhưng endpoint trả AwAdminOverviewDto {types:[...]} → picker rỗng/crash. FE copy nhầm pattern hỏng của ProposalCreatePage thay vì PE/Contract proven. Fix: - BE: thêm endpoint chuyên dụng PUT /{id}/workflow + Set{Module}WorkflowCommand/Handler cho 4 module — chỉ set ApprovalWorkflowId trên draft Nhap/TraLai (verify ApplicableType per module), KHÔNG validate field khác. Single-responsibility, bulletproof. - FE: sửa fetch mirror PE/Contract (data.types.find(t=>t.applicableType===X)?.history .filter(isUserSelectable)) + pin gọi endpoint mới. fe-admin+fe-user SHA256 identical. - Test: +3 SetWorkflow (happy no-status-change / wrong ApplicableType Conflict / submitted guard) → 141→144 PASS. Verify: BE build 0 error · 144 test PASS · FE build ×2 · SHA256 identical. Bonus phát hiện: ProposalCreatePage (S37) có bug #2 có sẵn (latent, chưa exercise UAT) → flag spawn task riêng, KHÔNG fix trong commit này. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -26,7 +26,7 @@ import {
|
||||
type Kind = 'leave' | 'ot' | 'travel' | 'vehicle'
|
||||
type ActionKind = 'approve' | 'reject' | 'return'
|
||||
|
||||
interface WorkflowOption { id: string; code: string; name: string }
|
||||
interface WorkflowOption { id: string; code: string; name: string; isActive: boolean; isUserSelectable: boolean }
|
||||
|
||||
function formatDate(iso?: string): string {
|
||||
if (!iso) return '—'
|
||||
@ -140,12 +140,19 @@ export function WorkflowAppDetailPage() {
|
||||
const hasWorkflow = !!d?.approvalWorkflowId
|
||||
|
||||
// Workflow picker — chỉ fetch khi draft chưa pin workflow.
|
||||
// Endpoint trả AwAdminOverviewDto { types: [{ applicableType, history: [...] }] } —
|
||||
// KHÔNG phải flat array. Mirror pattern ContractCreatePage/PeWorkspace: extract bucket
|
||||
// theo applicableType rồi filter isUserSelectable (admin ghim cho user pick).
|
||||
const workflows = useQuery({
|
||||
queryKey: ['approval-workflows-v2', { applicableType: config?.applicableType, isUserSelectable: true }],
|
||||
queryFn: async () =>
|
||||
(await api.get<WorkflowOption[]>('/approval-workflows-v2', {
|
||||
params: { applicableType: config.applicableType, isUserSelectable: true },
|
||||
})).data,
|
||||
queryKey: ['approval-workflows-v2', config?.applicableType],
|
||||
queryFn: async () => {
|
||||
const res = await api.get<{ types: { applicableType: number; history: WorkflowOption[] }[] }>(
|
||||
'/approval-workflows-v2',
|
||||
{ params: { applicableType: config.applicableType } },
|
||||
)
|
||||
const bucket = res.data.types.find((t) => t.applicableType === config.applicableType)
|
||||
return (bucket?.history ?? []).filter((w) => w.isUserSelectable)
|
||||
},
|
||||
enabled: !!config && isDraft && !hasWorkflow,
|
||||
})
|
||||
|
||||
@ -156,7 +163,9 @@ export function WorkflowAppDetailPage() {
|
||||
|
||||
const pinWorkflow = useMutation({
|
||||
mutationFn: async (workflowId: string) => {
|
||||
await api.put(`${config.endpoint}/${id}`, { approvalWorkflowId: workflowId })
|
||||
// Endpoint chuyên dụng /workflow — chỉ set ApprovalWorkflowId trên draft.
|
||||
// KHÔNG dùng PUT /{id} (UpdateDraft) vì nó validate Reason/NumDays... → 400.
|
||||
await api.put(`${config.endpoint}/${id}/workflow`, { approvalWorkflowId: workflowId })
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success('Đã chọn quy trình duyệt')
|
||||
|
||||
Reference in New Issue
Block a user