const fs = require('fs'); const path = require('path'); let passed = 0; let failed = 0; function assert(condition, testName, detail = '') { if (condition) { console.log(` [PASS] ${testName}`); passed++; } else { console.error(` [FAIL] ${testName} - ${detail}`); failed++; } } console.log("========================================================"); console.log(" dmepa汇率高精度(不四舍五入)全链路自适应规范自动化测试"); console.log("========================================================\n"); // 1. 验证 IdentityService.php 的 formatRate 改造 const identityPath = path.resolve(__dirname, '../addons/shopro/service/partner/IdentityService.php'); assert(fs.existsSync(identityPath), 'IdentityService.php 存在'); const identityContent = fs.readFileSync(identityPath, 'utf-8'); assert( !identityContent.includes("number_format((float) $value, 8, '.', '')"), 'formatRate() 已废除死锁的 8 位截断四舍五入 number_format(..., 8)' ); assert( identityContent.includes("number_format($floatVal, 12, '.', '')"), 'formatRate() 升级为 12 位高精度展开,杜绝科学计数法并容纳 9~12 位微小汇率' ); assert( identityContent.includes("rtrim(rtrim($formatted, '0'), '.')"), 'formatRate() 具备末尾无效 0 动态裁切能力,实现原值精准输出' ); // 2. 验证 RateService.php 的 calcRate 计算精度 const rateServicePath = path.resolve(__dirname, '../addons/shopro/service/partner/RateService.php'); assert(fs.existsSync(rateServicePath), 'RateService.php 存在'); const rateServiceContent = fs.readFileSync(rateServicePath, 'utf-8'); assert( rateServiceContent.includes("number_format($base, 12, '.', '')"), 'calcRate() 展开 baseStr 使用 12 位高精度,防止乘法前被截断' ); assert( rateServiceContent.includes("bcmul($baseStr, $multipleStr, 12)"), 'calcRate() 使用 bcmul 保留 12 位高精度安全计算' ); // 3. 验证 DailySettleService 与 PartnerClean 统一调用 const dailySettlePath = path.resolve(__dirname, '../addons/shopro/service/partner/DailySettleService.php'); const dailySettleContent = fs.readFileSync(dailySettlePath, 'utf-8'); assert( dailySettleContent.includes("'rate' => IdentityService::formatRate($rate)"), 'DailySettleService 试算预览统一使用 IdentityService::formatRate' ); const cleanCmdPath = path.resolve(__dirname, '../addons/shopro/console/PartnerClean.php'); const cleanCmdContent = fs.readFileSync(cleanCmdPath, 'utf-8'); assert( cleanCmdContent.includes("IdentityService::formatRate($resetRate)"), 'PartnerClean 重置提示统一使用 IdentityService::formatRate' ); // 4. 精确模拟 PHP formatRate 算法逻辑测试 function formatRateSim(value) { if (value === null || value === '' || value === undefined) { value = '0.00000075'; } const floatVal = parseFloat(value); if (isNaN(floatVal) || floatVal <= 0) { return '0'; } // 模拟 number_format($floatVal, 12, '.', '') const formatted = floatVal.toFixed(12); // 模拟 rtrim(rtrim($formatted, '0'), '.') const trimmed = formatted.replace(/\.?0+$/, ''); return trimmed !== '' ? trimmed : '0'; } // 针对用户实际痛点:设置 0.000000715 时不可四舍五入为 0.00000072 assert( formatRateSim('0.000000715') === '0.000000715', '汇率 0.000000715(9位小数)精准输出为 0.000000715,不发生四舍五入' ); assert( formatRateSim('0.000000715') !== '0.00000072', '汇率 0.000000715 绝对不能被四舍五入成 0.00000072' ); assert( formatRateSim('0.00000075') === '0.00000075', '默认汇率 0.00000075(8位小数)保持为 0.00000075' ); assert( formatRateSim('0.0000007153') === '0.0000007153', '高精度汇率 0.0000007153(10位小数)精准输出为 0.0000007153' ); assert( formatRateSim(0.000000715 * 2) === '0.00000143', '翻倍汇率 0.000000715 * 2 = 0.00000143 精确输出,不被截断' ); assert( formatRateSim('0') === '0', '0 值正确输出为 0' ); assert( formatRateSim(null) === '0.00000075', 'null 兜底输出基准汇率 0.00000075' ); console.log("\n--------------------------------------------------------"); console.log(`测试执行结果: 通过 ${passed} 项, 失败 ${failed} 项`); console.log("========================================================\n"); if (failed > 0) { process.exit(1); }