删除库存和旧回调管理
This commit is contained in:
@@ -1,16 +1,9 @@
|
||||
import { buildClaimUrl } from '../claim/claim-service.js'
|
||||
import { getClaimTokenById } from '../../repositories/claim-token-repo.js'
|
||||
import {
|
||||
getInventoryItemById,
|
||||
listInventoryItems,
|
||||
listInventorySkuSuggestions,
|
||||
} from '../../repositories/inventory-repo.js'
|
||||
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
|
||||
import { getOrderById, listOrders } from '../../repositories/order-repo.js'
|
||||
import { getTaskById, listTasks, listTasksByOrderId } from '../../repositories/task-repo.js'
|
||||
import { listTaskInventoryBindingsByTaskId } from '../../repositories/task-inventory-binding-repo.js'
|
||||
import { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
|
||||
import { getWebhookEventById, listWebhookEvents, listWebhookEventsByOrderId } from '../../repositories/webhook-event-repo.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { formatFenToAmount, normalizeFen } from '../../utils/money.js'
|
||||
import { normalizeDateQuery, normalizePage, normalizePageSize, safeParseJson } from './admin-query-utils.js'
|
||||
@@ -19,7 +12,6 @@ import {
|
||||
canRegenerateClaimLinkForViewer,
|
||||
createAdminViewerContext,
|
||||
getTaskPrimaryClaimTokenId,
|
||||
getTaskPrimaryInventoryItemId,
|
||||
isManualDispatchTask,
|
||||
mapKuaishouCloudFulfillmentContext,
|
||||
mapManualDispatchContext,
|
||||
@@ -31,36 +23,24 @@ import {
|
||||
resolveOrderItemDeliveryMode,
|
||||
resolveOrderItemTitle,
|
||||
} from './admin-read-shared-helpers.js'
|
||||
import { mapAdminInventoryListItem } from './admin-inventory-read-helpers.js'
|
||||
import { mapAdminOrderListItem, summarizeOrderItems } from './admin-order-read-helpers.js'
|
||||
import { mapAdminWebhookEvent } from './admin-webhook-read-helpers.js'
|
||||
import {
|
||||
buildOrderBindingSummary,
|
||||
createTaskBindingSummaryFromBindings,
|
||||
getRequiredTask,
|
||||
getTaskBindingSummary,
|
||||
getTaskBindingSummaryMap,
|
||||
mapAdminTaskEvent,
|
||||
mapAdminTaskInventoryBinding,
|
||||
mapAdminTaskListItem,
|
||||
mapAdminTaskSummary,
|
||||
} from './admin-task-read-helpers.js'
|
||||
|
||||
import type {
|
||||
AdminInventoryListResponse,
|
||||
AdminInventorySkuSuggestionResponse,
|
||||
AdminOrderListResponse,
|
||||
AdminTaskListResponse,
|
||||
AdminWebhookEventListResponse,
|
||||
} from '../../types/admin-read-models.js'
|
||||
import type {
|
||||
AdminEntityIdInput,
|
||||
AdminInventoryListQueryInput,
|
||||
AdminInventorySkuSuggestionQueryInput,
|
||||
AdminOrderListQueryInput,
|
||||
AdminTaskListQueryInput,
|
||||
AdminViewerSessionInput,
|
||||
AdminWebhookEventListQueryInput,
|
||||
} from '../../types/admin-read-inputs.js'
|
||||
|
||||
type JsonRecord = Record<string, any>
|
||||
@@ -94,12 +74,10 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
|
||||
})
|
||||
}
|
||||
|
||||
const [items, tasks, webhookEvents] = await Promise.all([
|
||||
const [items, tasks] = await Promise.all([
|
||||
listOrderItemsByOrderId(order.id),
|
||||
listTasksByOrderId(order.id),
|
||||
listWebhookEventsByOrderId(order.id),
|
||||
])
|
||||
const taskBindingSummaryMap = await getTaskBindingSummaryMap(tasks.map((task) => task.id))
|
||||
const itemSummary = summarizeOrderItems(items)
|
||||
|
||||
return {
|
||||
@@ -125,7 +103,7 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
|
||||
rawPayload: order.raw_payload_json && typeof order.raw_payload_json === 'object'
|
||||
? order.raw_payload_json
|
||||
: JSON.parse(String(order.raw_payload_json || '{}')),
|
||||
bindingSummary: buildOrderBindingSummary(tasks, taskBindingSummaryMap),
|
||||
bindingSummary: buildOrderBindingSummary(tasks),
|
||||
},
|
||||
items: items.map((item) => ({
|
||||
orderItemId: item.id,
|
||||
@@ -138,20 +116,7 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
|
||||
? item.spec_json
|
||||
: JSON.parse(String(item.spec_json || '{}')),
|
||||
})),
|
||||
tasks: tasks.map((task) => mapAdminTaskSummary(task, getTaskBindingSummary(taskBindingSummaryMap, task.id))),
|
||||
webhookEvents: webhookEvents.map((event) => ({
|
||||
eventId: event.id,
|
||||
provider: event.provider || '',
|
||||
platform: event.platform,
|
||||
shopId: event.shop_id || '',
|
||||
shopName: resolveDisplayShopName(event.provider, event.shop_id, event.shop_name),
|
||||
eventType: event.event_type,
|
||||
eventKey: event.event_key,
|
||||
signatureValid: Boolean(event.signature_valid),
|
||||
processed: Boolean(event.processed),
|
||||
processError: event.process_error,
|
||||
createdAt: event.created_at,
|
||||
})),
|
||||
tasks: tasks.map((task) => mapAdminTaskSummary(task)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,15 +137,10 @@ export async function getAdminTasks(
|
||||
dateFrom: normalizeDateQuery(query.dateFrom),
|
||||
dateTo: normalizeDateQuery(query.dateTo, true),
|
||||
})
|
||||
const taskBindingSummaryMap = await getTaskBindingSummaryMap(items.map((item) => item.id))
|
||||
const viewerContext = createAdminViewerContext(session)
|
||||
|
||||
return {
|
||||
items: items.map((item) => mapAdminTaskListItem(
|
||||
item,
|
||||
getTaskBindingSummary(taskBindingSummaryMap, item.id),
|
||||
viewerContext,
|
||||
)),
|
||||
items: items.map((item) => mapAdminTaskListItem(item, viewerContext)),
|
||||
pagination: { page, pageSize, total },
|
||||
}
|
||||
}
|
||||
@@ -198,20 +158,16 @@ export async function getAdminTaskDetail(
|
||||
})
|
||||
}
|
||||
|
||||
const [order, claimToken, inventoryItem, taskEvents, inventoryBindings] = await Promise.all([
|
||||
const [order, claimToken, taskEvents] = await Promise.all([
|
||||
getOrderById(task.order_id),
|
||||
getTaskPrimaryClaimTokenId(task) ? getClaimTokenById(getTaskPrimaryClaimTokenId(task)) : Promise.resolve(null),
|
||||
getTaskPrimaryInventoryItemId(task) ? getInventoryItemById(getTaskPrimaryInventoryItemId(task)) : Promise.resolve(null),
|
||||
listTaskEventsByTaskId(task.id),
|
||||
listTaskInventoryBindingsByTaskId(task.id),
|
||||
])
|
||||
const orderItems = order ? await listOrderItemsByOrderId(order.id) : []
|
||||
const orderItem = orderItems.find((item) => item.id === task.order_item_id) || null
|
||||
const taskContext = parseTaskContext(task)
|
||||
const taskState = parseTaskState(task)
|
||||
const taskBindingSummary = createTaskBindingSummaryFromBindings(inventoryBindings)
|
||||
const viewerContext = createAdminViewerContext(session)
|
||||
const mappedInventoryBindings = inventoryBindings.map((binding) => mapAdminTaskInventoryBinding(binding, task, viewerContext))
|
||||
const claimUrl = claimToken ? buildClaimUrl(claimToken.token) : ''
|
||||
const screenshotUrl = await resolveAdminTaskScreenshotUrl(task, viewerContext)
|
||||
const kuaishouCloudFulfillment = mapKuaishouCloudFulfillmentContext(taskContext.kuaishouCloudFulfillment)
|
||||
@@ -221,9 +177,8 @@ export async function getAdminTaskDetail(
|
||||
...task,
|
||||
sku_code: orderItem?.sku_code || '',
|
||||
sku_name: orderItem?.sku_name || '',
|
||||
inventory_display_value: inventoryItem?.display_value || '',
|
||||
claim_token: claimToken?.token || '',
|
||||
}, taskBindingSummary, viewerContext),
|
||||
}, viewerContext),
|
||||
order: order
|
||||
? {
|
||||
orderId: order.id,
|
||||
@@ -253,17 +208,6 @@ export async function getAdminTaskDetail(
|
||||
claimUrl,
|
||||
}
|
||||
: null,
|
||||
inventory: inventoryItem
|
||||
? {
|
||||
inventoryItemId: inventoryItem.id,
|
||||
skuCode: inventoryItem.sku_code,
|
||||
batchNo: inventoryItem.batch_no,
|
||||
credentialType: inventoryItem.credential_type || 'claim_code',
|
||||
displayValue: viewerContext.canViewSensitiveTaskData ? inventoryItem.display_value : '',
|
||||
status: inventoryItem.status,
|
||||
}
|
||||
: null,
|
||||
inventoryBindings: mappedInventoryBindings,
|
||||
artifacts: viewerContext.canViewSensitiveTaskData ? safeParseJson(task.artifacts_json) : {},
|
||||
screenshotUrl,
|
||||
review: {
|
||||
@@ -279,8 +223,7 @@ export async function getAdminTaskDetail(
|
||||
operations: {
|
||||
canRetry: viewerContext.canManageTaskLifecycle
|
||||
&& !isManualDispatchTask(task)
|
||||
&& ['retry_pending', 'manual_review', 'waiting_inventory'].includes(task.task_status),
|
||||
canReleaseInventory: mappedInventoryBindings.some((binding) => binding.canRelease),
|
||||
&& ['retry_pending', 'manual_review'].includes(task.task_status),
|
||||
canRegenerateClaimLink: canRegenerateClaimLinkForViewer(task, viewerContext),
|
||||
canClose: canViewerCloseTask(task, viewerContext),
|
||||
canMarkManualReview: viewerContext.canManageTaskLifecycle && !['redeemed', 'closed', 'manual_review'].includes(task.task_status),
|
||||
@@ -319,96 +262,3 @@ export async function getAdminTaskScreenshotPath(
|
||||
errorCode: 'admin_task_screenshot_not_found',
|
||||
})
|
||||
}
|
||||
|
||||
export async function getAdminInventoryItems(
|
||||
query: AdminInventoryListQueryInput = {},
|
||||
session: AdminViewerSessionInput | null = null,
|
||||
): Promise<AdminInventoryListResponse> {
|
||||
const page = normalizePage(query.page)
|
||||
const pageSize = normalizePageSize(query.pageSize)
|
||||
const viewerContext = createAdminViewerContext(session)
|
||||
const { items, total } = await listInventoryItems({
|
||||
page,
|
||||
pageSize,
|
||||
skuCode: String(query.skuCode || '').trim(),
|
||||
credentialType: String(query.credentialType || '').trim(),
|
||||
status: String(query.status || '').trim(),
|
||||
batchNo: String(query.batchNo || '').trim(),
|
||||
inventoryGroupCode: String(query.inventoryGroupCode || '').trim(),
|
||||
allowedInventoryGroupCodes: viewerContext.allowedInventoryGroupCodes,
|
||||
})
|
||||
|
||||
return {
|
||||
items: await Promise.all(items.map((item) => mapAdminInventoryListItem(item))),
|
||||
pagination: { page, pageSize, total },
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAdminInventorySkuSuggestions(
|
||||
query: AdminInventorySkuSuggestionQueryInput = {},
|
||||
session: AdminViewerSessionInput | null = null,
|
||||
): Promise<AdminInventorySkuSuggestionResponse> {
|
||||
const viewerContext = createAdminViewerContext(session)
|
||||
const credentialType = String(query.credentialType || '').trim()
|
||||
const keyword = String(query.keyword || '').trim()
|
||||
const inventoryGroupCode = String(query.inventoryGroupCode || '').trim()
|
||||
const requestedLimit = Number(query.limit)
|
||||
const limit = Number.isFinite(requestedLimit) && requestedLimit > 0
|
||||
? Math.min(100, Math.floor(requestedLimit))
|
||||
: 50
|
||||
const items = await listInventorySkuSuggestions({
|
||||
credentialType,
|
||||
keyword,
|
||||
limit,
|
||||
inventoryGroupCode,
|
||||
allowedInventoryGroupCodes: viewerContext.allowedInventoryGroupCodes,
|
||||
})
|
||||
|
||||
return {
|
||||
items: items.map((item) => ({
|
||||
skuCode: String(item.sku_code || '').trim(),
|
||||
credentialType: String(item.credential_type || '').trim() || 'claim_code',
|
||||
inventoryGroupCode: String(item.inventory_group_code || '').trim(),
|
||||
totalCount: Number(item.total_count || 0),
|
||||
availableCount: Number(item.available_count || 0),
|
||||
latestUpdatedAt: item.latest_updated_at || null,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAdminWebhookEvents(
|
||||
query: AdminWebhookEventListQueryInput = {},
|
||||
): Promise<AdminWebhookEventListResponse> {
|
||||
const page = normalizePage(query.page)
|
||||
const pageSize = normalizePageSize(query.pageSize)
|
||||
const { items, total } = await listWebhookEvents({
|
||||
page,
|
||||
pageSize,
|
||||
provider: String(query.provider || '').trim(),
|
||||
platform: String(query.platform || '').trim(),
|
||||
platformOrderId: String(query.platformOrderId || '').trim(),
|
||||
processed: String(query.processed || '').trim(),
|
||||
visibility: String(query.visibility || '').trim() || 'important',
|
||||
relatedOrderId: String(query.relatedOrderId || '').trim(),
|
||||
dateFrom: normalizeDateQuery(query.dateFrom),
|
||||
dateTo: normalizeDateQuery(query.dateTo, true),
|
||||
})
|
||||
|
||||
return {
|
||||
items: await Promise.all(items.map((item) => mapAdminWebhookEvent(item))),
|
||||
pagination: { page, pageSize, total },
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAdminWebhookEventDetail(eventId: AdminEntityIdInput): Promise<JsonRecord> {
|
||||
const event = await getWebhookEventById(Number(eventId))
|
||||
|
||||
if (!event) {
|
||||
throw createHttpError('Webhook 事件不存在', {
|
||||
statusCode: 404,
|
||||
errorCode: 'admin_webhook_not_found',
|
||||
})
|
||||
}
|
||||
|
||||
return mapAdminWebhookEvent(event, { includeRaw: true })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user