feat(finance): 商品渠道能力、自动发货转人工与成本异常收口
- 商品可同时支持自动发货/人工,新增渠道能力与成本冲销字段 - 卡券缺商品时按内部中文 SKU 自动建 tpv: 商品并补渠道规则 - 自动发货失败转人工并冲销原渠道成本 - 配置成本后按最早缺失订单生效并立即补算、关闭异常 - tpv: 商品来源计入第三方卡券
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import { query } from '../../db/client.js'
|
||||
import { assignPendingOrderItemChannels } from '../fulfillment/channel-assign-service.js'
|
||||
import { runAffiliateFallback } from '../fulfillment/affiliate-fallback-service.js'
|
||||
import {
|
||||
resolveExceptionsForItemsByReason,
|
||||
resolveOrphanCostExceptions,
|
||||
upsertAggregatedExceptionsBatch,
|
||||
type AggregatedExceptionEntry,
|
||||
} from '../cost-center/cost-exception-service.js'
|
||||
@@ -167,7 +169,7 @@ export async function runCarrierDispatchJob(job: JsonObject = {}) {
|
||||
SELECT 1 FROM cost_snapshots cs
|
||||
WHERE cs.subject_type = 'manual_case'
|
||||
AND cs.order_item_id = oi.id
|
||||
AND cs.superseded_at IS NULL
|
||||
AND cs.superseded_at IS NULL AND reversed_at IS NULL
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
@@ -252,17 +254,23 @@ export async function runCarrierDispatchJob(job: JsonObject = {}) {
|
||||
}
|
||||
|
||||
const resolved = await resolveCarrierDispatchExceptions()
|
||||
const fallback = await runAffiliateFallback({ limit: 200 }).catch(() => ({
|
||||
scanned: 0,
|
||||
switched: 0,
|
||||
}))
|
||||
const nextCursor = maxId === 0 ? 0 : maxId
|
||||
await touchWatermark('carrier_dispatch', { lastItemId: nextCursor })
|
||||
return {
|
||||
status: 'ok',
|
||||
message:
|
||||
`人工载体挂载 ${attached},缺配置 ${missingManual.rows.length},` +
|
||||
`缺履约载体 ${missingCarrier.rows.length},异常收口 ${resolved}`,
|
||||
`缺履约载体 ${missingCarrier.rows.length},异常收口 ${resolved},` +
|
||||
`自动转人工 ${fallback.switched}`,
|
||||
attached,
|
||||
missingManual: missingManual.rows.length,
|
||||
missingCarrier: missingCarrier.rows.length,
|
||||
resolved,
|
||||
affiliateFallback: fallback.switched,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +343,7 @@ async function resolveCarrierDispatchExceptions(): Promise<number> {
|
||||
SELECT 1 FROM cost_snapshots cs
|
||||
WHERE cs.subject_type = 'manual_case'
|
||||
AND cs.order_item_id = i.order_item_id
|
||||
AND cs.superseded_at IS NULL
|
||||
AND cs.superseded_at IS NULL AND reversed_at IS NULL
|
||||
)
|
||||
LIMIT 500
|
||||
`,
|
||||
@@ -383,6 +391,7 @@ export async function runCostSnapshotJob(job: JsonObject = {}) {
|
||||
await touchWatermark('cost_snapshot', { lastItemId: result.nextCursor })
|
||||
await touchWatermark('cost_snapshot_hot', { lastItemId: result.hotCursor })
|
||||
const refreshed = await refreshFactsForDates(result.affectedDates)
|
||||
await resolveOrphanCostExceptions().catch(() => undefined)
|
||||
return {
|
||||
status: 'ok',
|
||||
message:
|
||||
|
||||
Reference in New Issue
Block a user