import { WEB_SERVICE_PREFIX } from '@/constants/service'; import { request } from '../request'; import { type ProjectLocalDateValue, normalizeProjectLocalDate } from './project-shared'; import { type ServiceRequestResult, mapServiceResult, normalizeNullableStringId, normalizeStringId, safeJsonRequestConfig } from './shared'; const OVERTIME_APPLICATION_PREFIX = `${WEB_SERVICE_PREFIX}/project/overtime-applications`; type StringIdResponse = string | number; type OvertimeApplicationResponse = Omit< Api.OvertimeApplication.OvertimeApplication, 'id' | 'applicantId' | 'approverId' | 'overtimeDate' | 'allowEdit' | 'terminal' > & { id: StringIdResponse; applicantId: StringIdResponse; approverId: StringIdResponse; overtimeDate: ProjectLocalDateValue; allowEdit?: boolean | number | string | null; terminal?: boolean | number | string | null; }; type OvertimeApplicationPageResponse = Omit & { total: number | string; list: OvertimeApplicationResponse[]; }; type OvertimeApplicationStatusLogResponse = Omit< Api.OvertimeApplication.OvertimeApplicationStatusLog, 'id' | 'applicationId' | 'operatorUserId' | 'overtimeDateSnapshot' > & { id: StringIdResponse; applicationId: StringIdResponse; operatorUserId: StringIdResponse; overtimeDateSnapshot: ProjectLocalDateValue; }; function normalizeBooleanFlag(value: boolean | number | string | null | undefined) { if (typeof value === 'boolean') { return value; } if (typeof value === 'number') { return value === 1; } if (typeof value === 'string') { const normalized = value.trim().toLowerCase(); return !['', '0', 'false', 'n', 'no'].includes(normalized); } return false; } function normalizeTotal(total: number | string) { const value = Number(total); return Number.isFinite(value) ? Math.max(0, value) : 0; } function normalizeOvertimeApplication( response: OvertimeApplicationResponse ): Api.OvertimeApplication.OvertimeApplication { return { ...response, id: normalizeStringId(response.id), applicantId: normalizeStringId(response.applicantId), approverId: normalizeStringId(response.approverId), overtimeDate: normalizeProjectLocalDate(response.overtimeDate) ?? '', statusName: response.statusName || response.statusCode, allowEdit: normalizeBooleanFlag(response.allowEdit), terminal: normalizeBooleanFlag(response.terminal), approvalComment: response.approvalComment ?? null, approvalTime: response.approvalTime ?? null }; } function normalizeStatusLog( response: OvertimeApplicationStatusLogResponse ): Api.OvertimeApplication.OvertimeApplicationStatusLog { return { ...response, id: normalizeStringId(response.id), applicationId: normalizeStringId(response.applicationId), operatorUserId: normalizeStringId(response.operatorUserId), overtimeDateSnapshot: normalizeProjectLocalDate(response.overtimeDateSnapshot) ?? '', fromStatus: normalizeNullableStringId(response.fromStatus), reason: response.reason ?? null, remark: response.remark ?? null }; } function createPageQuery(params: Api.OvertimeApplication.OvertimeApplicationSearchParams = {}) { const query = new URLSearchParams(); query.append('pageNo', String(params.pageNo ?? 1)); query.append('pageSize', String(params.pageSize ?? 10)); if (params.keyword) { query.append('keyword', params.keyword); } if (params.applicantName) { query.append('applicantName', params.applicantName); } if (params.approverId) { query.append('approverId', params.approverId); } if (params.approverName) { query.append('approverName', params.approverName); } if (params.statusCode) { query.append('statusCode', params.statusCode); } params.overtimeDate?.forEach(item => { if (item) { query.append('overtimeDate', item); } }); params.createTime?.forEach(item => { if (item) { query.append('createTime', item); } }); return query.toString(); } function toSaveRequest(data: Api.OvertimeApplication.SaveOvertimeApplicationParams) { return { overtimeDate: data.overtimeDate, overtimeDuration: data.overtimeDuration, overtimeReason: data.overtimeReason.trim(), overtimeContent: data.overtimeContent.trim(), approverId: data.approverId }; } function toStatusActionRequest(data: Api.OvertimeApplication.StatusActionParams = {}) { return { reason: data.reason?.trim() || undefined }; } export async function fetchGetOvertimeApplicationPage( params: Api.OvertimeApplication.OvertimeApplicationSearchParams = {} ) { const query = createPageQuery(params); const result = await request({ ...safeJsonRequestConfig, url: query ? `${OVERTIME_APPLICATION_PREFIX}/page?${query}` : `${OVERTIME_APPLICATION_PREFIX}/page`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, data => ({ total: normalizeTotal(data.total), list: data.list.map(normalizeOvertimeApplication) })); } export async function fetchGetOvertimeApplicationApprovalPage( params: Api.OvertimeApplication.OvertimeApplicationSearchParams = {} ) { const query = createPageQuery(params); const result = await request({ ...safeJsonRequestConfig, url: query ? `${OVERTIME_APPLICATION_PREFIX}/approval-page?${query}` : `${OVERTIME_APPLICATION_PREFIX}/approval-page`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, data => ({ total: normalizeTotal(data.total), list: data.list.map(normalizeOvertimeApplication) })); } export async function fetchGetOvertimeApplicationDetail(id: string) { const result = await request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, normalizeOvertimeApplication); } export async function fetchCreateOvertimeApplication(data: Api.OvertimeApplication.SaveOvertimeApplicationParams) { const result = await request({ ...safeJsonRequestConfig, url: OVERTIME_APPLICATION_PREFIX, method: 'post', data: toSaveRequest(data) }); return mapServiceResult(result as ServiceRequestResult, normalizeStringId); } export function fetchUpdateRejectedOvertimeApplication( id: string, data: Api.OvertimeApplication.SaveOvertimeApplicationParams ) { return request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}`, method: 'put', data: toSaveRequest(data) }); } export function fetchApproveOvertimeApplication(id: string, data: Api.OvertimeApplication.StatusActionParams = {}) { return request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}/approve`, method: 'post', data: toStatusActionRequest(data) }); } export function fetchRejectOvertimeApplication(id: string, data: Api.OvertimeApplication.StatusActionParams) { return request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}/reject`, method: 'post', data: toStatusActionRequest(data) }); } export function fetchCancelOvertimeApplication(id: string, data: Api.OvertimeApplication.StatusActionParams) { return request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}/cancel`, method: 'post', data: toStatusActionRequest(data) }); } export function fetchDeleteOvertimeApplication(id: string) { return request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}`, method: 'delete' }); } export async function fetchGetOvertimeApplicationStatusLogs(id: string) { const result = await request({ ...safeJsonRequestConfig, url: `${OVERTIME_APPLICATION_PREFIX}/${id}/status-logs`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, data => data.map(normalizeStatusLog) ); } export function fetchExportOvertimeApplications(params: Api.OvertimeApplication.OvertimeApplicationSearchParams = {}) { const query = createPageQuery(params); return request({ url: query ? `${OVERTIME_APPLICATION_PREFIX}/export?${query}` : `${OVERTIME_APPLICATION_PREFIX}/export`, method: 'get', responseType: 'blob' }); }