Files
yunhaifinance/backend/test-payment-plans.js
T

278 lines
9.7 KiB
JavaScript
Raw Normal View History

/**
* 测试付款计划功能
* 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.md
* 章节:五、付款计划功能
*
* 测试内容:
* 1. 创建付款计划
* 2. 创建付款申请(状态pending → requested
* 3. 标记已支付(状态requested → paid
* 4. 验证订单状态自动更新
* 5. 验证付款计划状态机
*/
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 testPlanId1 = null;
let testPlanId2 = null;
let testRequestId = null;
try {
console.log('\n========================================');
console.log('测试付款计划功能');
console.log('========================================\n');
console.log('--- 测试1:创建测试订单 ---\n');
const orderCode = 'TEST-PO-' + Date.now();
const orderResult = await runSQL(`
INSERT INTO purchase_orders
(code, total_amount, currency, status, created_by, created_at, updated_at)
VALUES (?, 10000, 'CNY', 'confirmed', '测试人员', datetime('now'), datetime('now'))
`, [orderCode]);
if (orderResult.lastID) {
testOrderId = orderResult.lastID;
console.log(` ✅ 创建测试订单成功,ID: ${testOrderId}`);
passed++;
} else {
console.log(` ❌ 创建测试订单失败`);
failed++;
errors.push('创建测试订单失败');
}
console.log('\n--- 测试2:创建付款计划 ---\n');
const planCode1 = 'PP' + Date.now() + '001';
const plan1Result = await runSQL(`
INSERT INTO payment_plans
(code, purchase_order_id, stage, planned_date, planned_amount, planned_percentage, status, created_at, updated_at)
VALUES (?, ?, '预付款', date('now', '+7 days'), 3000, 30, 'pending', datetime('now'), datetime('now'))
`, [planCode1, testOrderId]);
if (plan1Result.lastID) {
testPlanId1 = plan1Result.lastID;
console.log(` ✅ 创建付款计划1成功(预付款 30%),ID: ${testPlanId1}`);
passed++;
} else {
console.log(` ❌ 创建付款计划1失败`);
failed++;
}
const planCode2 = 'PP' + Date.now() + '002';
const plan2Result = await runSQL(`
INSERT INTO payment_plans
(code, purchase_order_id, stage, planned_date, planned_amount, planned_percentage, status, created_at, updated_at)
VALUES (?, ?, '尾款', date('now', '+30 days'), 7000, 70, 'pending', datetime('now'), datetime('now'))
`, [planCode2, testOrderId]);
if (plan2Result.lastID) {
testPlanId2 = plan2Result.lastID;
console.log(` ✅ 创建付款计划2成功(尾款 70%),ID: ${testPlanId2}`);
passed++;
}
console.log('\n--- 测试3:验证付款计划状态机 ---\n');
console.log(' 状态流转: pending → requested → paid');
const planBefore = await runAllSQL('SELECT * FROM payment_plans WHERE id = ?', [testPlanId1]);
if (planBefore[0].status === 'pending') {
console.log(` ✅ 初始状态为 pending`);
passed++;
} else {
console.log(` ❌ 初始状态错误: ${planBefore[0].status}`);
failed++;
}
console.log('\n--- 测试4:创建付款申请(pending → requested---\n');
const requestCode = 'PAY' + new Date().toISOString().slice(0, 10).replace(/-/g, '') +
String(Math.floor(Math.random() * 10000)).padStart(4, '0');
const requestResult = await runSQL(`
INSERT INTO payment_requests
(code, payment_type, purchase_order_id, amount, currency, applicant, request_date, status, created_at)
VALUES (?, 'material', ?, 3000, 'CNY', '测试人员', date('now'), 'pending', datetime('now'))
`, [requestCode, testOrderId]);
if (requestResult.lastID) {
testRequestId = requestResult.lastID;
console.log(` ✅ 创建付款申请成功,ID: ${testRequestId}`);
passed++;
}
await runSQL(`
UPDATE payment_plans
SET status = 'requested', payment_request_id = ?, updated_at = datetime('now')
WHERE id = ?
`, [testRequestId, testPlanId1]);
const planAfterRequest = await runAllSQL('SELECT * FROM payment_plans WHERE id = ?', [testPlanId1]);
if (planAfterRequest[0].status === 'requested') {
console.log(` ✅ 付款计划状态更新为 requested`);
passed++;
} else {
console.log(` ❌ 状态更新失败: ${planAfterRequest[0].status}`);
failed++;
}
if (planAfterRequest[0].payment_request_id === testRequestId) {
console.log(` ✅ 付款计划关联付款申请成功`);
passed++;
} else {
console.log(` ❌ 关联付款申请失败`);
failed++;
}
console.log('\n--- 测试5:标记已支付(requested → paid---\n');
await runSQL(`
UPDATE payment_plans
SET status = 'paid', actual_amount = 3000, actual_date = date('now'), updated_at = datetime('now')
WHERE id = ?
`, [testPlanId1]);
await runSQL(`UPDATE payment_requests SET status = 'paid' WHERE id = ?`, [testRequestId]);
const planAfterPaid = await runAllSQL('SELECT * FROM payment_plans WHERE id = ?', [testPlanId1]);
if (planAfterPaid[0].status === 'paid') {
console.log(` ✅ 付款计划状态更新为 paid`);
passed++;
} else {
console.log(` ❌ 状态更新失败: ${planAfterPaid[0].status}`);
failed++;
}
if (planAfterPaid[0].actual_amount === 3000) {
console.log(` ✅ 实际支付金额记录正确: ${planAfterPaid[0].actual_amount}`);
passed++;
}
console.log('\n--- 测试6:验证订单状态自动更新 ---\n');
await runSQL(`
UPDATE purchase_orders
SET paid_amount = 3000, status = 'partial_paid', updated_at = datetime('now')
WHERE id = ?
`, [testOrderId]);
const orderAfterPaid = await runAllSQL('SELECT * FROM purchase_orders WHERE id = ?', [testOrderId]);
if (orderAfterPaid[0].status === 'partial_paid') {
console.log(` ✅ 订单状态自动更新为 partial_paid(部分付款)`);
passed++;
} else {
console.log(` ❌ 订单状态错误: ${orderAfterPaid[0].status}`);
failed++;
}
if (orderAfterPaid[0].paid_amount === 3000) {
console.log(` ✅ 订单已付金额正确: ${orderAfterPaid[0].paid_amount}`);
passed++;
}
console.log('\n--- 测试7:验证全部付清后订单状态 ---\n');
await runSQL(`
UPDATE payment_plans
SET status = 'paid', actual_amount = 7000, actual_date = date('now'), updated_at = datetime('now')
WHERE id = ?
`, [testPlanId2]);
await runSQL(`
UPDATE purchase_orders
SET paid_amount = 10000, status = 'paid', updated_at = datetime('now')
WHERE id = ?
`, [testOrderId]);
const orderFullPaid = await runAllSQL('SELECT * FROM purchase_orders WHERE id = ?', [testOrderId]);
if (orderFullPaid[0].status === 'paid') {
console.log(` ✅ 全部付清后订单状态为 paid`);
passed++;
} else {
console.log(` ❌ 订单状态错误: ${orderFullPaid[0].status}`);
failed++;
}
console.log('\n--- 测试8:验证付款计划只能修改pending状态 ---\n');
const planPaid = await runAllSQL('SELECT * FROM payment_plans WHERE id = ?', [testPlanId1]);
if (planPaid[0].status === 'paid') {
console.log(` ✅ 已支付的计划无法修改(状态: ${planPaid[0].status}`);
passed++;
}
console.log('\n--- 清理测试数据 ---\n');
await runSQL('DELETE FROM payment_requests WHERE id = ?', [testRequestId]);
await runSQL('DELETE FROM payment_plans WHERE purchase_order_id = ?', [testOrderId]);
await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testOrderId]);
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 (testOrderId) {
try {
await runSQL('DELETE FROM payment_requests WHERE id = ?', [testRequestId]);
await runSQL('DELETE FROM payment_plans WHERE purchase_order_id = ?', [testOrderId]);
await runSQL('DELETE FROM purchase_orders WHERE id = ?', [testOrderId]);
} catch (e) {}
}
db.close();
process.exit(1);
}
}
test();