文件
hyb-oa/client/src/api/apOperations.ts
T

158 行
4.6 KiB
TypeScript

import { apiRequestBlob, apiRequestData } from "./http";
import type { RiskFlag } from "./feeControl";
export type ApOperationsExportFormat = "csv" | "xlsx";
export type ApOperationsRiskBucket = "all" | "exception" | "budget_overspend";
export type ApOperationsPendingEntityType = "reimbursement" | "travel_order";
export type FinanceLedgerStatus = "draft" | "reviewing" | "approved" | "paid" | "rejected" | "cancelled";
export type FinanceLedgerPaymentStatus = "unpaid" | "paid";
export type FinanceLedgerInvoiceStatus = "none" | "pending_ocr" | "ocr_failed" | "available" | "bound" | "archived";
export type ApPendingPaymentBatchSummary = {
id: string;
batchNo: string;
entityType: string;
name: string;
status: string;
totalAmount: string;
highRisk: boolean;
createdAt: string | null;
};
export type ApFailedPaymentBatchItemSummary = {
id: string;
paymentBatchId: string;
entityId: string;
entityCode: string;
entityTitle: string;
amount: string;
currencyCode: string;
failureCode: string | null;
failureMessage: string | null;
createdAt: string | null;
};
export type ApPartialMatchItemSummary = {
id: string;
travelReconciliationBatchId: string;
travelOrderId: string | null;
travelRequestId: string | null;
matchStatus: string;
resolutionStatus: string;
anomalyCode: string | null;
orderAmount: string | null;
transactionAmount: string | null;
currency: string;
createdAt: string | null;
};
export type ApOperationsSummary = {
summary: {
pendingPaymentCount: number;
partialMatchCount: number;
exceptionCount: number;
budgetOverspendCount: number;
};
pendingPaymentBatches: ApPendingPaymentBatchSummary[];
failedPaymentBatchItems: ApFailedPaymentBatchItemSummary[];
exceptionRiskFlags: RiskFlag[];
budgetOverspendRisks: RiskFlag[];
partialMatchItems: ApPartialMatchItemSummary[];
};
export async function fetchApOperations() {
return apiRequestData<ApOperationsSummary>("/api/ap-operations");
}
export type FinanceLedgerItem = {
id: string;
formNumber: string | null;
reimbursementDate: string | null;
status: FinanceLedgerStatus;
totalAmount: string;
description: string | null;
owner: { id: string; employeeNo: string; name: string } | null;
submitter: { id: string; employeeNo: string; name: string } | null;
department: { id: string; name: string } | null;
project: { id: string; projectNo: string | null; name: string } | null;
payment: {
status: FinanceLedgerPaymentStatus;
paymentVoucherNo: string | null;
paymentDate: string | null;
paymentChannel: string | null;
paidAt: string | null;
paidBy: { id: string; employeeNo: string; name: string } | null;
};
invoice: {
status: FinanceLedgerInvoiceStatus | "mixed";
counts: {
total: number;
pendingOcr: number;
ocrFailed: number;
available: number;
bound: number;
archived: number;
usedComplete: number;
};
};
attachmentCount: number;
createdAt: string | null;
updatedAt: string | null;
};
export type FinanceLedgerQuery = {
page?: number;
pageSize?: number;
status?: FinanceLedgerStatus;
paymentStatus?: FinanceLedgerPaymentStatus;
invoiceStatus?: FinanceLedgerInvoiceStatus;
dateFrom?: string;
dateTo?: string;
q?: string;
};
export type FinanceLedgerResponse = {
page: number;
pageSize: number;
total: number;
items: FinanceLedgerItem[];
};
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 suffix = params.toString();
return suffix ? `?${suffix}` : "";
}
export async function fetchFinanceLedger(query: FinanceLedgerQuery = {}) {
return apiRequestData<FinanceLedgerResponse>(
`/api/ap-operations/reimbursement-ledger${toQueryString(query as Record<string, string | number | undefined>)}`,
);
}
export async function exportApOperations(params: {
format: ApOperationsExportFormat;
pendingEntityType?: ApOperationsPendingEntityType;
pendingCreatedAtFrom?: string;
pendingCreatedAtTo?: string;
riskBucket?: ApOperationsRiskBucket;
ledgerStatus?: FinanceLedgerStatus;
ledgerPaymentStatus?: FinanceLedgerPaymentStatus;
ledgerInvoiceStatus?: FinanceLedgerInvoiceStatus;
ledgerDateFrom?: string;
ledgerDateTo?: string;
ledgerSearch?: string;
}) {
return apiRequestBlob("/api/exports/ap-operations", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(params),
});
}