From 900c45c88f12e995b9b277a9c0c168b8593dc80a Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 21 Aug 2026 17:36:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E5=90=8E=E5=8F=B0=E6=92=A4?= =?UTF-8?q?=E5=8D=95=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin-work-order-cancellation-service.ts | 111 ++++++++++++++++++ .../src/services/worker-platform/index.ts | 4 + 2 files changed, 115 insertions(+) create mode 100644 apps/backend/src/services/worker-platform/admin-work-order-cancellation-service.ts diff --git a/apps/backend/src/services/worker-platform/admin-work-order-cancellation-service.ts b/apps/backend/src/services/worker-platform/admin-work-order-cancellation-service.ts new file mode 100644 index 00000000..0d9ac177 --- /dev/null +++ b/apps/backend/src/services/worker-platform/admin-work-order-cancellation-service.ts @@ -0,0 +1,111 @@ +import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js' +import { + cancelAssignedWorkOrder, + returnAssignedWorkOrderToHall, + unassignWorkOrder, +} from '../../repositories/worker-platform/index.js' +import type { JsonObject } from '../../types/json.js' +import { createHttpError } from '../../utils/http.js' +import { nowIso } from '../../utils/time.js' +import { + publishWorkerWalletRealtimeChange, + publishWorkOrderRealtimeChange, +} from '../realtime/realtime-event-service.js' +import { mapWorkOrderAdmin } from './mappers.js' +import { getRequiredWorkOrder } from './worker-session-context-service.js' + +export async function unassignAdminWorkOrder(workOrderId: number | string, actorName = '') { + const workOrder = await getRequiredWorkOrder(workOrderId) + if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) { + throw createHttpError('只有进行中且已指派打手的订单可以取消指派', { + statusCode: 409, + errorCode: 'work_order_unassign_status_invalid', + }) + } + const { order: updated, failureReason } = await unassignWorkOrder({ + workOrderId: workOrder.id, + now: nowIso(), + actorName, + }) + if (failureReason === 'work_order_not_in_progress') { + throw createHttpError('订单状态已变化,无法取消指派', { + statusCode: 409, + errorCode: 'work_order_unassign_status_invalid', + }) + } + if (failureReason === 'work_order_no_worker') { + throw createHttpError('该订单未指派打手', { + statusCode: 409, + errorCode: 'work_order_unassign_no_worker', + }) + } + if (!updated) { + throw createHttpError('取消指派失败,订单状态可能已变化', { + statusCode: 409, + errorCode: 'work_order_unassign_conflict', + }) + } + const workerId = Number(workOrder.assigned_worker_id) + publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), workerIds: [workerId] }) + publishWorkerWalletRealtimeChange(workerId) + return { order: mapWorkOrderAdmin(updated) } +} + +export async function cancelAdminWorkOrder( + workOrderId: number | string, + payload: JsonObject = {}, + actorName = '', +) { + const workOrder = await getRequiredWorkOrder(workOrderId) + if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) { + throw createHttpError('只有代练中且已接单的订单可以撤单', { + statusCode: 409, + errorCode: 'work_order_cancel_status_invalid', + }) + } + const action = String(payload.action || '').trim() + if (!['return_to_hall', 'cancel_order'].includes(action)) { + throw createHttpError('请选择撤单处理方式', { + statusCode: 400, + errorCode: 'work_order_cancel_action_required', + }) + } + const reason = String(payload.reason || '').trim() + if (action === 'cancel_order' && !reason) { + throw createHttpError('取消订单时请填写退款或撤单原因', { + statusCode: 400, + errorCode: 'work_order_cancel_reason_required', + }) + } + const input = { workOrderId: workOrder.id, now: nowIso(), reason, actorName } + const { order: updated, failureReason } = + action === 'return_to_hall' + ? await returnAssignedWorkOrderToHall(input) + : await cancelAssignedWorkOrder(input) + if (failureReason === 'work_order_not_in_progress') { + throw createHttpError('订单状态已变化,无法撤单', { + statusCode: 409, + errorCode: 'work_order_cancel_status_invalid', + }) + } + if (failureReason === 'work_order_no_worker') { + throw createHttpError('该订单尚未被打手接取', { + statusCode: 409, + errorCode: 'work_order_cancel_no_worker', + }) + } + if (!updated) { + throw createHttpError('撤单失败,订单状态可能已变化', { + statusCode: 409, + errorCode: 'work_order_cancel_conflict', + }) + } + const workerId = Number(workOrder.assigned_worker_id) + publishWorkOrderRealtimeChange({ + workOrderId: Number(workOrder.id), + workerIds: workerId ? [workerId] : [], + hallChanged: action === 'return_to_hall', + }) + if (workerId) publishWorkerWalletRealtimeChange(workerId) + return { order: mapWorkOrderAdmin(updated), action } +} diff --git a/apps/backend/src/services/worker-platform/index.ts b/apps/backend/src/services/worker-platform/index.ts index da095010..1aeb82ba 100644 --- a/apps/backend/src/services/worker-platform/index.ts +++ b/apps/backend/src/services/worker-platform/index.ts @@ -36,6 +36,10 @@ export * from './admin-work-order-management-service.js' export * from './admin-worker-platform-summary-service.js' export * from './admin-work-order-assignment-service.js' export * from './admin-work-order-deposit-service.js' +export { + cancelAdminWorkOrder, + unassignAdminWorkOrder, +} from './admin-work-order-cancellation-service.js' export { acceptAdminWorkOrder, acceptAdminWorkOrderShare,