优化快手 Cloud 主链路状态机

This commit is contained in:
yml
2026-05-28 10:03:23 +08:00
parent 0876e3ff5b
commit 9709643583
14 changed files with 513 additions and 122 deletions
@@ -8,6 +8,14 @@ import { listCloudtentaclesSources } from '../platforms/cloudtentacles/source-co
import { createHttpError } from '../../utils/http.js'
import { formatFenToAmount, normalizeFen } from '../../utils/money.js'
import { normalizeDateQuery, normalizePage, normalizePageSize, safeParseJson } from './admin-query-utils.js'
import {
canCompleteManualDispatchTaskStatus,
canDispatchKuaishouCloudFulfillmentStatus,
canMarkManualReviewTaskStatus,
canPrepareKuaishouCloudFulfillmentStatus,
canReturnKuaishouCloudFulfillmentStatus,
canRetryTaskStatus,
} from '../../domain/task-status.js'
import {
canViewerCloseTask,
canRegenerateClaimLinkForViewer,
@@ -228,25 +236,25 @@ export async function getAdminTaskDetail(
operations: {
canRetry: viewerContext.canManageTaskLifecycle
&& !isManualDispatchTask(task)
&& ['retry_pending', 'manual_review'].includes(task.task_status),
&& canRetryTaskStatus(task.task_status),
canRegenerateClaimLink: canRegenerateClaimLinkForViewer(task, viewerContext),
canClose: canViewerCloseTask(task, viewerContext),
canMarkManualReview: viewerContext.canManageTaskLifecycle && !['redeemed', 'closed', 'manual_review'].includes(task.task_status),
canCompleteManualDispatch: viewerContext.canManageTaskLifecycle && isManualDispatchTask(task) && !['redeemed', 'closed'].includes(task.task_status),
canMarkManualReview: viewerContext.canManageTaskLifecycle && canMarkManualReviewTaskStatus(task.task_status),
canCompleteManualDispatch: viewerContext.canManageTaskLifecycle && isManualDispatchTask(task) && canCompleteManualDispatchTaskStatus(task.task_status),
canPrepareKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& String(kuaishouCloudFulfillment?.dispatch.status || 'pending').trim() === 'pending'
&& String(kuaishouCloudFulfillment?.returnNumber.status || 'pending').trim() === 'pending'
&& ['pending_binding_prepare', 'manual_review', 'failed'].includes(String(task.task_status || '').trim()),
&& canPrepareKuaishouCloudFulfillmentStatus(task.task_status),
canRefreshKuaishouCloudRoleInfo: viewerContext.canOperateAssistedTask
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& Number(kuaishouCloudFulfillment?.binding.vnId || 0) > 0,
canDispatchKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& ['waiting_binding'].includes(String(task.task_status || '').trim()),
&& canDispatchKuaishouCloudFulfillmentStatus(task.task_status),
canReturnKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& ['dispatched_pending_return'].includes(String(task.task_status || '').trim()),
&& canReturnKuaishouCloudFulfillmentStatus(task.task_status),
canViewSensitiveTaskData: viewerContext.canViewSensitiveTaskData,
},
}
@@ -4,6 +4,10 @@ import {
parseTaskContext as parseTaskContextValue,
parseTaskState as parseTaskStateValue,
} from '../../utils/task-json.js'
import {
canRegenerateClaimLinkStatus,
isTaskFinalStatus,
} from '../../domain/task-status.js'
import type { AdminViewerSessionInput } from '../../types/admin/read-inputs.js'
import type { OrderItemRow, TaskRow } from '../../types/repository/rows.js'
@@ -220,7 +224,7 @@ export function canViewerCloseTask(task: TaskLike, viewerContext: AdminViewerCon
return false
}
return !['redeemed', 'completed', 'closed'].includes(String(task?.task_status || '').trim())
return !isTaskFinalStatus(task?.task_status)
}
export function resolveDisplayShopName(provider: unknown, shopId: unknown, shopName: unknown): string {
@@ -295,7 +299,7 @@ export function canRegenerateClaimLinkForViewer(task: TaskLike, viewerContext: A
return false
}
const baseAllowed = ['link_generated', 'claimed', 'role_confirmed', 'retry_pending', 'manual_review'].includes(String(task.task_status || '').trim())
const baseAllowed = canRegenerateClaimLinkStatus(task.task_status)
if (!baseAllowed) {
return false
@@ -1,6 +1,11 @@
import { getTaskById } from '../../repositories/task-repo.js'
import { createHttpError } from '../../utils/http.js'
import { safeParseJson } from './admin-query-utils.js'
import {
TASK_STATUS,
isTaskFulfillmentCompletedStatus,
normalizeTaskStatus,
} from '../../domain/task-status.js'
import {
createAdminViewerContext,
getTaskPrimaryClaimTokenId,
@@ -173,7 +178,7 @@ export function buildOrderFulfillmentProgress(
}
function buildTaskFulfillmentState(task: TaskRow | null | undefined): TaskFulfillmentState {
const normalizedStatus = String(task?.task_status || '').trim()
const normalizedStatus = normalizeTaskStatus(task?.task_status)
if (!normalizedStatus) {
return {
@@ -182,63 +187,63 @@ function buildTaskFulfillmentState(task: TaskRow | null | undefined): TaskFulfil
}
}
if (normalizedStatus === 'pending_payment') {
if (normalizedStatus === TASK_STATUS.PENDING_PAYMENT) {
return { resourceStatus: 'pending_payment', customerStatus: 'not_started' }
}
if (normalizedStatus === 'paid') {
if (normalizedStatus === TASK_STATUS.PAID) {
return { resourceStatus: 'pending_prepare', customerStatus: 'not_started' }
}
if (normalizedStatus === 'pending_binding_prepare') {
if (normalizedStatus === TASK_STATUS.PENDING_BINDING_PREPARE) {
return { resourceStatus: 'pending_prepare', customerStatus: 'not_started' }
}
if (normalizedStatus === 'waiting_binding') {
if (normalizedStatus === TASK_STATUS.WAITING_BINDING) {
return { resourceStatus: 'resource_ready', customerStatus: 'waiting_customer' }
}
if (normalizedStatus === 'dispatched_pending_return') {
if (normalizedStatus === TASK_STATUS.DISPATCHED_PENDING_RETURN) {
return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
}
if (normalizedStatus === 'completed') {
if (normalizedStatus === TASK_STATUS.COMPLETED) {
return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
}
if (normalizedStatus === 'manual_review') {
if (normalizedStatus === TASK_STATUS.MANUAL_REVIEW) {
return { resourceStatus: 'manual_review', customerStatus: 'customer_exception' }
}
if (normalizedStatus === 'retry_pending') {
if (normalizedStatus === TASK_STATUS.RETRY_PENDING) {
return { resourceStatus: 'retry_pending', customerStatus: 'customer_exception' }
}
if (normalizedStatus === 'closed') {
if (normalizedStatus === TASK_STATUS.CLOSED) {
return { resourceStatus: 'closed', customerStatus: 'closed' }
}
if (normalizedStatus === 'expired') {
if (normalizedStatus === TASK_STATUS.EXPIRED) {
return { resourceStatus: 'expired', customerStatus: 'expired' }
}
if (normalizedStatus === 'link_generated') {
if (normalizedStatus === TASK_STATUS.LINK_GENERATED) {
return { resourceStatus: 'resource_ready', customerStatus: 'waiting_customer' }
}
if (normalizedStatus === 'claimed') {
if (normalizedStatus === TASK_STATUS.CLAIMED) {
return { resourceStatus: 'resource_ready', customerStatus: 'link_opened' }
}
if (normalizedStatus === 'role_confirmed') {
if (normalizedStatus === TASK_STATUS.ROLE_CONFIRMED) {
return { resourceStatus: 'resource_ready', customerStatus: 'customer_confirmed' }
}
if (normalizedStatus === 'redeeming') {
if (normalizedStatus === TASK_STATUS.REDEEMING) {
return { resourceStatus: 'resource_ready', customerStatus: 'customer_processing' }
}
if (normalizedStatus === 'redeemed') {
if (normalizedStatus === TASK_STATUS.REDEEMED) {
return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
}
@@ -254,7 +259,7 @@ function isTaskResourcePrepared(task: TaskRow | null | undefined): boolean {
}
function isTaskFulfillmentCompleted(task: TaskRow | null | undefined): boolean {
return ['redeemed', 'completed', 'dispatched_pending_return'].includes(String(task?.task_status || '').trim())
return isTaskFulfillmentCompletedStatus(task?.task_status)
}
function normalizeRecord(value: unknown): JsonRecord {