From 1c1efebf2757d70f51ba8d8df6ffeeb3d6600ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=85=E5=B1=85?= Date: Tue, 20 Oct 2026 17:14:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(supply-chain):=20=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E5=81=9C=E4=BA=A7=E9=80=80=E5=B8=82=E5=95=86=E5=93=81=E9=99=90?= =?UTF-8?q?=E4=BB=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 42b374801df5926aba8f302af518a538e2baede1) --- .../supply-chain-limit-price-fields.test.ts | 38 +++++++++++++++++++ .../lib/supply-chain-limit-price-fields.ts | 29 ++++++++++---- ...ly-chain-product-archive-export.service.ts | 16 +++++--- .../supply-chain-product-archive.service.ts | 1 + 4 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 furniture-3d-system/src/lib/supply-chain-limit-price-fields.test.ts diff --git a/furniture-3d-system/src/lib/supply-chain-limit-price-fields.test.ts b/furniture-3d-system/src/lib/supply-chain-limit-price-fields.test.ts new file mode 100644 index 00000000..a976a7ca --- /dev/null +++ b/furniture-3d-system/src/lib/supply-chain-limit-price-fields.test.ts @@ -0,0 +1,38 @@ +import { resolveLimitPriceFields } from './supply-chain-limit-price-fields' + +const ACTIVE_INPUT = { + productStatus: '销售', + ownerLimitPrice: 286.9, + costPrice: '128.50', + limitUpdatedAt: new Date('2026-04-21T20:54:00.000Z'), + limitInitiator: '玉衡', +} + +describe('resolveLimitPriceFields', () => { + it('calculates all limit price fields for an active product', () => { + const fields = resolveLimitPriceFields(ACTIVE_INPUT) + + expect(fields.opsPriceLimit).toBe('286.90') + expect(fields.nonOwnerLimitPriceNew).toBe('301.25') + expect(fields.limitInitiator).toBe('玉衡') + }) + + it.each(['停产', ' 退市 '])('clears every limit field for %s products', (productStatus) => { + const fields = resolveLimitPriceFields({ + ...ACTIVE_INPUT, + productStatus, + }) + + expect(fields).toEqual({ + opsPriceLimit: '', + nonOwnerLimitPriceNew: '', + jxLimitPrice: '', + alibabaPageLimitPrice: '', + distributorPrice89: '', + distributorPrice85: '', + distributorPrice80: '', + limitUpdatedAt: '', + limitInitiator: '', + }) + }) +}) diff --git a/furniture-3d-system/src/lib/supply-chain-limit-price-fields.ts b/furniture-3d-system/src/lib/supply-chain-limit-price-fields.ts index f469d161..ef981308 100644 --- a/furniture-3d-system/src/lib/supply-chain-limit-price-fields.ts +++ b/furniture-3d-system/src/lib/supply-chain-limit-price-fields.ts @@ -3,24 +3,37 @@ * 负责人限价来自限价流程(货号维度);其余字段按固定公式从负责人限价 / 成本价推导。 * 供限价明细页查询(service)与导出(export service)共用。 */ +const INACTIVE_PRODUCT_STATUSES = new Set(['停产', '退市']) + +function emptyLimitPriceFields() { + return { + opsPriceLimit: '', + nonOwnerLimitPriceNew: '', + jxLimitPrice: '', + alibabaPageLimitPrice: '', + distributorPrice89: '', + distributorPrice85: '', + distributorPrice80: '', + limitUpdatedAt: '', + limitInitiator: '', + } +} + export function resolveLimitPriceFields(input: { + productStatus: string ownerLimitPrice: number | null costPrice: string limitUpdatedAt: Date | null limitInitiator: string }) { + if (INACTIVE_PRODUCT_STATUSES.has(input.productStatus.trim())) { + return emptyLimitPriceFields() + } const owner = input.ownerLimitPrice const format = (value: number | null) => (value === null ? '' : value.toFixed(2)) if (owner === null) { return { - opsPriceLimit: '', - nonOwnerLimitPriceNew: '', - jxLimitPrice: '', - alibabaPageLimitPrice: '', - distributorPrice89: '', - distributorPrice85: '', - distributorPrice80: '', - limitUpdatedAt: '', + ...emptyLimitPriceFields(), limitInitiator: input.limitInitiator, } } diff --git a/furniture-3d-system/src/server/services/supply-chain-product-archive-export.service.ts b/furniture-3d-system/src/server/services/supply-chain-product-archive-export.service.ts index 682d3c4a..662a1c5c 100644 --- a/furniture-3d-system/src/server/services/supply-chain-product-archive-export.service.ts +++ b/furniture-3d-system/src/server/services/supply-chain-product-archive-export.service.ts @@ -218,10 +218,19 @@ export class SupplyChainProductArchiveExportService { currentStorageType: row.storageType, config, }) + const styleLimit = styleLimitByCode.get(String(record.sku ?? '').trim()) + const limitFields = resolveLimitPriceFields({ + productStatus: row.productStatus, + ownerLimitPrice: styleLimit?.ownerLimitPrice ?? null, + costPrice: String(row.costPrice ?? ''), + limitUpdatedAt: styleLimit?.approvedAt ?? null, + limitInitiator: styleLimit?.initiator ?? '', + }) if (!ownerEmploymentIndex) { return { ...row, ...warehouseFields, + ...limitFields, } satisfies SupplyChainProductArchiveRow } return { @@ -230,12 +239,7 @@ export class SupplyChainProductArchiveExportService { ...warehouseFields, opsHead: resolveOwnerTakeover(record.opsHead ?? '', ownerEmploymentIndex).display || row.opsHead, designer: resolveDesignerView(record.designer ?? '', ownerEmploymentIndex).display || row.designer, - ...resolveLimitPriceFields({ - ownerLimitPrice: styleLimitByCode.get(String(record.sku ?? '').trim())?.ownerLimitPrice ?? null, - costPrice: String(row.costPrice ?? ''), - limitUpdatedAt: styleLimitByCode.get(String(record.sku ?? '').trim())?.approvedAt ?? null, - limitInitiator: styleLimitByCode.get(String(record.sku ?? '').trim())?.initiator ?? '', - }), + ...limitFields, } satisfies SupplyChainProductArchiveRow } } diff --git a/furniture-3d-system/src/server/services/supply-chain-product-archive.service.ts b/furniture-3d-system/src/server/services/supply-chain-product-archive.service.ts index 4a7b09a6..f11b9922 100644 --- a/furniture-3d-system/src/server/services/supply-chain-product-archive.service.ts +++ b/furniture-3d-system/src/server/services/supply-chain-product-archive.service.ts @@ -145,6 +145,7 @@ export class SupplyChainProductArchiveService { // 限价派生字段(限价明细页 / 导出共用):负责人限价 + 非负责人 / 京喜 / 阿里 / 分销商折扣 const styleLimit = styleLimitByCode.get(String(record.sku ?? '').trim()) const limitFields = resolveLimitPriceFields({ + productStatus: row.productStatus, ownerLimitPrice: styleLimit?.ownerLimitPrice ?? null, costPrice: String(row.costPrice ?? ''), limitUpdatedAt: styleLimit?.approvedAt ?? null,