feat(P19ERP3-3,P19ERP3-4): 新增资产ERP轨道接口与前端卡片挂件
这个提交包含在:
@@ -134,6 +134,81 @@ export type AssetMovementResponse = {
|
||||
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<string, string | boolean | undefined>) {
|
||||
const params = new URLSearchParams();
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
@@ -232,3 +307,21 @@ export async function transferAsset(
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchAssetErpTrack(assetId: string) {
|
||||
return apiRequestData<AssetErpTrack>(`/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({}),
|
||||
});
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户