拆分打手大厅操作服务
This commit is contained in:
@@ -15,6 +15,7 @@ export * from './worker-order-realtime-service.js'
|
|||||||
export * from './worker-collect-service.js'
|
export * from './worker-collect-service.js'
|
||||||
export * from './worker-acceptance-service.js'
|
export * from './worker-acceptance-service.js'
|
||||||
export * from './worker-my-order-service.js'
|
export * from './worker-my-order-service.js'
|
||||||
|
export * from './worker-hall-action-service.js'
|
||||||
export * from './worker-platform-defaults.js'
|
export * from './worker-platform-defaults.js'
|
||||||
export * from './work-order-timeout-policy.js'
|
export * from './work-order-timeout-policy.js'
|
||||||
export * from './after-sales-service.js'
|
export * from './after-sales-service.js'
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||||
|
import {
|
||||||
|
countWorkerActiveOrders,
|
||||||
|
createWorkOrderEvent,
|
||||||
|
grabWorkOrder,
|
||||||
|
joinWorkOrderShare,
|
||||||
|
type WorkOrderRow,
|
||||||
|
} 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 {
|
||||||
|
mapWorkOrderForWorker,
|
||||||
|
mapWorkOrderShare,
|
||||||
|
normalizePositiveInteger,
|
||||||
|
resolveFreezeDepositAmount,
|
||||||
|
resolveWorkerPermissions,
|
||||||
|
throwGrabWorkOrderFailure,
|
||||||
|
} from './mappers.js'
|
||||||
|
import { getWorkerHallConfig } from './worker-hall-config-service.js'
|
||||||
|
import { publishWorkOrderParticipantChange } from './worker-order-realtime-service.js'
|
||||||
|
import {
|
||||||
|
getRequiredWorkOrder,
|
||||||
|
getRequiredWorker,
|
||||||
|
requireActiveWorkerSession,
|
||||||
|
type WorkerSession,
|
||||||
|
} from './worker-session-context-service.js'
|
||||||
|
import {
|
||||||
|
publishWorkerWalletRealtimeChange,
|
||||||
|
publishWorkOrderRealtimeChange,
|
||||||
|
} from '../realtime/realtime-event-service.js'
|
||||||
|
|
||||||
|
export async function grabWorkerHallOrder(workOrderId: number | string, session: WorkerSession) {
|
||||||
|
requireActiveWorkerSession(session)
|
||||||
|
const worker = await getRequiredWorker(session.workerId)
|
||||||
|
const permissions = resolveWorkerPermissions(worker)
|
||||||
|
const hallConfig = getWorkerHallConfig()
|
||||||
|
const now = nowIso()
|
||||||
|
const visibleDelaySeconds = Number(permissions.visibleDelaySeconds || 0)
|
||||||
|
const visibleAfterIso =
|
||||||
|
visibleDelaySeconds > 0 ? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString() : ''
|
||||||
|
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||||
|
if (workOrder.status !== WORK_ORDER_STATUS.OPEN || workOrder.assigned_worker_id) {
|
||||||
|
throw createHttpError('该订单已不可抢', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'work_order_not_open',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workOrder.sharing_enabled) {
|
||||||
|
const result = await joinWorkOrderShare({
|
||||||
|
workOrderId: Number(workOrder.id),
|
||||||
|
workerId: Number(worker.id),
|
||||||
|
quantity: 0,
|
||||||
|
takeRemaining: true,
|
||||||
|
maxActiveOrders: permissions.maxActiveOrders,
|
||||||
|
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
||||||
|
visibleAfterIso,
|
||||||
|
now,
|
||||||
|
})
|
||||||
|
if (!result.share) {
|
||||||
|
throw resolveWorkOrderShareJoinError(result.failureReason)
|
||||||
|
}
|
||||||
|
await publishWorkOrderParticipantChange(Number(workOrder.id), {
|
||||||
|
workerIds: [Number(worker.id)],
|
||||||
|
hallChanged: true,
|
||||||
|
walletChangedWorkerIds: [Number(worker.id)],
|
||||||
|
})
|
||||||
|
return { order: mapWorkOrderForWorker(workOrder, permissions, result.share) }
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeCount = await countWorkerActiveOrders(worker.id)
|
||||||
|
if (activeCount >= permissions.maxActiveOrders) {
|
||||||
|
throw createHttpError('已达到当前等级最大同时接单量', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'worker_active_order_limit',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const freezeAmount = resolveFreezeDepositAmount(workOrder, permissions)
|
||||||
|
if (Number(worker.available_amount || 0) < freezeAmount) {
|
||||||
|
throw createHttpError('余额不足,无法冻结所需押金', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: 'worker_deposit_insufficient',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const grabbed = await grabWorkOrder({
|
||||||
|
workOrderId: Number(workOrder.id),
|
||||||
|
workerId: Number(worker.id),
|
||||||
|
depositAmount: freezeAmount,
|
||||||
|
maxActiveOrders: permissions.maxActiveOrders,
|
||||||
|
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
||||||
|
visibleAfterIso,
|
||||||
|
deadlineAt: resolveWorkOrderDeadlineAt(workOrder, now),
|
||||||
|
now,
|
||||||
|
})
|
||||||
|
if (!grabbed.order) {
|
||||||
|
throwGrabWorkOrderFailure(grabbed.failureReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
await createWorkOrderEvent({
|
||||||
|
workOrderId: workOrder.id,
|
||||||
|
actorType: 'worker',
|
||||||
|
actorId: String(worker.id),
|
||||||
|
eventType: 'grabbed',
|
||||||
|
fromStatus: workOrder.status,
|
||||||
|
toStatus: grabbed.order.status,
|
||||||
|
payloadJson: JSON.stringify({
|
||||||
|
workerId: worker.id,
|
||||||
|
workerName: worker.display_name || worker.username,
|
||||||
|
internal: worker.worker_type === 'internal',
|
||||||
|
}),
|
||||||
|
now: nowIso(),
|
||||||
|
})
|
||||||
|
publishWorkOrderRealtimeChange({
|
||||||
|
workOrderId: Number(workOrder.id),
|
||||||
|
workerIds: [Number(worker.id)],
|
||||||
|
hallChanged: true,
|
||||||
|
})
|
||||||
|
publishWorkerWalletRealtimeChange(Number(worker.id))
|
||||||
|
|
||||||
|
return { order: mapWorkOrderForWorker(grabbed.order, permissions) }
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function joinWorkerSharingOrder(
|
||||||
|
workOrderId: number | string,
|
||||||
|
payload: JsonObject = {},
|
||||||
|
session: WorkerSession,
|
||||||
|
) {
|
||||||
|
requireActiveWorkerSession(session)
|
||||||
|
const worker = await getRequiredWorker(session.workerId)
|
||||||
|
const permissions = resolveWorkerPermissions(worker)
|
||||||
|
const hallConfig = getWorkerHallConfig()
|
||||||
|
const visibleDelaySeconds = Number(permissions.visibleDelaySeconds || 0)
|
||||||
|
const visibleAfterIso =
|
||||||
|
visibleDelaySeconds > 0 ? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString() : ''
|
||||||
|
const quantity = normalizePositiveInteger(payload.quantity, 1)
|
||||||
|
const now = nowIso()
|
||||||
|
const result = await joinWorkOrderShare({
|
||||||
|
workOrderId: Number(workOrderId),
|
||||||
|
workerId: Number(worker.id),
|
||||||
|
quantity,
|
||||||
|
maxActiveOrders: permissions.maxActiveOrders,
|
||||||
|
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
||||||
|
visibleAfterIso,
|
||||||
|
now,
|
||||||
|
})
|
||||||
|
if (!result.share) {
|
||||||
|
throw resolveWorkOrderShareJoinError(result.failureReason)
|
||||||
|
}
|
||||||
|
await publishWorkOrderParticipantChange(Number(workOrderId), {
|
||||||
|
workerIds: [Number(worker.id)],
|
||||||
|
hallChanged: true,
|
||||||
|
walletChangedWorkerIds: [Number(worker.id)],
|
||||||
|
})
|
||||||
|
return { share: mapWorkOrderShare(result.share) }
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveWorkOrderDeadlineAt(workOrder: WorkOrderRow, now: string): string | null {
|
||||||
|
const timeoutMinutes = Number(workOrder.timeout_minutes || 0)
|
||||||
|
if (timeoutMinutes <= 0) return null
|
||||||
|
return new Date(new Date(now).getTime() + timeoutMinutes * 60 * 1000).toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveWorkOrderShareJoinError(
|
||||||
|
failureReason:
|
||||||
|
| 'work_order_not_open'
|
||||||
|
| 'sharing_disabled'
|
||||||
|
| 'work_order_owner_conflict'
|
||||||
|
| 'sharing_quantity_full'
|
||||||
|
| 'worker_active_order_limit'
|
||||||
|
| 'worker_deposit_insufficient'
|
||||||
|
| null,
|
||||||
|
): Error {
|
||||||
|
const messages: Record<string, string> = {
|
||||||
|
work_order_not_open: '该订单当前不可拼单',
|
||||||
|
sharing_disabled: '该订单未启用拼单',
|
||||||
|
work_order_owner_conflict: '你已整单接取该订单,无需拼单',
|
||||||
|
sharing_quantity_full: '拼单数量已满或超出剩余数量',
|
||||||
|
worker_active_order_limit: '已达到当前等级最大同时接单量',
|
||||||
|
worker_deposit_insufficient: '余额不足,无法冻结所需押金',
|
||||||
|
}
|
||||||
|
return createHttpError(messages[failureReason || ''] || '拼单失败', {
|
||||||
|
statusCode: 409,
|
||||||
|
errorCode: `work_order_sharing_${failureReason || 'failed'}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,78 +1,3 @@
|
|||||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
|
||||||
import {
|
|
||||||
countWorkerActiveOrders,
|
|
||||||
consumeWorkerSmsCode,
|
|
||||||
createWorkOrderEvent,
|
|
||||||
getLatestWorkerSmsCode,
|
|
||||||
recordWorkerSmsCodeFailure,
|
|
||||||
getWorkerUserById,
|
|
||||||
getWorkerUserByPhone,
|
|
||||||
getWorkerUserByUsername,
|
|
||||||
getWorkerUserByDisplayName,
|
|
||||||
getWorkOrderById,
|
|
||||||
grabWorkOrder,
|
|
||||||
createWorkerSessionRecord,
|
|
||||||
getWorkerSessionBySessionId,
|
|
||||||
listWorkerSessions,
|
|
||||||
revokeWorkerSession,
|
|
||||||
touchWorkerSession,
|
|
||||||
joinWorkOrderShare,
|
|
||||||
type WorkOrderRow,
|
|
||||||
type WorkerSessionRow,
|
|
||||||
} 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 { getWorkerHallConfig } from './worker-hall-config-service.js'
|
|
||||||
import {
|
|
||||||
getRequiredWorkOrder,
|
|
||||||
getRequiredWorker,
|
|
||||||
requireActiveWorkerSession,
|
|
||||||
type WorkerSession,
|
|
||||||
} from './worker-session-context-service.js'
|
|
||||||
import {
|
|
||||||
publishWorkerWalletRealtimeChange,
|
|
||||||
publishWorkOrderRealtimeChange,
|
|
||||||
} from '../realtime/realtime-event-service.js'
|
|
||||||
|
|
||||||
import {
|
|
||||||
mapWorkOrderForWorker,
|
|
||||||
mapWorkOrderShare,
|
|
||||||
normalizePositiveInteger,
|
|
||||||
resolveFreezeDepositAmount,
|
|
||||||
resolveWorkerPermissions,
|
|
||||||
throwGrabWorkOrderFailure,
|
|
||||||
} from './mappers.js'
|
|
||||||
import {
|
|
||||||
assertWorkerLoginAllowed,
|
|
||||||
normalizeWorkerDeviceId,
|
|
||||||
normalizeWorkerDeviceName,
|
|
||||||
normalizeWorkerDeviceType,
|
|
||||||
} from './worker-auth-policy.js'
|
|
||||||
import { ensureWorkerPlatformDefaults } from './worker-platform-defaults.js'
|
|
||||||
import {
|
|
||||||
deleteWorkerSessionWithCredentials,
|
|
||||||
loginWorker,
|
|
||||||
loginWorkerBySmsCode,
|
|
||||||
manageWorkerSessions,
|
|
||||||
} from './worker-login-service.js'
|
|
||||||
import { registerWorker, resetWorkerPassword } from './worker-registration-service.js'
|
|
||||||
import {
|
|
||||||
sendWorkerLoginSmsCode,
|
|
||||||
sendWorkerPasswordResetSmsCode,
|
|
||||||
sendWorkerSmsCode,
|
|
||||||
} from './worker-sms-service.js'
|
|
||||||
import { changeWorkerPassword } from './worker-credentials-service.js'
|
|
||||||
import {
|
|
||||||
deleteWorkerSession,
|
|
||||||
getWorkerSessionSummary,
|
|
||||||
getWorkerSessions,
|
|
||||||
logoutWorkerSession,
|
|
||||||
verifyWorkerSessionToken,
|
|
||||||
} from './worker-session-auth-service.js'
|
|
||||||
import { normalizeWorkOrderTimeoutPolicy } from './work-order-timeout-policy.js'
|
|
||||||
import { publishWorkOrderParticipantChange } from './worker-order-realtime-service.js'
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getRequiredWorkOrder,
|
getRequiredWorkOrder,
|
||||||
getRequiredWorker,
|
getRequiredWorker,
|
||||||
@@ -124,104 +49,7 @@ export {
|
|||||||
maskWorkerLeaderboardDisplayName,
|
maskWorkerLeaderboardDisplayName,
|
||||||
} from './worker-hall-service.js'
|
} from './worker-hall-service.js'
|
||||||
|
|
||||||
export async function grabWorkerHallOrder(workOrderId: number | string, session: WorkerSession) {
|
export { grabWorkerHallOrder } from './worker-hall-action-service.js'
|
||||||
requireActiveWorkerSession(session)
|
|
||||||
const worker = await getRequiredWorker(session.workerId)
|
|
||||||
const permissions = resolveWorkerPermissions(worker)
|
|
||||||
const hallConfig = getWorkerHallConfig()
|
|
||||||
const now = nowIso()
|
|
||||||
const visibleDelaySeconds = Number(permissions.visibleDelaySeconds || 0)
|
|
||||||
const visibleAfterIso =
|
|
||||||
visibleDelaySeconds > 0 ? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString() : ''
|
|
||||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
|
||||||
if (workOrder.status !== WORK_ORDER_STATUS.OPEN || workOrder.assigned_worker_id) {
|
|
||||||
throw createHttpError('该订单已不可抢', {
|
|
||||||
statusCode: 409,
|
|
||||||
errorCode: 'work_order_not_open',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workOrder.sharing_enabled) {
|
|
||||||
const result = await joinWorkOrderShare({
|
|
||||||
workOrderId: Number(workOrder.id),
|
|
||||||
workerId: Number(worker.id),
|
|
||||||
quantity: 0,
|
|
||||||
takeRemaining: true,
|
|
||||||
maxActiveOrders: permissions.maxActiveOrders,
|
|
||||||
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
|
||||||
visibleAfterIso,
|
|
||||||
now,
|
|
||||||
})
|
|
||||||
if (!result.share) {
|
|
||||||
throw resolveWorkOrderShareJoinError(result.failureReason)
|
|
||||||
}
|
|
||||||
await publishWorkOrderParticipantChange(Number(workOrder.id), {
|
|
||||||
workerIds: [Number(worker.id)],
|
|
||||||
hallChanged: true,
|
|
||||||
walletChangedWorkerIds: [Number(worker.id)],
|
|
||||||
})
|
|
||||||
return { order: mapWorkOrderForWorker(workOrder, permissions, result.share) }
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeCount = await countWorkerActiveOrders(worker.id)
|
|
||||||
if (activeCount >= permissions.maxActiveOrders) {
|
|
||||||
throw createHttpError('已达到当前等级最大同时接单量', {
|
|
||||||
statusCode: 409,
|
|
||||||
errorCode: 'worker_active_order_limit',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const freezeAmount = resolveFreezeDepositAmount(workOrder, permissions)
|
|
||||||
if (Number(worker.available_amount || 0) < freezeAmount) {
|
|
||||||
throw createHttpError('余额不足,无法冻结所需押金', {
|
|
||||||
statusCode: 409,
|
|
||||||
errorCode: 'worker_deposit_insufficient',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const grabbed = await grabWorkOrder({
|
|
||||||
workOrderId: Number(workOrder.id),
|
|
||||||
workerId: Number(worker.id),
|
|
||||||
depositAmount: freezeAmount,
|
|
||||||
maxActiveOrders: permissions.maxActiveOrders,
|
|
||||||
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
|
||||||
visibleAfterIso,
|
|
||||||
deadlineAt: resolveWorkOrderDeadlineAt(workOrder, now),
|
|
||||||
now,
|
|
||||||
})
|
|
||||||
if (!grabbed.order) {
|
|
||||||
throwGrabWorkOrderFailure(grabbed.failureReason)
|
|
||||||
}
|
|
||||||
|
|
||||||
await createWorkOrderEvent({
|
|
||||||
workOrderId: workOrder.id,
|
|
||||||
actorType: 'worker',
|
|
||||||
actorId: String(worker.id),
|
|
||||||
eventType: 'grabbed',
|
|
||||||
fromStatus: workOrder.status,
|
|
||||||
toStatus: grabbed.order.status,
|
|
||||||
payloadJson: JSON.stringify({
|
|
||||||
workerId: worker.id,
|
|
||||||
workerName: worker.display_name || worker.username,
|
|
||||||
internal: worker.worker_type === 'internal',
|
|
||||||
}),
|
|
||||||
now: nowIso(),
|
|
||||||
})
|
|
||||||
publishWorkOrderRealtimeChange({
|
|
||||||
workOrderId: Number(workOrder.id),
|
|
||||||
workerIds: [Number(worker.id)],
|
|
||||||
hallChanged: true,
|
|
||||||
})
|
|
||||||
publishWorkerWalletRealtimeChange(Number(worker.id))
|
|
||||||
|
|
||||||
return { order: mapWorkOrderForWorker(grabbed.order, permissions) }
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveWorkOrderDeadlineAt(workOrder: WorkOrderRow, now: string): string | null {
|
|
||||||
const timeoutMinutes = Number(workOrder.timeout_minutes || 0)
|
|
||||||
if (timeoutMinutes <= 0) return null
|
|
||||||
return new Date(new Date(now).getTime() + timeoutMinutes * 60 * 1000).toISOString()
|
|
||||||
}
|
|
||||||
|
|
||||||
export { settleDueDepositUnfreezes } from './worker-profile-service.js'
|
export { settleDueDepositUnfreezes } from './worker-profile-service.js'
|
||||||
|
|
||||||
@@ -240,63 +68,7 @@ export {
|
|||||||
submitWorkerOrderFeedback,
|
submitWorkerOrderFeedback,
|
||||||
} from './worker-my-order-service.js'
|
} from './worker-my-order-service.js'
|
||||||
|
|
||||||
export async function joinWorkerSharingOrder(
|
export { joinWorkerSharingOrder } from './worker-hall-action-service.js'
|
||||||
workOrderId: number | string,
|
|
||||||
payload: JsonObject = {},
|
|
||||||
session: WorkerSession,
|
|
||||||
) {
|
|
||||||
requireActiveWorkerSession(session)
|
|
||||||
const worker = await getRequiredWorker(session.workerId)
|
|
||||||
const permissions = resolveWorkerPermissions(worker)
|
|
||||||
const hallConfig = getWorkerHallConfig()
|
|
||||||
const visibleDelaySeconds = Number(permissions.visibleDelaySeconds || 0)
|
|
||||||
const visibleAfterIso =
|
|
||||||
visibleDelaySeconds > 0 ? new Date(Date.now() - visibleDelaySeconds * 1000).toISOString() : ''
|
|
||||||
const quantity = normalizePositiveInteger(payload.quantity, 1)
|
|
||||||
const now = nowIso()
|
|
||||||
const result = await joinWorkOrderShare({
|
|
||||||
workOrderId: Number(workOrderId),
|
|
||||||
workerId: Number(worker.id),
|
|
||||||
quantity,
|
|
||||||
maxActiveOrders: permissions.maxActiveOrders,
|
|
||||||
hallCandidateLimit: hallConfig.maxVisibleOrders,
|
|
||||||
visibleAfterIso,
|
|
||||||
now,
|
|
||||||
})
|
|
||||||
if (!result.share) {
|
|
||||||
throw resolveWorkOrderShareJoinError(result.failureReason)
|
|
||||||
}
|
|
||||||
await publishWorkOrderParticipantChange(Number(workOrderId), {
|
|
||||||
workerIds: [Number(worker.id)],
|
|
||||||
hallChanged: true,
|
|
||||||
walletChangedWorkerIds: [Number(worker.id)],
|
|
||||||
})
|
|
||||||
return { share: mapWorkOrderShare(result.share) }
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveWorkOrderShareJoinError(
|
|
||||||
failureReason:
|
|
||||||
| 'work_order_not_open'
|
|
||||||
| 'sharing_disabled'
|
|
||||||
| 'work_order_owner_conflict'
|
|
||||||
| 'sharing_quantity_full'
|
|
||||||
| 'worker_active_order_limit'
|
|
||||||
| 'worker_deposit_insufficient'
|
|
||||||
| null,
|
|
||||||
): Error {
|
|
||||||
const messages: Record<string, string> = {
|
|
||||||
work_order_not_open: '该订单当前不可拼单',
|
|
||||||
sharing_disabled: '该订单未启用拼单',
|
|
||||||
work_order_owner_conflict: '你已整单接取该订单,无需拼单',
|
|
||||||
sharing_quantity_full: '拼单数量已满或超出剩余数量',
|
|
||||||
worker_active_order_limit: '已达到当前等级最大同时接单量',
|
|
||||||
worker_deposit_insufficient: '余额不足,无法冻结所需押金',
|
|
||||||
}
|
|
||||||
return createHttpError(messages[failureReason || ''] || '拼单失败', {
|
|
||||||
statusCode: 409,
|
|
||||||
errorCode: `work_order_sharing_${failureReason || 'failed'}`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
remindWorkerOrderAcceptance,
|
remindWorkerOrderAcceptance,
|
||||||
|
|||||||
Reference in New Issue
Block a user