import { apiRequestData } from "./http"; export type TravelPaymentChannel = | "bank_transfer" | "corporate_card" | "virtual_card" | "manual" | "other"; export type TravelPaymentBudgetSummaryItem = { budgetPoolId: string; budgetPoolCode: string | null; budgetPoolName: string | null; outstanding: string; reserve?: string; confirm?: string; release?: string; confirmPending?: string; authorize?: string; settle?: string; reverse?: string; settlePending?: string; }; export type TravelPaymentAuthorization = { id: string; source: string; externalAuthNo: string; employeeId: string; departmentId: string | null; travelRequestId: string; budgetPoolId: string | null; legalEntityId: string; costCenterId: string; authorizedAmount: string; settledAmount: string; reversedAmount: string; currency: string; occurredAt: string | null; expiresAt: string | null; status: string; createdAt: string | null; updatedAt: string | null; }; export type TravelPaymentMatchedOrder = { id: string; externalOrderNo: string; status: string; amount: string; currency: string; exactMatch: boolean; }; export type TravelPaymentTransaction = { id: string; source: string; externalTxnId: string; cardAuthorizationId: string | null; employeeId: string; departmentId: string | null; travelRequestId: string; travelOrderId: string | null; amount: string; currency: string; txnType: string; status: string; occurredAt: string | null; freezeSuggestedAt: string | null; freezeSuggestedBy: string | null; freezeReasonCode: string | null; freezeReasonNote: string | null; matchedOrder: TravelPaymentMatchedOrder | null; createdAt: string | null; updatedAt: string | null; }; export type TravelPaymentBoundInvoice = { id: string; status: string; originalName: string | null; totalAmount: string | null; invoiceCode: string | null; invoiceNumber: string | null; invoiceDate: string | null; linkedReimbursementId: string | null; linkedTravelOrderId: string | null; }; export type TravelPaymentOrder = { id: string; externalOrderNo: string; source: string; amount: string; currency: string; status: string; paymentVoucherNo: string | null; paymentDate: string | null; paymentChannel: TravelPaymentChannel | null; paidAt: string | null; paidBy: string | null; boundInvoices: TravelPaymentBoundInvoice[]; matchedTransactions: TravelPaymentTransaction[]; actions: { canMarkPaid: boolean; canBindInvoice: boolean; }; }; export type TravelPaymentAnomaly = { code: string; level: "low" | "medium" | "high"; title: string; detail: string; transactionId: string; travelOrderId: string | null; }; export type TravelPaymentTrack = { travelRequestId: string; requestNo: string | null; requestBudgetTrack: { items: TravelPaymentBudgetSummaryItem[]; }; corporateBudgetTrack: { items: TravelPaymentBudgetSummaryItem[]; }; authorizations: TravelPaymentAuthorization[]; transactions: TravelPaymentTransaction[]; travelOrders: TravelPaymentOrder[]; anomalies: TravelPaymentAnomaly[]; permissions: { canManagePayments: boolean; }; }; export type TravelAuthorizationListResponse = { page: number; pageSize: number; total: number; items: TravelPaymentAuthorization[]; }; export type TravelTransactionListResponse = { page: number; pageSize: number; total: number; items: TravelPaymentTransaction[]; }; function toQueryString(query: Record) { const params = new URLSearchParams(); for (const [key, value] of Object.entries(query)) { if (value == null || value === "") { continue; } params.set(key, typeof value === "boolean" ? (value ? "1" : "0") : String(value)); } const encoded = params.toString(); return encoded ? `?${encoded}` : ""; } export async function fetchTravelAuthorizations(query: Record = {}) { return apiRequestData( `/api/travel/authorizations${toQueryString(query)}`, ); } export async function importTravelAuthorizations(payload: { authorizations: Array> }) { return apiRequestData>("/api/travel/authorizations/import", { method: "POST", body: JSON.stringify(payload), }); } export async function fetchTravelTransactions(query: Record = {}) { return apiRequestData( `/api/travel/transactions${toQueryString(query)}`, ); } export async function importTravelTransactions(payload: { transactions: Array> }) { return apiRequestData>("/api/travel/transactions/import", { method: "POST", body: JSON.stringify(payload), }); } export async function suggestFreezeTravelTransaction( transactionId: string, payload: { reasonCode: "amount_mismatch" | "currency_mismatch" | "missing_order" | "duplicate" | "manual_review"; note?: string | null; }, ) { return apiRequestData(`/api/travel/transactions/${transactionId}/freeze-suggestion`, { method: "POST", body: JSON.stringify(payload), }); } export async function markTravelOrderPaid( travelOrderId: string, payload: { paymentVoucherNo?: string | null; paymentDate?: string | null; paymentChannel?: TravelPaymentChannel | null; }, ) { return apiRequestData<{ travelOrderId: string; travelRequestId: string | null; status: string; paymentVoucherNo: string | null; paymentDate: string | null; paymentChannel: TravelPaymentChannel | null; }>(`/api/travel-orders/${travelOrderId}/mark-paid`, { method: "POST", body: JSON.stringify(payload), }); } export async function fetchTravelPaymentTrack(travelRequestId: string) { return apiRequestData(`/api/travel-requests/${travelRequestId}/payment-track`); }