diff --git a/apps/backend/src/services/worker-platform/admin-mock-work-order-service.ts b/apps/backend/src/services/worker-platform/admin-mock-work-order-service.ts index 56054ce0..0398d772 100644 --- a/apps/backend/src/services/worker-platform/admin-mock-work-order-service.ts +++ b/apps/backend/src/services/worker-platform/admin-mock-work-order-service.ts @@ -3,7 +3,11 @@ import { normalizeWorkOrderAcceptanceMode, normalizeWorkOrderGiftCooldownHours, } from '../../domain/work-order-acceptance-mode.js' -import { createWorkOrder, createWorkOrderEvent } from '../../repositories/worker-platform/index.js' +import { + createWorkOrder, + createWorkOrderEvent, + listWorkOrdersByPlatformOrderId, +} from '../../repositories/worker-platform/index.js' import type { JsonObject } from '../../types/json.js' import { createHttpError } from '../../utils/http.js' import { randomId } from '../../utils/random.js' @@ -46,6 +50,18 @@ export async function createAdminMockWorkOrder(payload: JsonObject = {}) { const materialComplete = payload.materialComplete === true || payload.materialComplete === 'true' const fields = normalizeRequirementFields(payload.fields) const { platformOrderId, productName, shop } = input + // 订单号全局唯一:与自动同步的真实工单也不能撞号,否则打手按单号回填资料会命中多条。 + const existingOrders = await listWorkOrdersByPlatformOrderId(platformOrderId) + if (existingOrders.length > 0) { + const existingNo = String(existingOrders[0]?.work_order_no || '').trim() + throw createHttpError( + `该订单号已存在工单${existingNo ? `(${existingNo})` : ''},请更换订单号`, + { + statusCode: 409, + errorCode: 'mock_work_order_platform_order_exists', + }, + ) + } const material = { ...(materialComplete ? { diff --git a/apps/backend/src/services/worker-platform/sync-worker-orders-service.ts b/apps/backend/src/services/worker-platform/sync-worker-orders-service.ts index e0f26980..5799acd7 100644 --- a/apps/backend/src/services/worker-platform/sync-worker-orders-service.ts +++ b/apps/backend/src/services/worker-platform/sync-worker-orders-service.ts @@ -9,6 +9,7 @@ import { createWorkOrder, createWorkOrderEvent, getWorkOrderByOrderItemId, + listWorkOrdersByPlatformOrderId, listWorkProductRuleMappings, listWorkProductRules, type WorkOrderRow, @@ -88,6 +89,18 @@ export async function syncWorkerOrdersForSourceOrder( skipped.push({ orderItemId: Number(item.id), reason: 'already_exists' }) continue } + // 订单号跨订单唯一:同一订单的多个 SKU 件允许共享订单号(按件建单是既有设计), + // 但订单号已挂在其他订单下时跳过,避免自动同步产生撞号工单。 + const samePlatformOrders = await listWorkOrdersByPlatformOrderId(order.platform_order_id) + if ( + samePlatformOrders.some((existing) => { + const existingOrderId = Number(existing.order_id || 0) + return existingOrderId > 0 && existingOrderId !== Number(order.id) + }) + ) { + skipped.push({ orderItemId: Number(item.id), reason: 'platform_order_exists' }) + continue + } const fields = normalizeRequirementFields(safeParseJson(rule.requirement_json).fields) const skuQuantity = resolveSkuNameQuantity(item.sku_name) diff --git a/apps/frontend/src/pages/admin/panels/WorkOrderPanelParts.tsx b/apps/frontend/src/pages/admin/panels/WorkOrderPanelParts.tsx index 598b83af..609ac2d2 100644 --- a/apps/frontend/src/pages/admin/panels/WorkOrderPanelParts.tsx +++ b/apps/frontend/src/pages/admin/panels/WorkOrderPanelParts.tsx @@ -111,6 +111,7 @@ export function MockWorkOrderForm({ onCreated }: { onCreated: () => Promise