fix(supply-chain): 仓库管理列表只取聚水潭仓库档案,档案历史名称不再补充展示

This commit is contained in:
WuYongJie 2026-10-16 14:00:12 +08:00
parent bb19f46301
commit 2965742bbc
2 changed files with 73 additions and 50 deletions

View File

@ -29,7 +29,7 @@ function jstWarehouse(
name: string
wmsCoId: number | null
isMain: boolean
attribute: string | null
attribute?: string | null
createdAt?: string | null
updatedAt?: string | null
status?: string | null
@ -54,10 +54,6 @@ function repository(
}
}
function jstWarehouse(records: Array<{ name: string; wmsCoId: number | null; isMain: boolean; status?: string | null }> = []) {
return { listWarehouses: jest.fn().mockResolvedValue(records) }
}
describe('SupplyChainProductArchiveWarehouseConfigService', () => {
it('infers ownership from the storage type and the warehouse name', () => {
// 名称含「工厂-」「配件-」→ 工厂
@ -70,39 +66,48 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
expect(inferProductArchiveWarehouseOwnership('横林二仓')).toBe('JIANSHANG')
})
it('combines archive warehouse names with saved configurations', async () => {
it('lists only warehouses that exist in the jst warehouse master', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['杭州仓', '上海仓'],
warehouseNames: ['上海仓', '北京仓'],
configurations: [configuration()],
}), jstWarehouse())
}), jstWarehouse([
{ name: '杭州仓', wmsCoId: 11, isMain: false },
]))
const result = await service.list({})
expect(result.items).toEqual([
expect.objectContaining({
id: null,
warehouseName: '上海仓',
// 未配置的仓库按名称给默认值:不含「代发」= 入库
storageType: 'INBOUND',
status: null,
configured: false,
}),
expect.objectContaining({
id: 'config-1',
warehouseName: '杭州仓',
storageType: 'INBOUND',
status: 'ACTIVE',
configured: true,
}),
])
// 档案历史名称与配置表里聚水潭查无此仓的条目都不展示。
expect(result.items.map((item) => item.warehouseName)).toEqual(['杭州仓'])
expect(result.items[0]).toEqual(expect.objectContaining({
id: 'config-1',
warehouseName: '杭州仓',
storageType: 'INBOUND',
status: 'ACTIVE',
configured: true,
}))
expect(result.pageInfo.total).toBe(1)
})
it('falls back to archive warehouse names when the jst master read fails', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['上海仓'],
configurations: [configuration()],
}), { listWarehouses: jest.fn().mockRejectedValue(new Error('source down')) })
const result = await service.list({})
// 聚水潭读取失败时降级为旧行为:档案历史名称兜底,配置照常展示,避免整页空白。
expect(result.items.map((item) => item.warehouseName)).toEqual(['上海仓', '杭州仓'])
expect(result.pageInfo.total).toBe(2)
})
it('matches saved configurations to archive warehouses ignoring case and spaces', async () => {
it('matches saved configurations to jst warehouses ignoring case and spaces', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: [' HangZhou '],
warehouseNames: ['历史仓'],
configurations: [configuration({ warehouseName: 'hangzhou' })],
}), jstWarehouse())
}), jstWarehouse([
{ name: ' HangZhou ', wmsCoId: 11, isMain: false },
]))
const result = await service.list({})
@ -111,14 +116,19 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
id: 'config-1',
warehouseName: 'hangzhou',
configured: true,
}), jstWarehouse())
wmsCoId: 11,
}))
})
it('can filter to unconfigured warehouse names before pagination', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['杭州仓', '上海仓', '北京仓'],
warehouseNames: ['历史仓'],
configurations: [configuration()],
}), jstWarehouse())
}), jstWarehouse([
{ name: '杭州仓', wmsCoId: 11, isMain: false },
{ name: '上海仓', wmsCoId: 22, isMain: false },
{ name: '北京仓', wmsCoId: 33, isMain: false },
]))
const result = await service.list({ status: 'UNCONFIGURED', page: 1, pageSize: 1 })
@ -129,9 +139,12 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
it('filters by config status codes and source status text together', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['杭州仓', '上海仓'],
warehouseNames: [],
configurations: [configuration({ status: 'INACTIVE' })],
}), jstWarehouse())
}), jstWarehouse([
{ name: '杭州仓', wmsCoId: 11, isMain: false },
{ name: '上海仓', wmsCoId: 22, isMain: false },
]))
// 配置状态多选:表头下拉的 启用/停用/未配置 走这一支。
expect((await service.list({ statuses: ['ACTIVE'] })).items).toHaveLength(0)
@ -145,9 +158,12 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
it('shows inferred ownership for unconfigured warehouse rows', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['工厂-常州仓', '横林二仓'],
warehouseNames: [],
configurations: [],
}), jstWarehouse())
}), jstWarehouse([
{ name: '工厂-常州仓', wmsCoId: 11, isMain: false },
{ name: '横林二仓', wmsCoId: 22, isMain: false },
]))
const result = await service.list({})
@ -162,9 +178,12 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
it('defaults the inbound/dropship flag from the warehouse name', async () => {
const service = new SupplyChainProductArchiveWarehouseConfigService(repository({
warehouseNames: ['工厂-常州博一代发仓', '简尚-横林三仓'],
warehouseNames: [],
configurations: [],
}), jstWarehouse())
}), jstWarehouse([
{ name: '工厂-常州博一代发仓', wmsCoId: 11, isMain: false },
{ name: '简尚-横林三仓', wmsCoId: 22, isMain: false },
]))
const result = await service.list({})
const byName = new Map(result.items.map((item) => [item.warehouseName, item]))
@ -217,6 +236,7 @@ describe('SupplyChainProductArchiveWarehouseConfigService', () => {
},
jstWarehouse([
{ name: '工厂-常州博一代发仓', wmsCoId: 1, isMain: false, attribute: null },
{ name: '杭州仓', wmsCoId: 2, isMain: false, attribute: null },
]),
)

View File

@ -243,15 +243,15 @@ export class SupplyChainProductArchiveWarehouseConfigService {
) {}
/**
* 仓库名称以聚水潭仓库档案(jst_warehouseInfo.name)为准,
* 读取失败时不阻断页面,退回到产品档案里的仓库名。
* 仓库名称只取聚水潭仓库档案(jst_warehouseInfo.name)。
* 读取失败时返回 null:调用方降级为产品档案历史名称兜底,避免数据源抖动把整页清空。
*/
private async loadJstWarehouses(): Promise<JstWarehouseRecord[]> {
private async loadJstWarehouses(): Promise<JstWarehouseRecord[] | null> {
try {
return await this.jstWarehouse.listWarehouses()
} catch (cause) {
console.error('[warehouse-config] jst warehouse read failed', cause)
return []
return null
}
}
@ -262,7 +262,7 @@ export class SupplyChainProductArchiveWarehouseConfigService {
async refreshWarehouseSource() {
this.jstWarehouse.invalidateCache()
const warehouses = await this.loadJstWarehouses()
return { warehouseCount: warehouses.length }
return { warehouseCount: (warehouses ?? []).length }
}
/** 产品档案的仓库→采购对照,用于工厂仓的默认负责人;读取失败不影响页面。 */
@ -324,7 +324,7 @@ export class SupplyChainProductArchiveWarehouseConfigService {
attribute: string | null
status: string | null
}>()
for (const warehouse of jstWarehouses) {
for (const warehouse of jstWarehouses ?? []) {
options.set(normalizeWarehouseName(warehouse.name), {
name: warehouse.name,
wmsCoId: warehouse.wmsCoId,
@ -386,7 +386,7 @@ export class SupplyChainProductArchiveWarehouseConfigService {
this.loadPurchaserByWarehouse(),
])
const jstWarehouseByName = new Map(
jstWarehouses.map((warehouse) => [normalizeWarehouseName(warehouse.name), warehouse]),
(jstWarehouses ?? []).map((warehouse) => [normalizeWarehouseName(warehouse.name), warehouse]),
)
const statuses = input.statuses ?? []
const ownerships = input.ownerships ?? []
@ -398,16 +398,19 @@ export class SupplyChainProductArchiveWarehouseConfigService {
const createdDates = input.createdDates ?? []
const updatedDates = input.updatedDates ?? []
const merged = new Map<string, WarehouseConfigDTO>()
// 仓库名称以聚水潭仓库档案为准,产品档案里的历史名称作为补充保留。
for (const warehouseName of [
...jstWarehouses.map((warehouse) => warehouse.name),
...result.warehouseNames,
]) {
// 仓库名称只取聚水潭仓库档案;产品档案里的历史名称聚水潭查无此仓,不再展示。
// 聚水潭读取失败时降级为档案历史名称兜底,避免数据源抖动把整页清空。
for (const warehouseName of jstWarehouses === null
? result.warehouseNames
: jstWarehouses.map((warehouse) => warehouse.name)) {
const key = normalizeWarehouseName(warehouseName)
if (key && !merged.has(key)) merged.set(key, mapUnconfigured(warehouseName))
}
for (const configuration of result.configurations) {
merged.set(normalizeWarehouseName(configuration.warehouseName), mapRecord(configuration))
const key = normalizeWarehouseName(configuration.warehouseName)
// 以聚水潭档案为基准时,配置表里聚水潭查无此仓的条目同样不展示。
if (jstWarehouses !== null && !jstWarehouseByName.has(key)) continue
merged.set(key, mapRecord(configuration))
}
// 仓库编号与仓库属性统一以聚水潭仓库档案为准,配置表里不重复存一份。
for (const [key, item] of merged) {