fix(worker): 不满额拼单母单显示待抢单,满额后才按份额状态推进

This commit is contained in:
2026-11-01 15:43:20 +08:00
parent 4fd533c678
commit 2ce8f601df
7 changed files with 83 additions and 18 deletions
@@ -196,7 +196,7 @@ export async function cancelAdminWorkOrderShare(
* 后台按份数撤销某个打手的部分份额。
*
* 减少的份数会随「大厅余量 = 总份数 − Σ有效份额数量」自动回到大厅;押金保持原冻结额,
* 母单状态按剩余份额重算(可能从待验收回到代练中,保留原大厅队列位置),
* 母单状态按剩余份额重算(可能从待验收回到待抢单,保留原大厅队列位置),
* 该份额的验收资料不动(之后仍可对该份额「单独验收」)。
*/
export async function reduceAdminWorkOrderShareQuantity(
@@ -198,12 +198,14 @@ export function resolveWorkOrderOperationalStatus(workOrder: WorkOrderRow): stri
const activeShareQuantity = Math.max(0, Number(workOrder.active_share_quantity || 0))
const pendingShareCount = Math.max(0, Number(workOrder.pending_share_count || 0))
const sharingTotalQuantity = Math.max(1, Number(workOrder.sharing_total_quantity || 1))
const hasActiveShares = activeShareQuantity > 0
const sharingFilled =
workOrder.sharing_enabled === true && activeShareQuantity >= sharingTotalQuantity
if (workOrder.status === WORK_ORDER_STATUS.OPEN && workOrder.sharing_enabled && hasActiveShares) {
return sharingFilled && pendingShareCount === 0
if (workOrder.status === WORK_ORDER_STATUS.OPEN && workOrder.sharing_enabled) {
// 有份额回到大厅(未满额)时,母单先回到「待抢单」:空位还在,就还没到按份额状态推进的时候。
// 满额后才按份额状态收敛:仍有 joined → 代练中;全部已提交 → 待验收。
if (!sharingFilled) return WORK_ORDER_STATUS.OPEN
return pendingShareCount === 0
? WORK_ORDER_STATUS.PENDING_ACCEPTANCE
: WORK_ORDER_STATUS.IN_PROGRESS
}
@@ -2046,6 +2046,7 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
assert.equal(waitingForClaim.status, 'open')
assert.equal(waitingForClaim.capabilities.canUpdateMaterial, true)
// 有份额回到大厅(未满额):空位还在,母单必须先显示「待抢单」。
const partial = mapWorkOrderAdmin(
buildWorkOrderRow({
status: 'open',
@@ -2055,7 +2056,7 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
pending_share_count: 1,
}),
)
assert.equal(partial.status, 'in_progress')
assert.equal(partial.status, 'open')
assert.equal(partial.rawStatus, 'open')
assert.equal(partial.hallAvailable, true)
assert.equal(partial.capabilities.canEdit, false)
@@ -2063,6 +2064,25 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
assert.equal(partial.capabilities.canAssign, false)
assert.equal(partial.capabilities.canUpdateMaterial, true)
assert.equal(partial.capabilities.canCancelSharing, true)
// 整单验收 / 整单标记问题单都要求满额且所有份额满足,不满额时不能走整单动作。
assert.equal(partial.capabilities.canAccept, false)
assert.equal(partial.capabilities.canMarkProblem, false)
// 满额但还有份额没提交:母单代练中,整单验收同样不可用。
const filledInProgress = mapWorkOrderAdmin(
buildWorkOrderRow({
status: 'open',
sharing_enabled: true,
sharing_total_quantity: 15,
active_share_quantity: 15,
pending_share_count: 1,
}),
)
assert.equal(filledInProgress.status, 'in_progress')
assert.equal(filledInProgress.rawStatus, 'open')
assert.equal(filledInProgress.hallAvailable, false)
assert.equal(filledInProgress.capabilities.canAccept, false)
assert.equal(filledInProgress.capabilities.canMarkProblem, true)
const filled = mapWorkOrderAdmin(
buildWorkOrderRow({
@@ -2080,6 +2100,38 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
assert.equal(filled.capabilities.canCancelSharing, true)
})
test('后台运营态先判空位:不满额必须显示待抢单,满额后才按份额推进', async () => {
const { readFile } = await import('node:fs/promises')
const queryRepo = await readFile(
new URL('../../repositories/worker-platform/work-order-query-repo.ts', import.meta.url),
'utf8',
)
const start = queryRepo.indexOf('function adminOperationalStatusExpression')
assert.ok(start >= 0, '缺少 adminOperationalStatusExpression')
const end = queryRepo.indexOf('/** 工单统一搜索字段', start)
const block = queryRepo.slice(start, end > start ? end : start + 4000)
// 两个分支(带 share summary 别名 / 不带别名)都必须先判「有效份数 < 总份数」。
assert.equal(
(block.match(/< \$\{alias\}\.sharing_total_quantity/g) || []).length,
2,
'空位判定必须在两版运营态表达式里都存在',
)
assert.ok(
block.indexOf("THEN 'open'") < block.indexOf("THEN 'pending_acceptance'"),
'空位分支必须排在待验收之前,否则不满额拼单会被误判为待验收',
)
assert.ok(
block.indexOf("THEN 'open'") < block.indexOf("ELSE 'in_progress'"),
'空位分支必须排在代练中之前,否则不满额拼单会被误判为代练中',
)
assert.equal(
(block.match(/THEN 'open'/g) || []).length,
2,
'空位分支必须在两版运营态表达式里都以待抢单收口',
)
})
test('已取消工单可重新启用,恢复未分配后可编辑和发布', () => {
const cancelled = mapWorkOrderAdmin(buildWorkOrderRow({ status: 'cancelled' }))
assert.equal(cancelled.capabilities.canReopen, true)