完成五人团队正式内用最小收口(07-18-small-team-internal-readiness)

这个提交包含在:
2026-07-18 15:46:14 +08:00
父节点 58c8decef9
当前提交 5d0a5f9a38
共修改 134 个文件,包含 10790 行新增和 1413 行删除
+1 -2
查看文件
@@ -7,8 +7,7 @@ export type ApprovalRoleCode =
| "finance"
| "finance_mgr"
| "administration"
| "hr"
| "admin";
| "hr";
export type ApprovalOwnerSelfFallbackRoleCode = "finance_mgr";
export type ApprovalRule = {
+5 -4
查看文件
@@ -164,7 +164,7 @@ export type EmployeeContract = {
startDate: string | null;
endDate: string | null;
terminatedDate: string | null;
attachmentPath: string | null;
hasAttachment: boolean;
attachmentUrl: string | null;
status: EmployeeContractStatus;
createdAt: string | null;
@@ -285,6 +285,7 @@ export type FetchEmployeesParams = {
hireDateFrom?: string;
hireDateTo?: string;
employmentStatus?: EmployeeEmploymentStatus;
scope?: "directory" | "management";
};
export type BatchOperationResult = {
@@ -384,6 +385,7 @@ export async function fetchEmployees(params: FetchEmployeesParams) {
if (params.hireDateFrom) search.set("hireDateFrom", params.hireDateFrom);
if (params.hireDateTo) search.set("hireDateTo", params.hireDateTo);
if (params.employmentStatus) search.set("employmentStatus", params.employmentStatus);
if (params.scope) search.set("scope", params.scope);
return apiRequestData<EmployeeListResponse>(`/api/employees?${search.toString()}`);
}
@@ -547,7 +549,6 @@ export async function createEmployeeContract(
startDate: string;
endDate: string;
terminatedDate?: string | null;
attachmentPath?: string | null;
},
) {
return apiRequestData<EmployeeContract>(`/api/employees/${employeeId}/contracts`, {
@@ -565,7 +566,6 @@ export async function patchEmployeeContract(
startDate: string;
endDate: string;
terminatedDate: string | null;
attachmentPath: string | null;
}>,
) {
return apiRequestData<EmployeeContract>(`/api/employees/${employeeId}/contracts/${contractId}`, {
@@ -588,9 +588,10 @@ export async function downloadEmployeeContractAttachment(attachmentUrl: string):
return apiRequestBlob(attachmentUrl);
}
export async function deleteEmployeeContract(employeeId: string, contractId: string) {
export async function deleteEmployeeContract(employeeId: string, contractId: string, reason: string) {
return apiRequestData<{ contractId: string; deleted: boolean }>(`/api/employees/${employeeId}/contracts/${contractId}`, {
method: "DELETE",
body: JSON.stringify({ reason }),
});
}
+17 -9
查看文件
@@ -138,7 +138,23 @@ export function mapApiErrorMessage(
}
if (details?.payment === "already_paid_conflict") {
return "该报销单已支付且付款信息冲突,请刷新后确认。";
return "该单据已由其他付款动作处理,请刷新后核对付款记录。";
}
if (details?.payment === "source_amount_changed") {
return "源单金额已发生变化,本次付款未执行,请刷新后重新制单。";
}
if (details?.payment === "payment_batch_v1_required") {
return "付款批次已启用,请从付款页面完成制单、复核和执行。";
}
if (details?.entityIds === "contains_active_payment_batch") {
return "所选报销已进入其他有效付款批次,请刷新候选列表。";
}
if (details?.receiptAttachment === "void_required") {
return "银行回单不能直接删除,请填写原因后作废。";
}
if (details?.status === "invalid_pay_status") {
@@ -149,14 +165,6 @@ export function mapApiErrorMessage(
return "复核人与批次创建人不能是同一人。";
}
if (details?.review === "second_reviewer_conflict") {
return "二次复核人不能与首个复核人相同。";
}
if (details?.review === "high_risk_second_review_required") {
return "当前为高风险付款批次,完成二次复核后才能执行。";
}
if (details?.review === "batch_review_required") {
return "当前批次尚未完成复核,不能执行。";
}
+39 -7
查看文件
@@ -39,7 +39,7 @@ export type PaymentBatch = {
thresholdAmount: string;
requiredReviewCount: number;
completedReviewCount: number;
nextStep: "first_review" | "second_review" | "ready_for_execute";
nextStep: "first_review" | "ready_for_execute";
makerCheckerRequired: boolean;
reviewerPermission: string;
};
@@ -57,9 +57,32 @@ export type PaymentBatch = {
executedBy: string | null;
cancelledAt: string | null;
cancelledBy: string | null;
cancelledReason: string | null;
items: PaymentBatchItem[];
};
export type PaymentBatchCandidate = {
entityId: string;
entityType: "reimbursement";
businessNo: string;
employee: {
id: string;
employeeNo: string;
name: string;
};
amount: string;
currencyCode: "CNY";
businessDate: string | null;
summary: string | null;
};
export type PaymentBatchCandidatesResponse = {
items: PaymentBatchCandidate[];
page: number;
pageSize: number;
total: number;
};
export type PaymentBatchReceiptAttachment = {
id: string;
originalName: string;
@@ -89,6 +112,15 @@ export async function fetchPaymentBatchDetail(batchId: string) {
return apiRequestData<{ item: PaymentBatch }>(`/api/payment-batches/${batchId}`);
}
export async function fetchPaymentBatchCandidates(query: { q?: string; page?: number; pageSize?: number } = {}) {
const params = new URLSearchParams();
if (query.q?.trim()) params.set("q", query.q.trim());
if (query.page) params.set("page", String(query.page));
if (query.pageSize) params.set("pageSize", String(query.pageSize));
const suffix = params.toString() ? `?${params.toString()}` : "";
return apiRequestData<PaymentBatchCandidatesResponse>(`/api/payment-batches/candidates${suffix}`);
}
export async function createPaymentBatch(payload: {
entityType: PaymentBatchEntityType;
name: string;
@@ -131,10 +163,10 @@ export async function executePaymentBatch(batchId: string) {
});
}
export async function cancelPaymentBatch(batchId: string) {
export async function cancelPaymentBatch(batchId: string, reason: string) {
return apiRequestData<{ item: PaymentBatch }>(`/api/payment-batches/${batchId}/cancel`, {
method: "POST",
body: JSON.stringify({}),
body: JSON.stringify({ reason }),
});
}
@@ -170,9 +202,9 @@ export async function downloadPaymentBatchReceiptAttachment(
return apiRequestBlob(buildAttachmentFileUrl(paymentBatchReceiptAttachmentFileUrl(batchId, attachmentId), reason));
}
export async function deletePaymentBatchReceiptAttachment(batchId: string, attachmentId: string) {
return apiRequestData<{ attachmentId: string; outcome: "deleted" }>(
`/api/payment-batches/${batchId}/receipt-attachments/${attachmentId}`,
{ method: "DELETE" },
export async function voidPaymentBatchReceiptAttachment(batchId: string, attachmentId: string, reason: string) {
return apiRequestData<{ attachmentId: string; outcome: "voided"; voidedAt: string }>(
`/api/payment-batches/${batchId}/receipt-attachments/${attachmentId}/void`,
{ method: "POST", body: JSON.stringify({ reason }) },
);
}
+2 -1
查看文件
@@ -377,11 +377,12 @@ export async function uploadPurchaseAttachment(purchaseRequestId: string, file:
});
}
export async function deletePurchaseAttachment(purchaseRequestId: string, attachmentId: string) {
export async function deletePurchaseAttachment(purchaseRequestId: string, attachmentId: string, reason: string) {
return apiRequestData<{ outcome: "deleted"; attachmentId: string }>(
`/api/purchase-requests/${purchaseRequestId}/attachments/${attachmentId}`,
{
method: "DELETE",
body: JSON.stringify({ reason }),
},
);
}
+2 -1
查看文件
@@ -505,11 +505,12 @@ export async function uploadReimbursementAttachments(reimbursementId: string, fi
);
}
export async function deleteReimbursementAttachment(reimbursementId: string, attachmentId: string) {
export async function deleteReimbursementAttachment(reimbursementId: string, attachmentId: string, reason: string) {
return apiRequestData<{ attachmentId: string; outcome: string }>(
`/api/reimbursements/${reimbursementId}/attachments/${attachmentId}`,
{
method: "DELETE",
body: JSON.stringify({ reason }),
},
);
}