fix: 修复中介导入成功条数计算错误
问题: - 导入成功条数显示为负数 - 原因:成功数量计算使用 validRecords.size() - failures.size() - 但没有使用实际的数据库操作返回值 修复: - saveBatchWithUpsert 和 saveBatch 方法现在返回 int - 累加实际的数据库影响行数 - 使用 actualSuccessCount 变量跟踪真实成功数量 影响范围: - CcdiIntermediaryPersonImportServiceImpl - CcdiIntermediaryEntityImportServiceImpl
This commit is contained in:
269
doc/test-data/purchase_transaction/test-import-debug.js
Normal file
269
doc/test-data/purchase_transaction/test-import-debug.js
Normal file
@@ -0,0 +1,269 @@
|
||||
const axios = require('axios');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const FormData = require('form-data');
|
||||
|
||||
// 配置
|
||||
const BASE_URL = 'http://localhost:8080';
|
||||
const LOGIN_URL = `${BASE_URL}/login/test`;
|
||||
const IMPORT_URL = `${BASE_URL}/ccdi/purchaseTransaction/importData`;
|
||||
const STATUS_URL_TEMPLATE = `${BASE_URL}/ccdi/purchaseTransaction/importStatus`;
|
||||
const FAILURES_URL_TEMPLATE = `${BASE_URL}/ccdi/purchaseTransaction/importFailures`;
|
||||
|
||||
// 测试账号
|
||||
const USERNAME = 'admin';
|
||||
const PASSWORD = 'admin123';
|
||||
|
||||
// 测试文件
|
||||
const TEST_FILE = path.join(__dirname, 'purchase_test_data_2000_v2.xlsx');
|
||||
|
||||
/**
|
||||
* 登录获取token
|
||||
*/
|
||||
async function login() {
|
||||
try {
|
||||
console.log('正在登录...');
|
||||
const response = await axios.post(LOGIN_URL, {
|
||||
username: USERNAME,
|
||||
password: PASSWORD
|
||||
});
|
||||
|
||||
if (response.data.code === 200) {
|
||||
console.log('✓ 登录成功');
|
||||
return response.data.token;
|
||||
} else {
|
||||
throw new Error(`登录失败: ${response.data.msg}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('✗ 登录异常:', error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
async function importData(token, updateSupport = false) {
|
||||
try {
|
||||
console.log('\n========================================');
|
||||
console.log('开始导入测试');
|
||||
console.log('========================================');
|
||||
console.log(`文件: ${TEST_FILE}`);
|
||||
console.log(`更新支持: ${updateSupport}`);
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!fs.existsSync(TEST_FILE)) {
|
||||
throw new Error(`测试文件不存在: ${TEST_FILE}`);
|
||||
}
|
||||
|
||||
// 创建form-data
|
||||
const formData = new FormData();
|
||||
formData.append('file', fs.createReadStream(TEST_FILE));
|
||||
|
||||
console.log('\n正在上传文件...');
|
||||
|
||||
const response = await axios.post(
|
||||
`${IMPORT_URL}?updateSupport=${updateSupport}`,
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
...formData.getHeaders(),
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log('\n响应状态:', response.status);
|
||||
console.log('响应数据:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
if (response.data.code === 200) {
|
||||
console.log('\n✓ 导入任务已提交');
|
||||
return response.data.data.taskId;
|
||||
} else {
|
||||
throw new Error(`导入失败: ${response.data.msg}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('\n✗ 导入异常:', error.message);
|
||||
if (error.response) {
|
||||
console.error('响应数据:', JSON.stringify(error.response.data, null, 2));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询导入状态
|
||||
*/
|
||||
async function getImportStatus(token, taskId) {
|
||||
try {
|
||||
console.log(`\n查询导入状态 (taskId: ${taskId})...`);
|
||||
|
||||
const response = await axios.get(
|
||||
`${STATUS_URL_TEMPLATE}/${taskId}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log('导入状态:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
if (response.data.code === 200) {
|
||||
return response.data.data;
|
||||
} else {
|
||||
throw new Error(`查询状态失败: ${response.data.msg}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('✗ 查询状态异常:', error.message);
|
||||
if (error.response) {
|
||||
console.error('响应数据:', JSON.stringify(error.response.data, null, 2));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询失败记录
|
||||
*/
|
||||
async function getImportFailures(token, taskId) {
|
||||
try {
|
||||
console.log(`\n查询失败记录 (taskId: ${taskId})...`);
|
||||
|
||||
const response = await axios.get(
|
||||
`${FAILURES_URL_TEMPLATE}/${taskId}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log('失败记录数量:', response.data.total || response.data.data?.length);
|
||||
console.log('失败记录:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
if (response.data.code === 200) {
|
||||
return response.data.data || response.data.rows;
|
||||
} else {
|
||||
throw new Error(`查询失败记录失败: ${response.data.msg}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('✗ 查询失败记录异常:', error.message);
|
||||
if (error.response) {
|
||||
console.error('响应数据:', JSON.stringify(error.response.data, null, 2));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 轮询导入状态
|
||||
*/
|
||||
async function pollImportStatus(token, taskId, maxPolls = 30) {
|
||||
let pollCount = 0;
|
||||
const interval = 2000; // 2秒
|
||||
|
||||
console.log(`\n开始轮询导入状态 (最多${maxPolls}次, 间隔${interval}ms)...`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setInterval(async () => {
|
||||
pollCount++;
|
||||
|
||||
try {
|
||||
const status = await getImportStatus(token, taskId);
|
||||
|
||||
console.log(`\n[轮询 ${pollCount}/${maxPolls}] 状态: ${status.status}`);
|
||||
|
||||
if (status.status !== 'PROCESSING' && status.status !== 'PENDING' && status.status !== 'RUNNING') {
|
||||
clearInterval(timer);
|
||||
console.log('\n✓ 导入完成!');
|
||||
resolve(status);
|
||||
} else if (pollCount >= maxPolls) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('轮询超时'));
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(timer);
|
||||
reject(error);
|
||||
}
|
||||
}, interval);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*/
|
||||
async function main() {
|
||||
let token;
|
||||
let taskId;
|
||||
|
||||
try {
|
||||
// 登录
|
||||
token = await login();
|
||||
|
||||
// 导入数据
|
||||
taskId = await importData(token, false);
|
||||
|
||||
// 轮询状态
|
||||
const finalStatus = await pollImportStatus(token, taskId);
|
||||
|
||||
console.log('\n========================================');
|
||||
console.log('最终导入结果');
|
||||
console.log('========================================');
|
||||
console.log('状态:', finalStatus.status);
|
||||
console.log('总数:', finalStatus.totalCount);
|
||||
console.log('成功:', finalStatus.successCount);
|
||||
console.log('失败:', finalStatus.failureCount);
|
||||
console.log('消息:', finalStatus.message);
|
||||
|
||||
// 如果有失败记录,查询失败记录
|
||||
if (finalStatus.failureCount > 0) {
|
||||
console.log('\n有失败记录,正在查询...');
|
||||
const failures = await getImportFailures(token, taskId);
|
||||
|
||||
console.log('\n========================================');
|
||||
console.log('失败记录详情');
|
||||
console.log('========================================');
|
||||
console.log(`失败记录数: ${failures.length}`);
|
||||
|
||||
// 显示前10条失败记录
|
||||
const displayCount = Math.min(10, failures.length);
|
||||
console.log(`\n前${displayCount}条失败记录:`);
|
||||
|
||||
for (let i = 0; i < displayCount; i++) {
|
||||
const failure = failures[i];
|
||||
console.log(`\n[${i + 1}] 采购事项ID: ${failure.purchaseId}`);
|
||||
console.log(` 项目名称: ${failure.projectName || '(空)'}`);
|
||||
console.log(` 标的物名称: ${failure.subjectName || '(空)'}`);
|
||||
console.log(` 失败原因: ${failure.errorMessage}`);
|
||||
}
|
||||
|
||||
if (failures.length > displayCount) {
|
||||
console.log(`\n... 还有 ${failures.length - displayCount} 条失败记录`);
|
||||
}
|
||||
|
||||
// 统计失败原因
|
||||
const errorReasons = {};
|
||||
failures.forEach(f => {
|
||||
const reason = f.errorMessage;
|
||||
errorReasons[reason] = (errorReasons[reason] || 0) + 1;
|
||||
});
|
||||
|
||||
console.log('\n失败原因统计:');
|
||||
Object.entries(errorReasons)
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.forEach(([reason, count]) => {
|
||||
console.log(` ${reason}: ${count}条`);
|
||||
});
|
||||
} else {
|
||||
console.log('\n✓ 全部导入成功,无失败记录');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n✗ 测试失败:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user