import { apiRequestData } from "./http"; import type { ExpenseStandardCheck } from "./feeControl"; export type WorkflowTaskSummary = { id: string; instanceId: string; stepId: string; stepName: string; assigneeId: string | null; assigneeRole: string | null; status: "pending" | "completed" | "rejected" | "cancelled" | "skipped"; outcome: string | null; createdAt: string; completedAt: string | null; workflowInstance: { entityType: string; entityId: string; currentStatus: string; } | null; allowedActions: Array<"approve" | "reject" | "return" | "transfer">; }; export type WorkflowTaskListResponse = { page: number; pageSize: number; total: number; items: WorkflowTaskSummary[]; }; export type WorkflowHistoryItem = { id: string; taskId: string | null; actorId: string; actorName: string; actorEmployeeNo: string; action: string; comment: string | null; payload: Record | null; createdAt: string | null; }; export type WorkflowTaskDetail = { task: { id: string; instanceId: string; stepId: string; stepName: string; assigneeId: string | null; assigneeRole: string | null; status: string; outcome: string | null; comment: string | null; createdAt: string | null; completedAt: string | null; }; workflowInstance: { id: string; entityType: string; currentStatus: string; currentStepId: string; contextData: { standardViolations: ExpenseStandardCheck[]; }; startedAt: string | null; completedAt: string | null; } | null; reimbursement: { id: string; formNumber: string | null; status: string; reimbursementDate: string | null; totalAmount: string | null; description: string | null; owner: { id: string; employeeNo: string; name: string; } | null; submitter: { id: string; employeeNo: string; name: string; } | null; } | null; leaveRequest: { id: string; status: string; startDate: string | null; endDate: string | null; startSession: "am" | "pm"; endSession: "am" | "pm"; requestedDays: number; reason: string | null; attachment: { originalName: string | null; mimeType: string | null; } | null; leaveType: { id: string; code: string; name: string; } | null; owner: { id: string; employeeNo: string; name: string; } | null; } | null; purchaseRequest: { id: string; requestNo: string | null; status: string; title: string; reason: string | null; currencyCode: string; totalAmount: string | null; expectedDeliveryDate: string | null; applicant: { id: string; employeeNo: string; name: string; } | null; supplier: { id: string; code: string; name: string; } | null; legalEntity: { id: string; code: string; name: string; } | null; costCenter: { id: string; code: string; name: string; } | null; documentCategory: { id: string; code: string; name: string; } | null; } | null; travelRequest: { id: string; requestNo: string | null; status: string; purpose: string; tripType: string; startDate: string | null; endDate: string | null; estimatedAmount: string | null; applicant: { id: string; employeeNo: string; name: string; } | null; legalEntity: { id: string; code: string; name: string; } | null; costCenter: { id: string; code: string; name: string; } | null; segments: Array<{ id: string; sortOrder: number; segmentRole: string; transportType: string; fromCity: string; toCity: string; }>; } | null; allowedActions: Array<"approve" | "reject" | "return" | "transfer">; history: WorkflowHistoryItem[]; }; export type WorkflowApprover = { id: string; employeeNo: string; name: string; email: string; roleCodes: string[]; }; export type WorkflowApproverListResponse = { page: number; pageSize: number; total: number; items: WorkflowApprover[]; }; export type WorkflowTaskListQuery = { status?: "pending" | "completed" | "rejected" | "cancelled" | "skipped"; page?: number; pageSize?: number; }; export type WorkflowApproverQuery = { keyword?: string; page?: number; pageSize?: number; }; export type WorkflowBatchActionResult = { taskId: string; outcome: "approved" | "rejected" | "skipped" | "error"; reason?: string; }; export type WorkflowBatchActionSummary = { approved: number; rejected?: number; skipped: number; errored: number; }; export type WorkflowBatchActionResponse = { results: WorkflowBatchActionResult[]; summary: WorkflowBatchActionSummary; }; function toQueryString(query: Record) { const params = new URLSearchParams(); for (const [key, value] of Object.entries(query)) { if (value == null || value === "") { continue; } params.set(key, String(value)); } const encoded = params.toString(); return encoded ? `?${encoded}` : ""; } export async function fetchWorkflowTasks(query: WorkflowTaskListQuery) { return apiRequestData(`/api/workflow/tasks${toQueryString(query)}`); } export async function fetchWorkflowTaskDetail(taskId: string) { return apiRequestData(`/api/workflow/tasks/${taskId}`); } export async function fetchWorkflowApprovers(query: WorkflowApproverQuery = {}) { return apiRequestData( `/api/workflow/approvers${toQueryString(query as Record)}`, ); } export async function approveWorkflowTask(taskId: string) { return apiRequestData>(`/api/workflow/tasks/${taskId}/approve`, { method: "POST", body: JSON.stringify({}), }); } export async function rejectWorkflowTask(taskId: string, comment: string) { return apiRequestData>(`/api/workflow/tasks/${taskId}/reject`, { method: "POST", body: JSON.stringify({ comment }), }); } export async function returnWorkflowTask(taskId: string, comment: string) { return apiRequestData>(`/api/workflow/tasks/${taskId}/return`, { method: "POST", body: JSON.stringify({ comment }), }); } export async function transferWorkflowTask(taskId: string, toApproverId: string, reason: string) { return apiRequestData>(`/api/workflow/tasks/${taskId}/transfer`, { method: "POST", body: JSON.stringify({ toApproverId, reason }), }); } export async function batchApproveWorkflowTasks(payload: { taskIds: string[]; comment?: string }) { return apiRequestData("/api/workflow/batch-approve", { method: "POST", body: JSON.stringify(payload), }); } export async function batchRejectWorkflowTasks(payload: { taskIds: string[]; comment: string }) { return apiRequestData("/api/workflow/batch-reject", { method: "POST", body: JSON.stringify(payload), }); }