修复拼单工单打手展示

This commit is contained in:
yml2213
2026-08-19 19:31:55 +08:00
parent df90b67d8e
commit f1575aec85
6 changed files with 83 additions and 7 deletions
@@ -255,7 +255,7 @@ async function publishWorkOrderSnapshots(input: {
.reduce((sum, share) => sum + Number(share.quantity || 0), 0)
const pendingSubmissionCount = shares.filter((share) => share.status === 'joined').length
const adminSnapshot = {
...mapWorkOrderAdmin(workOrder),
...mapWorkOrderAdmin(workOrder, shares),
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(workOrderId) || 0,
sharingProgress: {
joinedQuantity,
@@ -45,6 +45,7 @@ import {
listWorkerUsers,
listWorkerWithdrawalAccounts,
listWorkOrderShares,
listWorkOrderSharesByOrderIds,
sumPendingUnfreezeByOrderIds,
resolveProblemWorkOrder,
reviewWorkerFinanceRequest,
@@ -1300,10 +1301,18 @@ export async function listAdminWorkOrders(query: JsonObject = {}) {
const pendingUnfreezeByOrderId = await sumPendingUnfreezeByOrderIds(
items.map((item) => Number(item.id)),
)
const shares = await listWorkOrderSharesByOrderIds(items.map((item) => Number(item.id)))
const sharesByOrderId = new Map<number, typeof shares>()
for (const share of shares) {
const workOrderId = Number(share.work_order_id)
const current = sharesByOrderId.get(workOrderId) || []
current.push(share)
sharesByOrderId.set(workOrderId, current)
}
return {
items: items.map((item) => {
return {
...mapWorkOrderAdmin(item),
...mapWorkOrderAdmin(item, sharesByOrderId.get(Number(item.id)) || []),
pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(Number(item.id)) || 0,
}
}),
@@ -1377,7 +1386,7 @@ export async function getAdminWorkOrderSharing(workOrderId: number | string) {
const workOrder = await getRequiredWorkOrder(workOrderId)
const shares = await listWorkOrderShares(workOrder.id)
return {
order: mapWorkOrderAdmin(workOrder),
order: mapWorkOrderAdmin(workOrder, shares),
shares: shares.map(mapWorkOrderShare),
}
}
@@ -2428,7 +2437,7 @@ export async function syncWorkerOrdersForSourceOrder(
}
return {
created: created.map(mapWorkOrderAdmin),
created: created.map((workOrder) => mapWorkOrderAdmin(workOrder)),
skipped,
createdCount: created.length,
skippedCount: skipped.length,
@@ -341,7 +341,33 @@ export function resolveWorkOrderOperationalStatus(workOrder: WorkOrderRow): stri
return workOrder.status
}
export function mapWorkOrderAdmin(workOrder: WorkOrderRow) {
/** 汇总拼单参与者,已撤销份额不应继续展示为当前打手。 */
export function mapWorkOrderSharingWorkers(shares: WorkOrderShareRow[]) {
const workers = new Map<
number,
{ workerId: number; username: string; displayName: string; quantity: number }
>()
for (const share of shares) {
if (share.status === 'cancelled') continue
const workerId = Number(share.worker_id || 0)
if (workerId <= 0) continue
const existing = workers.get(workerId)
if (existing) {
existing.quantity += Number(share.quantity || 0)
continue
}
const username = String(share.worker_username || '').trim()
workers.set(workerId, {
workerId,
username,
displayName: String(share.worker_display_name || username || `打手#${workerId}`).trim(),
quantity: Number(share.quantity || 0),
})
}
return [...workers.values()]
}
export function mapWorkOrderAdmin(workOrder: WorkOrderRow, shares?: WorkOrderShareRow[]) {
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))
@@ -437,6 +463,7 @@ export function mapWorkOrderAdmin(workOrder: WorkOrderRow) {
displayName: workOrder.worker_display_name || '',
}
: null,
...(shares ? { sharingWorkers: mapWorkOrderSharingWorkers(shares) } : {}),
publishedAt: workOrder.published_at,
pinnedAt: workOrder.pinned_at,
assignedAt: workOrder.assigned_at,
@@ -22,6 +22,7 @@ import {
normalizeRequirementFields,
mapWorkOrderForWorker,
mapWorkOrderAdmin,
mapWorkOrderSharingWorkers,
maskWorkerLeaderboardDisplayName,
resolveCollectSubmitTargetWorkOrder,
resolveAdminMaterialRewardAmount,
@@ -733,6 +734,20 @@ test('后台拼单聚合状态同时收敛筛选语义和操作能力', () => {
assert.equal(filled.capabilities.canUnpublish, false)
})
test('拼单打手汇总展示当前参与者并合并同一打手的份数', () => {
const workers = mapWorkOrderSharingWorkers([
buildWorkOrderShareRow({ worker_id: 1, quantity: 2, worker_username: 'alpha' }),
buildWorkOrderShareRow({ id: 2, worker_id: 1, quantity: 3, worker_username: 'alpha' }),
buildWorkOrderShareRow({ id: 3, worker_id: 2, quantity: 1, worker_display_name: 'Beta' }),
buildWorkOrderShareRow({ id: 4, worker_id: 3, quantity: 9, status: 'cancelled' }),
])
assert.deepEqual(workers, [
{ workerId: 1, username: 'alpha', displayName: 'alpha', quantity: 5 },
{ workerId: 2, username: '', displayName: 'Beta', quantity: 1 },
])
})
test('拼单份额撤单只允许未验收份额并让母工单回到大厅状态', () => {
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'joined'), 'open')
assert.equal(resolveWorkOrderShareCancellationStatus('open', 'submitted'), 'open')