拆分后台模拟工单服务
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||
import { createWorkOrder, createWorkOrderEvent } from '../../repositories/worker-platform/index.js'
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { randomId } from '../../utils/random.js'
|
||||
import { nowIso } from '../../utils/time.js'
|
||||
import {
|
||||
getKuaishouIndustrySourceConfig,
|
||||
listKuaishouIndustryShopConfigs,
|
||||
type KuaishouIndustryShopConfig,
|
||||
} from '../platforms/kuaishou-industry/source-config-service.js'
|
||||
import {
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
mapWorkOrderAdmin,
|
||||
normalizeAmountFen,
|
||||
normalizeInteger,
|
||||
normalizeRequirementFields,
|
||||
} from './mappers.js'
|
||||
import { ensureWorkerPlatformDefaults } from './worker-platform-defaults.js'
|
||||
import { normalizeWorkOrderTimeoutPolicy } from './work-order-timeout-policy.js'
|
||||
|
||||
export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
const defaults = await ensureWorkerPlatformDefaults()
|
||||
const now = nowIso()
|
||||
const input = resolveAdminMockWorkOrderInput(
|
||||
payload,
|
||||
listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig()),
|
||||
)
|
||||
const rewardAmount = input.rewardAmount
|
||||
const depositThresholdAmount = normalizeAmountFen(
|
||||
payload.depositThresholdAmount ?? payload.depositThresholdAmountYuan,
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
)
|
||||
const requiredDepositAmount =
|
||||
payload.requiredDepositAmount === undefined
|
||||
? rewardAmount > depositThresholdAmount
|
||||
? rewardAmount
|
||||
: 0
|
||||
: normalizeAmountFen(payload.requiredDepositAmount, 0)
|
||||
const paymentFen = input.paymentAmount
|
||||
const materialComplete = payload.materialComplete === true || payload.materialComplete === 'true'
|
||||
const fields = normalizeRequirementFields(payload.fields)
|
||||
const { platformOrderId, productName, shop } = input
|
||||
const material = {
|
||||
...(materialComplete
|
||||
? {
|
||||
collect: {
|
||||
complete: true,
|
||||
submittedAt: now,
|
||||
fields: fields.reduce<Record<string, string>>((result, field) => {
|
||||
result[field.key] = String(field.mockValue || `${field.label}测试值`)
|
||||
return result
|
||||
}, {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
source: {
|
||||
orderAmountFen: paymentFen,
|
||||
syncSource: 'mock',
|
||||
mock: true,
|
||||
provider: 'mock',
|
||||
platform: 'mock',
|
||||
sellerId: String(shop.sellerId || shop.shopId || '').trim(),
|
||||
shopId: String(shop.shopId || shop.sellerId || '').trim(),
|
||||
shopName: String(
|
||||
shop.customShopName || shop.shopName || shop.shopId || shop.sellerId || '',
|
||||
).trim(),
|
||||
},
|
||||
}
|
||||
const workOrder = await createWorkOrder({
|
||||
workOrderNo: randomId('WO'),
|
||||
platformOrderId,
|
||||
productName,
|
||||
categoryId: defaults.category?.id || null,
|
||||
status: materialComplete ? WORK_ORDER_STATUS.UNASSIGNED : WORK_ORDER_STATUS.PENDING_MATERIAL,
|
||||
rewardAmount,
|
||||
requiredDepositAmount,
|
||||
depositThresholdAmount,
|
||||
timeoutMinutes: Math.max(0, normalizeInteger(payload.timeoutMinutes, 0)),
|
||||
timeoutPolicy: normalizeWorkOrderTimeoutPolicy(payload.timeoutPolicy),
|
||||
materialJson: JSON.stringify(material),
|
||||
requirementJson: JSON.stringify({ fields }),
|
||||
now,
|
||||
})
|
||||
if (!workOrder) {
|
||||
throw createHttpError('接单工单创建失败', {
|
||||
statusCode: 500,
|
||||
errorCode: 'work_order_create_failed',
|
||||
})
|
||||
}
|
||||
await createWorkOrderEvent({
|
||||
workOrderId: workOrder.id,
|
||||
actorType: 'admin',
|
||||
actorId: 'dev_mock',
|
||||
eventType: 'mock_created',
|
||||
fromStatus: '',
|
||||
toStatus: workOrder.status,
|
||||
payloadJson: JSON.stringify({
|
||||
platformOrderId,
|
||||
productName,
|
||||
rewardAmount,
|
||||
sellerId: String(shop.sellerId || shop.shopId || '').trim(),
|
||||
}),
|
||||
now,
|
||||
})
|
||||
return { order: mapWorkOrderAdmin(workOrder) }
|
||||
}
|
||||
|
||||
/** 本地 Mock 与真实订单保持相同的关键字段约束,避免生成无法追溯的测试工单。 */
|
||||
export function resolveAdminMockWorkOrderInput(
|
||||
payload: JsonObject,
|
||||
shops: KuaishouIndustryShopConfig[],
|
||||
) {
|
||||
const platformOrderId = String(payload.platformOrderId || '').trim()
|
||||
if (!platformOrderId) {
|
||||
throw createHttpError('请填写订单号', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_no_required',
|
||||
})
|
||||
}
|
||||
|
||||
const productName = String(payload.productName || '').trim()
|
||||
if (!productName) {
|
||||
throw createHttpError('请填写商品名称', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_product_name_required',
|
||||
})
|
||||
}
|
||||
|
||||
const shopId = String(payload.sellerId || payload.shopId || '').trim()
|
||||
if (!shopId) {
|
||||
throw createHttpError('请选择店铺', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_shop_required',
|
||||
})
|
||||
}
|
||||
const shop =
|
||||
shops.find(
|
||||
(item) =>
|
||||
String(item.sellerId || item.shopId || '').trim() === shopId ||
|
||||
String(item.shopId || '').trim() === shopId,
|
||||
) || null
|
||||
if (!shop) {
|
||||
throw createHttpError('所选店铺不存在', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_shop_invalid',
|
||||
})
|
||||
}
|
||||
if (shop.enabled === false) {
|
||||
throw createHttpError('所选店铺已停用', {
|
||||
statusCode: 409,
|
||||
errorCode: 'mock_work_order_shop_disabled',
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
platformOrderId,
|
||||
productName,
|
||||
shop,
|
||||
rewardAmount: requireMockWorkOrderAmount(payload.rewardAmount, '接单金额', 'reward_amount'),
|
||||
paymentAmount: requireMockWorkOrderAmount(
|
||||
payload.paymentAmount,
|
||||
'用户付款金额',
|
||||
'payment_amount',
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
function requireMockWorkOrderAmount(value: unknown, label: string, field: string): number {
|
||||
if (value === undefined || value === null || String(value).trim() === '') {
|
||||
throw createHttpError(`请填写${label}`, {
|
||||
statusCode: 400,
|
||||
errorCode: `mock_work_order_${field}_required`,
|
||||
})
|
||||
}
|
||||
const amount = normalizeAmountFen(value, 0)
|
||||
if (amount <= 0) {
|
||||
throw createHttpError(`${label}必须大于 0`, {
|
||||
statusCode: 400,
|
||||
errorCode: `mock_work_order_${field}_invalid`,
|
||||
})
|
||||
}
|
||||
return amount
|
||||
}
|
||||
@@ -51,7 +51,6 @@ import {
|
||||
} from './publish-voucher-service.js'
|
||||
|
||||
import {
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
mapWorkOrderAdmin,
|
||||
mapWorkOrderShare,
|
||||
normalizeAmountFen,
|
||||
@@ -71,15 +70,9 @@ import {
|
||||
resolveWorkerPermissions,
|
||||
resolveWorkOrderOperationalStatus,
|
||||
} from './mappers.js'
|
||||
import { ensureWorkerPlatformDefaults } from './worker-platform-defaults.js'
|
||||
import { normalizeWorkOrderTimeoutPolicy } from './work-order-timeout-policy.js'
|
||||
import { getRequiredWorkOrder, getRequiredWorker } from './worker-session-context-service.js'
|
||||
import { resolveWorkOrderRealtimeWorkerIds } from './admin-work-order-realtime-service.js'
|
||||
import {
|
||||
getKuaishouIndustrySourceConfig,
|
||||
listKuaishouIndustryShopConfigs,
|
||||
type KuaishouIndustryShopConfig,
|
||||
} from '../platforms/kuaishou-industry/source-config-service.js'
|
||||
|
||||
export {
|
||||
listAdminWorkerUsers,
|
||||
@@ -292,169 +285,10 @@ export {
|
||||
submitAdminWorkOrderMaterial,
|
||||
} from './admin-work-order-material-service.js'
|
||||
|
||||
export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
const defaults = await ensureWorkerPlatformDefaults()
|
||||
const now = nowIso()
|
||||
const input = resolveAdminMockWorkOrderInput(
|
||||
payload,
|
||||
listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig()),
|
||||
)
|
||||
const rewardAmount = input.rewardAmount
|
||||
const depositThresholdAmount = normalizeAmountFen(
|
||||
payload.depositThresholdAmount ?? payload.depositThresholdAmountYuan,
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
)
|
||||
const requiredDepositAmount =
|
||||
payload.requiredDepositAmount === undefined
|
||||
? rewardAmount > depositThresholdAmount
|
||||
? rewardAmount
|
||||
: 0
|
||||
: normalizeAmountFen(payload.requiredDepositAmount, 0)
|
||||
const paymentFen = input.paymentAmount
|
||||
const materialComplete = payload.materialComplete === true || payload.materialComplete === 'true'
|
||||
const fields = normalizeRequirementFields(payload.fields)
|
||||
const { platformOrderId, productName, shop } = input
|
||||
const material = {
|
||||
...(materialComplete
|
||||
? {
|
||||
collect: {
|
||||
complete: true,
|
||||
submittedAt: now,
|
||||
fields: fields.reduce<Record<string, string>>((result, field) => {
|
||||
result[field.key] = String(field.mockValue || `${field.label}测试值`)
|
||||
return result
|
||||
}, {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
source: {
|
||||
orderAmountFen: paymentFen,
|
||||
syncSource: 'mock',
|
||||
mock: true,
|
||||
provider: 'mock',
|
||||
platform: 'mock',
|
||||
sellerId: String(shop.sellerId || shop.shopId || '').trim(),
|
||||
shopId: String(shop.shopId || shop.sellerId || '').trim(),
|
||||
shopName: String(
|
||||
shop.customShopName || shop.shopName || shop.shopId || shop.sellerId || '',
|
||||
).trim(),
|
||||
},
|
||||
}
|
||||
const workOrder = await createWorkOrder({
|
||||
workOrderNo: randomId('WO'),
|
||||
platformOrderId,
|
||||
productName,
|
||||
categoryId: defaults.category?.id || null,
|
||||
status: materialComplete ? WORK_ORDER_STATUS.UNASSIGNED : WORK_ORDER_STATUS.PENDING_MATERIAL,
|
||||
rewardAmount,
|
||||
requiredDepositAmount,
|
||||
depositThresholdAmount,
|
||||
timeoutMinutes: Math.max(0, normalizeInteger(payload.timeoutMinutes, 0)),
|
||||
timeoutPolicy: normalizeWorkOrderTimeoutPolicy(payload.timeoutPolicy),
|
||||
materialJson: JSON.stringify(material),
|
||||
requirementJson: JSON.stringify({ fields }),
|
||||
now,
|
||||
})
|
||||
if (!workOrder) {
|
||||
throw createHttpError('接单工单创建失败', {
|
||||
statusCode: 500,
|
||||
errorCode: 'work_order_create_failed',
|
||||
})
|
||||
}
|
||||
await createWorkOrderEvent({
|
||||
workOrderId: workOrder.id,
|
||||
actorType: 'admin',
|
||||
actorId: 'dev_mock',
|
||||
eventType: 'mock_created',
|
||||
fromStatus: '',
|
||||
toStatus: workOrder.status,
|
||||
payloadJson: JSON.stringify({
|
||||
platformOrderId,
|
||||
productName,
|
||||
rewardAmount,
|
||||
sellerId: String(shop.sellerId || shop.shopId || '').trim(),
|
||||
}),
|
||||
now,
|
||||
})
|
||||
return { order: mapWorkOrderAdmin(workOrder) }
|
||||
}
|
||||
|
||||
/** 本地 Mock 与真实订单保持相同的关键字段约束,避免生成无法追溯的测试工单。 */
|
||||
export function resolveAdminMockWorkOrderInput(
|
||||
payload: JsonObject,
|
||||
shops: KuaishouIndustryShopConfig[],
|
||||
) {
|
||||
const platformOrderId = String(payload.platformOrderId || '').trim()
|
||||
if (!platformOrderId) {
|
||||
throw createHttpError('请填写订单号', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_no_required',
|
||||
})
|
||||
}
|
||||
|
||||
const productName = String(payload.productName || '').trim()
|
||||
if (!productName) {
|
||||
throw createHttpError('请填写商品名称', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_product_name_required',
|
||||
})
|
||||
}
|
||||
|
||||
const shopId = String(payload.sellerId || payload.shopId || '').trim()
|
||||
if (!shopId) {
|
||||
throw createHttpError('请选择店铺', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_shop_required',
|
||||
})
|
||||
}
|
||||
const shop =
|
||||
shops.find(
|
||||
(item) =>
|
||||
String(item.sellerId || item.shopId || '').trim() === shopId ||
|
||||
String(item.shopId || '').trim() === shopId,
|
||||
) || null
|
||||
if (!shop) {
|
||||
throw createHttpError('所选店铺不存在', {
|
||||
statusCode: 400,
|
||||
errorCode: 'mock_work_order_shop_invalid',
|
||||
})
|
||||
}
|
||||
if (shop.enabled === false) {
|
||||
throw createHttpError('所选店铺已停用', {
|
||||
statusCode: 409,
|
||||
errorCode: 'mock_work_order_shop_disabled',
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
platformOrderId,
|
||||
productName,
|
||||
shop,
|
||||
rewardAmount: requireMockWorkOrderAmount(payload.rewardAmount, '接单金额', 'reward_amount'),
|
||||
paymentAmount: requireMockWorkOrderAmount(
|
||||
payload.paymentAmount,
|
||||
'用户付款金额',
|
||||
'payment_amount',
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
function requireMockWorkOrderAmount(value: unknown, label: string, field: string): number {
|
||||
if (value === undefined || value === null || String(value).trim() === '') {
|
||||
throw createHttpError(`请填写${label}`, {
|
||||
statusCode: 400,
|
||||
errorCode: `mock_work_order_${field}_required`,
|
||||
})
|
||||
}
|
||||
const amount = normalizeAmountFen(value, 0)
|
||||
if (amount <= 0) {
|
||||
throw createHttpError(`${label}必须大于 0`, {
|
||||
statusCode: 400,
|
||||
errorCode: `mock_work_order_${field}_invalid`,
|
||||
})
|
||||
}
|
||||
return amount
|
||||
}
|
||||
export {
|
||||
createAdminMockWorkOrder,
|
||||
resolveAdminMockWorkOrderInput,
|
||||
} from './admin-mock-work-order-service.js'
|
||||
|
||||
export async function updateAdminWorkOrder(
|
||||
workOrderId: number | string,
|
||||
|
||||
@@ -31,6 +31,7 @@ export * from './admin-worker-cancel-service.js'
|
||||
export * from './admin-work-order-sharing-service.js'
|
||||
export * from './admin-work-order-realtime-service.js'
|
||||
export * from './admin-work-order-material-service.js'
|
||||
export * from './admin-mock-work-order-service.js'
|
||||
export * from './worker-product-match-config-service.js'
|
||||
export * from './worker-announcement-config-service.js'
|
||||
export * from './worker-hall-config-service.js'
|
||||
|
||||
Reference in New Issue
Block a user