import { api as client } from "@/auth/http"; import { URL_CONSTANTS } from "@/constants/URLS"; import type { ApproveRatePayload, RuleEngineListMeta, RuleEngineListResult, RuleEngineRecord, RuleEngineResourceSlug, } from "@/types/rule-engine"; import { unwrap } from "@/utils/endpoint"; export interface RuleEngineListParams { search?: string; page?: number; pageSize?: number; isActive?: boolean; status?: string; } const RESOURCE_BASE: Record = { "cargo-types": URL_CONSTANTS.RULE_ENGINE.CARGO_TYPES, "container-types": URL_CONSTANTS.RULE_ENGINE.CONTAINER_TYPES, "priority-rules": URL_CONSTANTS.RULE_ENGINE.PRIORITY_RULES, "service-types": URL_CONSTANTS.RULE_ENGINE.SERVICE_TYPES, "surcharge-types": URL_CONSTANTS.RULE_ENGINE.SURCHARGE_TYPES, "weight-limit-rules": URL_CONSTANTS.RULE_ENGINE.WEIGHT_LIMIT_RULES, yards: URL_CONSTANTS.RULE_ENGINE.YARDS, "shipping-lines": URL_CONSTANTS.RULE_ENGINE.SHIPPING_LINES, rates: URL_CONSTANTS.RULE_ENGINE.RATES, "approval-rules": URL_CONSTANTS.RULE_ENGINE.APPROVAL_RULES, }; const byIdPath = (resource: RuleEngineResourceSlug, id: string): string => { switch (resource) { case "cargo-types": return URL_CONSTANTS.RULE_ENGINE.CARGO_TYPE_BY_ID(id); case "container-types": return URL_CONSTANTS.RULE_ENGINE.CONTAINER_TYPE_BY_ID(id); case "priority-rules": return URL_CONSTANTS.RULE_ENGINE.PRIORITY_RULE_BY_ID(id); case "service-types": return URL_CONSTANTS.RULE_ENGINE.SERVICE_TYPE_BY_ID(id); case "surcharge-types": return URL_CONSTANTS.RULE_ENGINE.SURCHARGE_TYPE_BY_ID(id); case "weight-limit-rules": return URL_CONSTANTS.RULE_ENGINE.WEIGHT_LIMIT_RULE_BY_ID(id); case "yards": return URL_CONSTANTS.RULE_ENGINE.YARD_BY_ID(id); case "shipping-lines": return URL_CONSTANTS.RULE_ENGINE.SHIPPING_LINE_BY_ID(id); case "rates": return URL_CONSTANTS.RULE_ENGINE.RATE_BY_ID(id); case "approval-rules": return URL_CONSTANTS.RULE_ENGINE.APPROVAL_RULE_BY_ID(id); default: return `${RESOURCE_BASE[resource]}/${id}`; } }; const defaultMeta = (dataLength: number, page = 1, pageSize = 20): RuleEngineListMeta => ({ total: dataLength, page, pageSize, totalPages: Math.max(1, Math.ceil(dataLength / pageSize)), }); const normalizeList = ( payload: unknown, page = 1, pageSize = 20, ): RuleEngineListResult => { const body = unwrap(payload as { data: unknown }) as unknown; if (body && typeof body === "object" && "data" in body && Array.isArray((body as RuleEngineListResult).data)) { const typed = body as RuleEngineListResult; return { data: typed.data, meta: typed.meta ?? defaultMeta(typed.data.length, page, pageSize), }; } if (Array.isArray(body)) { return { data: body as T[], meta: defaultMeta(body.length, page, pageSize) }; } return { data: [], meta: defaultMeta(0, page, pageSize) }; }; const normalizeEntity = (payload: unknown): T => { return unwrap(payload as { data: T }) as T; }; export const ruleEngineService = { list: async ( resource: RuleEngineResourceSlug, params?: RuleEngineListParams, ): Promise> => { const page = params?.page ?? 1; const pageSize = params?.pageSize ?? 20; const response = await client.get(RESOURCE_BASE[resource], { params: { page, pageSize, search: params?.search, isActive: params?.isActive, status: params?.status, }, }); return normalizeList(response.data, page, pageSize); }, getById: async ( resource: RuleEngineResourceSlug, id: string, ): Promise => { const response = await client.get(byIdPath(resource, id)); return normalizeEntity(response.data); }, create: async ( resource: RuleEngineResourceSlug, payload: Record, ): Promise => { const response = await client.post(RESOURCE_BASE[resource], payload); return normalizeEntity(response.data); }, update: async ( resource: RuleEngineResourceSlug, id: string, payload: Record, ): Promise => { const response = await client.patch(byIdPath(resource, id), payload); return normalizeEntity(response.data); }, remove: async (resource: RuleEngineResourceSlug, id: string): Promise => { await client.delete(byIdPath(resource, id)); }, submitRate: async (id: string): Promise => { const response = await client.post(URL_CONSTANTS.RULE_ENGINE.RATE_SUBMIT(id)); return normalizeEntity(response.data); }, approveRate: async ( id: string, payload: ApproveRatePayload, ): Promise => { const response = await client.post(URL_CONSTANTS.RULE_ENGINE.RATE_APPROVE(id), payload); return normalizeEntity(response.data); }, getApprovalChain: async ( requiresDirectorApproval = true, ): Promise => { const response = await client.get(URL_CONSTANTS.RULE_ENGINE.APPROVAL_RULES_CHAIN, { params: { requiresDirectorApproval }, }); const body = unwrap(response.data) as unknown; if (Array.isArray(body)) return body as RuleEngineRecord[]; if (body && typeof body === "object" && "data" in body && Array.isArray((body as { data: unknown }).data)) { return (body as { data: RuleEngineRecord[] }).data; } return []; }, };