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

278 lines
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 测试付款计划功能
* 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.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();