import { apiRequestData } from "./http"; export type AssetStatus = "in_stock" | "in_use" | "under_repair" | "retired" | "archived"; export type AssetType = "fixed_asset" | "electronic_document" | "electronic_system" | "code_repository" | "backup_media"; export type AssetSensitivityLevel = "public_candidate" | "internal" | "confidential" | "strictly_confidential"; export type AssetCategoryItem = { id: string; code: string; name: string; documentCategoryId: string | null; enabled: boolean; archivedAt: string | null; createdAt: string | null; updatedAt: string | null; documentCategory: { id: string; code: string; name: string; entityType: string; } | null; }; export type AssetAssigneeOption = { id: string; employeeNo: string; name: string; department: { id: string; name: string; } | null; }; export type AssetItem = { id: string; assetNo: string; name: string; assetType: AssetType; sensitivityLevel: AssetSensitivityLevel; categoryId: string; legalEntityId: string; costCenterId: string; purchaseRequestId: string | null; serialNo: string | null; location: string | null; status: AssetStatus; assigneeEmployeeId: string | null; ownerEmployeeId: string | null; keeperEmployeeId: string | null; archiveLocation: string | null; externalRef: string | null; sourceHash: string | null; verificationNo: string | null; confidentialityNote: string | null; metadata: Record | null; sensitiveFieldsRedacted?: boolean; lastVerifiedAt: string | null; expiresAt: string | null; activatedAt: string | null; retiredAt: string | null; createdAt: string | null; updatedAt: string | null; category: { id: string; code: string; name: string; documentCategoryId: string | null; documentCategory: { id: string; code: string; name: string; } | null; } | null; legalEntity: { id: string; code: string; name: string; } | null; costCenter: { id: string; code: string; name: string; legalEntityId: string; } | null; purchaseRequest: { id: string; requestNo: string | null; title: string; status: string; } | null; assignee: { id: string; employeeNo: string; name: string; department: { id: string; name: string; } | null; } | null; owner: AssetAssigneeOption | null; keeper: AssetAssigneeOption | null; permissions: { canEdit: boolean; }; }; export type AssetCategoryListResponse = { includeArchived: boolean; items: AssetCategoryItem[]; }; export type AssetListResponse = { mine: boolean; items: AssetItem[]; }; export type AssetListQuery = { status?: AssetStatus; assetType?: AssetType; sensitivityLevel?: AssetSensitivityLevel; categoryId?: string; assigneeId?: string; ownerId?: string; keeperId?: string; legalEntityId?: string; costCenterId?: string; q?: string; mine?: boolean; }; export type CreateAssetPayload = { name: string; assetType?: AssetType; sensitivityLevel?: AssetSensitivityLevel; categoryId: string; legalEntityId: string; costCenterId: string; purchaseRequestId?: string | null; serialNo?: string | null; location?: string | null; status?: AssetStatus; assigneeEmployeeId?: string | null; ownerEmployeeId?: string | null; keeperEmployeeId?: string | null; archiveLocation?: string | null; externalRef?: string | null; sourceHash?: string | null; verificationNo?: string | null; confidentialityNote?: string | null; metadata?: Record | null; lastVerifiedAt?: string | null; expiresAt?: string | null; activatedAt?: string | null; retiredAt?: string | null; }; export type PatchAssetPayload = Partial< Omit >; export type AssetMovementResponse = { assetId: string; assetNo: string; status: AssetStatus; assigneeEmployeeId: string | null; location: string | null; assignmentId?: string | null; transferId?: string | null; }; export type AssetErpTrackStatus = | "not_triggered" | "pending" | "processing" | "succeeded" | "failed" | "dead_letter" | "skipped"; export type AssetErpBinding = { id: string; provider: string; entityType: string; localId: string; externalId: string | null; externalCode: string | null; lastSyncedAt: string | null; }; export type AssetErpOutbox = { id: string; eventType: string; status: string; attempts: number; lastError: string | null; processedAt: string | null; updatedAt: string | null; }; export type AssetErpStage = { eligible: boolean; reason: string | null; deliveryStatus: AssetErpTrackStatus | string; actionHint: "none" | "backfill" | "retry" | "resync"; preview: { changeType: string | null; sourceEventName: string | null; categoryCode: string | null; legalEntityCode: string | null; costCenterCode: string | null; status: string | null; }; outbox: AssetErpOutbox | null; binding: AssetErpBinding | null; }; export type AssetErpTrack = { asset: { id: string; assetNo: string | null; name: string | null; status: string | null; legalEntity: { id: string; code: string | null; name: string | null; } | null; costCenter: { id: string; code: string | null; name: string | null; } | null; purchaseRequest: { id: string; requestNo: string | null; title: string | null; } | null; }; stage: AssetErpStage; permissions: { canRetry: boolean; canSeeExternalRefs: 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") : value); } const encoded = params.toString(); return encoded ? `?${encoded}` : ""; } export async function fetchAssetCategories(params: { includeArchived?: boolean; enabled?: boolean } = {}) { return apiRequestData( `/api/asset-categories${toQueryString(params as Record)}`, ); } export async function createAssetCategory(payload: { code: string; name: string; documentCategoryId?: string | null; enabled?: boolean; }) { return apiRequestData<{ assetCategory: AssetCategoryItem }>("/api/asset-categories", { method: "POST", body: JSON.stringify(payload), }); } export async function patchAssetCategory( assetCategoryId: string, payload: Partial<{ code: string; name: string; documentCategoryId: string | null; enabled: boolean; }>, ) { return apiRequestData<{ assetCategory: AssetCategoryItem }>(`/api/asset-categories/${assetCategoryId}`, { method: "PATCH", body: JSON.stringify(payload), }); } export async function fetchAssetAssignees(params: { q?: string } = {}) { return apiRequestData<{ items: AssetAssigneeOption[] }>( `/api/assets/assignees${toQueryString(params as Record)}`, ); } export async function fetchAssets(params: AssetListQuery = {}) { return apiRequestData( `/api/assets${toQueryString(params as Record)}`, ); } export async function fetchAssetDetail(assetId: string) { return apiRequestData<{ asset: AssetItem }>(`/api/assets/${assetId}`); } export async function createAsset(payload: CreateAssetPayload) { return apiRequestData<{ asset: AssetItem }>("/api/assets", { method: "POST", body: JSON.stringify(payload), }); } export async function patchAsset(assetId: string, payload: PatchAssetPayload) { return apiRequestData<{ asset: AssetItem }>(`/api/assets/${assetId}`, { method: "PATCH", body: JSON.stringify(payload), }); } export async function assignAsset(assetId: string, payload: { employeeId: string; note?: string | null }) { return apiRequestData(`/api/assets/${assetId}/assign`, { method: "POST", body: JSON.stringify(payload), }); } export async function returnAsset(assetId: string, payload: { note?: string | null } = {}) { return apiRequestData(`/api/assets/${assetId}/return`, { method: "POST", body: JSON.stringify(payload), }); } export async function transferAsset( assetId: string, payload: { toEmployeeId?: string | null; toLocation?: string | null; note?: string | null }, ) { return apiRequestData(`/api/assets/${assetId}/transfer`, { method: "POST", body: JSON.stringify(payload), }); } export async function fetchAssetErpTrack(assetId: string) { return apiRequestData(`/api/integrations/erp/assets/${assetId}/track`); } export async function requeueAssetErpSync(assetId: string, runNow = true) { const query = runNow ? '?runNow=1' : '?runNow=0'; return apiRequestData<{ outboxId: string; status: string; duplicated: boolean; requeued: boolean; eventType: string; }>(`/api/integrations/erp/assets/${assetId}/requeue${query}`, { method: 'POST', body: JSON.stringify({}), }); }