201 行
6.8 KiB
TypeScript
201 行
6.8 KiB
TypeScript
import type { PurchaseRequestStatus } from "../api/purchaseRequests";
|
|
import type { AssetSensitivityLevel, AssetStatus, AssetType } from "../api/assets";
|
|
|
|
const PURCHASE_STATUS_VALUES = new Set<PurchaseRequestStatus>([
|
|
"draft",
|
|
"reviewing",
|
|
"approved",
|
|
"rejected",
|
|
"cancelled",
|
|
]);
|
|
const ASSET_STATUS_VALUES = new Set<AssetStatus>([
|
|
"in_stock",
|
|
"in_use",
|
|
"under_repair",
|
|
"retired",
|
|
"archived",
|
|
]);
|
|
const ASSET_TYPE_VALUES = new Set<AssetType>([
|
|
"fixed_asset",
|
|
"electronic_document",
|
|
"electronic_system",
|
|
"code_repository",
|
|
"backup_media",
|
|
]);
|
|
const ASSET_SENSITIVITY_VALUES = new Set<AssetSensitivityLevel>([
|
|
"public_candidate",
|
|
"internal",
|
|
"confidential",
|
|
"strictly_confidential",
|
|
]);
|
|
|
|
export const ASSET_CREATE_PATH = "/assets/new";
|
|
|
|
function normalizedEntityId(value: string) {
|
|
return value.trim();
|
|
}
|
|
|
|
function optionalSearchValue(searchParams: URLSearchParams, key: string) {
|
|
return (searchParams.get(key) ?? "").trim();
|
|
}
|
|
|
|
function positivePage(value: string | null) {
|
|
if (!value || !/^[1-9]\d*$/.test(value)) {
|
|
return 1;
|
|
}
|
|
const parsed = Number(value);
|
|
return Number.isSafeInteger(parsed) ? parsed : 1;
|
|
}
|
|
|
|
function appendOptional(target: URLSearchParams, key: string, value: string) {
|
|
if (value) {
|
|
target.set(key, value);
|
|
}
|
|
}
|
|
|
|
export function buildPurchaseRequestDetailPath(purchaseRequestId: string) {
|
|
const normalized = normalizedEntityId(purchaseRequestId);
|
|
return normalized ? `/purchase-requests/${encodeURIComponent(normalized)}` : "/purchase-requests";
|
|
}
|
|
|
|
export function buildAssetDetailPath(assetId: string) {
|
|
const normalized = normalizedEntityId(assetId);
|
|
return normalized ? `/assets/${encodeURIComponent(normalized)}` : "/assets";
|
|
}
|
|
|
|
export function readPurchaseListFilters(
|
|
searchParams: URLSearchParams,
|
|
canViewAll: boolean,
|
|
): {
|
|
status: PurchaseRequestStatus | "";
|
|
mine: boolean;
|
|
supplierId: string;
|
|
legalEntityId: string;
|
|
costCenterId: string;
|
|
page: number;
|
|
} {
|
|
const rawStatus = searchParams.get("status");
|
|
const status = rawStatus === "all"
|
|
? ""
|
|
: rawStatus && PURCHASE_STATUS_VALUES.has(rawStatus as PurchaseRequestStatus)
|
|
? rawStatus as PurchaseRequestStatus
|
|
: "draft";
|
|
const scope = searchParams.get("scope");
|
|
|
|
return {
|
|
status,
|
|
mine: !(canViewAll && scope === "all"),
|
|
supplierId: optionalSearchValue(searchParams, "supplierId"),
|
|
legalEntityId: optionalSearchValue(searchParams, "legalEntityId"),
|
|
costCenterId: optionalSearchValue(searchParams, "costCenterId"),
|
|
page: positivePage(searchParams.get("page")),
|
|
};
|
|
}
|
|
|
|
export function normalizePurchaseListSearchParams(searchParams: URLSearchParams) {
|
|
const normalized = new URLSearchParams();
|
|
const rawStatus = searchParams.get("status");
|
|
if (rawStatus === "all" || (rawStatus && PURCHASE_STATUS_VALUES.has(rawStatus as PurchaseRequestStatus))) {
|
|
normalized.set("status", rawStatus);
|
|
}
|
|
const rawScope = searchParams.get("scope");
|
|
if (rawScope === "own" || rawScope === "all") {
|
|
normalized.set("scope", rawScope);
|
|
}
|
|
appendOptional(normalized, "supplierId", optionalSearchValue(searchParams, "supplierId"));
|
|
appendOptional(normalized, "legalEntityId", optionalSearchValue(searchParams, "legalEntityId"));
|
|
appendOptional(normalized, "costCenterId", optionalSearchValue(searchParams, "costCenterId"));
|
|
const page = positivePage(searchParams.get("page"));
|
|
if (page > 1) {
|
|
normalized.set("page", String(page));
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
export function readAssetListFilters(
|
|
searchParams: URLSearchParams,
|
|
canViewAll: boolean,
|
|
): {
|
|
q: string;
|
|
status: AssetStatus | "";
|
|
assetType: AssetType | "";
|
|
sensitivity: AssetSensitivityLevel | "";
|
|
categoryId: string;
|
|
legalEntityId: string;
|
|
costCenterId: string;
|
|
assigneeId: string;
|
|
mine: boolean;
|
|
} {
|
|
const rawStatus = searchParams.get("status");
|
|
const rawAssetType = searchParams.get("assetType");
|
|
const rawSensitivity = searchParams.get("sensitivity");
|
|
const scope = searchParams.get("scope");
|
|
|
|
return {
|
|
q: searchParams.get("q") ?? "",
|
|
status: rawStatus && ASSET_STATUS_VALUES.has(rawStatus as AssetStatus) ? rawStatus as AssetStatus : "",
|
|
assetType: rawAssetType && ASSET_TYPE_VALUES.has(rawAssetType as AssetType) ? rawAssetType as AssetType : "",
|
|
sensitivity: rawSensitivity && ASSET_SENSITIVITY_VALUES.has(rawSensitivity as AssetSensitivityLevel)
|
|
? rawSensitivity as AssetSensitivityLevel
|
|
: "",
|
|
categoryId: optionalSearchValue(searchParams, "categoryId"),
|
|
legalEntityId: optionalSearchValue(searchParams, "legalEntityId"),
|
|
costCenterId: optionalSearchValue(searchParams, "costCenterId"),
|
|
assigneeId: optionalSearchValue(searchParams, "assigneeId"),
|
|
mine: scope === "own" || !(canViewAll && (scope === "all" || scope == null)),
|
|
};
|
|
}
|
|
|
|
export function normalizeAssetListSearchParams(searchParams: URLSearchParams) {
|
|
const normalized = new URLSearchParams();
|
|
appendOptional(normalized, "q", optionalSearchValue(searchParams, "q"));
|
|
const rawStatus = searchParams.get("status");
|
|
if (rawStatus && ASSET_STATUS_VALUES.has(rawStatus as AssetStatus)) {
|
|
normalized.set("status", rawStatus);
|
|
}
|
|
const rawAssetType = searchParams.get("assetType");
|
|
if (rawAssetType && ASSET_TYPE_VALUES.has(rawAssetType as AssetType)) {
|
|
normalized.set("assetType", rawAssetType);
|
|
}
|
|
const rawSensitivity = searchParams.get("sensitivity");
|
|
if (rawSensitivity && ASSET_SENSITIVITY_VALUES.has(rawSensitivity as AssetSensitivityLevel)) {
|
|
normalized.set("sensitivity", rawSensitivity);
|
|
}
|
|
appendOptional(normalized, "categoryId", optionalSearchValue(searchParams, "categoryId"));
|
|
appendOptional(normalized, "legalEntityId", optionalSearchValue(searchParams, "legalEntityId"));
|
|
appendOptional(normalized, "costCenterId", optionalSearchValue(searchParams, "costCenterId"));
|
|
appendOptional(normalized, "assigneeId", optionalSearchValue(searchParams, "assigneeId"));
|
|
const rawScope = searchParams.get("scope");
|
|
if (rawScope === "own" || rawScope === "all") {
|
|
normalized.set("scope", rawScope);
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
function listSource(pathname: string, searchParams: URLSearchParams) {
|
|
const search = searchParams.toString();
|
|
return search ? `${pathname}?${search}` : pathname;
|
|
}
|
|
|
|
export function resolvePurchaseRequestLegacyRedirect(searchParams: URLSearchParams) {
|
|
const purchaseRequestId = normalizedEntityId(searchParams.get("id") ?? "");
|
|
if (!purchaseRequestId) {
|
|
return null;
|
|
}
|
|
return {
|
|
to: buildPurchaseRequestDetailPath(purchaseRequestId),
|
|
from: listSource("/purchase-requests", normalizePurchaseListSearchParams(searchParams)),
|
|
};
|
|
}
|
|
|
|
export function resolveAssetLegacyRedirect(searchParams: URLSearchParams) {
|
|
const assetId = normalizedEntityId(searchParams.get("id") ?? "");
|
|
if (!assetId) {
|
|
return null;
|
|
}
|
|
return {
|
|
to: buildAssetDetailPath(assetId),
|
|
from: listSource("/assets", normalizeAssetListSearchParams(searchParams)),
|
|
};
|
|
}
|