Files
yunhaifinance/backend/test-procurement-logistics-tables.js
T

209 lines
8.2 KiB
JavaScript

/**
* 测试采购-付款-物流-退库一体化流程数据库表结构
* 验证所有表是否正确创建,字段是否完整
*/
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 runAllSQL = (sql, params = []) => {
return new Promise((resolve, reject) => {
db.all(sql, params, (err, rows) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
};
async function testTableStructure() {
let passed = 0;
let failed = 0;
const errors = [];
try {
console.log('\n========================================');
console.log('测试数据库表结构');
console.log('========================================\n');
const expectedTables = {
'logistics_companies': [
'id', 'code', 'name', 'address', 'phone', 'email', 'quotation_description', 'status', 'remark', 'created_at', 'updated_at'
],
'logistics_company_payment_infos': [
'id', 'logistics_company_id', 'account_name', 'account_number', 'bank_name', 'qr_code', 'is_default', 'created_at', 'updated_at'
],
'logistics_records': [
'id', 'code', 'purchase_order_id', 'ship_from', 'logistics_company_id', 'logistics_company',
'tracking_number', 'ship_date', 'ship_location', 'estimated_arrival_date',
'customs_arrival_date', 'customs_clearance_date',
'use_hub', 'hub_arrival_date', 'hub_receiver', 'hub_verified_quantity', 'second_ship_date',
'primary_freight', 'primary_freight_currency', 'primary_freight_status', 'primary_freight_document',
'secondary_freight', 'secondary_freight_currency', 'secondary_freight_status',
'driver_phone', 'cargo_weight', 'transport_distance',
'final_arrival_date', 'final_location', 'status', 'remark', 'created_by', 'created_at', 'updated_at'
],
'verification_records': [
'id', 'code', 'purchase_order_id', 'logistics_record_id',
'verification_type', 'verification_date', 'verifier', 'items',
'total_ordered', 'total_received', 'total_verified', 'total_rejected',
'project_id', 'storage_type', 'status', 'remark', 'attachments', 'created_at'
],
'return_records': [
'id', 'code', 'project_id', 'return_type', 'return_date', 'applicant',
'items', 'total_quantity', 'total_amount', 'cost_adjustment', 'refund_amount',
'status', 'remark', 'attachments', 'created_at'
],
'material_price_history': [
'id', 'product_id', 'purchase_order_id', 'supplier_id', 'supplier_country',
'unit_price', 'currency', 'quantity', 'purchase_date', 'created_at'
],
'project_material_inventory': [
'id', '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'
]
};
const expectedExtendedFields = {
'purchase_orders': ['project_id', 'supplier_country', 'estimated_amount', 'paid_amount', 'contract_url', 'quotation_url', 'actual_delivery_date', 'remark'],
'purchase_order_items': ['received_quantity', 'verified_quantity'],
'payment_plans': ['stage', 'planned_date', 'planned_amount', 'planned_percentage', 'actual_amount', 'actual_date', 'payment_request_id', 'reminder_days', 'remark'],
'payment_requests': ['payment_type', 'purchase_order_id', 'logistics_company_id', 'logistics_document_url', 'driver_phone', 'cargo_weight', 'transport_distance'],
'suppliers': ['supply_category', 'country', 'address', 'phone', 'email', 'status'],
'purchase_requests': ['expected_date']
};
console.log('--- 测试新创建的表 ---\n');
for (const [tableName, expectedColumns] of Object.entries(expectedTables)) {
console.log(`测试表: ${tableName}`);
const tableInfo = await runAllSQL(`PRAGMA table_info(${tableName})`);
if (tableInfo.length === 0) {
console.log(` ❌ 表 ${tableName} 不存在`);
failed++;
errors.push(`表 ${tableName} 不存在`);
continue;
}
const actualColumns = tableInfo.map(col => col.name);
let tablePassed = true;
for (const col of expectedColumns) {
if (!actualColumns.includes(col)) {
console.log(` ❌ 缺少字段: ${col}`);
tablePassed = false;
errors.push(`表 ${tableName} 缺少字段 ${col}`);
}
}
if (tablePassed) {
console.log(` ✅ 表 ${tableName} 结构正确 (${actualColumns.length} 个字段)`);
passed++;
} else {
failed++;
}
}
console.log('\n--- 测试扩展的字段 ---\n');
for (const [tableName, expectedColumns] of Object.entries(expectedExtendedFields)) {
console.log(`测试表扩展字段: ${tableName}`);
const tableInfo = await runAllSQL(`PRAGMA table_info(${tableName})`);
if (tableInfo.length === 0) {
console.log(` ❌ 表 ${tableName} 不存在`);
failed++;
continue;
}
const actualColumns = tableInfo.map(col => col.name);
let tablePassed = true;
for (const col of expectedColumns) {
if (!actualColumns.includes(col)) {
console.log(` ❌ 缺少扩展字段: ${col}`);
tablePassed = false;
errors.push(`表 ${tableName} 缺少扩展字段 ${col}`);
}
}
if (tablePassed) {
console.log(` ✅ 表 ${tableName} 扩展字段正确`);
passed++;
} else {
failed++;
}
}
console.log('\n--- 测试索引 ---\n');
const expectedIndexes = [
{ table: 'logistics_companies', index: 'idx_logistics_companies_code' },
{ table: 'logistics_companies', index: 'idx_logistics_companies_status' },
{ table: 'logistics_records', index: 'idx_logistics_records_code' },
{ table: 'logistics_records', index: 'idx_logistics_records_order' },
{ table: 'logistics_records', index: 'idx_logistics_records_status' },
{ table: 'verification_records', index: 'idx_verification_records_code' },
{ table: 'verification_records', index: 'idx_verification_records_order' },
{ table: 'return_records', index: 'idx_return_records_code' },
{ table: 'return_records', index: 'idx_return_records_project' },
{ table: 'material_price_history', index: 'idx_material_price_history_product' },
{ table: 'project_material_inventory', index: 'idx_project_material_inventory_project' },
{ table: 'purchase_orders', index: 'idx_purchase_orders_project' },
{ table: 'payment_requests', index: 'idx_payment_requests_type' }
];
for (const { table, index } of expectedIndexes) {
const indexList = await runAllSQL(`PRAGMA index_list(${table})`);
const indexNames = indexList.map(i => i.name);
if (indexNames.includes(index)) {
console.log(` ✅ 索引 ${index} 存在`);
passed++;
} else {
console.log(` ❌ 索引 ${index} 不存在`);
failed++;
errors.push(`索引 ${index} 不存在`);
}
}
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);
db.close();
process.exit(1);
}
}
testTableStructure();