feat(consignment): 停用客服手动入库,寄卖货源只走平台提报
背景:手动入库是唯一会造出「没有提报单的现货」的入口,这类货没有寄卖单号, 统一状态机/凭证链/搜索/卖家端单号锚定都串不起来,只能在界面回退显示内部仓库号 INV, 正是"一件货两个号"的残留。业务定调:寄卖货源只走「打手平台提报 → 客服审核入库」。 - 前端寄售仓库的「手动入库」入口整块删除(按钮 + 入库弹窗 + 提交逻辑 + 服务函数) - 后端同时挡住,防旧页面缓存或直接调接口绕过: POST /worker-platform/consignment/inventories 返回 409 consignment_manual_inbound_disabled; 死代码一并清掉(服务层原实现、仓库层 createConsignmentInventory) - 提报审核入库路径不受影响,照旧生成内部仓库号 INV 并写 source_submission_id, 即每件货都必然挂着寄卖单号,INV 只作为内部编号存在、界面不展示 真实库验证:接口被拒(409),且「没有提报单的现货行数」前后均为 0。
This commit is contained in:
@@ -3,7 +3,6 @@ import {
|
||||
type ConsignmentInventoryRow,
|
||||
type ConsignmentSubmissionRow,
|
||||
approveConsignmentSubmissionWithInbound,
|
||||
createConsignmentInventory,
|
||||
getConsignmentInventoryById,
|
||||
getConsignmentInventoryStats,
|
||||
getConsignmentSubmissionById,
|
||||
@@ -279,46 +278,19 @@ export async function getAdminConsignmentInventory(id: number | string) {
|
||||
return mapConsignmentInventory(item)
|
||||
}
|
||||
|
||||
export async function createAdminConsignmentInventory(payload: JsonObject, actorName = '') {
|
||||
const itemName = String(payload.itemName || '').trim()
|
||||
if (!itemName) {
|
||||
throw createHttpError('物品名称不能为空', { statusCode: 400, errorCode: 'invalid_item_name' })
|
||||
}
|
||||
|
||||
const now = nowIso()
|
||||
const inventoryNo = generateConsignmentInventoryNo()
|
||||
const costPriceFen = Math.max(0, Math.round(Number(payload.costPriceFen || 0)))
|
||||
|
||||
const row = await createConsignmentInventory({
|
||||
inventoryNo,
|
||||
gameName: String(payload.gameName || '和平精英').trim(),
|
||||
categoryId: payload.categoryId ? Number(payload.categoryId) : null,
|
||||
itemName,
|
||||
system: String(payload.system || '').trim(),
|
||||
serverZone: String(payload.serverZone || '').trim(),
|
||||
series: String(payload.series || '').trim(),
|
||||
diamondLevel: Math.max(1, Math.min(7, Number(payload.diamondLevel || 1))),
|
||||
brillianceCount: Math.max(0, Math.min(7, Number(payload.brillianceCount || 0))),
|
||||
costPriceFen,
|
||||
buyerName: String(payload.buyerName || actorName || '').trim(),
|
||||
inboundBatch: String(payload.inboundBatch || '').trim(),
|
||||
sellerContact: String(payload.sellerContact || '').trim(),
|
||||
sellerGameId: String(payload.sellerGameId || '').trim(),
|
||||
sellerPaymentInfo: String(payload.sellerPaymentInfo || '').trim(),
|
||||
sellerPhone: String(payload.sellerPhone || '').trim(),
|
||||
credentialsJson: pickCredentialsJson(payload) ?? {},
|
||||
screenshotsJson: pickScreenshotsJson(payload) ?? [],
|
||||
remark: String(payload.remark || '').trim(),
|
||||
allowMatching: payload.allowMatching !== false,
|
||||
sourceType: 'manual',
|
||||
workerId: payload.workerId ? Number(payload.workerId) : null,
|
||||
workerName: String(payload.workerName || '').trim(),
|
||||
workerPhone: String(payload.workerPhone || '').trim(),
|
||||
depositAmountFen: payload.depositAmountFen ? Number(payload.depositAmountFen) : 0,
|
||||
now,
|
||||
/**
|
||||
* 客服手动入库——**业务已停用**。
|
||||
*
|
||||
* 寄卖的货源只允许走「打手在平台提报 → 客服审核入库」这一条路:手动入库的货没有提报单,
|
||||
* 也就没有寄卖单号,全流程(状态机/凭证链/搜索/卖家端)都无法用同一个号锚定。
|
||||
* 这里保留一个明确的拒绝而不是静默删除,是为了挡住旧页面缓存或直接调接口的写入,
|
||||
* 避免又冒出没有提报单的货;将来要恢复也只需回退这个守卫。
|
||||
*/
|
||||
export async function createAdminConsignmentInventory(_payload: JsonObject, _actorName = '') {
|
||||
throw createHttpError('客服手动入库已停用:寄卖货源请统一走打手在平台提报后审核入库', {
|
||||
statusCode: 409,
|
||||
errorCode: 'consignment_manual_inbound_disabled',
|
||||
})
|
||||
|
||||
return mapConsignmentInventory(row)
|
||||
}
|
||||
|
||||
export async function updateAdminConsignmentInventory(
|
||||
|
||||
@@ -144,3 +144,17 @@ test('提报行同样带出赠送凭证(审核界面要看这件货有没有
|
||||
assert.equal(mapped.giftEvidenceReviewStatus, 'accepted')
|
||||
assert.equal(mapped.giftWorkOrderNo, 'WO1')
|
||||
})
|
||||
|
||||
test('客服手动入库已停用:接口必须明确拒绝,不能再造出没有提报单的货', async () => {
|
||||
const { createAdminConsignmentInventory } = await import('./consignment-admin-service.js')
|
||||
// 手动入库的货没有提报单 → 没有寄卖单号 → 全流程无法用一个号锚定,业务已改为只允许平台提报
|
||||
await assert.rejects(
|
||||
() => createAdminConsignmentInventory({ itemName: '不该被创建的货' }, 'admin'),
|
||||
(error: unknown) => {
|
||||
const err = error as { errorCode?: string; code?: string; statusCode?: number }
|
||||
assert.equal(err.errorCode || err.code, 'consignment_manual_inbound_disabled')
|
||||
assert.equal(err.statusCode, 409)
|
||||
return true
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user