Files
edr-platform/apps/edr-freight-web/backoffice/src/services/ruleEngine/ruleEngine.service.ts

226 lines
6.6 KiB
TypeScript

import { api as client } from "@/auth/http";
import { URL_CONSTANTS } from "@/constants/URLS";
import type {
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;
sortBy?: string;
sortOrder?: "ASC" | "DESC";
requiresDirectorApproval?: boolean;
}
export interface RuleEngineReorderPayload {
ids: string[];
requiresDirectorApproval?: boolean;
}
const RESOURCE_BASE: Record<RuleEngineResourceSlug, string> = {
"cargo-types": URL_CONSTANTS.RULE_ENGINE.CARGO_TYPES,
"container-types": URL_CONSTANTS.RULE_ENGINE.CONTAINER_TYPES,
"wagon-types": URL_CONSTANTS.RULE_ENGINE.WAGON_TYPES,
"priority-configs": URL_CONSTANTS.RULE_ENGINE.PRIORITY_CONFIGS,
"service-types": URL_CONSTANTS.RULE_ENGINE.SERVICE_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 "wagon-types":
return URL_CONSTANTS.RULE_ENGINE.WAGON_TYPE_BY_ID(id);
case "priority-configs":
return URL_CONSTANTS.RULE_ENGINE.PRIORITY_CONFIG_BY_ID(id);
case "service-types":
return URL_CONSTANTS.RULE_ENGINE.SERVICE_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 = 10,
): RuleEngineListMeta => ({
total: dataLength,
page,
pageSize,
totalPages: Math.max(1, Math.ceil(dataLength / pageSize)),
});
const isPaginatedListResult = <T extends RuleEngineRecord>(
value: unknown,
): value is RuleEngineListResult<T> =>
Boolean(value) &&
typeof value === "object" &&
"data" in (value ?? {}) &&
Array.isArray((value as RuleEngineListResult<T>).data);
const normalizeList = <T extends RuleEngineRecord>(
payload: unknown,
page = 1,
pageSize = 10,
): RuleEngineListResult<T> => {
if (isPaginatedListResult<T>(payload)) {
return {
data: payload.data,
meta: payload.meta ?? defaultMeta(payload.data.length, page, pageSize),
};
}
const body = unwrap(payload as { data: unknown }) as unknown;
if (isPaginatedListResult<T>(body)) {
return {
data: body.data,
meta: body.meta ?? defaultMeta(body.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 = <T extends RuleEngineRecord>(payload: unknown): T => {
return unwrap(payload as { data: T }) as T;
};
export const ruleEngineService = {
list: async <T extends RuleEngineRecord>(
resource: RuleEngineResourceSlug,
params?: RuleEngineListParams,
): Promise<RuleEngineListResult<T>> => {
const page = params?.page ?? 1;
const pageSize = params?.pageSize ?? 10;
const response = await client.get(RESOURCE_BASE[resource], {
params: {
page,
pageSize,
search: params?.search,
isActive: params?.isActive,
status: params?.status,
sortBy: params?.sortBy,
sortOrder: params?.sortOrder,
requiresDirectorApproval: params?.requiresDirectorApproval,
},
});
return normalizeList<T>(response.data, page, pageSize);
},
getById: async <T extends RuleEngineRecord>(
resource: RuleEngineResourceSlug,
id: string,
): Promise<T> => {
const response = await client.get(byIdPath(resource, id));
return normalizeEntity<T>(response.data);
},
create: async <T extends RuleEngineRecord>(
resource: RuleEngineResourceSlug,
payload: Record<string, unknown>,
): Promise<T> => {
const response = await client.post(RESOURCE_BASE[resource], payload);
return normalizeEntity<T>(response.data);
},
update: async <T extends RuleEngineRecord>(
resource: RuleEngineResourceSlug,
id: string,
payload: Record<string, unknown>,
): Promise<T> => {
const response = await client.patch(byIdPath(resource, id), payload);
return normalizeEntity<T>(response.data);
},
remove: async (
resource: RuleEngineResourceSlug,
id: string,
): Promise<void> => {
await client.delete(byIdPath(resource, id));
},
reorder: async (
resource: RuleEngineResourceSlug,
payload: RuleEngineReorderPayload,
): Promise<void> => {
await client.post(`${RESOURCE_BASE[resource]}/reorder`, payload);
},
moveOrder: async (
resource: RuleEngineResourceSlug,
id: string,
direction: "up" | "down",
): Promise<void> => {
await client.post(`${byIdPath(resource, id)}/move-order`, { direction });
},
submitRate: async <T extends RuleEngineRecord>(id: string): Promise<T> => {
const response = await client.post(
URL_CONSTANTS.RULE_ENGINE.RATE_SUBMIT(id),
);
return normalizeEntity<T>(response.data);
},
approveRate: async <T extends RuleEngineRecord>(id: string): Promise<T> => {
const response = await client.post(
URL_CONSTANTS.RULE_ENGINE.RATE_APPROVE(id),
);
return normalizeEntity<T>(response.data);
},
getApprovalChain: async (
requiresDirectorApproval = true,
): Promise<RuleEngineRecord[]> => {
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 [];
},
};