feat(supply-chain): 同款编码重复映射取创建时间最新的一条

This commit is contained in:
居居 2026-09-29 16:47:06 +08:00
parent 9f89ccbb7e
commit 7838b82655
2 changed files with 16 additions and 11 deletions

View File

@ -3,13 +3,15 @@ import { prisma } from '@/lib/prisma'
export type ProductArchiveReplacementRule = {
sku: string
replaceSku: string
sourceCreatedAt: string | null
sourceId: number
}
// 简尚「替换款管理」换货规则:sku = 原编码(老),replaceSku = 替换编码(新)。
export async function listProductArchiveReplacementRules(): Promise<ProductArchiveReplacementRule[]> {
try {
return await prisma.$queryRaw<ProductArchiveReplacementRule[]>`
SELECT sku, "replaceSku"
SELECT sku, "replaceSku", "sourceCreatedAt"::text AS "sourceCreatedAt", "sourceId"
FROM "SupplyChainProductArchiveReplacementRule"
WHERE "replaceSku" <> ''
ORDER BY "sourceCreatedAt" ASC NULLS LAST, "sourceId" ASC

View File

@ -135,21 +135,24 @@ function normalizeCode(value: string) {
return String(value ?? '').trim().toUpperCase()
}
// 同款商品编码(业绩&费比合并计算)规则:新编码承接老编码业绩;一个老编码对应多个新编码或形成替换链时暂不合并。
function buildReplacementIndex(rules: Array<{ sku: string; replaceSku: string }>): ReplacementIndex {
const oldToNews = new Map<string, Set<string>>()
// 同款商品编码(业绩&费比合并计算)规则:新编码承接老编码业绩;
// 同一老编码有多条规则时取创建时间(sourceCreatedAt)最新的一条;替换链(A→B 且 B→C)暂不合并。
function buildReplacementIndex(rules: Array<{ sku: string; replaceSku: string; sourceCreatedAt?: string | null; sourceId?: number }>): ReplacementIndex {
const latestByOld = new Map<string, { newCode: string; at: string; sourceId: number }>()
for (const rule of rules) {
const oldCode = normalizeCode(rule.sku)
const newCode = normalizeCode(rule.replaceSku)
if (!oldCode || !newCode || oldCode === newCode) continue
const set = oldToNews.get(oldCode) ?? new Set<string>()
set.add(newCode)
oldToNews.set(oldCode, set)
}
const oldToNew = new Map<string, string>()
for (const [oldCode, news] of oldToNews) {
if (news.size === 1) oldToNew.set(oldCode, [...news][0])
const at = String(rule.sourceCreatedAt ?? '')
const sourceId = Number(rule.sourceId ?? 0)
const current = latestByOld.get(oldCode)
if (!current || at > current.at || (at === current.at && sourceId >= current.sourceId)) {
latestByOld.set(oldCode, { newCode, at, sourceId })
}
}
const oldToNew = new Map<string, string>(
[...latestByOld.entries()].map(([oldCode, value]) => [oldCode, value.newCode]),
)
for (const [oldCode, newCode] of [...oldToNew]) {
if (oldToNew.has(newCode)) oldToNew.delete(oldCode)
}