209 lines
8.2 KiB
JavaScript
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();
|