优化本地Mock接单
This commit is contained in:
@@ -165,6 +165,11 @@ import {
|
||||
normalizeWorkOrderTimeoutPolicy,
|
||||
} from './worker-service.js'
|
||||
import { reprocessKuaishouSendCodeWorkOrders } from './sync-work-orders-from-send-code.js'
|
||||
import {
|
||||
getKuaishouIndustrySourceConfig,
|
||||
listKuaishouIndustryShopConfigs,
|
||||
type KuaishouIndustryShopConfig,
|
||||
} from '../platforms/kuaishou-industry/source-config-service.js'
|
||||
|
||||
export async function listAdminWorkerLevels() {
|
||||
await ensureWorkerPlatformDefaults()
|
||||
@@ -1881,7 +1886,11 @@ export function resolveAdminMaterialRewardAmount(input: {
|
||||
export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
const defaults = await ensureWorkerPlatformDefaults()
|
||||
const now = nowIso()
|
||||
const rewardAmount = normalizeAmountFen(payload.rewardAmount ?? payload.rewardAmountYuan, 2500)
|
||||
const input = resolveAdminMockWorkOrderInput(
|
||||
payload,
|
||||
listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig()),
|
||||
)
|
||||
const rewardAmount = input.rewardAmount
|
||||
const depositThresholdAmount = normalizeAmountFen(
|
||||
payload.depositThresholdAmount ?? payload.depositThresholdAmountYuan,
|
||||
DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
|
||||
@@ -1892,21 +1901,10 @@ export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
? rewardAmount
|
||||
: 0
|
||||
: normalizeAmountFen(payload.requiredDepositAmount, 0)
|
||||
const paymentFen =
|
||||
payload.paymentAmount === undefined &&
|
||||
payload.paymentAmountYuan === undefined &&
|
||||
payload.userPaymentAmount === undefined
|
||||
? rewardAmount
|
||||
: normalizeAmountFen(
|
||||
payload.paymentAmount ?? payload.paymentAmountYuan ?? payload.userPaymentAmount,
|
||||
rewardAmount,
|
||||
)
|
||||
const paymentFen = input.paymentAmount
|
||||
const materialComplete = payload.materialComplete === true || payload.materialComplete === 'true'
|
||||
const fields = normalizeRequirementFields(payload.fields)
|
||||
const platformOrderId = String(
|
||||
payload.platformOrderId || payload.orderNo || `MOCKWORK${Date.now()}`,
|
||||
).trim()
|
||||
const productName = String(payload.productName || '指挥官秘钥1个').trim()
|
||||
const { platformOrderId, productName, shop } = input
|
||||
const material = {
|
||||
...(materialComplete
|
||||
? {
|
||||
@@ -1926,7 +1924,11 @@ export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
mock: true,
|
||||
provider: 'mock',
|
||||
platform: 'mock',
|
||||
shopName: '模拟店铺',
|
||||
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({
|
||||
@@ -1957,12 +1959,94 @@ export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
|
||||
eventType: 'mock_created',
|
||||
fromStatus: '',
|
||||
toStatus: workOrder.status,
|
||||
payloadJson: JSON.stringify({ platformOrderId, productName, rewardAmount }),
|
||||
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 async function updateAdminWorkOrder(
|
||||
workOrderId: number | string,
|
||||
payload: JsonObject = {},
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
maskWorkerLeaderboardDisplayName,
|
||||
resolveCollectSubmitTargetWorkOrder,
|
||||
resolveAdminMaterialRewardAmount,
|
||||
resolveAdminMockWorkOrderInput,
|
||||
resolveMatchingProductRuleDecision,
|
||||
resolveWorkerPermissions,
|
||||
resolveSkuNameQuantity,
|
||||
@@ -172,6 +173,78 @@ test('接单密码至少八位且必须包含英文字母和数字', () => {
|
||||
assert.throws(() => validateWorkerPassword('12345678'), { errorCode: 'worker_password_invalid' })
|
||||
})
|
||||
|
||||
test('本地 Mock 工单要求订单、店铺、商品与两个金额完整有效', () => {
|
||||
const shops = [
|
||||
{
|
||||
enabled: true,
|
||||
sellerId: 'seller-1',
|
||||
shopId: 'shop-1',
|
||||
shopName: '测试店铺',
|
||||
customShopName: '',
|
||||
authState: '',
|
||||
accessToken: '',
|
||||
refreshToken: '',
|
||||
accessTokenExpiresAt: '',
|
||||
refreshTokenExpiresAt: '',
|
||||
openId: '',
|
||||
grantedScopes: '',
|
||||
lastRefreshedAt: '',
|
||||
lastRefreshError: '',
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
sellerId: 'seller-disabled',
|
||||
shopId: 'shop-disabled',
|
||||
shopName: '已停用店铺',
|
||||
customShopName: '',
|
||||
authState: '',
|
||||
accessToken: '',
|
||||
refreshToken: '',
|
||||
accessTokenExpiresAt: '',
|
||||
refreshTokenExpiresAt: '',
|
||||
openId: '',
|
||||
grantedScopes: '',
|
||||
lastRefreshedAt: '',
|
||||
lastRefreshError: '',
|
||||
},
|
||||
]
|
||||
const baseInput = {
|
||||
platformOrderId: 'MOCK-1',
|
||||
productName: '测试商品',
|
||||
sellerId: 'seller-1',
|
||||
rewardAmount: 25,
|
||||
paymentAmount: 30,
|
||||
}
|
||||
|
||||
assert.throws(() => resolveAdminMockWorkOrderInput({}, shops), {
|
||||
errorCode: 'mock_work_order_no_required',
|
||||
})
|
||||
assert.throws(() => resolveAdminMockWorkOrderInput({ platformOrderId: 'MOCK-1' }, shops), {
|
||||
errorCode: 'mock_work_order_product_name_required',
|
||||
})
|
||||
assert.throws(
|
||||
() =>
|
||||
resolveAdminMockWorkOrderInput({ platformOrderId: 'MOCK-1', productName: '测试商品' }, shops),
|
||||
{ errorCode: 'mock_work_order_shop_required' },
|
||||
)
|
||||
assert.throws(
|
||||
() => resolveAdminMockWorkOrderInput({ ...baseInput, sellerId: 'unknown' }, shops),
|
||||
{ errorCode: 'mock_work_order_shop_invalid' },
|
||||
)
|
||||
assert.throws(
|
||||
() => resolveAdminMockWorkOrderInput({ ...baseInput, sellerId: 'seller-disabled' }, shops),
|
||||
{ errorCode: 'mock_work_order_shop_disabled' },
|
||||
)
|
||||
assert.throws(
|
||||
() => resolveAdminMockWorkOrderInput({ ...baseInput, rewardAmount: undefined }, shops),
|
||||
{ errorCode: 'mock_work_order_reward_amount_required' },
|
||||
)
|
||||
assert.throws(() => resolveAdminMockWorkOrderInput({ ...baseInput, paymentAmount: 0 }, shops), {
|
||||
errorCode: 'mock_work_order_payment_amount_invalid',
|
||||
})
|
||||
assert.deepEqual(resolveAdminMockWorkOrderInput(baseInput, shops).rewardAmount, 2500)
|
||||
})
|
||||
|
||||
test('排行榜打手名称仅展示首字符', () => {
|
||||
assert.equal(maskWorkerLeaderboardDisplayName('张三'), '张****')
|
||||
assert.equal(maskWorkerLeaderboardDisplayName('Alice'), 'A****')
|
||||
|
||||
Reference in New Issue
Block a user