/** * 测试验收和退库管理功能 * 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.md * 章节:八、验收管理功能 * * 测试内容: * 1. 创建验收单 * 2. 验证一次验收/二次验收 * 3. 验证部分签收 * 4. 验证验收后更新项目材料库存 * 5. 创建退库单 * 6. 验证退库后更新项目材料库存 */ 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 errors = []; let testOrderId = null; let testProjectId = null; let testVerificationId = null; let testReturnId = null; try { console.log('\n========================================'); console.log('测试验收和退库管理功能'); console.log('========================================\n'); console.log('--- 测试1:创建测试数据 ---\n'); const projectResult = await runSQL(` INSERT INTO projects (name, status, created_at, updated_at) VALUES ('测试项目', 'active', datetime('now'), datetime('now')) `); testProjectId = projectResult.lastID; console.log(` ✅ 创建测试项目,ID: ${testProjectId}`); passed++; const orderCode = 'TEST-PO-' + Date.now(); const orderResult = await runSQL(` INSERT INTO purchase_orders (code, project_id, total_amount, currency, status, created_by, created_at, updated_at) VALUES (?, ?, 10000, 'CNY', 'confirmed', '测试人员', datetime('now'), datetime('now')) `, [orderCode, testProjectId]); testOrderId = orderResult.lastID; console.log(` ✅ 创建测试订单,ID: ${testOrderId}`); passed++; console.log('\n--- 测试2:创建验收单(一次验收)---\n'); const verificationCode = 'VR' + new Date().toISOString().slice(0, 10).replace(/-/g, '') + String(Math.floor(Math.random() * 10000)).padStart(4, '0'); const items = [ { product_id: 1, product_name: '测试商品A', unit: '个', ordered_quantity: 100, received_quantity: 100, verified_quantity: 100, rejected_quantity: 0, unit_price: 50 } ]; const verificationResult = await runSQL(` INSERT INTO verification_records (code, purchase_order_id, verification_type, verification_date, verifier, items, project_id, total_ordered, total_received, total_verified, total_rejected, status, created_at) VALUES (?, ?, 'direct', date('now'), '测试验收员', ?, ?, 100, 100, 100, 0, 'pending', datetime('now')) `, [verificationCode, testOrderId, JSON.stringify(items), testProjectId]); testVerificationId = verificationResult.lastID; console.log(` ✅ 创建验收单成功,ID: ${testVerificationId},类型: direct(一次验收)`); passed++; console.log('\n--- 测试3:确认验收并更新项目材料库存 ---\n'); await runSQL("UPDATE verification_records SET status = 'confirmed' WHERE id = ?", [testVerificationId]); const inventoryResult = await runSQL(` INSERT INTO project_material_inventory (project_id, product_id, product_name, unit, purchased_quantity, received_quantity, current_quantity, total_amount, average_price, created_at, updated_at) VALUES (?, 1, '测试商品A', '个', 100, 100, 100, 5000, 50, datetime('now'), datetime('now')) `, [testProjectId]); console.log(` ✅ 项目材料库存已更新,库存ID: ${inventoryResult.lastID}`); passed++; const inventory = await runAllSQL('SELECT * FROM project_material_inventory WHERE project_id = ?', [testProjectId]); if (inventory.length > 0 && inventory[0].received_quantity === 100) { console.log(` ✅ 验收后库存正确: 收货数量=${inventory[0].received_quantity}, 当前库存=${inventory[0].current_quantity}`); passed++; } else { console.log(` ❌ 库存数据错误`); failed++; } console.log('\n--- 测试4:创建退库单 ---\n'); const returnCode = 'RT' + new Date().toISOString().slice(0, 10).replace(/-/g, '') + String(Math.floor(Math.random() * 10000)).padStart(4, '0'); const returnItems = [ { product_id: 1, product_name: '测试商品A', unit: '个', quantity: 20, unit_price: 50, amount: 1000 } ]; const returnResult = await runSQL(` INSERT INTO return_records (code, project_id, return_type, return_date, applicant, items, total_quantity, total_amount, status, created_at) VALUES (?, ?, 'warehouse', date('now'), '测试人员', ?, 20, 1000, 'pending', datetime('now')) `, [returnCode, testProjectId, JSON.stringify(returnItems)]); testReturnId = returnResult.lastID; console.log(` ✅ 创建退库单成功,ID: ${testReturnId},类型: warehouse(退回仓库)`); passed++; console.log('\n--- 测试5:确认退库并更新项目材料库存 ---\n'); await runSQL("UPDATE return_records SET status = 'confirmed' WHERE id = ?", [testReturnId]); await runSQL(` UPDATE project_material_inventory SET returned_quantity = 20, current_quantity = 80, total_amount = 4000, updated_at = datetime('now') WHERE project_id = ? AND product_id = 1 `, [testProjectId]); const inventoryAfterReturn = await runAllSQL('SELECT * FROM project_material_inventory WHERE project_id = ?', [testProjectId]); if (inventoryAfterReturn.length > 0 && inventoryAfterReturn[0].current_quantity === 80) { console.log(` ✅ 退库后库存正确: 退库数量=${inventoryAfterReturn[0].returned_quantity}, 当前库存=${inventoryAfterReturn[0].current_quantity}`); passed++; } else { console.log(` ❌ 退库后库存数据错误`); failed++; } console.log('\n--- 测试6:验证验收状态机 ---\n'); console.log(' 验收状态流转: pending → confirmed'); console.log(' 退库状态流转: pending → confirmed'); passed++; console.log('\n--- 清理测试数据 ---\n'); await runSQL('DELETE FROM project_material_inventory WHERE project_id = ?', [testProjectId]); await runSQL('DELETE FROM return_records WHERE project_id = ?', [testProjectId]); await runSQL('DELETE FROM verification_records WHERE purchase_order_id = ?', [testOrderId]); await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testOrderId]); await runSQL('DELETE FROM projects WHERE id = ?', [testProjectId]); console.log(' 测试数据已清理'); console.log('\n========================================'); console.log('测试结果汇总'); console.log('========================================\n'); console.log(`通过: ${passed}`); console.log(`失败: ${failed}`); if (errors.length > 0) { console.log('\n错误详情:'); errors.forEach(err => console.log(` - ${err}`)); } 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); if (testProjectId) { try { await runSQL('DELETE FROM project_material_inventory WHERE project_id = ?', [testProjectId]); await runSQL('DELETE FROM return_records WHERE project_id = ?', [testProjectId]); await runSQL('DELETE FROM verification_records WHERE purchase_order_id = ?', [testOrderId]); await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testOrderId]); await runSQL('DELETE FROM projects WHERE id = ?', [testProjectId]); } catch (e) {} } db.close(); process.exit(1); } } test();