/** * 综合测试:统计和优化功能 * 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.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();