重构 lewan 履约:拆分发货模块并统一 registry 入口
将 task-finalization 拆为 dispatch/stock/return/redeem/confirm 等用例, claim 与 admin 经 executor registry 调用;admin 退号仅清理虚拟号不核销。
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { createTaskEvent } from '../../../repositories/task-event-repo.js'
|
||||
import { updateTask } from '../../../repositories/task-repo.js'
|
||||
import {
|
||||
TASK_STATUS,
|
||||
isKuaishouCloudRoleConfirmSettledStatus,
|
||||
} from '../../../domain/task-status.js'
|
||||
import { createHttpError } from '../../../utils/http.js'
|
||||
import { nowIso } from '../../../utils/time.js'
|
||||
import type { TaskRow } from '../../../types/repository/rows.js'
|
||||
import {
|
||||
assertBoundUidMatchesExpected,
|
||||
assertClaimExpectedUidReady,
|
||||
} from '../../claim/claim-identity.js'
|
||||
import { isKuaishouCloudTask, normalizeKuaishouCloudFlow, type JsonObject } from './domain.js'
|
||||
import { isKuaishouCloudMockContext, isKuaishouCloudMockTask } from './mock-helpers.js'
|
||||
import { refreshKuaishouCloudTaskRoleInfo } from './refresh-role-info.js'
|
||||
import { normalizeActor, parseTaskContext } from './task-context.js'
|
||||
|
||||
export type ConfirmKuaishouCloudRoleResult = {
|
||||
task: TaskRow
|
||||
alreadySettled: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* lewan 确认角色用例:刷新角色 → UID 闸门 → ROLE_CONFIRMED。
|
||||
* 一键兑换路径里 WAITING_BINDING 的自动晋升在 redeem 内完成,不必先调本函数。
|
||||
*/
|
||||
export async function confirmKuaishouCloudTaskRole(
|
||||
task: TaskRow,
|
||||
options: JsonObject = {},
|
||||
): Promise<ConfirmKuaishouCloudRoleResult> {
|
||||
if (!isKuaishouCloudTask(task)) {
|
||||
throw createHttpError('当前任务不是 kuaishou-lewan 履约任务', {
|
||||
statusCode: 409,
|
||||
errorCode: 'kuaishou_cloud_task_invalid',
|
||||
})
|
||||
}
|
||||
|
||||
const now = String(options.now || '').trim() || nowIso()
|
||||
const source = String(options.source || 'system_confirm_role').trim() || 'system_confirm_role'
|
||||
const actor = normalizeActor(options.actor)
|
||||
const errorCodePrefix =
|
||||
String(options.errorCodePrefix || 'kuaishou_cloud_confirm').trim() || 'kuaishou_cloud_confirm'
|
||||
|
||||
if (isKuaishouCloudRoleConfirmSettledStatus(task.task_status)) {
|
||||
return { task, alreadySettled: true }
|
||||
}
|
||||
|
||||
const expectedUid = assertClaimExpectedUidReady(task)
|
||||
const mockMode = isKuaishouCloudMockTask(task) || isKuaishouCloudMockContext(parseTaskContext(task))
|
||||
|
||||
const refreshed = mockMode
|
||||
? { task }
|
||||
: await refreshKuaishouCloudTaskRoleInfo(task, {
|
||||
source,
|
||||
actor,
|
||||
recordEvent: options.recordEvent === true,
|
||||
forceProbe: options.forceProbe !== false,
|
||||
})
|
||||
|
||||
const flow = normalizeKuaishouCloudFlow(
|
||||
parseTaskContext(refreshed.task).kuaishouCloudFulfillment,
|
||||
)
|
||||
|
||||
if (!flow.binding.vnPhone || !flow.binding.roleName || !flow.binding.roleId) {
|
||||
throw createHttpError('角色信息还未刷新到系统,请完成绑定后稍等片刻再试', {
|
||||
statusCode: 409,
|
||||
errorCode: `${errorCodePrefix}_role_not_ready`,
|
||||
})
|
||||
}
|
||||
|
||||
if (!mockMode) {
|
||||
assertBoundUidMatchesExpected(refreshed.task, flow, {
|
||||
errorCodePrefix,
|
||||
})
|
||||
}
|
||||
|
||||
const updatedTask =
|
||||
(await updateTask(task.id, {
|
||||
task_status: TASK_STATUS.ROLE_CONFIRMED,
|
||||
role_id: flow.binding.roleId,
|
||||
role_name: flow.binding.roleName,
|
||||
user_action_status: TASK_STATUS.ROLE_CONFIRMED,
|
||||
role_confirmed_at: now,
|
||||
last_error: '',
|
||||
updated_at: now,
|
||||
})) ||
|
||||
refreshed.task ||
|
||||
task
|
||||
|
||||
await createTaskEvent(
|
||||
task.id,
|
||||
'kuaishou_cloud_role_confirmed',
|
||||
{
|
||||
expectedUid,
|
||||
vnPhone: flow.binding.vnPhone,
|
||||
roleName: flow.binding.roleName,
|
||||
roleId: flow.binding.roleId,
|
||||
source,
|
||||
actor,
|
||||
},
|
||||
now,
|
||||
)
|
||||
|
||||
return { task: updatedTask, alreadySettled: false }
|
||||
}
|
||||
Reference in New Issue
Block a user