R57 A1-A6:报销模板与差旅申请关联
这个提交包含在:
@@ -0,0 +1,86 @@
|
||||
import { apiRequestData } from "./http";
|
||||
|
||||
export type ReimbursementTemplateItem = {
|
||||
expenseTypeId: string;
|
||||
description: string;
|
||||
defaultAmount?: string;
|
||||
};
|
||||
|
||||
export type ReimbursementTemplate = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
items: ReimbursementTemplateItem[];
|
||||
sortOrder: number;
|
||||
enabled: boolean;
|
||||
createdAt: string | null;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
|
||||
export type ReimbursementTemplateListResponse = {
|
||||
enabled: boolean | null;
|
||||
items: ReimbursementTemplate[];
|
||||
};
|
||||
|
||||
export type ReimbursementTemplateListQuery = {
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
export type CreateReimbursementTemplatePayload = {
|
||||
name: string;
|
||||
description?: string | null;
|
||||
items?: ReimbursementTemplateItem[];
|
||||
sortOrder?: number;
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
export type UpdateReimbursementTemplatePayload = {
|
||||
name?: string;
|
||||
description?: string | null;
|
||||
items?: ReimbursementTemplateItem[];
|
||||
sortOrder?: number;
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
function toQueryString(query: Record<string, string | number | boolean | 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 fetchReimbursementTemplates(query: ReimbursementTemplateListQuery = {}) {
|
||||
return apiRequestData<ReimbursementTemplateListResponse>(
|
||||
`/api/reimbursement-templates${toQueryString(query as Record<string, string | number | boolean | undefined>)}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function createReimbursementTemplate(payload: CreateReimbursementTemplatePayload) {
|
||||
return apiRequestData<ReimbursementTemplate>("/api/reimbursement-templates", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateReimbursementTemplate(
|
||||
templateId: string,
|
||||
payload: UpdateReimbursementTemplatePayload,
|
||||
) {
|
||||
return apiRequestData<ReimbursementTemplate>(`/api/reimbursement-templates/${templateId}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteReimbursementTemplate(templateId: string) {
|
||||
return apiRequestData<ReimbursementTemplate>(`/api/reimbursement-templates/${templateId}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
@@ -24,6 +24,15 @@ export type ReimbursementItem = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type LinkedTravelRequestSummary = {
|
||||
id: string;
|
||||
requestNo: string | null;
|
||||
purpose: string | null;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
estimatedAmount: string;
|
||||
};
|
||||
|
||||
export type ReimbursementListItem = {
|
||||
id: string;
|
||||
formNumber: string | null;
|
||||
@@ -113,6 +122,8 @@ export type ReimbursementDetail = {
|
||||
totalAmount: string | null;
|
||||
description: string | null;
|
||||
projectId: string | null;
|
||||
linkedTravelRequestId: string | null;
|
||||
linkedTravelRequest: LinkedTravelRequestSummary | null;
|
||||
project: {
|
||||
id: string;
|
||||
projectNo: string;
|
||||
@@ -207,6 +218,48 @@ export type ReimbursementPayPayload = {
|
||||
paymentChannel?: "bank" | "alipay" | "wechat" | "cash" | "other";
|
||||
};
|
||||
|
||||
export type ReimbursementCreatePayload = {
|
||||
ownerEmployeeId?: string;
|
||||
reimbursementDate?: string;
|
||||
description?: string;
|
||||
templateId?: string;
|
||||
linkedTravelRequestId?: string;
|
||||
};
|
||||
|
||||
export type ReimbursementCreateResponse = {
|
||||
id: string;
|
||||
formNumber: string | null;
|
||||
submitterId: string;
|
||||
ownerId: string;
|
||||
reimbursementDate: string | null;
|
||||
status: ReimbursementStatus;
|
||||
description: string | null;
|
||||
projectId: string | null;
|
||||
project: {
|
||||
id: string;
|
||||
projectNo: string;
|
||||
name: string;
|
||||
} | null;
|
||||
totalAmount: string;
|
||||
linkedTravelRequestId: string | null;
|
||||
linkedTravelRequest: LinkedTravelRequestSummary | null;
|
||||
items: ReimbursementItem[];
|
||||
};
|
||||
|
||||
export type LinkableTravelRequestSummary = {
|
||||
id: string;
|
||||
requestNo: string | null;
|
||||
purpose: string;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
estimatedAmount: string;
|
||||
};
|
||||
|
||||
export type LinkableTravelRequestListResponse = {
|
||||
ownerEmployeeId: string;
|
||||
items: LinkableTravelRequestSummary[];
|
||||
};
|
||||
|
||||
export type ReimbursementItemPayload = {
|
||||
expenseTypeId: string;
|
||||
expenseDate: string;
|
||||
@@ -301,17 +354,19 @@ export async function fetchReimbursementDetail(reimbursementId: string) {
|
||||
return apiRequestData<ReimbursementDetail>(`/api/reimbursements/${reimbursementId}`);
|
||||
}
|
||||
|
||||
export async function createReimbursement(payload: {
|
||||
ownerEmployeeId?: string;
|
||||
reimbursementDate?: string;
|
||||
description?: string;
|
||||
} = {}) {
|
||||
return apiRequestData<{ id: string }>(`/api/reimbursements`, {
|
||||
export async function createReimbursement(payload: ReimbursementCreatePayload = {}) {
|
||||
return apiRequestData<ReimbursementCreateResponse>(`/api/reimbursements`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchLinkableTravelRequests(query: { ownerEmployeeId?: string } = {}) {
|
||||
return apiRequestData<LinkableTravelRequestListResponse>(
|
||||
`/api/reimbursements/linkable-travel-requests${toQueryString(query as Record<string, string | number | undefined>)}`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function precheckReimbursement(reimbursementId: string) {
|
||||
return apiRequestData<PrecheckResponse>(`/api/reimbursements/${reimbursementId}/precheck`, {
|
||||
method: "POST",
|
||||
|
||||
在新工单中引用
屏蔽一个用户