'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const { _test: { buildProductCodeRequest, buildProductCodeRequestHash, normalizeProductCodeConfig, normalizeProductCodeMeta, validateProductCodeResponse, }, } = require('../src/services/planningSelectionFissionService'); const remoteMeta = { operationCenters: [{ name: '运营一部' }], categories: [{ name: '住宅家具' }], productTagOptionGroups: [ { key: 'taxStatus', options: ['含税'] }, { key: 'invoiceType', options: ['专票'] }, { key: 'installationService', options: ['不安装'] }, { key: 'installationMode', options: ['无需安装'] }, ], }; const configInput = { operationCenter: '运营一部', categoryName: '住宅家具', taxStatus: '含税', invoiceType: '专票', installationService: '不安装', installationMode: '无需安装', }; const rows = [ { skuCode: 'SOURCE-SKU-02', selectedSkuName: '胡桃色 120cm 茶几', colorName: '胡桃色', colorSpec: '胡桃色;120cm', lengthCm: 120, widthCm: 60, heightCm: 45, weight: 20, }, { skuCode: 'SOURCE-SKU-01', selectedSkuName: '原木色 90cm 茶几', colorName: '原木色', colorSpec: '原木色;90cm', lengthCm: 90, widthCm: 50, heightCm: 42, weight: 16, }, ]; test('product-code meta and required options are normalized from the remote contract', () => { assert.deepEqual(normalizeProductCodeMeta(remoteMeta), { operationCenters: ['运营一部'], categories: ['住宅家具'], tagOptions: { taxStatus: ['含税'], invoiceType: ['专票'], installationService: ['不安装'], installationMode: ['无需安装'], }, }); assert.deepEqual(normalizeProductCodeConfig(configInput, remoteMeta), configInput); }); test('product-code request preserves canonical SKU order and confirmed SKU names', () => { const request = buildProductCodeRequest(configInput, rows, { name: '测试运营' }); assert.equal(request.skuItems.length, 2); assert.equal(request.skuItems[0].productName, '胡桃色 120cm 茶几'); assert.equal(request.skuItems[1].productName, '原木色 90cm 茶几'); assert.deepEqual(request.skuItems[0], { productName: '胡桃色 120cm 茶几', colorSpec: '胡桃色;120cm', lengthCm: 120, widthCm: 60, heightCm: 45, weight: 20, }); }); test('product-code result must match SKU count, order and exact confirmed names', () => { const response = { styleCode: 'STYLE-001', items: [ { productCode: 'SKU-001-01', productName: rows[0].selectedSkuName, colorSpec: rows[0].colorSpec }, { productCode: 'SKU-001-02', productName: rows[1].selectedSkuName, colorSpec: rows[1].colorSpec }, ], }; assert.deepEqual(validateProductCodeResponse(response, rows).map((row) => row.productCode), [ 'SKU-001-01', 'SKU-001-02', ]); assert.throws( () => validateProductCodeResponse({ ...response, items: [response.items[1], response.items[0]], }, rows), (error) => error.code === 'PRODUCT_CODE_NAME_MISMATCH' && error.indeterminate === true ); }); test('product-code request hash changes when SKU order or final name changes', () => { const request = buildProductCodeRequest(configInput, rows, { name: '测试运营' }); const originalHash = buildProductCodeRequestHash(request, rows); const reversedRows = [...rows].reverse(); const reversedHash = buildProductCodeRequestHash( buildProductCodeRequest(configInput, reversedRows, { name: '测试运营' }), reversedRows ); const renamedRows = rows.map((row, index) => index === 0 ? { ...row, selectedSkuName: `${row.selectedSkuName} 新名称` } : row); const renamedHash = buildProductCodeRequestHash( buildProductCodeRequest(configInput, renamedRows, { name: '测试运营' }), renamedRows ); assert.notEqual(originalHash, reversedHash); assert.notEqual(originalHash, renamedHash); }); test('1688 pricing confirmation reuses the global registry and never requests another code set', () => { const serviceSource = fs.readFileSync( path.join(__dirname, '../src/services/planningSelectionFissionService.js'), 'utf8' ); const saveStart = serviceSource.indexOf('async function saveSelectionFissionProfitPricingTable'); const saveEnd = serviceSource.indexOf('\nasync function generateSelectionFissionSkuNames', saveStart); assert.notEqual(saveStart, -1); assert.notEqual(saveEnd, -1); const saveSource = serviceSource.slice(saveStart, saveEnd); assert.match(saveSource, /loadAlibaba1688GlobalEncoding/); assert.match(saveSource, /product_code_status = 'completed'/); assert.doesNotMatch(saveSource, /createProductCodes|getProductCodeMeta/); assert.doesNotMatch(saveSource, /product_code_status = 'requesting'/); });