189 lines
7.5 KiB
JavaScript
189 lines
7.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const root = path.resolve(__dirname, '..');
|
|
const html = [
|
|
fs.readFileSync(path.join(root, 'prototype-src', 'modules', '03-overseas-warehouse.html'), 'utf8'),
|
|
fs.readFileSync(path.join(root, 'prototype-src', 'app.js'), 'utf8'),
|
|
].join('\n');
|
|
const failures = [];
|
|
|
|
function expectMatch(pattern, label, source = html) {
|
|
if (!pattern.test(source)) failures.push(`missing ${label}`);
|
|
}
|
|
|
|
function functionSource(name, source = html) {
|
|
const match = new RegExp(`function\\s+${name}\\s*\\([^)]*\\)\\s*\\{`).exec(source);
|
|
if (!match) return '';
|
|
const start = source.indexOf('{', match.index);
|
|
let depth = 0;
|
|
let quote = '';
|
|
let escaped = false;
|
|
for (let index = start; index < source.length; index += 1) {
|
|
const char = source[index];
|
|
if (quote) {
|
|
if (escaped) escaped = false;
|
|
else if (char === '\\') escaped = true;
|
|
else if (char === quote) quote = '';
|
|
continue;
|
|
}
|
|
if (char === "'" || char === '"' || char === '`') {
|
|
quote = char;
|
|
continue;
|
|
}
|
|
if (char === '{') depth += 1;
|
|
if (char === '}' && --depth === 0) return source.slice(match.index, index + 1);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
expectMatch(/onclick="openFbaRelabelCreate\(\)"/, '新增换标单真实入口');
|
|
expectMatch(/id="modal-fba-relabel-form"/, '新增编辑共用弹框');
|
|
for (const id of [
|
|
'fbro-form-order-no',
|
|
'fbro-form-related-order',
|
|
'fbro-form-sku',
|
|
'fbro-form-cn-name',
|
|
'fbro-form-boxes',
|
|
'fbro-form-label-req',
|
|
'fbro-form-file',
|
|
'fbro-form-status',
|
|
'fbro-form-budget-total',
|
|
'fbro-form-cost-row',
|
|
'fbro-form-relabel-cost',
|
|
'fbro-form-remark',
|
|
]) {
|
|
expectMatch(new RegExp(`id="${id}"`), `${id} 表单字段`);
|
|
}
|
|
expectMatch(/data-fbro-audit-order/, '列表审核数据入口');
|
|
expectMatch(/data-fbro-view-order/, '列表查看数据入口');
|
|
expectMatch(/预算总价/, '预算总价字段');
|
|
expectMatch(/预算报价/, '审核预算报价字段');
|
|
expectMatch(/id="fbro-form-relabel-cost"[^>]*type="number"/, '审核预算报价输入框');
|
|
|
|
const sources = Object.fromEntries([
|
|
'nextFbaRelabelOrderNo',
|
|
'formatFbaRelabelFee',
|
|
'calculateFbaRelabelFeeTotal',
|
|
'buildFbaRelabelRecord',
|
|
'openFbaRelabelCreate',
|
|
'openFbaRelabelEdit',
|
|
'readFbaRelabelForm',
|
|
'saveFbaRelabelOrder',
|
|
'openFbaRelabelOrderDetail',
|
|
].map((name) => [name, functionSource(name)]));
|
|
|
|
for (const [name, source] of Object.entries(sources)) {
|
|
if (!source) failures.push(`missing ${name} function`);
|
|
}
|
|
|
|
if (sources.nextFbaRelabelOrderNo) {
|
|
try {
|
|
const nextFbaRelabelOrderNo = new Function(`return (${sources.nextFbaRelabelOrderNo});`)();
|
|
assert.equal(nextFbaRelabelOrderNo('2026-08-12', [
|
|
{ orderNo: 'FBRO20260812001' },
|
|
{ orderNo: 'FBRO20260812009' },
|
|
{ orderNo: 'FBRO20260811099' },
|
|
]), 'FBRO20260812010');
|
|
} catch (error) {
|
|
failures.push(`换标单号生成行为失败:${error.message}`);
|
|
}
|
|
}
|
|
|
|
if (sources.formatFbaRelabelFee) {
|
|
try {
|
|
const formatFbaRelabelFee = new Function(`return (${sources.formatFbaRelabelFee});`)();
|
|
assert.equal(formatFbaRelabelFee(null), '-');
|
|
assert.equal(formatFbaRelabelFee(''), '-');
|
|
assert.equal(formatFbaRelabelFee('abc'), 'abc');
|
|
assert.equal(formatFbaRelabelFee(0), '$0.00');
|
|
assert.equal(formatFbaRelabelFee(12.5), '$12.50');
|
|
} catch (error) {
|
|
failures.push(`换标费用格式化行为失败:${error.message}`);
|
|
}
|
|
}
|
|
|
|
if (sources.calculateFbaRelabelFeeTotal) {
|
|
try {
|
|
const calculateFbaRelabelFeeTotal = new Function(`return (${sources.calculateFbaRelabelFeeTotal});`)();
|
|
assert.equal(calculateFbaRelabelFeeTotal({ openBoxFee: 10, pickingFee: '2.5', relabelFee: 3, cartonMarkFee: 4, relabelCost: 99 }), 19.5);
|
|
assert.equal(calculateFbaRelabelFeeTotal({ openBoxFee: null, pickingFee: 'invalid', relabelFee: undefined, cartonMarkFee: 0 }), 0);
|
|
} catch (error) {
|
|
failures.push(`换标费总计行为失败:${error.message}`);
|
|
}
|
|
} else {
|
|
failures.push('missing calculateFbaRelabelFeeTotal function');
|
|
}
|
|
|
|
if (sources.buildFbaRelabelRecord) {
|
|
try {
|
|
const buildFbaRelabelRecord = new Function(`${sources.nextFbaRelabelOrderNo}\nreturn (${sources.buildFbaRelabelRecord});`)();
|
|
const form = {
|
|
relatedOrderNo: 'RMA-NEW', sku: 'SKU-NEW', cnName: '新品', boxes: 3,
|
|
labelReq: '加贴新标', file: 'new.pdf', status: '已完成', remark: '新建备注', relabelCost: 21.75, budgetTotal: 18.5,
|
|
};
|
|
const orders = [{ orderNo: 'FBRO20260812001' }];
|
|
const created = buildFbaRelabelRecord(form, null, '2026-08-12 19:00', orders);
|
|
assert.equal(created.orderNo, 'FBRO20260812002');
|
|
assert.equal(created.status, '待处理');
|
|
assert.equal(created.createdAt, '2026-08-12 19:00');
|
|
assert.equal(created.updatedAt, '2026-08-12 19:00');
|
|
assert.equal(created.budgetTotal, 18.5);
|
|
assert.deepEqual(created.fees, {});
|
|
|
|
const current = {
|
|
orderNo: 'FBRO20260720001', lastMileNo: 'LMO-KEEP', createdAt: '2026-07-20 10:15',
|
|
updatedAt: '2026-07-21 15:40', fees: { openBoxFee: 12 }, sku: 'OLD', status: '处理中',
|
|
};
|
|
const edited = buildFbaRelabelRecord({ ...form, status: '已完成', relabelCost: 22.5, budgetTotal: 19.25 }, current, '2026-08-12 19:10', orders);
|
|
assert.equal(edited.orderNo, current.orderNo);
|
|
assert.equal(edited.lastMileNo, current.lastMileNo);
|
|
assert.equal(edited.createdAt, current.createdAt);
|
|
assert.equal(edited.fees.openBoxFee, current.fees.openBoxFee);
|
|
assert.equal(edited.fees.relabelCost, 22.5);
|
|
assert.equal(edited.budgetTotal, 19.25);
|
|
assert.equal(edited.sku, 'SKU-NEW');
|
|
assert.equal(edited.status, '已完成');
|
|
assert.equal(edited.updatedAt, '2026-08-12 19:10');
|
|
} catch (error) {
|
|
failures.push(`换标单构建行为失败:${error.message}`);
|
|
}
|
|
}
|
|
|
|
if (sources.openFbaRelabelOrderDetail) {
|
|
for (const label of ['商品信息', '预算总价', '费用明细', '开箱费', '挑货费', '换标费', '换箱唛标费', '换标费总计']) {
|
|
expectMatch(new RegExp(label), `详情${label}`, sources.openFbaRelabelOrderDetail);
|
|
}
|
|
if (/换标成本/.test(sources.openFbaRelabelOrderDetail)) failures.push('详情仍展示换标成本');
|
|
expectMatch(/formatFbaRelabelFee/, '详情使用统一费用格式化', sources.openFbaRelabelOrderDetail);
|
|
expectMatch(/calculateFbaRelabelFeeTotal/, '详情使用换标费总计函数', sources.openFbaRelabelOrderDetail);
|
|
}
|
|
|
|
if (sources.openFbaRelabelEdit) {
|
|
expectMatch(/审核换标单/, '审核弹窗标题', sources.openFbaRelabelEdit);
|
|
expectMatch(/fbro-form-cost-row/, '审核显示换标成本区域', sources.openFbaRelabelEdit);
|
|
expectMatch(/fbro-form-relabel-cost/, '审核回填预算报价', sources.openFbaRelabelEdit);
|
|
}
|
|
|
|
if (sources.readFbaRelabelForm) {
|
|
expectMatch(/fbro-form-relabel-cost/, '表单读取换标成本', sources.readFbaRelabelForm);
|
|
}
|
|
|
|
if (sources.saveFbaRelabelOrder) {
|
|
expectMatch(/buildFbaRelabelRecord/, '保存调用记录构建函数', sources.saveFbaRelabelOrder);
|
|
expectMatch(/Number\.isInteger/, '箱数正整数校验', sources.saveFbaRelabelOrder);
|
|
expectMatch(/relabelCost/, '保存换标报价选择', sources.saveFbaRelabelOrder);
|
|
expectMatch(/fbroApplyCurrentSearch/, '保存后保留当前筛选结果', sources.saveFbaRelabelOrder);
|
|
}
|
|
|
|
if (failures.length) {
|
|
console.error('FBA_RELABEL_CREATE_EDIT_FEES_CHECK_FAIL');
|
|
failures.forEach((failure) => console.error(`- ${failure}`));
|
|
process.exitCode = 1;
|
|
} else {
|
|
console.log('FBA_RELABEL_CREATE_EDIT_FEES_CHECK_PASS');
|
|
}
|