fix: 修复中介导入成功条数计算错误

问题:
- 导入成功条数显示为负数
- 原因:成功数量计算使用 validRecords.size() - failures.size()
- 但没有使用实际的数据库操作返回值

修复:
- saveBatchWithUpsert 和 saveBatch 方法现在返回 int
- 累加实际的数据库影响行数
- 使用 actualSuccessCount 变量跟踪真实成功数量

影响范围:
- CcdiIntermediaryPersonImportServiceImpl
- CcdiIntermediaryEntityImportServiceImpl
This commit is contained in:
wkc
2026-02-08 17:18:18 +08:00
parent bb0d68c41d
commit 5ec5913759
2058 changed files with 234134 additions and 269 deletions

View File

@@ -0,0 +1,226 @@
const Excel = require('exceljs');
// 配置
const OUTPUT_FILE = 'purchase_test_data_2000_v2.xlsx';
const RECORD_COUNT = 2000;
// 数据池
const PURCHASE_CATEGORIES = ['货物类', '工程类', '服务类', '软件系统', '办公设备', '家具用具', '专用设备', '通讯设备'];
const PURCHASE_METHODS = ['公开招标', '邀请招标', '询价采购', '单一来源', '竞争性谈判'];
const DEPARTMENTS = ['人事部', '行政部', '财务部', '技术部', '市场部', '采购部', '研发部'];
const EMPLOYEES = [
{ id: 'EMP0001', name: '张伟' },
{ id: 'EMP0002', name: '王芳' },
{ id: 'EMP0003', name: '李娜' },
{ id: 'EMP0004', name: '刘洋' },
{ id: 'EMP0005', name: '陈静' },
{ id: 'EMP0006', name: '杨强' },
{ id: 'EMP0007', name: '赵敏' },
{ id: 'EMP0008', name: '孙杰' },
{ id: 'EMP0009', name: '周涛' },
{ id: 'EMP0010', name: '吴刚' },
{ id: 'EMP0011', name: '郑丽' },
{ id: 'EMP0012', name: '钱勇' },
{ id: 'EMP0013', name: '何静' },
{ id: 'EMP0014', name: '朱涛' },
{ id: 'EMP0015', name: '马超' }
];
// 生成随机整数
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 生成随机浮点数
function randomFloat(min, max, decimals = 2) {
const num = Math.random() * (max - min) + min;
return parseFloat(num.toFixed(decimals));
}
// 从数组中随机选择
function randomChoice(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
// 生成随机日期
function randomDate(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
// 生成采购事项ID
function generatePurchaseId(index) {
const timestamp = Date.now();
const num = String(index + 1).padStart(4, '0');
return `PUR${timestamp}${num}`;
}
// 生成测试数据
function generateTestData(count) {
const data = [];
const startDate = new Date('2023-01-01');
const endDate = new Date('2025-12-31');
for (let i = 0; i < count; i++) {
const purchaseQty = randomFloat(1, 5000, 2);
const unitPrice = randomFloat(100, 50000, 2);
const budgetAmount = parseFloat((purchaseQty * unitPrice).toFixed(2));
const discount = randomFloat(0.85, 0.98, 2);
const actualAmount = parseFloat((budgetAmount * discount).toFixed(2));
const employee = randomChoice(EMPLOYEES);
// 生成Date对象
const applyDateObj = randomDate(startDate, endDate);
// 生成后续日期(都比申请日期晚)
const planApproveDate = new Date(applyDateObj);
planApproveDate.setDate(planApproveDate.getDate() + randomInt(1, 7));
const announceDate = new Date(planApproveDate);
announceDate.setDate(announceDate.getDate() + randomInt(3, 15));
const bidOpenDate = new Date(announceDate);
bidOpenDate.setDate(bidOpenDate.getDate() + randomInt(5, 20));
const contractSignDate = new Date(bidOpenDate);
contractSignDate.setDate(contractSignDate.getDate() + randomInt(3, 10));
const expectedDeliveryDate = new Date(contractSignDate);
expectedDeliveryDate.setDate(expectedDeliveryDate.getDate() + randomInt(15, 60));
const actualDeliveryDate = new Date(expectedDeliveryDate);
actualDeliveryDate.setDate(actualDeliveryDate.getDate() + randomInt(-2, 5));
const acceptanceDate = new Date(actualDeliveryDate);
acceptanceDate.setDate(acceptanceDate.getDate() + randomInt(1, 7));
const settlementDate = new Date(acceptanceDate);
settlementDate.setDate(settlementDate.getDate() + randomInt(7, 30));
data.push({
purchaseId: generatePurchaseId(i),
purchaseCategory: randomChoice(PURCHASE_CATEGORIES),
projectName: `${randomChoice(PURCHASE_CATEGORIES)}采购项目-${String(i + 1).padStart(4, '0')}`,
subjectName: `${randomChoice(PURCHASE_CATEGORIES).replace('类', '')}配件-${String(i + 1).padStart(4, '0')}`,
subjectDesc: `${randomChoice(PURCHASE_CATEGORIES)}采购项目标的物详细描述-${String(i + 1).padStart(4, '0')}`,
purchaseQty: purchaseQty,
budgetAmount: budgetAmount,
bidAmount: actualAmount,
actualAmount: actualAmount,
contractAmount: actualAmount,
settlementAmount: actualAmount,
purchaseMethod: randomChoice(PURCHASE_METHODS),
supplierName: `供应商公司-${String(i + 1).padStart(4, '0')}有限公司`,
contactPerson: `联系人-${String(i + 1).padStart(4, '0')}`,
contactPhone: `13${randomInt(0, 9)}${String(randomInt(10000000, 99999999))}`,
supplierUscc: `91${randomInt(10000000, 99999999)}MA${String(randomInt(1000, 9999))}`,
supplierBankAccount: `6222${String(randomInt(100000000000000, 999999999999999))}`,
applyDate: applyDateObj, // Date对象
planApproveDate: planApproveDate,
announceDate: announceDate,
bidOpenDate: bidOpenDate,
contractSignDate: contractSignDate,
expectedDeliveryDate: expectedDeliveryDate,
actualDeliveryDate: actualDeliveryDate,
acceptanceDate: acceptanceDate,
settlementDate: settlementDate,
applicantId: employee.id,
applicantName: employee.name,
applyDepartment: randomChoice(DEPARTMENTS),
purchaseLeaderId: randomChoice(EMPLOYEES).id,
purchaseLeaderName: randomChoice(EMPLOYEES).name,
purchaseDepartment: '采购部'
});
}
return data;
}
// 创建Excel文件
async function createExcelFile() {
console.log('开始生成测试数据...');
console.log(`记录数: ${RECORD_COUNT}`);
// 生成测试数据
const testData = generateTestData(RECORD_COUNT);
console.log('测试数据生成完成');
// 创建工作簿
const workbook = new Excel.Workbook();
const worksheet = workbook.addWorksheet('采购交易数据');
// 定义列按照Excel实体类的index顺序
worksheet.columns = [
{ header: '采购事项ID', key: 'purchaseId', width: 25 },
{ header: '采购类别', key: 'purchaseCategory', width: 15 },
{ header: '项目名称', key: 'projectName', width: 30 },
{ header: '标的物名称', key: 'subjectName', width: 30 },
{ header: '标的物描述', key: 'subjectDesc', width: 35 },
{ header: '采购数量', key: 'purchaseQty', width: 15 },
{ header: '预算金额', key: 'budgetAmount', width: 18 },
{ header: '中标金额', key: 'bidAmount', width: 18 },
{ header: '实际采购金额', key: 'actualAmount', width: 18 },
{ header: '合同金额', key: 'contractAmount', width: 18 },
{ header: '结算金额', key: 'settlementAmount', width: 18 },
{ header: '采购方式', key: 'purchaseMethod', width: 15 },
{ header: '中标供应商名称', key: 'supplierName', width: 30 },
{ header: '供应商联系人', key: 'contactPerson', width: 15 },
{ header: '供应商联系电话', key: 'contactPhone', width: 18 },
{ header: '供应商统一信用代码', key: 'supplierUscc', width: 25 },
{ header: '供应商银行账户', key: 'supplierBankAccount', width: 25 },
{ header: '采购申请日期', key: 'applyDate', width: 18 },
{ header: '采购计划批准日期', key: 'planApproveDate', width: 18 },
{ header: '采购公告发布日期', key: 'announceDate', width: 18 },
{ header: '开标日期', key: 'bidOpenDate', width: 18 },
{ header: '合同签订日期', key: 'contractSignDate', width: 18 },
{ header: '预计交货日期', key: 'expectedDeliveryDate', width: 18 },
{ header: '实际交货日期', key: 'actualDeliveryDate', width: 18 },
{ header: '验收日期', key: 'acceptanceDate', width: 18 },
{ header: '结算日期', key: 'settlementDate', width: 18 },
{ header: '申请人工号', key: 'applicantId', width: 15 },
{ header: '申请人姓名', key: 'applicantName', width: 15 },
{ header: '申请部门', key: 'applyDepartment', width: 18 },
{ header: '采购负责人工号', key: 'purchaseLeaderId', width: 15 },
{ header: '采购负责人姓名', key: 'purchaseLeaderName', width: 15 },
{ header: '采购部门', key: 'purchaseDepartment', width: 18 }
];
// 添加数据
worksheet.addRows(testData);
// 设置表头样式
const headerRow = worksheet.getRow(1);
headerRow.font = { bold: true };
headerRow.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE6E6FA' }
};
// 保存文件
console.log('正在写入Excel文件...');
await workbook.xlsx.writeFile(OUTPUT_FILE);
console.log(`✓ 文件已保存: ${OUTPUT_FILE}`);
// 显示统计信息
console.log('\n========================================');
console.log('数据统计');
console.log('========================================');
console.log(`总记录数: ${testData.length}`);
console.log(`采购数量范围: ${Math.min(...testData.map(d => d.purchaseQty))} - ${Math.max(...testData.map(d => d.purchaseQty))}`);
console.log(`预算金额范围: ${Math.min(...testData.map(d => d.budgetAmount))} - ${Math.max(...testData.map(d => d.budgetAmount))}`);
console.log('\n前3条记录预览:');
testData.slice(0, 3).forEach((record, index) => {
console.log(`\n记录 ${index + 1}:`);
console.log(` 采购事项ID: ${record.purchaseId}`);
console.log(` 项目名称: ${record.projectName}`);
console.log(` 采购数量: ${record.purchaseQty}`);
console.log(` 预算金额: ${record.budgetAmount}`);
console.log(` 申请人: ${record.applicantName} (${record.applicantId})`);
console.log(` 申请部门: ${record.applyDepartment}`);
console.log(` 申请日期: ${record.applyDate}`);
});
}
// 运行
createExcelFile().catch(console.error);