import { apiRequestData } from "./http"; export type PurchaseRequestStatus = "draft" | "reviewing" | "approved" | "rejected" | "cancelled"; export type PurchaseRequestSummary = { id: string; requestNo: string | null; applicantId: string; submitterId: string | null; departmentId: string; legalEntityId: string | null; costCenterId: string | null; supplierId: string | null; documentCategoryId: string | null; budgetPoolId: string | null; title: string; reason: string | null; currencyCode: string; totalAmount: string; expectedDeliveryDate: string | null; status: PurchaseRequestStatus; createdAt: string | null; updatedAt: string | null; applicant: { id: string; employeeNo: string; name: string; } | null; submitter: { id: string; employeeNo: string; name: string; } | null; department: { id: string; name: string; } | null; legalEntity: { id: string; code: string; name: string; } | null; costCenter: { id: string; code: string; name: string; legalEntityId: string; } | null; supplier: { id: string; code: string; name: string; } | null; documentCategory: { id: string; code: string; name: string; entityType: string; } | null; budgetPool: { id: string; code: string; name: string; } | null; }; export type PurchaseRequestItem = { id: string; description: string; specification: string | null; quantity: string; unitPrice: string; lineAmount: string; isAssetCandidate: boolean; createdAt: string | null; updatedAt: string | null; }; export type PurchaseAttachment = { id: string; originalName: string; mimeType: string; fileSize: number; uploadedBy: string; createdAt: string | null; uploader: { id: string; employeeNo: string; name: string; } | null; }; export type PurchaseArchivedFile = { storagePath: string | null; originalName: string | null; mimeType: string | null; fileSize: number; }; export type PurchaseOrderArchive = { id: string; poNo: string; contractNo: string | null; archivedAt: string | null; archivedBy: string; archivedByEmployee: { id: string; employeeNo: string; name: string; } | null; archivedFiles: PurchaseArchivedFile[]; }; export type PurchaseRequestDetail = PurchaseRequestSummary & { items: PurchaseRequestItem[]; attachments: PurchaseAttachment[]; pendingWorkflow: { instanceId: string; currentStatus: string; currentStepId: string; task: { id: string; stepId: string; stepName: string; assigneeId: string | null; assigneeRole: string | null; } | null; } | null; archiveOrder: PurchaseOrderArchive | null; permissions: { canEditDraft: boolean; canSubmit: boolean; canWithdraw: boolean; canArchiveOrder: boolean; }; }; export type PurchaseRequestListResponse = { page: number; pageSize: number; total: number; mine: boolean; items: PurchaseRequestSummary[]; }; export type PurchaseRequestListQuery = { status?: PurchaseRequestStatus; page?: number; pageSize?: number; mine?: boolean; supplierId?: string; legalEntityId?: string; costCenterId?: string; }; export type PurchaseRequestItemPayload = { description: string; specification?: string | null; quantity: string; unitPrice: string; isAssetCandidate?: boolean; }; 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 fetchPurchaseRequests(query: PurchaseRequestListQuery = {}) { return apiRequestData( `/api/purchase-requests${toQueryString(query as Record)}`, ); } export async function createPurchaseRequest() { return apiRequestData<{ purchaseRequest: PurchaseRequestDetail }>("/api/purchase-requests", { method: "POST", body: JSON.stringify({}), }); } export async function fetchPurchaseRequestDetail(purchaseRequestId: string) { return apiRequestData(`/api/purchase-requests/${purchaseRequestId}`); } export async function updatePurchaseRequest( purchaseRequestId: string, payload: Partial<{ title: string; reason: string | null; currencyCode: string; legalEntityId: string | null; costCenterId: string | null; supplierId: string | null; documentCategoryId: string | null; budgetPoolId: string | null; expectedDeliveryDate: string | null; items: PurchaseRequestItemPayload[]; }>, ) { return apiRequestData<{ purchaseRequest: PurchaseRequestDetail }>(`/api/purchase-requests/${purchaseRequestId}`, { method: "PATCH", body: JSON.stringify(payload), }); } export async function submitPurchaseRequest(purchaseRequestId: string) { return apiRequestData<{ purchaseRequestId: string; requestNo: string; status: "reviewing"; workflowInstanceId: string; currentTaskId: string; budgetPoolId: string | null; warnings: string[]; budgetReservation: { applied: boolean; reservedAmount: string; }; }>(`/api/purchase-requests/${purchaseRequestId}/submit`, { method: "POST", body: JSON.stringify({}), }); } export async function withdrawPurchaseRequest(purchaseRequestId: string) { return apiRequestData<{ purchaseRequestId: string; status: "draft"; workflowInstanceId: string | null; budgetRelease: { applied: boolean; items: Array<{ budgetPoolId: string; amount: string }>; }; }>(`/api/purchase-requests/${purchaseRequestId}/withdraw`, { method: "POST", body: JSON.stringify({}), }); } export async function fetchPurchaseOrderArchive(purchaseRequestId: string) { return apiRequestData<{ archiveOrder: PurchaseOrderArchive | null }>(`/api/purchase-requests/${purchaseRequestId}/archive-order`); } export async function archivePurchaseOrder( purchaseRequestId: string, payload: { poNo: string; contractNo?: string | null; archivedFiles?: PurchaseArchivedFile[]; }, ) { return apiRequestData<{ archiveOrder: PurchaseOrderArchive }>(`/api/purchase-requests/${purchaseRequestId}/archive-order`, { method: "POST", body: JSON.stringify(payload), }); } export async function uploadPurchaseAttachment(purchaseRequestId: string, file: File) { const formData = new FormData(); formData.append("file", file); return apiRequestData<{ attachment: PurchaseAttachment }>(`/api/purchase-requests/${purchaseRequestId}/attachments`, { method: "POST", body: formData, }); } export async function deletePurchaseAttachment(purchaseRequestId: string, attachmentId: string) { return apiRequestData<{ outcome: "deleted"; attachmentId: string }>( `/api/purchase-requests/${purchaseRequestId}/attachments/${attachmentId}`, { method: "DELETE", }, ); } export async function issuePurchaseAttachmentSignedUrl(purchaseRequestId: string, attachmentId: string) { return apiRequestData<{ signedUrl: string; expiresAt: string }>( `/api/purchase-requests/${purchaseRequestId}/attachments/${attachmentId}/signed-url`, { method: "POST", body: JSON.stringify({}), }, ); }