优化接单商品匹配
This commit is contained in:
@@ -204,6 +204,7 @@ export async function listKuaishouIndustryVouchersByOid(
|
||||
export type KuaishouIndustryVoucherWorkOrderSyncSource = {
|
||||
oid: string
|
||||
raw_payload_json: string | Record<string, unknown>
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export async function listKuaishouIndustryVoucherWorkOrderSyncSources(
|
||||
@@ -211,7 +212,7 @@ export async function listKuaishouIndustryVoucherWorkOrderSyncSources(
|
||||
): Promise<KuaishouIndustryVoucherWorkOrderSyncSource[]> {
|
||||
const result = await query<KuaishouIndustryVoucherWorkOrderSyncSource>(
|
||||
`
|
||||
SELECT oid, raw_payload_json
|
||||
SELECT oid, raw_payload_json, updated_at
|
||||
FROM (
|
||||
SELECT DISTINCT ON (oid) oid, raw_payload_json, updated_at, id
|
||||
FROM kuaishou_industry_vouchers
|
||||
|
||||
@@ -2,4 +2,5 @@ export * from './types.js'
|
||||
export * from './shared.js'
|
||||
export * from './worker-repo.js'
|
||||
export * from './work-order-repo.js'
|
||||
export * from './product-match-repo.js'
|
||||
export * from './sms-code-repo.js'
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
import { query } from '../../db/client.js'
|
||||
import type { WorkProductMatchLogRow, WorkProductRuleMappingRow } from './types.js'
|
||||
|
||||
const MAPPING_SELECT = `
|
||||
SELECT
|
||||
wprm.*,
|
||||
wpr.rule_key,
|
||||
wpr.product_name
|
||||
FROM work_product_rule_mappings wprm
|
||||
INNER JOIN work_product_rules wpr ON wpr.id = wprm.rule_id
|
||||
`
|
||||
|
||||
export async function listWorkProductRuleMappings(
|
||||
input: {
|
||||
enabled?: boolean | null
|
||||
sellerId?: string
|
||||
} = {},
|
||||
): Promise<WorkProductRuleMappingRow[]> {
|
||||
const conditions: string[] = []
|
||||
const params: unknown[] = []
|
||||
if (input.enabled !== undefined && input.enabled !== null) {
|
||||
params.push(input.enabled)
|
||||
conditions.push(`wprm.enabled = $${params.length}`)
|
||||
}
|
||||
const sellerId = String(input.sellerId || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
if (sellerId) {
|
||||
params.push(sellerId)
|
||||
conditions.push(`wprm.seller_ids_json ? $${params.length}`)
|
||||
}
|
||||
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
|
||||
const result = await query<WorkProductRuleMappingRow>(
|
||||
`${MAPPING_SELECT}
|
||||
${where}
|
||||
ORDER BY wprm.seller_ids_json::text ASC, wprm.rel_item_id ASC, wprm.item_title ASC,
|
||||
CASE WHEN wprm.mapping_type = 'product_default' THEN 0 ELSE 1 END ASC,
|
||||
wprm.id ASC`,
|
||||
params,
|
||||
)
|
||||
return result.rows
|
||||
}
|
||||
|
||||
export async function upsertWorkProductRuleMapping(input: {
|
||||
mappingId?: number | null
|
||||
ruleId: number
|
||||
sellerIds: string[]
|
||||
relItemId: string
|
||||
itemTitle: string
|
||||
relSkuId: string
|
||||
skuNick: string
|
||||
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
||||
enabled: boolean
|
||||
now: string
|
||||
}): Promise<WorkProductRuleMappingRow | null> {
|
||||
if (input.mappingId) {
|
||||
const result = await query<WorkProductRuleMappingRow>(
|
||||
`
|
||||
UPDATE work_product_rule_mappings
|
||||
SET
|
||||
rule_id = $2,
|
||||
seller_ids_json = $3::jsonb,
|
||||
rel_item_id = $4,
|
||||
item_title = $5,
|
||||
rel_sku_id = $6,
|
||||
sku_nick = $7,
|
||||
mapping_type = $8,
|
||||
enabled = $9,
|
||||
updated_at = $10
|
||||
WHERE id = $1
|
||||
RETURNING *
|
||||
`,
|
||||
[
|
||||
input.mappingId,
|
||||
input.ruleId,
|
||||
JSON.stringify(input.sellerIds),
|
||||
input.relItemId,
|
||||
input.itemTitle,
|
||||
input.relSkuId,
|
||||
input.skuNick,
|
||||
input.mappingType,
|
||||
input.enabled,
|
||||
input.now,
|
||||
],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
const result = await query<WorkProductRuleMappingRow>(
|
||||
`
|
||||
INSERT INTO work_product_rule_mappings (
|
||||
rule_id, seller_ids_json, rel_item_id, item_title, rel_sku_id, sku_nick,
|
||||
mapping_type, enabled, created_at, updated_at
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $9)
|
||||
RETURNING *
|
||||
`,
|
||||
[
|
||||
input.ruleId,
|
||||
JSON.stringify(input.sellerIds),
|
||||
input.relItemId,
|
||||
input.itemTitle,
|
||||
input.relSkuId,
|
||||
input.skuNick,
|
||||
input.mappingType,
|
||||
input.enabled,
|
||||
input.now,
|
||||
],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function deleteWorkProductRuleMapping(mappingId: number | string) {
|
||||
const result = await query<{ id: number }>(
|
||||
'DELETE FROM work_product_rule_mappings WHERE id = $1 RETURNING id',
|
||||
[Number(mappingId)],
|
||||
)
|
||||
return { deleted: Boolean(result.rows[0]) }
|
||||
}
|
||||
|
||||
export async function createWorkProductMatchLog(input: {
|
||||
orderId?: number | null
|
||||
orderItemId?: number | null
|
||||
source: string
|
||||
sellerId: string
|
||||
relItemId: string
|
||||
itemTitle: string
|
||||
relSkuId: string
|
||||
skuNick: string
|
||||
matchStatus: 'matched' | 'unmatched' | 'ambiguous'
|
||||
ruleId?: number | null
|
||||
mappingId?: number | null
|
||||
candidatesJson: string
|
||||
rawPayloadJson: string
|
||||
now: string
|
||||
}): Promise<WorkProductMatchLogRow | null> {
|
||||
const result = await query<WorkProductMatchLogRow>(
|
||||
`
|
||||
INSERT INTO work_product_match_logs (
|
||||
order_id, order_item_id, source, seller_id, rel_item_id, item_title,
|
||||
rel_sku_id, sku_nick, match_status, rule_id, mapping_id,
|
||||
candidates_json, raw_payload_json, created_at
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6,
|
||||
$7, $8, $9, $10, $11,
|
||||
$12::jsonb, $13::jsonb, $14
|
||||
)
|
||||
RETURNING *
|
||||
`,
|
||||
[
|
||||
input.orderId || null,
|
||||
input.orderItemId || null,
|
||||
input.source,
|
||||
input.sellerId,
|
||||
input.relItemId,
|
||||
input.itemTitle,
|
||||
input.relSkuId,
|
||||
input.skuNick,
|
||||
input.matchStatus,
|
||||
input.ruleId || null,
|
||||
input.mappingId || null,
|
||||
input.candidatesJson,
|
||||
input.rawPayloadJson,
|
||||
input.now,
|
||||
],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function listWorkProductMatchLogs(limit = 100): Promise<WorkProductMatchLogRow[]> {
|
||||
const result = await query<WorkProductMatchLogRow>(
|
||||
`
|
||||
SELECT wpml.*, wpr.rule_key, wpr.product_name
|
||||
FROM work_product_match_logs wpml
|
||||
LEFT JOIN work_product_rules wpr ON wpr.id = wpml.rule_id
|
||||
ORDER BY wpml.created_at DESC, wpml.id DESC
|
||||
LIMIT $1
|
||||
`,
|
||||
[Math.min(500, Math.max(1, Math.floor(Number(limit) || 100)))],
|
||||
)
|
||||
return result.rows
|
||||
}
|
||||
@@ -160,6 +160,42 @@ export type WorkProductRuleRow = {
|
||||
category_name?: string
|
||||
}
|
||||
|
||||
export type WorkProductRuleMappingRow = {
|
||||
id: number
|
||||
rule_id: number
|
||||
seller_ids_json: string | string[]
|
||||
rel_item_id: string
|
||||
item_title: string
|
||||
rel_sku_id: string
|
||||
sku_nick: string
|
||||
mapping_type: 'product_default' | 'sku_exact' | 'sku_series' | string
|
||||
enabled: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
rule_key?: string
|
||||
product_name?: string
|
||||
}
|
||||
|
||||
export type WorkProductMatchLogRow = {
|
||||
id: number
|
||||
order_id: number | null
|
||||
order_item_id: number | null
|
||||
source: string
|
||||
seller_id: string
|
||||
rel_item_id: string
|
||||
item_title: string
|
||||
rel_sku_id: string
|
||||
sku_nick: string
|
||||
match_status: 'matched' | 'unmatched' | 'ambiguous' | string
|
||||
rule_id: number | null
|
||||
mapping_id: number | null
|
||||
candidates_json: string | Record<string, unknown> | unknown[]
|
||||
raw_payload_json: string | Record<string, unknown>
|
||||
created_at: string
|
||||
rule_key?: string
|
||||
product_name?: string
|
||||
}
|
||||
|
||||
export type WorkOrderShareRow = {
|
||||
id: number
|
||||
work_order_id: number
|
||||
|
||||
Reference in New Issue
Block a user