fix(fulfillment): 封堵重复载体并完善统一SKU映射

This commit is contained in:
yml2213
2026-11-03 12:28:05 +08:00
parent 3ba808b814
commit e6763882f5
27 changed files with 1506 additions and 45 deletions
@@ -8,13 +8,21 @@ import {
type FulfillmentBindingLike,
} from '../fulfillment/planner.js'
import { preparePaidFulfillmentTask } from '../fulfillment/executors/registry.js'
import type { FulfillmentPrepareDeps } from '../fulfillment/executors/types.js'
import {
FULFILLMENT_EXECUTOR_KEYS,
type FulfillmentPrepareDeps,
} from '../fulfillment/executors/types.js'
import { nowIso } from '../../utils/time.js'
import { randomId } from '../../utils/random.js'
import { logInfo, logWarn } from '../../utils/logger.js'
import { TASK_STATUS, resolveInitialPaidTaskStatus } from '../../domain/task-status.js'
import type { JsonObject } from '../../types/json.js'
import type { OrderItemRow, OrderRow, TaskRow } from '../../types/repository/rows.js'
import {
findConflictingCarrier,
loadActiveCarrierEvidence,
} from '../fulfillment/carrier-evidence-service.js'
import type { FulfillmentChannel } from '../fulfillment/channel-types.js'
type ClaimTokenLike = {
token: string
@@ -30,6 +38,7 @@ type DeliveryTaskRow = TaskRow & {
type DeliveryTaskDeps = {
createTask?: typeof createTask
listTasksByOrderId?: typeof listTasksByOrderId
loadActiveCarrierEvidence?: typeof loadActiveCarrierEvidence
updateTask?: typeof updateTask
getFulfillmentProfileByKey?: (profileKey: string) => Promise<FulfillmentBindingLike | null>
createTaskClaimToken?: (taskId: number | string) => Promise<ClaimTokenLike>
@@ -60,6 +69,7 @@ export async function syncDeliveryTasksForOrderWithDeps(
const {
createTask: createDeliveryTask = createTask,
listTasksByOrderId: listTasks = listTasksByOrderId,
loadActiveCarrierEvidence: loadCarrierEvidence = loadActiveCarrierEvidence,
updateTask: updateDeliveryTask = updateTask,
getFulfillmentProfileByKey: getProfileByKey = getFulfillmentProfileByKey,
createTaskClaimToken: createClaimToken = createTaskClaimToken,
@@ -81,6 +91,7 @@ export async function syncDeliveryTasksForOrderWithDeps(
const existingTasks = await listTasks(order.id)
const tasks: DeliveryTaskRow[] = [...existingTasks]
const existingTaskKeys = new Set(existingTasks.map(buildTaskUnitKey))
const carrierEvidence = await loadCarrierEvidence(orderItems.map((item) => Number(item.id)))
writeInfoLog('[delivery-task-service]', '开始核对订单履约任务完整性', {
...buildOrderLogContext(order),
@@ -126,6 +137,32 @@ export async function syncDeliveryTasksForOrderWithDeps(
continue
}
const plannedChannel = executorKeyToFulfillmentChannel(plan.executorKey)
if (plannedChannel) {
const assignedChannel = String(item.fulfillment_channel || '').trim()
if (item.fulfillment_status === 'assigned' && assignedChannel !== plannedChannel) {
writeInfoLog('[delivery-task-service]', '订单项已分配其它渠道,跳过载体补建', {
...buildOrderItemLogContext(item),
assignedChannel,
plannedChannel,
})
continue
}
const conflictingCarrier = findConflictingCarrier(
carrierEvidence.get(Number(item.id)),
plannedChannel,
)
if (conflictingCarrier) {
writeWarnLog('[delivery-task-service]', '订单项已有其它真实载体,跳过载体补建', {
...buildOrderItemLogContext(item),
existingCarrier: conflictingCarrier,
plannedChannel,
})
continue
}
}
for (const unitIndex of missingUnitIndexes) {
const createdAt = getNowIso()
const initialStatus =
@@ -256,6 +293,12 @@ export async function syncDeliveryTasksForOrderWithDeps(
return preparedTasks.filter(isTaskRow)
}
function executorKeyToFulfillmentChannel(executorKey: string): FulfillmentChannel | null {
if (executorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH) return 'affiliate_dash'
if (executorKey === FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH) return 'manual'
return null
}
async function preparePaidTaskWithDiagnostics(
order: OrderRow,
task: TaskRow,