fix(supply-chain): 仅在品牌页按GBSFY归类
This commit is contained in:
parent
9915d7764b
commit
f00d686c76
@ -237,11 +237,13 @@ describe('限价管理', () => {
|
||||
|
||||
const bulkRequest = productRequests().at(-1) ?? ''
|
||||
expect(brandFilterOf(bulkRequest)).toEqual(['自有品牌-亿家达', '其他品牌-普通大货'])
|
||||
expect(JSON.parse(new URL(bulkRequest, 'http://localhost').searchParams.get('filters') ?? '{}').limitProductKind).toBe('bulk')
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '品牌商品' }))
|
||||
await waitFor(() => {
|
||||
const brandRequest = productRequests().at(-1) ?? ''
|
||||
expect(brandFilterOf(brandRequest)).toEqual(['代理品牌-顾家', '代理品牌-索菲亚', '自有品牌-朴美'])
|
||||
expect(JSON.parse(new URL(brandRequest, 'http://localhost').searchParams.get('filters') ?? '{}').limitProductKind).toBe('brand')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -206,6 +206,9 @@ export function LimitPriceTab({ userId, canExport = false }: { userId: string; c
|
||||
const effectiveFilters = useMemo(() => {
|
||||
const next: ProductArchiveFilters = { ...filters }
|
||||
const tabBrands = productKind === 'combo' ? [] : (brandPartition?.[productKind] ?? [])
|
||||
if (productKind === 'bulk' || productKind === 'brand') {
|
||||
next.limitProductKind = productKind
|
||||
}
|
||||
if (tabBrands.length) {
|
||||
const selected = filters.brand ?? []
|
||||
const intersection = selected.length
|
||||
|
||||
@ -195,6 +195,8 @@ export const PRODUCT_ARCHIVE_KEYWORD_FIELDS = ['barcode', 'spu', 'sku', 'product
|
||||
export type ProductArchiveKeywordField = typeof PRODUCT_ARCHIVE_KEYWORD_FIELDS[number]
|
||||
|
||||
export type ProductArchiveFilters = {
|
||||
/** 仅限价管理页签使用:品牌页额外纳入 GBSFY,大货页排除 GBSFY;不改档案品牌字段。 */
|
||||
limitProductKind?: 'bulk' | 'brand'
|
||||
salesGranularity?: 'day' | 'month' | 'year'
|
||||
salesPeriod?: string
|
||||
keyword?: string
|
||||
|
||||
@ -26,6 +26,25 @@ describe('supply-chain product archive query filters', () => {
|
||||
expect(sorted.map((row) => row.id)).toEqual(['high-new', 'high-old', 'low', 'none'])
|
||||
})
|
||||
|
||||
it('moves GBSFY into brand tab and excludes it from bulk without changing brand data', () => {
|
||||
const sofiaCodeClause = { sku: { startsWith: 'GBSFY', mode: 'insensitive' } }
|
||||
const brandWhere = buildProductArchiveWhere({
|
||||
brand: ['代理品牌-索菲亚'],
|
||||
limitProductKind: 'brand',
|
||||
})
|
||||
const bulkWhere = buildProductArchiveWhere({
|
||||
brand: ['其他品牌-普通大货'],
|
||||
limitProductKind: 'bulk',
|
||||
})
|
||||
|
||||
expect(brandWhere.AND).toEqual(expect.arrayContaining([
|
||||
{ OR: [{ brand: { in: ['代理品牌-索菲亚'] } }, sofiaCodeClause] },
|
||||
]))
|
||||
expect(bulkWhere.AND).toEqual(expect.arrayContaining([
|
||||
{ AND: [{ brand: { in: ['其他品牌-普通大货'] } }, { NOT: sofiaCodeClause }] },
|
||||
]))
|
||||
})
|
||||
|
||||
it('field permission limits keyword matches to visible fields', () => {
|
||||
const where = buildProductArchiveWhere(stripProductArchiveBlockedFilters(
|
||||
{ keyword: '机密供应商' }, new Set(['supplier', 'sku']),
|
||||
|
||||
@ -284,6 +284,19 @@ export function buildProductArchiveWhere(
|
||||
const emptyClause = includesEmpty
|
||||
? buildEmptyValueClause(databaseField)
|
||||
: null
|
||||
if (filterKey === 'brand' && filters.limitProductKind) {
|
||||
const brandClause = valueClause && emptyClause
|
||||
? { OR: [valueClause, emptyClause] }
|
||||
: valueClause || emptyClause
|
||||
if (!brandClause) continue
|
||||
const sofiaCodeClause = {
|
||||
sku: { startsWith: 'GBSFY', mode: 'insensitive' as const },
|
||||
}
|
||||
clauses.push(filters.limitProductKind === 'brand'
|
||||
? { OR: [brandClause, sofiaCodeClause] }
|
||||
: { AND: [brandClause, { NOT: sofiaCodeClause }] })
|
||||
continue
|
||||
}
|
||||
if (valueClause && emptyClause) {
|
||||
clauses.push({ OR: [valueClause, emptyClause] } as Prisma.SupplyChainProductArchiveWhereInput)
|
||||
} else if (valueClause || emptyClause) {
|
||||
|
||||
@ -4,7 +4,6 @@ import {
|
||||
PRODUCT_DEVELOPMENT_ARCHIVE_SOURCE_CODE,
|
||||
SupplyChainProductArchiveSyncService,
|
||||
mapProductCatalogWideArchiveSource,
|
||||
normalizeProductArchiveBrand,
|
||||
} from '../supply-chain-product-archive-sync.service'
|
||||
import {
|
||||
recordProductArchiveFieldChanges,
|
||||
@ -102,20 +101,6 @@ describe('supply-chain product archive wide-catalog sync', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('corrects mislabeled Sofia products from the GBSFY SKU prefix', () => {
|
||||
const mapped = mapProductCatalogWideArchiveSource({
|
||||
...createSourceRecord(),
|
||||
archive_spu: 'GBSFY-XG0293',
|
||||
archive_sku: 'GBSFY-XG029301',
|
||||
barcode_business_key: 'GBSFY-XG029301N1441V01',
|
||||
brand_name: '其他品牌-普通大货',
|
||||
})
|
||||
|
||||
expect(mapped?.archive.brand).toBe('代理品牌-索菲亚')
|
||||
expect(normalizeProductArchiveBrand('gbsfy-ad036001', '')).toBe('代理品牌-索菲亚')
|
||||
expect(normalizeProductArchiveBrand('CZ014006', '其他品牌-普通大货')).toBe('其他品牌-普通大货')
|
||||
})
|
||||
|
||||
it('leaves the image empty when the current SKU has no image', () => {
|
||||
const mapped = mapProductCatalogWideArchiveSource({
|
||||
...createSourceRecord(),
|
||||
|
||||
@ -23,6 +23,7 @@ const archiveExcludeRuleSchema = z.object({
|
||||
}).strict()
|
||||
|
||||
const productArchiveFiltersSchema = z.object({
|
||||
limitProductKind: z.enum(['bulk', 'brand']).optional(),
|
||||
salesGranularity: archiveSalesGranularitySchema.optional(),
|
||||
salesPeriod: archiveSalesPeriodSchema.optional(),
|
||||
keyword: z.string().trim().min(1).max(160).optional(),
|
||||
|
||||
@ -87,13 +87,6 @@ export function resolveProductArchivePackageType(value: string) {
|
||||
return PACKAGE_TYPE_BY_SET_COUNT[value.trim()] ?? ''
|
||||
}
|
||||
|
||||
/** 索菲亚货号以 GBSFY 开头;源品牌字段偶有误标,以货号前缀纠正。 */
|
||||
export function normalizeProductArchiveBrand(sku: string, brand: string) {
|
||||
return sku.trim().toUpperCase().startsWith('GBSFY')
|
||||
? '代理品牌-索菲亚'
|
||||
: brand.trim()
|
||||
}
|
||||
|
||||
export function calculateProductArchiveVolume(
|
||||
length: string,
|
||||
width: string,
|
||||
@ -167,7 +160,7 @@ export function mapProductCatalogWideArchiveSource(
|
||||
installDocId: text(record.drawing_id),
|
||||
installMethod: text(record.install_method),
|
||||
spec: text(record.archive_spec),
|
||||
brand: normalizeProductArchiveBrand(text(record.archive_sku), text(record.brand_name)),
|
||||
brand: text(record.brand_name),
|
||||
orderType: normalizeProductArchiveOrderType(record.purchase_order_method),
|
||||
inOutWarehouse: text(record.factory_warehouse),
|
||||
isSeasonal: '',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user