Files
yunhaifinance/backend/test-verification-returns.js
T

208 lines
8.5 KiB
JavaScript

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