fix(consignment): 兼容历史整单履约的赠送操作
无占用记录时按库存绑定工单兜底;前端无 allocation/share 时不再传 workOrderId,修复卖家提交赠送截图的订单占用报错。
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { isLegacyBoundConsignmentTarget } from './consignment-action-target.js'
|
||||
|
||||
function baseInput() {
|
||||
return {
|
||||
inventoryStatus: 'consumed',
|
||||
boundWorkOrderId: 204855,
|
||||
allocationId: 0,
|
||||
shareId: 0,
|
||||
workOrderId: 204855,
|
||||
hasActiveAllocation: false,
|
||||
}
|
||||
}
|
||||
|
||||
test('历史整单履约:没有占用记录且指向库存绑定工单时允许继续', () => {
|
||||
assert.equal(isLegacyBoundConsignmentTarget(baseInput()), true)
|
||||
})
|
||||
|
||||
test('历史兜底只接受 consumed 库存', () => {
|
||||
assert.equal(
|
||||
isLegacyBoundConsignmentTarget({ ...baseInput(), inventoryStatus: 'in_stock' }),
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
test('有新的有效占用时不得回退到库存绑定工单', () => {
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), hasActiveAllocation: true }), false)
|
||||
})
|
||||
|
||||
test('显式指定 allocation/share 但没有匹配记录时不得兜底', () => {
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), allocationId: 11 }), false)
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), shareId: 22 }), false)
|
||||
})
|
||||
|
||||
test('工单号与库存绑定工单不一致时不得兜底', () => {
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), workOrderId: 204856 }), false)
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), boundWorkOrderId: null }), false)
|
||||
})
|
||||
|
||||
test('没有传工单号时不需要历史兜底', () => {
|
||||
assert.equal(isLegacyBoundConsignmentTarget({ ...baseInput(), workOrderId: 0 }), false)
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 历史整单履约兼容判断。
|
||||
*
|
||||
* 旧的后台「内部库存履约」只写 consignment_inventories.bound_work_order_id,
|
||||
* 不会生成 consignment_inventory_allocations。卖家端按绑定工单发起操作时,
|
||||
* 只要库存仍是 consumed 且没有新的有效占用,就允许按整单继续。
|
||||
*/
|
||||
export function isLegacyBoundConsignmentTarget(input: {
|
||||
inventoryStatus: string
|
||||
boundWorkOrderId: number | string | null | undefined
|
||||
allocationId: number
|
||||
shareId: number
|
||||
workOrderId: number
|
||||
hasActiveAllocation: boolean
|
||||
}): boolean {
|
||||
if (input.hasActiveAllocation) return false
|
||||
if (input.allocationId > 0 || input.shareId > 0) return false
|
||||
if (input.workOrderId <= 0) return false
|
||||
if (String(input.inventoryStatus || '').trim() !== 'consumed') return false
|
||||
return Number(input.boundWorkOrderId || 0) === input.workOrderId
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
resolvePriceDropSuggestion,
|
||||
} from './consignment-profile-service.js'
|
||||
import { suggestConsignmentPriceFromRules } from './consignment-matching-service.js'
|
||||
import { isLegacyBoundConsignmentTarget } from './consignment-action-target.js'
|
||||
import {
|
||||
getEnabledWorkProductRuleByKey,
|
||||
parseTemplateSpecs,
|
||||
@@ -1010,7 +1011,19 @@ async function resolveSellerConsignmentWorkOrder(
|
||||
errorCode: 'consignment_allocation_selection_required',
|
||||
})
|
||||
}
|
||||
if ((allocationIdInput > 0 || shareIdInput > 0 || workOrderIdInput > 0) && !allocation) {
|
||||
const isLegacyBoundTarget = isLegacyBoundConsignmentTarget({
|
||||
inventoryStatus: inventory.status,
|
||||
boundWorkOrderId: inventory.bound_work_order_id,
|
||||
allocationId: allocationIdInput,
|
||||
shareId: shareIdInput,
|
||||
workOrderId: workOrderIdInput,
|
||||
hasActiveAllocation: allocations.length > 0,
|
||||
})
|
||||
if (
|
||||
(allocationIdInput > 0 || shareIdInput > 0 || workOrderIdInput > 0) &&
|
||||
!allocation &&
|
||||
!isLegacyBoundTarget
|
||||
) {
|
||||
throw createHttpError('未找到该寄卖单对应的订单占用,请刷新后重试', {
|
||||
statusCode: 404,
|
||||
errorCode: 'consignment_allocation_not_found',
|
||||
|
||||
Reference in New Issue
Block a user