优化快手电子凭证发码和手动处理

This commit is contained in:
yml2213
2026-07-08 17:28:01 +08:00
parent 647f038061
commit 3ad7c2e50e
17 changed files with 761 additions and 10 deletions
@@ -4,6 +4,10 @@ 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 { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
import {
listKuaishouIndustryVouchersByOid,
listKuaishouIndustryVouchersByTaskId,
} from '../../repositories/kuaishou-industry-voucher-repo.js'
import { listCloudtentaclesSources } from '../platforms/cloudtentacles/source-config-service.js'
import { resolveKuaishouFeifeiClaimUrl } from '../fulfillment/kuaishou-feifei/index.js'
import { createHttpError } from '../../utils/http.js'
@@ -83,7 +87,10 @@ export async function getAdminOrders(
}
}
export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<JsonRecord> {
export async function getAdminOrderDetail(
orderId: AdminEntityIdInput,
session: AdminViewerSessionInput | null = null,
): Promise<JsonRecord> {
const order = await getOrderById(Number(orderId))
if (!order) {
@@ -97,7 +104,9 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
listOrderItemsByOrderId(order.id),
listTasksByOrderId(order.id),
])
const kuaishouIndustryVouchers = await listKuaishouIndustryVouchersByOid(order.platform_order_id)
const itemSummary = summarizeOrderItems(items)
const viewerContext = createAdminViewerContext(session)
return {
order: {
@@ -138,6 +147,37 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
: JSON.parse(String(item.spec_json || '{}')),
})),
tasks: tasks.map((task) => mapAdminTaskSummary(task)),
kuaishouIndustryVouchers: kuaishouIndustryVouchers.map(mapAdminKuaishouIndustryVoucher),
operations: {
canResendKuaishouIndustryVoucherCode:
viewerContext.canManageTaskLifecycle && kuaishouIndustryVouchers.length > 0,
},
}
}
function mapAdminKuaishouIndustryVoucher(voucher: {
voucher_code?: unknown
oid?: unknown
unit_index?: unknown
status?: unknown
send_callback_status?: unknown
send_callback_attempt_count?: unknown
send_callback_last_error?: unknown
send_callback_sent_at?: unknown
consumed_at?: unknown
destroyed_at?: unknown
}) {
return {
oid: String(voucher.oid || '').trim(),
voucherCode: String(voucher.voucher_code || '').trim(),
unitIndex: Number(voucher.unit_index || 0) || 0,
status: String(voucher.status || '').trim(),
sendCallbackStatus: String(voucher.send_callback_status || '').trim(),
sendCallbackAttemptCount: Number(voucher.send_callback_attempt_count || 0) || 0,
sendCallbackLastError: String(voucher.send_callback_last_error || '').trim(),
sendCallbackSentAt: voucher.send_callback_sent_at || null,
consumedAt: voucher.consumed_at || null,
destroyedAt: voucher.destroyed_at || null,
}
}
@@ -180,10 +220,11 @@ export async function getAdminTaskDetail(
}
const primaryClaimTokenId = getTaskPrimaryClaimTokenId(task)
const [order, claimToken, taskEvents] = await Promise.all([
const [order, claimToken, taskEvents, taskKuaishouIndustryVouchers] = await Promise.all([
getOrderById(task.order_id),
primaryClaimTokenId ? getClaimTokenById(primaryClaimTokenId) : Promise.resolve(null),
listTaskEventsByTaskId(task.id),
listKuaishouIndustryVouchersByTaskId(task.id),
])
const orderItems = order ? await listOrderItemsByOrderId(order.id) : []
const orderItem = orderItems.find((item) => item.id === task.order_item_id) || null
@@ -200,6 +241,18 @@ export async function getAdminTaskDetail(
mapKuaishouCloudFulfillmentContext(taskContext.kuaishouCloudFulfillment, {
cloudSourceLabelMap,
}) || mapKuaishouCloudTaskStateProjection(task, { cloudSourceLabelMap })
const firstKuaishouIndustryVoucher = taskKuaishouIndustryVouchers[0] || null
const kuaishouIndustryVoucher =
firstKuaishouIndustryVoucher
? mapAdminKuaishouIndustryVoucher(firstKuaishouIndustryVoucher)
: mapKuaishouIndustryVoucherContext(taskContext.kuaishouIndustryVoucher)
const hasKuaishouIndustryVoucher = Boolean(
kuaishouIndustryVoucher && String(kuaishouIndustryVoucher.voucherCode || '').trim(),
)
const kuaishouIndustryVoucherStatus =
String(kuaishouIndustryVoucher?.status || '').trim().toUpperCase()
const kuaishouIndustryVoucherSendCallbackStatus =
String(kuaishouIndustryVoucher?.sendCallbackStatus || '').trim().toLowerCase()
return {
task: mapAdminTaskListItem(
@@ -250,6 +303,7 @@ export async function getAdminTaskDetail(
},
redeemResolution: mapRedeemResolutionContext(taskContext.redeemResolution),
kuaishouCloudFulfillment,
kuaishouIndustryVoucher,
manualDispatch: mapManualDispatchContext(taskContext.manualDispatch, viewerContext),
events: taskEvents.map(mapAdminTaskEvent),
operations: {
@@ -289,11 +343,38 @@ export async function getAdminTaskDetail(
viewerContext.canManageTaskLifecycle &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
canReturnKuaishouCloudFulfillmentStatus(task.task_status),
canResendKuaishouIndustryVoucherCode:
viewerContext.canManageTaskLifecycle && hasKuaishouIndustryVoucher,
canConsumeKuaishouIndustryVoucher:
viewerContext.canManageTaskLifecycle &&
hasKuaishouIndustryVoucher &&
kuaishouIndustryVoucherStatus !== 'CONSUMED' &&
kuaishouIndustryVoucherSendCallbackStatus === 'success',
canViewSensitiveTaskData: viewerContext.canViewSensitiveTaskData,
},
}
}
function mapKuaishouIndustryVoucherContext(value: unknown): JsonRecord | null {
if (!value || typeof value !== 'object' || Array.isArray(value)) {
return null
}
const record = value as JsonRecord
return {
oid: String(record.oid || '').trim(),
voucherCode: String(record.voucherCode || record.eticketId || '').trim(),
unitIndex: Number(record.unitIndex || 0) || 0,
status: String(record.status || '').trim(),
sendCallbackStatus: String(record.sendCallbackStatus || '').trim(),
sendCallbackLastError: String(record.sendCallbackLastError || '').trim(),
sendCallbackAttemptCount: Number(record.sendCallbackAttemptCount || 0) || 0,
sendCallbackSentAt: record.sendCallbackSentAt || null,
consumedAt: record.consumedAt || null,
destroyedAt: record.destroyedAt || null,
}
}
function buildCloudSourceLabelMap() {
const labelMap = new Map<string, string>()