解耦接单与履约订单处理
This commit is contained in:
@@ -118,29 +118,8 @@ export async function upsertOrderFromSource(
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
const configuredItems = (resolvedItems as FulfillmentOrderItem[]).filter(
|
const resolvedFulfillmentItems = resolvedItems as FulfillmentOrderItem[]
|
||||||
(item) => item.isConfigured,
|
const configuredItems = resolvedFulfillmentItems.filter((item) => item.isConfigured)
|
||||||
)
|
|
||||||
|
|
||||||
if (configuredItems.length === 0) {
|
|
||||||
logIntegration('[order-service]', `${sourceLabel} 订单已忽略:未命中任何已配置履约商品`, {
|
|
||||||
provider: event.provider,
|
|
||||||
platform: event.platform,
|
|
||||||
shopId: event.shopId,
|
|
||||||
shopName: event.shopName,
|
|
||||||
platformOrderId: event.platformOrderId,
|
|
||||||
existingOrderId: existing?.id || null,
|
|
||||||
rawItemCount: event.items.length,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
ignored: true,
|
|
||||||
ignoreReason: 'unconfigured_items',
|
|
||||||
order: null,
|
|
||||||
orderItems: [],
|
|
||||||
tasks: [],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const basePayload = {
|
const basePayload = {
|
||||||
provider: event.provider,
|
provider: event.provider,
|
||||||
@@ -182,7 +161,7 @@ export async function upsertOrderFromSource(
|
|||||||
|
|
||||||
const orderItems = await replaceOrderItems(
|
const orderItems = await replaceOrderItems(
|
||||||
order.id,
|
order.id,
|
||||||
configuredItems.map((item) => ({
|
resolvedFulfillmentItems.map((item) => ({
|
||||||
skuCode: item.skuCode,
|
skuCode: item.skuCode,
|
||||||
skuName: item.skuName,
|
skuName: item.skuName,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
@@ -193,7 +172,11 @@ export async function upsertOrderFromSource(
|
|||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
|
||||||
const readiness = await resolveOrderFulfillmentReadiness(order)
|
const configuredOrderItems = orderItems.filter(isOrderItemConfiguredForFulfillment)
|
||||||
|
const readiness =
|
||||||
|
configuredOrderItems.length > 0
|
||||||
|
? await resolveOrderFulfillmentReadiness(order)
|
||||||
|
: { allowed: true as const, voucherCount: 0, reason: '', blockReason: '' }
|
||||||
if (!readiness.allowed) {
|
if (!readiness.allowed) {
|
||||||
logIntegration(
|
logIntegration(
|
||||||
'[order-service]',
|
'[order-service]',
|
||||||
@@ -209,6 +192,10 @@ export async function upsertOrderFromSource(
|
|||||||
{ level: 'warn' },
|
{ level: 'warn' },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await syncWorkerOrdersForSourceOrder(order, orderItems, {
|
||||||
|
source: `${sourceLabel}_order_upsert`,
|
||||||
|
autoOnly: true,
|
||||||
|
})
|
||||||
return {
|
return {
|
||||||
ignoreReason: readiness.blockReason || 'fulfillment_not_ready',
|
ignoreReason: readiness.blockReason || 'fulfillment_not_ready',
|
||||||
order,
|
order,
|
||||||
@@ -217,7 +204,10 @@ export async function upsertOrderFromSource(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tasks = await syncDeliveryTasksForOrder(order, orderItems)
|
const tasks =
|
||||||
|
configuredOrderItems.length > 0
|
||||||
|
? await syncDeliveryTasksForOrder(order, configuredOrderItems)
|
||||||
|
: []
|
||||||
await syncOrderFulfillmentAttachments(order, tasks, {
|
await syncOrderFulfillmentAttachments(order, tasks, {
|
||||||
source: `${sourceLabel}_order_upsert`,
|
source: `${sourceLabel}_order_upsert`,
|
||||||
now,
|
now,
|
||||||
@@ -293,6 +283,20 @@ export function mergeSourceOrderState(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isOrderItemConfiguredForFulfillment(item: OrderItemRow): boolean {
|
||||||
|
try {
|
||||||
|
const snapshot = JSON.parse(String(item.item_snapshot_json || '{}'))
|
||||||
|
return Boolean(
|
||||||
|
snapshot &&
|
||||||
|
typeof snapshot === 'object' &&
|
||||||
|
!Array.isArray(snapshot) &&
|
||||||
|
snapshot.isConfigured === true,
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function chooseHigherPriorityStatus(
|
function chooseHigherPriorityStatus(
|
||||||
existingValue: string,
|
existingValue: string,
|
||||||
incomingValue: string,
|
incomingValue: string,
|
||||||
|
|||||||
@@ -594,12 +594,21 @@ export function resolveMatchingProductRule(
|
|||||||
if (!matchesOptionalText(rule.platform, order.platform)) return false
|
if (!matchesOptionalText(rule.platform, order.platform)) return false
|
||||||
if (!matchesOptionalText(rule.shop_id, order.shop_id)) return false
|
if (!matchesOptionalText(rule.shop_id, order.shop_id)) return false
|
||||||
|
|
||||||
const skuCode = String(item.sku_code || '')
|
const snapshot = safeParseJson(item.item_snapshot_json)
|
||||||
.trim()
|
const skuCodes = [item.sku_code, snapshot.externalSkuCode, snapshot.externalItemId]
|
||||||
.toLowerCase()
|
.map((value) =>
|
||||||
const skuName = String(item.sku_name || '')
|
String(value || '')
|
||||||
.trim()
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase(),
|
||||||
|
)
|
||||||
|
.filter(Boolean)
|
||||||
|
const skuNames = [item.sku_name, snapshot.externalSkuName, snapshot.externalSkuNameNormalized]
|
||||||
|
.map((value) =>
|
||||||
|
String(value || '')
|
||||||
|
.trim()
|
||||||
|
.toLowerCase(),
|
||||||
|
)
|
||||||
|
.filter(Boolean)
|
||||||
const ruleSkuCode = String(rule.sku_code || '')
|
const ruleSkuCode = String(rule.sku_code || '')
|
||||||
.trim()
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@@ -607,16 +616,19 @@ export function resolveMatchingProductRule(
|
|||||||
.trim()
|
.trim()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
|
|
||||||
if (ruleSkuCode && ruleSkuCode !== skuCode) {
|
if (ruleSkuCode && !skuCodes.includes(ruleSkuCode)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (!ruleProductName) {
|
if (!ruleProductName) {
|
||||||
return Boolean(ruleSkuCode)
|
return Boolean(ruleSkuCode)
|
||||||
}
|
}
|
||||||
if (rule.match_type === 'exact') {
|
if (rule.match_type === 'exact') {
|
||||||
return ruleProductName === skuName || ruleProductName === skuCode
|
return skuNames.includes(ruleProductName) || skuCodes.includes(ruleProductName)
|
||||||
}
|
}
|
||||||
return skuName.includes(ruleProductName) || skuCode.includes(ruleProductName)
|
return (
|
||||||
|
skuNames.some((value) => value.includes(ruleProductName)) ||
|
||||||
|
skuCodes.some((value) => value.includes(ruleProductName))
|
||||||
|
)
|
||||||
}) || null
|
}) || null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user