294 行
7.1 KiB
TypeScript
294 行
7.1 KiB
TypeScript
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<string, unknown> | 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<string, string | number | undefined>) {
|
|
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<WorkflowTaskListResponse>(`/api/workflow/tasks${toQueryString(query)}`);
|
|
}
|
|
|
|
export async function fetchWorkflowTaskDetail(taskId: string) {
|
|
return apiRequestData<WorkflowTaskDetail>(`/api/workflow/tasks/${taskId}`);
|
|
}
|
|
|
|
export async function fetchWorkflowApprovers(query: WorkflowApproverQuery = {}) {
|
|
return apiRequestData<WorkflowApproverListResponse>(
|
|
`/api/workflow/approvers${toQueryString(query as Record<string, string | number | undefined>)}`,
|
|
);
|
|
}
|
|
|
|
export async function approveWorkflowTask(taskId: string) {
|
|
return apiRequestData<Record<string, unknown>>(`/api/workflow/tasks/${taskId}/approve`, {
|
|
method: "POST",
|
|
body: JSON.stringify({}),
|
|
});
|
|
}
|
|
|
|
export async function rejectWorkflowTask(taskId: string, comment: string) {
|
|
return apiRequestData<Record<string, unknown>>(`/api/workflow/tasks/${taskId}/reject`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ comment }),
|
|
});
|
|
}
|
|
|
|
export async function returnWorkflowTask(taskId: string, comment: string) {
|
|
return apiRequestData<Record<string, unknown>>(`/api/workflow/tasks/${taskId}/return`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ comment }),
|
|
});
|
|
}
|
|
|
|
export async function transferWorkflowTask(taskId: string, toApproverId: string, reason: string) {
|
|
return apiRequestData<Record<string, unknown>>(`/api/workflow/tasks/${taskId}/transfer`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ toApproverId, reason }),
|
|
});
|
|
}
|
|
|
|
export async function batchApproveWorkflowTasks(payload: { taskIds: string[]; comment?: string }) {
|
|
return apiRequestData<WorkflowBatchActionResponse>("/api/workflow/batch-approve", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function batchRejectWorkflowTasks(payload: { taskIds: string[]; comment: string }) {
|
|
return apiRequestData<WorkflowBatchActionResponse>("/api/workflow/batch-reject", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|