备份:修复前完整项目快照 2026-04-19
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* 测试采购-付款-物流-退库一体化流程数据库表结构
|
||||
* 验证所有表是否正确创建,字段是否完整
|
||||
*/
|
||||
|
||||
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();
|
||||
Reference in New Issue
Block a user