fix(supply-chain): 产品全量档案 DF 条码成本价改为统一取 jst_sku.cost_price
- enrichment 价格补丁不再区分 DF/非 DF:purchasePrice 与 costPrice 均取 rpt.jst_sku(purchase_price / cost_price) - 删除 dws_sn_sales_full_info_di.goods_cost 取价链路(dws-sales-goods-cost.repository.ts 整删,DWS_SALES_GOODS_COST 来源常量移除) - 单测与《供应链产品全量档案字段来源对照表》同步更新 预期效果(部署后下一轮同步):约 1874 条 DF 成本价由空变有值、约 230 条由 dws 金额口径变为 jst 单价口径、约 4516 条数值不变、0 条丢值。
This commit is contained in:
parent
4bd48d8bc0
commit
77c91bd689
@ -1,6 +1,6 @@
|
||||
# 供应链产品全量档案字段来源对照表
|
||||
|
||||
更新时间:2026-08-10
|
||||
更新时间:2026-10-16
|
||||
|
||||
## 1. 合并与追踪规则
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
| `sales7d` | 7日日销 | | | `rpt.pm_stockMonitor.sevenAvgSale` | 按条码匹配最新记录 |
|
||||
| `sales15d` | 15日日销 | | | `rpt.pm_stockMonitor.fifteenAvgSale` | 按条码匹配最新记录 |
|
||||
| `purchasePrice` | 采购价 | `rpt.jst_sku.purchase_price` | | | 按档案条码精确匹配 `jst_sku.sku_id`;匹配不到时留空 |
|
||||
| `costPrice` | 成本价(聚水潭) | `rpt.jst_sku.cost_price` | | | 按档案条码精确匹配 `jst_sku.sku_id`;匹配不到时留空 |
|
||||
| `costPrice` | 成本价(聚水潭) | `rpt.jst_sku.cost_price` | | | 按档案条码精确匹配 `jst_sku.sku_id`;匹配不到时留空。DF 条码自 2026-10-16 起同样取本来源(原 `rpt.dws_sn_sales_full_info_di.goods_cost` 为金额口径,已停用) |
|
||||
| `costPriceSecondary` | 成本价(新品) | | `external.product_catalog_wide_v1.cost_price` | | 按档案条码精确匹配 `barcode_business_key`,只读取 `catalog_source = INTAKE_READY` 的新品行;匹配不到或来源为空时留空 |
|
||||
|
||||
## 3. JST_SKU 第一批字段覆盖率
|
||||
|
||||
@ -13,7 +13,6 @@ export const JST_FACTORY_STOCK_ARCHIVE_SOURCE_CODE = 'JST_FACTORY_STOCK'
|
||||
export const SUPPLY_CHAIN_OWNER_CONFIG_ARCHIVE_SOURCE_CODE = 'SUPPLY_CHAIN_OWNER_CONFIG'
|
||||
export const INTAKE_PROFILE_ARCHIVE_SOURCE_CODE = 'INTAKE_NON_INTEGRATED_PROFILE'
|
||||
export const JST_SKUMAP_PIC_ARCHIVE_SOURCE_CODE = 'JST_SKUMAP_PIC'
|
||||
export const DWS_SALES_GOODS_COST_ARCHIVE_SOURCE_CODE = 'DWS_SALES_GOODS_COST'
|
||||
export const DWS_SALES_OPS_ARCHIVE_SOURCE_CODE = 'DWS_SALES_OPS'
|
||||
export const JST_PUBLIC_AVAILABLE_STOCK_ARCHIVE_SOURCE_CODE = 'JST_PUBLIC_AVAILABLE_STOCK'
|
||||
export const JST_WAREHOUSE_ARCHIVE_SOURCE_CODE = 'JST_WAREHOUSE_INFO'
|
||||
|
||||
@ -1,139 +0,0 @@
|
||||
import sql from 'mssql'
|
||||
|
||||
export type DwsSalesGoodsCostProfile = {
|
||||
skuoid: string
|
||||
goodsCost: string
|
||||
}
|
||||
|
||||
export type DwsSalesOpsOwnerProfile = {
|
||||
skuoid: string
|
||||
cater: string
|
||||
ider: string
|
||||
lastSaleDate: string
|
||||
}
|
||||
|
||||
export interface DwsSalesGoodsCostRepository {
|
||||
listDfLatestGoodsCost(): Promise<DwsSalesGoodsCostProfile[]>
|
||||
listLatestOpsOwners(): Promise<DwsSalesOpsOwnerProfile[]>
|
||||
close(): Promise<void>
|
||||
}
|
||||
|
||||
function requiredEnv(name: string) {
|
||||
const value = process.env[name]?.trim()
|
||||
if (!value) throw new Error(`Missing required environment variable: ${name}`)
|
||||
return value
|
||||
}
|
||||
|
||||
function booleanEnv(name: string, fallback: boolean) {
|
||||
const value = process.env[name]?.trim().toLowerCase()
|
||||
if (!value) return fallback
|
||||
return value === 'true' || value === '1'
|
||||
}
|
||||
|
||||
function safeIdentifier(value: string, label: string) {
|
||||
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
||||
throw new Error(`${label} is not a valid SQL Server identifier`)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
class DwsSalesGoodsCostRepositoryClass implements DwsSalesGoodsCostRepository {
|
||||
private pool: sql.ConnectionPool | null = null
|
||||
|
||||
private async getPool() {
|
||||
if (this.pool?.connected) return this.pool
|
||||
|
||||
this.pool = await new sql.ConnectionPool({
|
||||
server: requiredEnv('JST_REPORT_DB_HOST'),
|
||||
port: Number(process.env.JST_REPORT_DB_PORT?.trim() || '1433'),
|
||||
database: requiredEnv('JST_REPORT_DB_NAME'),
|
||||
user: requiredEnv('JST_REPORT_DB_USER'),
|
||||
password: requiredEnv('JST_REPORT_DB_PASSWORD'),
|
||||
options: {
|
||||
encrypt: booleanEnv('JST_REPORT_DB_ENCRYPT', true),
|
||||
trustServerCertificate: booleanEnv(
|
||||
'JST_REPORT_DB_TRUST_SERVER_CERTIFICATE',
|
||||
true,
|
||||
),
|
||||
},
|
||||
pool: {
|
||||
min: 0,
|
||||
max: 4,
|
||||
idleTimeoutMillis: 30_000,
|
||||
},
|
||||
requestTimeout: 120_000,
|
||||
connectionTimeout: 20_000,
|
||||
}).connect()
|
||||
return this.pool
|
||||
}
|
||||
|
||||
// Latest non-zero sales goods_cost per DF (dropship) skuoid. One row per
|
||||
// skuoid, keyed the same way the archive barcode is stored (DF-xxx).
|
||||
async listDfLatestGoodsCost() {
|
||||
const schema = safeIdentifier(
|
||||
process.env.JST_REPORT_DB_SCHEMA?.trim() || 'rpt',
|
||||
'JST_REPORT_DB_SCHEMA',
|
||||
)
|
||||
const pool = await this.getPool()
|
||||
const result = await pool.request().query<DwsSalesGoodsCostProfile>(`
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200))))) AS skuoid,
|
||||
LTRIM(RTRIM(CAST(goods_cost AS varchar(50)))) AS goodsCost,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200)))))
|
||||
ORDER BY stat_date DESC
|
||||
) AS rn
|
||||
FROM [${schema}].[dws_sn_sales_full_info_di]
|
||||
WHERE UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200))))) LIKE 'DF%'
|
||||
AND goods_cost IS NOT NULL AND goods_cost <> 0
|
||||
)
|
||||
SELECT skuoid, goodsCost
|
||||
FROM ranked
|
||||
WHERE rn = 1
|
||||
`)
|
||||
return result.recordset
|
||||
}
|
||||
|
||||
// Latest non-empty ops owners per skuoid (all barcodes, not only DF).
|
||||
// One row per skuoid from the newest stat_date; cater/ider are returned
|
||||
// as-is and the mapper decides per field whether to overwrite.
|
||||
async listLatestOpsOwners() {
|
||||
const schema = safeIdentifier(
|
||||
process.env.JST_REPORT_DB_SCHEMA?.trim() || 'rpt',
|
||||
'JST_REPORT_DB_SCHEMA',
|
||||
)
|
||||
const pool = await this.getPool()
|
||||
const result = await pool.request().query<DwsSalesOpsOwnerProfile>(`
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200))))) AS skuoid,
|
||||
LTRIM(RTRIM(CAST(cater AS varchar(100)))) AS cater,
|
||||
LTRIM(RTRIM(CAST(ider AS varchar(100)))) AS ider,
|
||||
CAST(MAX(stat_date) AS date) AS last_sale_date,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200)))))
|
||||
ORDER BY stat_date DESC
|
||||
) AS rn
|
||||
FROM [${schema}].[dws_sn_sales_full_info_di]
|
||||
WHERE skuoid IS NOT NULL
|
||||
AND LTRIM(RTRIM(CAST(skuoid AS varchar(200)))) <> ''
|
||||
AND ((cater IS NOT NULL AND LTRIM(RTRIM(CAST(cater AS varchar(100)))) <> '')
|
||||
OR (ider IS NOT NULL AND LTRIM(RTRIM(CAST(ider AS varchar(100)))) <> ''))
|
||||
GROUP BY UPPER(LTRIM(RTRIM(CAST(skuoid AS varchar(200))))), LTRIM(RTRIM(CAST(cater AS varchar(100)))), LTRIM(RTRIM(CAST(ider AS varchar(100)))), stat_date
|
||||
)
|
||||
SELECT skuoid, cater, ider, CONVERT(varchar(10), last_sale_date, 23) AS lastSaleDate
|
||||
FROM ranked
|
||||
WHERE rn = 1
|
||||
`)
|
||||
return result.recordset
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (!this.pool) return
|
||||
await this.pool.close()
|
||||
this.pool = null
|
||||
}
|
||||
}
|
||||
|
||||
export const dwsSalesGoodsCostRepository = new DwsSalesGoodsCostRepositoryClass()
|
||||
@ -23,9 +23,6 @@ jest.mock('@/server/repositories/supply-chain-product-archive-enrichment-sync.re
|
||||
jest.mock('@/server/repositories/supply-chain-product-archive-clearance-stock.repository', () => ({
|
||||
productArchiveClearanceStockRepository: {},
|
||||
}))
|
||||
jest.mock('@/server/repositories/dws-sales-goods-cost.repository', () => ({
|
||||
dwsSalesGoodsCostRepository: {},
|
||||
}))
|
||||
jest.mock('@/server/repositories/jst-skumap-pic.repository', () => ({
|
||||
jstSkumapPicRepository: {},
|
||||
}))
|
||||
@ -59,7 +56,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -84,7 +80,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
{ barcode: 'DF-A3BJ006601', purchasePrice: '', costPrice: '' },
|
||||
{ barcode: 'BAR-001', purchasePrice: '90.00', costPrice: '76.20' },
|
||||
],
|
||||
dwsGoodsCosts: [{ skuoid: 'DF-A3BJ006601', goodsCost: '70.18' }],
|
||||
skumapPics: [{ skuId: 'DF-A3BJ006601', pic: 'https://img.pddpic.com/mms-material-img/df.jpg' }],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -158,7 +153,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [{ skuId: 'BAR-001', pic: 'https://img.example.com/bar-001.jpg' }],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -215,7 +209,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map([['BJ0220', '萧何']]),
|
||||
@ -259,7 +252,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map([['BJ0220', '萧何']]),
|
||||
@ -294,7 +286,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -358,7 +349,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -403,7 +393,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [],
|
||||
dwsGoodsCosts: [],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -435,7 +424,7 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
expect(hierarchyUpdate?.patch).toEqual({ opsDeptHead: '半夏', opsDirector: '江陵' })
|
||||
})
|
||||
|
||||
it('takes dropship (DF) cost from the sales goods_cost source and keeps jst_sku cost for others', () => {
|
||||
it('takes cost from jst_sku.cost_price for dropship (DF) and normal barcodes alike', () => {
|
||||
const lookups = {
|
||||
clearanceStocks: [],
|
||||
publicAvailableStocks: [],
|
||||
@ -443,10 +432,9 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
stocks: [],
|
||||
warehouses: [],
|
||||
prices: [
|
||||
{ barcode: 'DF-A3BJ006601', purchasePrice: '', costPrice: '' },
|
||||
{ barcode: 'DF-A3BJ006601', purchasePrice: '80.00', costPrice: '70.18' },
|
||||
{ barcode: 'BAR-001', purchasePrice: '90.00', costPrice: '76.20' },
|
||||
],
|
||||
dwsGoodsCosts: [{ skuoid: 'DF-A3BJ006601', goodsCost: '70.18' }],
|
||||
skumapPics: [],
|
||||
skumapFillPics: [],
|
||||
intakeSpuOwners: new Map(),
|
||||
@ -468,21 +456,18 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
},
|
||||
lookups,
|
||||
)
|
||||
const dfPriceUpdate = dfUpdates.find((update) => 'purchasePrice' in update.patch)
|
||||
const dfCostUpdate = dfUpdates.find((update) => 'costPrice' in update.patch)
|
||||
expect(dfPriceUpdate?.patch).toEqual({ purchasePrice: '' })
|
||||
expect(dfPriceUpdate?.source.sourceCode).toBe('JST_SKU_PRICE')
|
||||
expect(dfCostUpdate?.patch).toEqual({ costPrice: '70.18' })
|
||||
expect(dfCostUpdate?.source).toEqual(
|
||||
const dfPriceUpdate = dfUpdates.find((update) => 'costPrice' in update.patch)
|
||||
expect(dfPriceUpdate?.patch).toEqual({ purchasePrice: '80.00', costPrice: '70.18' })
|
||||
expect(dfPriceUpdate?.source).toEqual(
|
||||
expect.objectContaining({
|
||||
sourceCode: 'DWS_SALES_GOODS_COST',
|
||||
sourceObject: 'dws_sn_sales_full_info_di',
|
||||
sourceColumns: { costPrice: 'goods_cost' },
|
||||
sourceCode: 'JST_SKU_PRICE',
|
||||
sourceObject: 'jst_sku',
|
||||
sourceColumns: { purchasePrice: 'purchase_price', costPrice: 'cost_price' },
|
||||
}),
|
||||
)
|
||||
|
||||
// without sales cost the DF cost is cleared instead of falling back to jst_sku
|
||||
const dfWithoutSales = buildProductArchiveEnrichmentUpdates(
|
||||
// DF without a jst_sku price row clears both price fields (no dws fallback anymore)
|
||||
const dfWithoutJst = buildProductArchiveEnrichmentUpdates(
|
||||
{
|
||||
id: 'archive-df-2',
|
||||
barcode: 'DF-A3BJ006602',
|
||||
@ -492,11 +477,11 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
inOutWarehouse: '',
|
||||
image: '',
|
||||
},
|
||||
{ ...lookups, dwsGoodsCosts: [] },
|
||||
lookups,
|
||||
)
|
||||
const clearedCost = dfWithoutSales.find((update) => 'costPrice' in update.patch)
|
||||
expect(clearedCost?.patch).toEqual({ costPrice: '' })
|
||||
expect(clearedCost?.source.sourceCode).toBe('DWS_SALES_GOODS_COST')
|
||||
const clearedCost = dfWithoutJst.find((update) => 'costPrice' in update.patch)
|
||||
expect(clearedCost?.patch).toEqual({ purchasePrice: '', costPrice: '' })
|
||||
expect(clearedCost?.source.sourceCode).toBe('JST_SKU_PRICE')
|
||||
|
||||
// non-DF keeps the jst_sku price source untouched
|
||||
const barUpdates = buildProductArchiveEnrichmentUpdates(
|
||||
@ -514,7 +499,7 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
const barPriceUpdate = barUpdates.find((update) => 'costPrice' in update.patch)
|
||||
expect(barPriceUpdate?.patch).toEqual({ purchasePrice: '90.00', costPrice: '76.20' })
|
||||
expect(barPriceUpdate?.source.sourceCode).toBe('JST_SKU_PRICE')
|
||||
expect(barUpdates.some((update) => update.source.sourceCode === 'DWS_SALES_GOODS_COST')).toBe(false)
|
||||
expect(barUpdates.every((update) => update.source.sourceCode !== 'DWS_SALES_GOODS_COST')).toBe(true)
|
||||
})
|
||||
|
||||
it('persists every external group and logs only later value changes', async () => {
|
||||
@ -623,16 +608,6 @@ describe('supply-chain product archive enrichment sync', () => {
|
||||
}
|
||||
const service = new SupplyChainProductArchiveEnrichmentSyncService({
|
||||
clearanceStockRepository,
|
||||
dwsGoodsCostRepository: {
|
||||
listDfLatestGoodsCost: jest.fn().mockResolvedValue([]),
|
||||
listLatestOpsOwners: jest.fn().mockResolvedValue([{
|
||||
skuoid: 'BAR-001',
|
||||
cater: '李逍遥',
|
||||
ider: '丹参',
|
||||
lastSaleDate: '2026-09-01',
|
||||
}]),
|
||||
close: jest.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
skumapPicRepository: {
|
||||
listDfLatestSkuPics: jest.fn().mockResolvedValue([]),
|
||||
listLatestSkuPicsForBarcodes: jest.fn().mockResolvedValue([]),
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
DWS_SALES_GOODS_COST_ARCHIVE_SOURCE_CODE,
|
||||
JST_CLEARANCE_STOCK_ARCHIVE_SOURCE_CODE,
|
||||
JST_FACTORY_STOCK_ARCHIVE_SOURCE_CODE,
|
||||
JST_PUBLIC_AVAILABLE_STOCK_ARCHIVE_SOURCE_CODE,
|
||||
@ -14,7 +13,6 @@ import {
|
||||
WAREHOUSE_CONFIG_ARCHIVE_SOURCE_CODE,
|
||||
} from '@/lib/supply-chain-product-archive-field-source'
|
||||
import type { ProductArchiveClearanceStockProfile } from '@/server/repositories/supply-chain-product-archive-clearance-stock.repository'
|
||||
import type { DwsSalesGoodsCostProfile } from '@/server/repositories/dws-sales-goods-cost.repository'
|
||||
import type { JstSkumapPicProfile } from '@/server/repositories/jst-skumap-pic.repository'
|
||||
import type { JstInventoryPublicAvailableProfile } from '@/server/repositories/jst-inventory-public-available.repository'
|
||||
import type { JstSkuPriceProfile } from '@/server/repositories/jst-sku-price.repository'
|
||||
@ -49,7 +47,6 @@ export type ProductArchiveEnrichmentLookups = {
|
||||
stocks: readonly JstStockMonitorProfile[]
|
||||
warehouses: readonly JstWarehouseProfile[]
|
||||
prices: readonly JstSkuPriceProfile[]
|
||||
dwsGoodsCosts: readonly DwsSalesGoodsCostProfile[]
|
||||
skumapPics: readonly JstSkumapPicProfile[]
|
||||
skumapFillPics: readonly JstSkumapPicProfile[]
|
||||
intakeSpuOwners: ReadonlyMap<string, string>
|
||||
@ -145,12 +142,9 @@ export function buildProductArchiveEnrichmentUpdates(
|
||||
const publicAvailableStock = lookups.publicAvailableStocks.find(
|
||||
(profile) => normalizeIdentity(profile.barcode) === normalizeIdentity(target.barcode),
|
||||
)
|
||||
// Dropship (DF-prefixed) SKUs take their cost from the sales detail table's
|
||||
// goods_cost instead of jst_sku, per the agreed data contract.
|
||||
// 成本价自 2026-10-16 起 DF 条码与普通条码统一取 jst_sku.cost_price
|
||||
// (原 dws_sn_sales_full_info_di.goods_cost 为金额口径,停用)。
|
||||
const isDropshipSku = normalizeIdentity(target.barcode).startsWith('DF')
|
||||
const dwsGoodsCost = lookups.dwsGoodsCosts.find(
|
||||
(profile) => normalizeIdentity(profile.skuoid) === normalizeIdentity(target.barcode),
|
||||
)
|
||||
// Dropship SKUs take their picture from the skumap platform tables as well.
|
||||
const skumapPic = isDropshipSku
|
||||
? lookups.skumapPics.find(
|
||||
@ -403,51 +397,20 @@ export function buildProductArchiveEnrichmentUpdates(
|
||||
),
|
||||
},
|
||||
] : []),
|
||||
...(isDropshipSku
|
||||
? [
|
||||
{
|
||||
patch: {
|
||||
purchasePrice: price?.purchasePrice ?? '',
|
||||
},
|
||||
source: source(
|
||||
JST_SKU_PRICE_ARCHIVE_SOURCE_CODE,
|
||||
JST_SOURCE_SYSTEM,
|
||||
JST_SOURCE_SCHEMA,
|
||||
'jst_sku',
|
||||
price?.barcode || target.barcode,
|
||||
{ purchasePrice: 'purchase_price' },
|
||||
),
|
||||
},
|
||||
{
|
||||
patch: {
|
||||
costPrice: dwsGoodsCost?.goodsCost ?? '',
|
||||
},
|
||||
source: source(
|
||||
DWS_SALES_GOODS_COST_ARCHIVE_SOURCE_CODE,
|
||||
JST_SOURCE_SYSTEM,
|
||||
JST_SOURCE_SCHEMA,
|
||||
'dws_sn_sales_full_info_di',
|
||||
dwsGoodsCost?.skuoid || target.barcode,
|
||||
{ costPrice: 'goods_cost' },
|
||||
),
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
patch: {
|
||||
purchasePrice: price?.purchasePrice ?? '',
|
||||
costPrice: price?.costPrice ?? '',
|
||||
},
|
||||
source: source(
|
||||
JST_SKU_PRICE_ARCHIVE_SOURCE_CODE,
|
||||
JST_SOURCE_SYSTEM,
|
||||
JST_SOURCE_SCHEMA,
|
||||
'jst_sku',
|
||||
price?.barcode || target.barcode,
|
||||
{ purchasePrice: 'purchase_price', costPrice: 'cost_price' },
|
||||
),
|
||||
},
|
||||
]),
|
||||
{
|
||||
patch: {
|
||||
purchasePrice: price?.purchasePrice ?? '',
|
||||
costPrice: price?.costPrice ?? '',
|
||||
},
|
||||
source: source(
|
||||
JST_SKU_PRICE_ARCHIVE_SOURCE_CODE,
|
||||
JST_SOURCE_SYSTEM,
|
||||
JST_SOURCE_SCHEMA,
|
||||
'jst_sku',
|
||||
price?.barcode || target.barcode,
|
||||
{ purchasePrice: 'purchase_price', costPrice: 'cost_price' },
|
||||
),
|
||||
},
|
||||
{
|
||||
patch: { costPriceSecondary: catalogCost?.costPrice ?? '' },
|
||||
source: source(
|
||||
|
||||
@ -2,10 +2,6 @@ import {
|
||||
productArchiveClearanceStockRepository,
|
||||
type ProductArchiveClearanceStockRepository,
|
||||
} from '@/server/repositories/supply-chain-product-archive-clearance-stock.repository'
|
||||
import {
|
||||
dwsSalesGoodsCostRepository,
|
||||
type DwsSalesGoodsCostRepository,
|
||||
} from '@/server/repositories/dws-sales-goods-cost.repository'
|
||||
import {
|
||||
jstSkumapPicRepository,
|
||||
type JstSkumapPicRepository,
|
||||
@ -63,10 +59,6 @@ type EnrichmentDependencies = {
|
||||
ProductArchiveClearanceStockRepository,
|
||||
'listByBarcodes' | 'close'
|
||||
>
|
||||
dwsGoodsCostRepository: Pick<
|
||||
DwsSalesGoodsCostRepository,
|
||||
'listDfLatestGoodsCost' | 'close'
|
||||
>
|
||||
skumapPicRepository: Pick<
|
||||
JstSkumapPicRepository,
|
||||
'listDfLatestSkuPics' | 'listLatestSkuPicsForBarcodes' | 'close'
|
||||
@ -99,7 +91,6 @@ export class SupplyChainProductArchiveEnrichmentSyncService {
|
||||
constructor(
|
||||
private readonly dependencies: EnrichmentDependencies = {
|
||||
clearanceStockRepository: productArchiveClearanceStockRepository,
|
||||
dwsGoodsCostRepository: dwsSalesGoodsCostRepository,
|
||||
skumapPicRepository: jstSkumapPicRepository,
|
||||
publicAvailableStockRepository: jstInventoryPublicAvailableRepository,
|
||||
repository: supplyChainProductArchiveEnrichmentSyncRepository,
|
||||
@ -124,8 +115,6 @@ export class SupplyChainProductArchiveEnrichmentSyncService {
|
||||
lastId: '',
|
||||
}
|
||||
const warehouseConfigs = await this.dependencies.configRepository.listActive()
|
||||
// One shot: latest non-zero sales goods_cost for every DF skuoid.
|
||||
const dwsGoodsCosts = await this.dependencies.dwsGoodsCostRepository.listDfLatestGoodsCost()
|
||||
// One shot: latest platform picture for every DF skuoid.
|
||||
const skumapPics = await this.dependencies.skumapPicRepository.listDfLatestSkuPics()
|
||||
// 运营负责人(opsHead)自 2026-10 起为一次性定标冻结口径,enrichment 不再
|
||||
@ -209,7 +198,6 @@ export class SupplyChainProductArchiveEnrichmentSyncService {
|
||||
stocks,
|
||||
warehouses,
|
||||
prices,
|
||||
dwsGoodsCosts,
|
||||
skumapPics,
|
||||
skumapFillPics,
|
||||
intakeSpuOwners,
|
||||
@ -256,7 +244,6 @@ export class SupplyChainProductArchiveEnrichmentSyncService {
|
||||
} finally {
|
||||
await Promise.all([
|
||||
this.dependencies.clearanceStockRepository.close(),
|
||||
this.dependencies.dwsGoodsCostRepository.close(),
|
||||
this.dependencies.skumapPicRepository.close(),
|
||||
this.dependencies.publicAvailableStockRepository.close(),
|
||||
this.dependencies.supplierRepository.close(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user