Files
yunhaifinance/backend/test-statistics.js
T

403 lines
16 KiB
JavaScript

/**
* 综合测试:统计和优化功能
* 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.md
* 章节:步骤11 - 统计和优化
*
* 测试内容:
* 1. 材料价格历史查询API
* 2. 项目材料库存统计
* 3. 供应商财务统计
* 4. 物流公司财务统计
*/
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const dbPath = path.join(__dirname, 'company_finance.db');
const db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error('数据库连接失败:', err.message);
process.exit(1);
}
console.log('SQLite数据库连接成功:', dbPath);
});
const runSQL = (sql, params = []) => {
return new Promise((resolve, reject) => {
db.run(sql, params, function(err) {
if (err) {
reject(err);
} else {
resolve({ lastID: this.lastID, changes: this.changes });
}
});
});
};
const runAllSQL = (sql, params = []) => {
return new Promise((resolve, reject) => {
db.all(sql, params, (err, rows) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
};
async function test() {
let passed = 0;
let failed = 0;
const testData = {
projectId: null,
projectCode: null,
supplierId: null,
logisticsCompanyId: null,
productId: null,
orderId: null,
logisticsId: null
};
try {
console.log('\n========================================');
console.log('综合测试:统计和优化功能');
console.log('========================================\n');
console.log('--- 准备测试数据 ---\n');
testData.projectCode = 'TEST-STAT-' + Date.now();
const projectResult = await runSQL(`
INSERT INTO projects (code, name, status, created_at, updated_at)
VALUES (?, '统计测试项目', 'active', datetime('now'), datetime('now'))
`, [testData.projectCode]);
testData.projectId = projectResult.lastID;
console.log(` ✅ 创建测试项目,ID: ${testData.projectId}`);
passed++;
const supplierResult = await runSQL(`
INSERT INTO suppliers (name, supply_category, country, created_at, updated_at)
VALUES ('统计测试供应商', '电力设备', 'Laos', datetime('now'), datetime('now'))
`);
testData.supplierId = supplierResult.lastID;
console.log(` ✅ 创建测试供应商,ID: ${testData.supplierId}`);
passed++;
const logisticsResult = await runSQL(`
INSERT INTO logistics_companies (code, name, status, created_at, updated_at)
VALUES (?, '统计测试物流公司', 'active', datetime('now'), datetime('now'))
`, ['LOG-STAT-' + Date.now()]);
testData.logisticsCompanyId = logisticsResult.lastID;
console.log(` ✅ 创建测试物流公司,ID: ${testData.logisticsCompanyId}`);
passed++;
const productResult = await runSQL(`
INSERT INTO products (name, specification, unit, created_at, updated_at)
VALUES ('统计测试材料', '规格A', '个', datetime('now'), datetime('now'))
`);
testData.productId = productResult.lastID;
console.log(` ✅ 创建测试商品,ID: ${testData.productId}`);
passed++;
const orderResult = await runSQL(`
INSERT INTO purchase_orders
(code, project_id, supplier_id, total_amount, paid_amount, order_date, status, currency, created_at, updated_at)
VALUES (?, ?, ?, 100000, 40000, date('now'), 'confirmed', 'CNY', datetime('now'), datetime('now'))
`, ['PO-STAT-' + Date.now(), testData.projectId, testData.supplierId]);
testData.orderId = orderResult.lastID;
console.log(` ✅ 创建测试订单,ID: ${testData.orderId}`);
passed++;
const logisticsRecordResult = await runSQL(`
INSERT INTO logistics_records
(code, purchase_order_id, logistics_company_id, ship_date, status,
primary_freight, primary_freight_currency, primary_freight_status,
secondary_freight, secondary_freight_currency, secondary_freight_status,
created_at, updated_at)
VALUES (?, ?, ?, date('now'), 'arrived',
5000, 'CNY', 'paid',
2000, 'CNY', 'pending',
datetime('now'), datetime('now'))
`, ['LR-STAT-' + Date.now(), testData.orderId, testData.logisticsCompanyId]);
testData.logisticsId = logisticsRecordResult.lastID;
console.log(` ✅ 创建测试物流记录,ID: ${testData.logisticsId}`);
passed++;
console.log('\n========================================');
console.log('测试1:材料价格历史查询API');
console.log('========================================\n');
await runSQL(`
INSERT INTO material_price_history
(product_id, purchase_order_id, supplier_id, unit_price, currency, quantity, purchase_date, created_at)
VALUES (?, ?, ?, 100, 'CNY', 500, date('now'), datetime('now'))
`, [testData.productId, testData.orderId, testData.supplierId]);
await runSQL(`
INSERT INTO material_price_history
(product_id, purchase_order_id, supplier_id, unit_price, currency, quantity, purchase_date, created_at)
VALUES (?, ?, ?, 95, 'CNY', 300, date('now', '-7 day'), datetime('now'))
`, [testData.productId, testData.orderId, testData.supplierId]);
const priceHistory = await runAllSQL(`
SELECT * FROM material_price_history WHERE product_id = ? ORDER BY purchase_date DESC
`, [testData.productId]);
if (priceHistory.length === 2) {
console.log(` ✅ 价格历史查询成功,共 ${priceHistory.length} 条记录`);
priceHistory.forEach((ph, i) => {
console.log(` 记录${i + 1}: 单价=${ph.unit_price}, 数量=${ph.quantity}, 日期=${ph.purchase_date}`);
});
passed++;
} else {
console.log(` ❌ 价格历史查询失败`);
failed++;
}
const avgPrice = await runAllSQL(`
SELECT
AVG(unit_price) as avg_price,
MIN(unit_price) as min_price,
MAX(unit_price) as max_price,
SUM(quantity) as total_quantity
FROM material_price_history WHERE product_id = ?
`, [testData.productId]);
if (avgPrice.length > 0 && avgPrice[0].avg_price > 0) {
console.log(` ✅ 平均价格统计:`);
console.log(` 平均价格: ${avgPrice[0].avg_price}`);
console.log(` 最低价格: ${avgPrice[0].min_price}`);
console.log(` 最高价格: ${avgPrice[0].max_price}`);
console.log(` 总数量: ${avgPrice[0].total_quantity}`);
passed++;
} else {
console.log(` ❌ 平均价格统计失败`);
failed++;
}
console.log('\n========================================');
console.log('测试2:项目材料库存统计');
console.log('========================================\n');
await runSQL(`
INSERT INTO project_material_inventory
(project_id, product_id, product_name, unit, purchased_quantity, received_quantity,
used_quantity, returned_quantity, current_quantity, total_amount, average_price, created_at, updated_at)
VALUES (?, ?, '统计测试材料', '个', 500, 500, 100, 50, 350, 47500, 95, datetime('now'), datetime('now'))
`, [testData.projectId, testData.productId]);
const inventory = await runAllSQL(`
SELECT * FROM project_material_inventory WHERE project_id = ?
`, [testData.projectId]);
if (inventory.length > 0) {
const inv = inventory[0];
console.log(` ✅ 库存查询成功:`);
console.log(` 采购数量: ${inv.purchased_quantity}`);
console.log(` 收货数量: ${inv.received_quantity}`);
console.log(` 已用数量: ${inv.used_quantity}`);
console.log(` 退库数量: ${inv.returned_quantity}`);
console.log(` 当前库存: ${inv.current_quantity}`);
passed++;
if (inv.current_quantity === 350) {
console.log(` ✅ 库存计算正确 (500-100-50=350)`);
passed++;
} else {
console.log(` ❌ 库存计算错误`);
failed++;
}
} else {
console.log(` ❌ 库存查询失败`);
failed++;
}
const inventorySummary = await runAllSQL(`
SELECT
COUNT(*) as item_count,
SUM(purchased_quantity) as total_purchased,
SUM(current_quantity) as total_current,
SUM(total_amount) as total_value
FROM project_material_inventory WHERE project_id = ?
`, [testData.projectId]);
if (inventorySummary.length > 0) {
console.log(` ✅ 库存汇总:`);
console.log(` 材料种类: ${inventorySummary[0].item_count}`);
console.log(` 总采购数量: ${inventorySummary[0].total_purchased}`);
console.log(` 总库存: ${inventorySummary[0].total_current}`);
console.log(` 总金额: ${inventorySummary[0].total_value}`);
passed++;
}
console.log('\n========================================');
console.log('测试3:供应商财务统计');
console.log('========================================\n');
const supplierLedger = await runAllSQL(`
SELECT
COUNT(*) as order_count,
COALESCE(SUM(total_amount), 0) as total_amount,
COALESCE(SUM(paid_amount), 0) as paid_amount,
COALESCE(SUM(total_amount - paid_amount), 0) as unpaid_amount
FROM purchase_orders WHERE supplier_id = ?
`, [testData.supplierId]);
if (supplierLedger.length > 0) {
const s = supplierLedger[0];
console.log(` ✅ 供应商财务汇总:`);
console.log(` 订单数量: ${s.order_count}`);
console.log(` 订单总额: ${s.total_amount}`);
console.log(` 已付金额: ${s.paid_amount}`);
console.log(` 未付金额: ${s.unpaid_amount}`);
passed++;
if (s.total_amount === 100000 && s.paid_amount === 40000 && s.unpaid_amount === 60000) {
console.log(` ✅ 供应商财务计算正确`);
passed++;
} else {
console.log(` ❌ 供应商财务计算错误`);
failed++;
}
} else {
console.log(` ❌ 供应商财务统计失败`);
failed++;
}
const supplierOrders = await runAllSQL(`
SELECT po.id, po.code, po.total_amount, po.paid_amount,
(po.total_amount - po.paid_amount) as unpaid_amount,
po.status, p.name as project_name
FROM purchase_orders po
LEFT JOIN projects p ON po.project_id = p.id
WHERE po.supplier_id = ?
`, [testData.supplierId]);
if (supplierOrders.length > 0) {
console.log(` ✅ 供应商订单列表,共 ${supplierOrders.length} 条`);
passed++;
} else {
console.log(` ❌ 供应商订单列表查询失败`);
failed++;
}
console.log('\n========================================');
console.log('测试4:物流公司财务统计');
console.log('========================================\n');
const logisticsLedger = await runAllSQL(`
SELECT
COUNT(*) as order_count,
COALESCE(SUM(primary_freight), 0) as total_primary_freight,
COALESCE(SUM(secondary_freight), 0) as total_secondary_freight,
COALESCE(SUM(primary_freight + secondary_freight), 0) as total_freight,
COALESCE(SUM(CASE WHEN primary_freight_status = 'paid' THEN primary_freight ELSE 0 END), 0) as paid_primary,
COALESCE(SUM(CASE WHEN secondary_freight_status = 'paid' THEN secondary_freight ELSE 0 END), 0) as paid_secondary
FROM logistics_records WHERE logistics_company_id = ?
`, [testData.logisticsCompanyId]);
if (logisticsLedger.length > 0) {
const l = logisticsLedger[0];
const totalPaid = (l.paid_primary || 0) + (l.paid_secondary || 0);
const totalUnpaid = (l.total_freight || 0) - totalPaid;
console.log(` ✅ 物流公司财务汇总:`);
console.log(` 订单数量: ${l.order_count}`);
console.log(` 一次运费总额: ${l.total_primary_freight}`);
console.log(` 二次运费总额: ${l.total_secondary_freight}`);
console.log(` 运费总额: ${l.total_freight}`);
console.log(` 已付金额: ${totalPaid}`);
console.log(` 未付金额: ${totalUnpaid}`);
passed++;
if (l.total_freight === 7000 && totalPaid === 5000 && totalUnpaid === 2000) {
console.log(` ✅ 物流公司财务计算正确 (总额7000, 已付5000, 未付2000)`);
passed++;
} else {
console.log(` ❌ 物流公司财务计算错误`);
failed++;
}
} else {
console.log(` ❌ 物流公司财务统计失败`);
failed++;
}
console.log('\n========================================');
console.log('测试5:整体数据一致性验证');
console.log('========================================\n');
const allOrders = await runAllSQL(`
SELECT
po.id, po.code, po.total_amount, po.paid_amount,
s.name as supplier_name,
lr.primary_freight, lr.secondary_freight,
lc.name as logistics_company_name
FROM purchase_orders po
LEFT JOIN suppliers s ON po.supplier_id = s.id
LEFT JOIN logistics_records lr ON po.id = lr.purchase_order_id
LEFT JOIN logistics_companies lc ON lr.logistics_company_id = lc.id
WHERE po.id = ?
`, [testData.orderId]);
if (allOrders.length > 0) {
const order = allOrders[0];
console.log(` ✅ 订单关联数据验证:`);
console.log(` 订单号: ${order.code}`);
console.log(` 供应商: ${order.supplier_name}`);
console.log(` 物流公司: ${order.logistics_company_name}`);
console.log(` 订单金额: ${order.total_amount}`);
console.log(` 一次运费: ${order.primary_freight}`);
console.log(` 二次运费: ${order.secondary_freight}`);
passed++;
} else {
console.log(` ❌ 订单关联数据验证失败`);
failed++;
}
console.log('\n--- 清理测试数据 ---\n');
await runSQL('DELETE FROM material_price_history WHERE product_id = ?', [testData.productId]);
await runSQL('DELETE FROM project_material_inventory WHERE project_id = ?', [testData.projectId]);
await runSQL('DELETE FROM logistics_records WHERE id = ?', [testData.logisticsId]);
await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testData.orderId]);
await runSQL('DELETE FROM products WHERE id = ?', [testData.productId]);
await runSQL('DELETE FROM suppliers WHERE id = ?', [testData.supplierId]);
await runSQL('DELETE FROM logistics_companies WHERE id = ?', [testData.logisticsCompanyId]);
await runSQL('DELETE FROM projects WHERE id = ?', [testData.projectId]);
console.log(' 测试数据已清理');
console.log('\n========================================');
console.log('测试结果汇总');
console.log('========================================\n');
console.log(`通过: ${passed}`);
console.log(`失败: ${failed}`);
console.log('\n========================================');
if (failed === 0) {
console.log('✅ 所有测试通过!统计和优化功能符合设计方案。');
} else {
console.log('❌ 部分测试失败,请检查错误详情。');
}
console.log('========================================\n');
db.close();
process.exit(failed > 0 ? 1 : 0);
} catch (error) {
console.error('测试失败:', error);
try {
await runSQL('DELETE FROM material_price_history WHERE product_id = ?', [testData.productId]);
await runSQL('DELETE FROM project_material_inventory WHERE project_id = ?', [testData.projectId]);
await runSQL('DELETE FROM logistics_records WHERE id = ?', [testData.logisticsId]);
await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testData.orderId]);
await runSQL('DELETE FROM products WHERE id = ?', [testData.productId]);
await runSQL('DELETE FROM suppliers WHERE id = ?', [testData.supplierId]);
await runSQL('DELETE FROM logistics_companies WHERE id = ?', [testData.logisticsCompanyId]);
await runSQL('DELETE FROM projects WHERE id = ?', [testData.projectId]);
} catch (e) {}
db.close();
process.exit(1);
}
}
test();