You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1555 lines
62 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. package com.inscloudtech.bankStatementAnalysis.helper;
  2. import cn.hutool.core.date.DateUtil;
  3. import cn.hutool.core.io.FileUtil;
  4. import cn.hutool.core.util.IdUtil;
  5. import cn.hutool.core.util.NumberUtil;
  6. import cn.hutool.core.util.StrUtil;
  7. import com.alibaba.excel.EasyExcel;
  8. import com.alibaba.excel.ExcelReader;
  9. import com.alibaba.excel.context.AnalysisContext;
  10. import com.alibaba.excel.exception.ExcelAnalysisStopException;
  11. import com.alibaba.excel.read.listener.ReadListener;
  12. import com.alibaba.excel.read.metadata.ReadSheet;
  13. import com.alibaba.excel.util.ListUtils;
  14. import com.aspose.cells.*;
  15. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  16. import com.inscloudtech.bankStatementAnalysis.helper.HelperUtil;
  17. import com.inscloudtech.bankStatementAnalysis.mapper.*;
  18. import com.inscloudtech.common.constant.BankStatementConstants;
  19. import com.inscloudtech.common.constant.Constants;
  20. import com.inscloudtech.common.exception.dc.AnalyzeDataFailedException;
  21. import com.inscloudtech.common.exception.dc.ImportDataFailedException;
  22. import com.inscloudtech.common.exception.dc.TemplateNotFindException;
  23. import com.inscloudtech.common.utils.bean.BeanUtils;
  24. import com.inscloudtech.common.utils.file.FileUtils;
  25. import com.inscloudtech.datacenter.domain.PlateNumberInfo;
  26. import com.inscloudtech.datacenter.mapper.es.*;
  27. import com.inscloudtech.datacenter.service.ImportResultService;
  28. import com.inscloudtech.bankStatementAnalysis.listener.ReadCCBCurrentAccountInfoListener;
  29. import com.inscloudtech.datacenter.domain.BankStatement;
  30. import com.inscloudtech.datacenter.domain.OpeningAccountInfo;
  31. import com.inscloudtech.bankStatementAnalysis.domain.entity.*;
  32. import com.inscloudtech.bankStatementAnalysis.util.AnalyzeFileHelper;
  33. import com.inscloudtech.bankStatementAnalysis.util.AsposeUtil;
  34. import lombok.Data;
  35. import lombok.RequiredArgsConstructor;
  36. import lombok.extern.slf4j.Slf4j;
  37. import org.apache.poi.openxml4j.util.ZipSecureFile;
  38. import org.springframework.stereotype.Component;
  39. import java.io.File;
  40. import java.math.BigDecimal;
  41. import java.util.*;
  42. import java.util.concurrent.atomic.AtomicInteger;
  43. import java.util.stream.Collectors;
  44. import com.alibaba.excel.converters.Converter;
  45. /**
  46. * 建设银行数据分析
  47. */
  48. @Slf4j
  49. @RequiredArgsConstructor
  50. @Component
  51. public class CCBDataAnalysisHelper {
  52. private final ImportResultService importResultService;
  53. private final EsCCBCurrentAccountInfoMapper accountInfoMapper;
  54. private final EsCCBRegularAccountInfoMapper esCCBRegularAccountInfoMapper;
  55. private final EsCCBElectronicCashAccountInfoMapper esCCBElectronicCashAccountInfoMapper;
  56. private final EsCCBElectronicCashBankStatementMapper esCCBElectronicCashBankStatementMapper;
  57. private final EsCCBRegularBankStatementMapper esCCBRegularBankStatementMapper;
  58. private final EsCCBCurrentBankStatementMapper esCCBCurrentBankStatementMapper;
  59. private final static String BANK_NAME = "建设银行";
  60. public void analyzeData(String caseId) {
  61. analyzeOAI(caseId);
  62. analyzeBS(caseId);
  63. }
  64. /**
  65. * 开户信息分析
  66. */
  67. private void analyzeOAI(String caseId) {
  68. analyzeElectronicCashOpeningAccountInfo(caseId);
  69. analyzeOtherOpeningAccountInfo(caseId);
  70. }
  71. private void analyzeElectronicCashOpeningAccountInfo(String caseId) {
  72. List<OpeningAccountInfo> oaiList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  73. List<CCBElectronicCashAccountInfoEntity> entityList = HelperUtil.getEntityList(
  74. esCCBElectronicCashAccountInfoMapper, CCBElectronicCashAccountInfoEntity.class);
  75. Set<String> uniqueKeySet = new HashSet();
  76. for (CCBElectronicCashAccountInfoEntity entity : entityList) {
  77. String cardHolderName = entity.getCardHolderName();
  78. if (StringUtils.isEmpty(cardHolderName)) {
  79. continue;
  80. }
  81. OpeningAccountInfo oai = new OpeningAccountInfo();
  82. oai.setName(cardHolderName);
  83. oai.setBankName(BANK_NAME);
  84. oai.setAccountNumber(entity.getCardNumber());
  85. oai.setIdType(entity.getIdType());
  86. oai.setIdNo(entity.getIdCardNo());
  87. String md5Id = HelperUtil.generateMD5Id4OAI(oai,caseId);
  88. //未导入数据内部去重
  89. if(HelperUtil.deduplication(md5Id,uniqueKeySet)){
  90. continue;
  91. }
  92. oai.setId(md5Id);
  93. oai.setCaseId(caseId);
  94. oaiList.add(oai);
  95. if (oaiList.size() >= Constants.BATCH_SIZE) {
  96. List<OpeningAccountInfo> dest = HelperUtil.getDest(oaiList);
  97. HelperUtil.batchSaveOAI2Es(dest, caseId);
  98. oaiList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  99. }
  100. }
  101. if (!oaiList.isEmpty()) {
  102. HelperUtil.batchSaveOAI2Es(oaiList, caseId);
  103. }
  104. }
  105. private void analyzeOtherOpeningAccountInfo(String caseId) {
  106. List<OpeningAccountInfo> oaiList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  107. List<CCBCurrentAccountInfoEntity> entityList =
  108. HelperUtil.getEntityList(accountInfoMapper, CCBCurrentAccountInfoEntity.class);
  109. Set<String> uniqueKeySet = new HashSet();
  110. for (CCBCurrentAccountInfoEntity entity : entityList) {
  111. String cardHolderName = entity.getCardHolderName();
  112. if (StringUtils.isEmpty(cardHolderName)) {
  113. continue;
  114. }
  115. OpeningAccountInfo oai = getOpeningAccountInfo(BANK_NAME, entity);
  116. String md5Id = HelperUtil.generateMD5Id4OAI(oai,caseId);
  117. //未导入数据内部去重
  118. if(HelperUtil.deduplication(md5Id,uniqueKeySet)){
  119. continue;
  120. }
  121. oai.setId(md5Id);
  122. oai.setCaseId(caseId);
  123. oaiList.add(oai);
  124. if (oaiList.size() >= Constants.BATCH_SIZE) {
  125. List<OpeningAccountInfo> dest = HelperUtil.getDest(oaiList);
  126. HelperUtil.batchSaveOAI2Es(dest, caseId);
  127. oaiList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  128. }
  129. }
  130. if (!oaiList.isEmpty()) {
  131. HelperUtil.batchSaveOAI2Es(oaiList, caseId);
  132. }
  133. }
  134. private static OpeningAccountInfo getOpeningAccountInfo(String bankName, CCBCurrentAccountInfoEntity entity) {
  135. OpeningAccountInfo oai = new OpeningAccountInfo();
  136. oai.setName(entity.getCardHolderName());
  137. oai.setBankName(BANK_NAME);
  138. oai.setAccountNumber(entity.getCardNumber());
  139. oai.setIdType(entity.getIdType());
  140. oai.setIdNo(entity.getIdCardNo());
  141. oai.setOpeningAccountDate(entity.getOpeningAccountDate());
  142. oai.setClosingDate(entity.getClosingDate());
  143. oai.setStatus(entity.getStatus());
  144. oai.setAccountOpeningInstitution(entity.getAccountOpeningInstitution());
  145. oai.setBalance(
  146. StrUtil.isEmpty(entity.getBalance()) ? BigDecimal.ZERO : NumberUtil.toBigDecimal(entity.getBalance()));
  147. oai.setFreezeInfo(entity.getFreezeInfo());
  148. return oai;
  149. }
  150. /**
  151. * 分析交易流水
  152. */
  153. private void analyzeBS(String caseId) {
  154. analyzeCurrentBS(caseId);
  155. analyzeRegularBS(caseId);
  156. analyzeElectronicCashBS(caseId);
  157. }
  158. private void analyzeElectronicCashBS(String caseId) {
  159. List<BankStatement> bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  160. List<CCBElectronicCashBankStatementEntity> entityList = HelperUtil.getEntityList(
  161. esCCBElectronicCashBankStatementMapper, CCBElectronicCashBankStatementEntity.class);
  162. // 根据名称去查找基本信息
  163. List<CCBElectronicCashAccountInfoEntity> infoList = HelperUtil.getEntityList(esCCBElectronicCashAccountInfoMapper,
  164. CCBElectronicCashAccountInfoEntity.class);
  165. Map<String, List<CCBElectronicCashAccountInfoEntity>> groupByCardHolderName = infoList.stream().filter(item ->StrUtil.isNotEmpty(item.getCardHolderName())).collect(Collectors.groupingBy(CCBElectronicCashAccountInfoEntity::getCardHolderName));
  166. Set<String> uniqueKeySet = new HashSet();
  167. List<PlateNumberInfo> plateNumberInfoList = new ArrayList<>();
  168. for (CCBElectronicCashBankStatementEntity entity : entityList) {
  169. String sourceFile = entity.getSourceFile();
  170. try {
  171. String cardHolderName = entity.getCardHolderName();
  172. if (StringUtils.isEmpty(cardHolderName)) {
  173. continue;
  174. }
  175. // 流水
  176. BankStatement bs = new BankStatement();
  177. bs.setBankName(BANK_NAME);
  178. bs.setCardHolderName(cardHolderName);
  179. if(StrUtil.isNotEmpty(cardHolderName) && StrUtil.isEmpty(bs.getIdCardNo())) {
  180. if (groupByCardHolderName.containsKey(cardHolderName)) {
  181. List<CCBElectronicCashAccountInfoEntity> infoEntities = groupByCardHolderName.get(cardHolderName);
  182. for (CCBElectronicCashAccountInfoEntity infoEntity : infoEntities) {
  183. if (StrUtil.isNotEmpty(infoEntity.getIdCardNo())) {
  184. bs.setIdCardNo(infoEntity.getIdCardNo());
  185. break;
  186. }
  187. }
  188. }
  189. }
  190. bs.setCardNumber(entity.getCardNumber());
  191. // 1 货币类型
  192. // 人民币
  193. bs.setTransCurrencyType(Constants.CURRENCY_TYPE_CHINA);
  194. // 2 交易金额 可能是double或者int类型
  195. String expenditureAmount = entity.getExpenditureAmount();
  196. if (StrUtil.isNotEmpty(expenditureAmount)) {
  197. bs.setTransactionAmount(new BigDecimal(expenditureAmount));
  198. }
  199. String incomeAmount = entity.getIncomeAmount();
  200. if (StrUtil.isNotEmpty(incomeAmount)) {
  201. BigDecimal value =new BigDecimal(incomeAmount);
  202. bs.setTransactionAmount(BigDecimal.ZERO.subtract(value));
  203. }
  204. // 3 余额
  205. bs.setBalance(BigDecimal.valueOf(Double.parseDouble(entity.getBalance())));
  206. // 4 交易日期
  207. String transDate = entity.getTransDate();
  208. if (StrUtil.isNotEmpty(transDate)) {
  209. String transTime = entity.getTransTime();
  210. try {
  211. if (StrUtil.isNotEmpty(transTime)) {
  212. bs.setTransactionTime(DateUtil.parse(transDate + " " + transTime, "yyyy-MM-dd HH:mm:ss"));
  213. } else {
  214. bs.setTransactionTime(DateUtil.parse(transDate, "yyyy-MM-dd"));
  215. }
  216. } catch (Exception e) {
  217. log.error("解析日期出错", e);
  218. throw new AnalyzeDataFailedException(
  219. StrUtil.format("日期格式为:yyyy-MM-dd HH:mm:ss,日期为:{}", transDate), e, sourceFile);
  220. }
  221. }
  222. String counterpartyName = entity.getCounterpartyName();
  223. bs.setCounterpartyName(counterpartyName);
  224. bs.setCounterpartyAccount(entity.getCounterpartyAccount());
  225. bs.setCounterpartyBankName(entity.getCounterpartyBankName());
  226. bs.setTransRemark(entity.getTansRemark());
  227. String md5Id = HelperUtil.generateMD5Id(bs,caseId);
  228. //未导入数据内部去重
  229. if(HelperUtil.deduplication(md5Id,uniqueKeySet)){
  230. continue;
  231. }
  232. bs.setSourceFile(entity.getSourceFile());
  233. bs.setId(md5Id);
  234. bs.setCaseId(caseId);
  235. try {
  236. BeanUtils.beanAttributeValueTrim(bs);
  237. } catch (Exception e) {
  238. e.printStackTrace();
  239. }
  240. bsList.add(bs);
  241. HelperUtil.extractPlateNumber(bs,plateNumberInfoList);
  242. if (bsList.size() >= Constants.BATCH_SIZE) {
  243. List<BankStatement> dest = HelperUtil.getDest(bsList);
  244. HelperUtil.batchInsert2Es(dest, caseId);
  245. bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  246. }
  247. } catch (Exception e) {
  248. importResultService.record(caseId, BANK_NAME, e,sourceFile);
  249. }
  250. }
  251. uniqueKeySet.clear();
  252. HelperUtil.batchInsertPlateNumber(plateNumberInfoList);
  253. // 保存数据库
  254. if (!bsList.isEmpty()) {
  255. List<BankStatement> dest = HelperUtil.getDest(bsList);
  256. HelperUtil.batchInsert2Es(dest, caseId);
  257. }
  258. }
  259. private void analyzeRegularBS(String caseId) {
  260. List<BankStatement> bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  261. List<CCBRegularBankStatementEntity> entityList =
  262. HelperUtil.getEntityList(esCCBRegularBankStatementMapper, CCBRegularBankStatementEntity.class);
  263. // 根据名称去查找基本信息
  264. List<CCBRegularAccountInfoEntity> infoList = HelperUtil.getEntityList(esCCBRegularAccountInfoMapper, CCBRegularAccountInfoEntity.class);
  265. Map<String, List<CCBRegularAccountInfoEntity>> groupByCardHolderName = infoList.stream().filter(item ->StrUtil.isNotEmpty(item.getCardHolderName())).collect(Collectors.groupingBy(CCBRegularAccountInfoEntity::getCardHolderName));
  266. Set<String> uniqueKeySet = new HashSet();
  267. List<PlateNumberInfo> plateNumberInfoList = new ArrayList<>();
  268. for (CCBRegularBankStatementEntity entity : entityList) {
  269. String sourceFile = entity.getSourceFile();
  270. try {
  271. String cardHolderName = entity.getCardHolderName();
  272. if (StringUtils.isEmpty(cardHolderName)) {
  273. continue;
  274. }
  275. // 流水
  276. BankStatement bs = new BankStatement();
  277. bs.setBankName(BANK_NAME);
  278. bs.setCardHolderName(cardHolderName);
  279. if(StrUtil.isNotEmpty(cardHolderName) && StrUtil.isEmpty(bs.getIdCardNo())) {
  280. if (groupByCardHolderName.containsKey(cardHolderName)) {
  281. List<CCBRegularAccountInfoEntity> infoEntities = groupByCardHolderName.get(cardHolderName);
  282. for (CCBRegularAccountInfoEntity infoEntity : infoEntities) {
  283. if (StrUtil.isNotEmpty(infoEntity.getIdCardNo())) {
  284. bs.setIdCardNo(infoEntity.getIdCardNo());
  285. break;
  286. }
  287. }
  288. }
  289. }
  290. bs.setCardNumber(entity.getCardNumber());
  291. // 1 货币类型
  292. // 人民币
  293. bs.setTransCurrencyType(Constants.CURRENCY_TYPE_CHINA);
  294. // 2 交易金额 可能是double或者int类型
  295. BigDecimal transactionAmount = entity.getTransactionAmount();
  296. String loanFlag = entity.getLoanFlag();
  297. if (StrUtil.isNotEmpty(loanFlag)) {
  298. if (Objects.equals("贷", loanFlag)) {
  299. bs.setTransactionAmount(transactionAmount);
  300. } else {
  301. bs.setTransactionAmount(BigDecimal.ZERO.subtract(transactionAmount));
  302. }
  303. }
  304. // 3 余额
  305. bs.setBalance(entity.getBalance());
  306. // 4 交易日期
  307. String transDate = entity.getTransDate();
  308. if (StrUtil.isNotEmpty(transDate)) {
  309. String transTime = entity.getTransTime();
  310. try {
  311. if (StrUtil.isNotEmpty(transTime)) {
  312. bs.setTransactionTime(DateUtil.parse(transDate + " " + transTime, "yyyy-MM-dd HH:mm:ss"));
  313. } else {
  314. bs.setTransactionTime(DateUtil.parse(transDate, "yyyy-MM-dd"));
  315. }
  316. } catch (Exception e) {
  317. log.error("日期转换异常", e);
  318. throw new AnalyzeDataFailedException(StrUtil.format("日期转换异常,日期:{},时间:{}", transDate), e, sourceFile);
  319. }
  320. }
  321. String counterpartyName = entity.getCounterpartyName();
  322. bs.setCounterpartyName(counterpartyName);
  323. bs.setTransactionInstitutions(entity.getTransactionInstitutions());
  324. bs.setCounterpartyAccount(entity.getCounterpartyAccount());
  325. bs.setTransChannel(entity.getTransChannel());
  326. bs.setSummary(entity.getSummary());
  327. String md5Id = HelperUtil.generateMD5Id(bs,caseId);
  328. //未导入数据内部去重
  329. if(HelperUtil.deduplication(md5Id,uniqueKeySet)){
  330. continue;
  331. }
  332. bs.setSourceFile(entity.getSourceFile());
  333. bs.setId(md5Id);
  334. bs.setCaseId(caseId);
  335. try {
  336. BeanUtils.beanAttributeValueTrim(bs);
  337. } catch (Exception e) {
  338. e.printStackTrace();
  339. }
  340. bsList.add(bs);
  341. HelperUtil.extractPlateNumber(bs,plateNumberInfoList);
  342. if (bsList.size() >= Constants.BATCH_SIZE) {
  343. List<BankStatement> dest = HelperUtil.getDest(bsList);
  344. HelperUtil.batchInsert2Es(dest, caseId);
  345. bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  346. }
  347. } catch (Exception e) {
  348. importResultService.record(caseId, BANK_NAME, e,sourceFile);
  349. }
  350. }
  351. uniqueKeySet.clear();
  352. HelperUtil.batchInsertPlateNumber(plateNumberInfoList);
  353. // 保存数据库
  354. if (!bsList.isEmpty()) {
  355. List<BankStatement> dest = HelperUtil.getDest(bsList);
  356. HelperUtil.batchInsert2Es(dest, caseId);
  357. }
  358. }
  359. private void analyzeCurrentBS(String caseId) {
  360. List<BankStatement> bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  361. List<CCBCurrentBankStatementEntity> entityList =
  362. HelperUtil.getEntityList(esCCBCurrentBankStatementMapper, CCBCurrentBankStatementEntity.class);
  363. List<CCBCurrentAccountInfoEntity> oaiList =
  364. HelperUtil.getEntityList(accountInfoMapper, CCBCurrentAccountInfoEntity.class);
  365. Map<String, List<CCBCurrentAccountInfoEntity>> groupByCardNumber = oaiList.stream().filter(item ->StrUtil.isNotEmpty(item.getCardNumber())).collect(Collectors.groupingBy(CCBCurrentAccountInfoEntity::getCardNumber));
  366. Map<String, List<CCBCurrentAccountInfoEntity>> groupByCardHolderName = oaiList.stream().filter(item ->StrUtil.isNotEmpty(item.getCardHolderName())).collect(Collectors.groupingBy(CCBCurrentAccountInfoEntity::getCardHolderName));
  367. Map<String, List<CCBCurrentBankStatementEntity>> map = new HashMap<>();
  368. Set<String> uniqueKeySet = new HashSet();
  369. List<PlateNumberInfo> plateNumberInfoList = new ArrayList<>();
  370. for (CCBCurrentBankStatementEntity entity : entityList) {
  371. String sourceFile = entity.getSourceFile();
  372. try {
  373. boolean isSame = false;
  374. String cardHolderName = entity.getCardHolderName();
  375. String cardNumber = entity.getCardNumber();
  376. if (StringUtils.isEmpty(cardHolderName)) {//这个判断直接过滤了企业数据
  377. if (groupByCardNumber.containsKey(cardNumber)) {
  378. List<CCBCurrentAccountInfoEntity> tempList = groupByCardNumber.get(cardNumber);
  379. for (CCBCurrentAccountInfoEntity oai : tempList) {
  380. if(StrUtil.isNotEmpty(oai.getCardHolderName())){
  381. cardHolderName = oai.getCardHolderName();
  382. }
  383. }
  384. }
  385. }
  386. if (HelperUtil.isContainsChinese(entity.getTransDate())) {
  387. continue;
  388. }
  389. // 去重
  390. String serialNumber = entity.getSerialNumber();
  391. if (StringUtils.isEmpty(serialNumber)) {
  392. serialNumber = "-";
  393. }
  394. List<CCBCurrentBankStatementEntity> value = map.getOrDefault(serialNumber, null);
  395. if (value == null) {
  396. value = new ArrayList<>();
  397. value.add(entity);
  398. map.put(serialNumber, value);
  399. } else {
  400. for (CCBCurrentBankStatementEntity entry : value) {
  401. if (HelperUtil.isTheSameBankStatement(entity, entry)) {
  402. isSame = true;
  403. break;
  404. }
  405. }
  406. if (isSame) {
  407. continue;
  408. } else {
  409. map.get(serialNumber).add(entity);
  410. }
  411. }
  412. // 流水
  413. BankStatement bs = new BankStatement();
  414. bs.setBankName(BANK_NAME);
  415. bs.setCardHolderName(cardHolderName);
  416. // 根据名称去查找基本信息
  417. if(StrUtil.isNotEmpty(cardHolderName) && StrUtil.isEmpty(bs.getIdCardNo())) {
  418. if (groupByCardHolderName.containsKey(cardHolderName)) {
  419. List<CCBCurrentAccountInfoEntity> infoEntities = groupByCardHolderName.get(cardHolderName);
  420. for (CCBCurrentAccountInfoEntity infoEntity : infoEntities) {
  421. if (StrUtil.isNotEmpty(infoEntity.getIdCardNo())) {
  422. bs.setIdCardNo(infoEntity.getIdCardNo());
  423. break;
  424. }
  425. }
  426. }
  427. }
  428. bs.setCardNumber(entity.getCardNumber());
  429. // 1 货币类型
  430. // 人民币
  431. bs.setTransCurrencyType(Constants.CURRENCY_TYPE_CHINA);
  432. // 2 交易金额 可能是double或者int类型
  433. try {
  434. if(StrUtil.isEmpty(entity.getLoanFlag()) && entity.getExpenditureAmount() != null && entity.getIncomeAmount() != null){
  435. BigDecimal expenditureAmount = BigDecimal.valueOf(Double.parseDouble(entity.getExpenditureAmount()));
  436. BigDecimal incomeAmount = BigDecimal.valueOf(Double.parseDouble(entity.getIncomeAmount()));
  437. bs.setTransactionAmount(incomeAmount.subtract(expenditureAmount));
  438. }else {
  439. BigDecimal transactionAmount = new BigDecimal(entity.getTransactionAmount());
  440. if(entity.getLoanFlag().contains("借")){
  441. bs.setTransactionAmount(transactionAmount.negate());
  442. } else {
  443. bs.setTransactionAmount(transactionAmount);
  444. }
  445. }
  446. } catch (Exception e) {
  447. throw new AnalyzeDataFailedException("金额解析异常", e, sourceFile);
  448. }
  449. // 3 余额
  450. bs.setBalance(BigDecimal.valueOf(Double.parseDouble(entity.getBalance())));
  451. // 4 交易日期
  452. String transDate = entity.getTransDate();
  453. if (StrUtil.isNotEmpty(transDate)) {
  454. String transTime = entity.getTransTime();
  455. try {
  456. if (StrUtil.isNotEmpty(transTime)) {
  457. bs.setTransactionTime(DateUtil.parse(transDate + " " + transTime, "yyyy-MM-dd HH:mm:ss"));
  458. } else {
  459. bs.setTransactionTime(DateUtil.parse(transDate, "yyyy-MM-dd"));
  460. }
  461. } catch (Exception e) {
  462. log.error("日期转换异常", e);
  463. throw new AnalyzeDataFailedException(StrUtil.format("日期转换异常:{}", transDate), e, sourceFile);
  464. }
  465. }else {
  466. continue;
  467. }
  468. String counterpartyName = entity.getCounterpartyName();
  469. bs.setCounterpartyName(counterpartyName);
  470. bs.setTransactionInstitutions(entity.getTransactionInstitutions());
  471. bs.setCounterpartyAccount(entity.getCounterpartyAccount());
  472. bs.setCounterpartyBankName(entity.getCounterpartyBankName());
  473. bs.setTransChannel(entity.getTransChannel());
  474. bs.setTransRemark(entity.getTansRemark());
  475. bs.setSummary(entity.getSummary());
  476. String md5Id = HelperUtil.generateMD5Id(bs,caseId);
  477. //未导入数据内部去重
  478. if(HelperUtil.deduplication(md5Id,uniqueKeySet)){
  479. continue;
  480. }
  481. bs.setSourceFile(entity.getSourceFile());
  482. bs.setId(md5Id);
  483. bs.setCaseId(caseId);
  484. try {
  485. BeanUtils.beanAttributeValueTrim(bs);
  486. } catch (Exception e) {
  487. e.printStackTrace();
  488. }
  489. bsList.add(bs);
  490. HelperUtil.extractPlateNumber(bs,plateNumberInfoList);
  491. if (bsList.size() >= Constants.BATCH_SIZE) {
  492. List<BankStatement> dest = HelperUtil.getDest(bsList);
  493. HelperUtil.batchInsert2Es(dest, caseId);
  494. bsList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  495. }
  496. } catch (Exception e) {
  497. e.printStackTrace();
  498. importResultService.record(caseId, BANK_NAME, e,sourceFile);
  499. }
  500. }
  501. uniqueKeySet.clear();
  502. HelperUtil.batchInsertPlateNumber(plateNumberInfoList);
  503. // 保存数据库
  504. if (!bsList.isEmpty()) {
  505. List<BankStatement> dest = HelperUtil.getDest(bsList);
  506. HelperUtil.batchInsert2Es(dest, caseId);
  507. }
  508. }
  509. public void importData(File file,String caseId) throws Exception {
  510. List<File> fileList = FileUtil.loopFiles(file);
  511. if (fileList.isEmpty()) {
  512. throw new ImportDataFailedException(
  513. StrUtil.format("导入失败,未找到Excel文件:{}", file.getName()), file.getAbsolutePath());
  514. }
  515. // 剔除汇总表
  516. fileList = fileList.stream()
  517. .filter(f -> {
  518. if (FileUtil.mainName(f).contains("汇总")) {
  519. AnalyzeFileHelper.putBSFile(f);
  520. return false;
  521. }
  522. return true;
  523. })
  524. .collect(Collectors.toList());
  525. List<File> excelFileList = HelperUtil.getExcelFile(fileList);
  526. for (File excelFile : excelFileList) {
  527. try {
  528. analysisCCBExcel(excelFile,caseId);
  529. } catch (Exception e) {
  530. importResultService.record(caseId, BANK_NAME, e);
  531. }
  532. }
  533. }
  534. private void analysisCCBExcel(File excelFile,String caseId) throws Exception {
  535. ZipSecureFile.setMinInflateRatio(0.001);
  536. String absolutePath = excelFile.getAbsolutePath();
  537. Workbook wb = new Workbook(absolutePath);
  538. WorksheetCollection worksheets = wb.getWorksheets();
  539. String sourceFile = HelperUtil.getSourceFileName(absolutePath,BANK_NAME);
  540. int count = worksheets.getCount();
  541. for (int sheetNo = 0; sheetNo < count; sheetNo++) {
  542. Worksheet ws = worksheets.get(sheetNo);
  543. String sheetName = ws.getName();
  544. Cells cells = ws.getCells();
  545. String ssss = sourceFile + BankStatementConstants.NAME_WITH_SHEET_NAME + sheetName;
  546. try {
  547. if (AsposeUtil.getCell(cells, "有无查询结果") != null) {
  548. continue;
  549. }else if (AsposeUtil.getCell(cells, "查询无数据") != null) {
  550. continue;
  551. } else if (AsposeUtil.getCell(cells, "个人账户信息") != null) {
  552. // 读取账户信息
  553. readAccountInfo(excelFile, cells, sheetNo, ssss);
  554. } else if (AsposeUtil.getCell(cells, "个人活期明细信息") != null) {
  555. // 读取活期信息
  556. readCurrentDetailsV2(excelFile, cells, sheetNo, ssss);
  557. } else if (AsposeUtil.getCell(cells, "个人定期明细信息") != null) {
  558. // 读取定期明细
  559. readRegularDetailsV2(excelFile, cells, sheetNo, ssss);
  560. } else if (AsposeUtil.getCell(cells, "新一代电子现金") != null || AsposeUtil.getCell(cells, "电子现金-新一代") != null) {
  561. // 读取电子现金明细
  562. readElectronicCashDetails(excelFile, cells, sheetNo, ssss);
  563. } else if (AsposeUtil.getCell(cells, "企业账户信息") != null) {
  564. // 读取企业账户信息
  565. readCompanyAccountInfo(excelFile, cells, sheetNo, ssss);
  566. } else if (AsposeUtil.getCell(cells, "企业活期明细信息") != null) {
  567. // 读取活期明细
  568. // readCompanyCurrentDetails(excelFile, cells, sheetNo);
  569. xiangjiaoTemplate(excelFile, sheetNo, ssss);
  570. } else if (AsposeUtil.getCell(cells, "企业定期明细信息") != null) {
  571. // 读取定期明细
  572. readCompanyRegularDetails(excelFile, cells, sheetNo);
  573. } else if (AsposeUtil.getCell(cells, "笔号") != null) {
  574. if(AsposeUtil.getCell(cells, "交易日期") != null ){
  575. readBSTemplate20240417(absolutePath, sheetNo,caseId, ssss);
  576. }else if(AsposeUtil.getCell(cells, "开户日期") != null ){
  577. readOAITemplate20240417(absolutePath, sheetNo,caseId, ssss);
  578. }
  579. } else if (AsposeUtil.getCell(cells, "错误原因") != null) {
  580. continue;
  581. }else {
  582. throw new TemplateNotFindException(ssss);
  583. }
  584. } catch (Exception e) {
  585. importResultService.record(caseId, BANK_NAME, e,ssss);
  586. }
  587. }
  588. }
  589. private void readOAITemplate20240417(String excelFile, int sheetNo, String caseId, String sourceFile) {
  590. ExcelReader reader = EasyExcel.read(excelFile).build();
  591. ReadSheet sheet = EasyExcel.readSheet(sheetNo)
  592. .headRowNumber(1)
  593. .head(CCBCurrentAccountInfoEntity.class)
  594. .registerReadListener(readTemplate20240417OAIReadListener(caseId,sourceFile))
  595. .build();
  596. reader.read(sheet);
  597. }
  598. private void readBSTemplate20240417(String excelFile,int sheetNo,String caseId,String sourceFile) {
  599. ExcelReader reader = EasyExcel.read(excelFile).build();
  600. ReadSheet sheet = EasyExcel.readSheet(sheetNo)
  601. .headRowNumber(1)
  602. .head(CCBCurrentBankStatementEntity.class)
  603. .registerReadListener(readTemplate20240417ReadListener(caseId,sourceFile))
  604. .build();
  605. reader.read(sheet);
  606. }
  607. public ReadListener<CCBCurrentAccountInfoEntity> readTemplate20240417OAIReadListener(String caseId,String sourceFile) {
  608. return new ReadListener<CCBCurrentAccountInfoEntity>() {
  609. List<CCBCurrentAccountInfoEntity> cacheList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  610. @Override
  611. public void invoke(CCBCurrentAccountInfoEntity entity, AnalysisContext context) {
  612. entity.setId(IdUtil.objectId());
  613. entity.setSourceFile(sourceFile);
  614. entity.setCaseId(caseId);
  615. cacheList.add(entity);
  616. if (cacheList.size() >= Constants.BATCH_SIZE) {
  617. save();
  618. }
  619. }
  620. @Override
  621. public void doAfterAllAnalysed(AnalysisContext context) {
  622. if (!cacheList.isEmpty()) {
  623. save();
  624. }
  625. }
  626. private void save() {
  627. accountInfoMapper.insertBatch(cacheList);
  628. cacheList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  629. }
  630. };
  631. }
  632. public ReadListener<CCBCurrentBankStatementEntity> readTemplate20240417ReadListener(String caseId,String sourceFile) {
  633. return new ReadListener<CCBCurrentBankStatementEntity>() {
  634. List<CCBCurrentBankStatementEntity> cacheList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  635. @Override
  636. public void invoke(CCBCurrentBankStatementEntity entity, AnalysisContext context) {
  637. entity.setId(IdUtil.objectId());
  638. entity.setSourceFile(sourceFile);
  639. entity.setCaseId(caseId);
  640. cacheList.add(entity);
  641. if (cacheList.size() >= Constants.BATCH_SIZE) {
  642. save();
  643. }
  644. }
  645. @Override
  646. public void doAfterAllAnalysed(AnalysisContext context) {
  647. if (!cacheList.isEmpty()) {
  648. save();
  649. }
  650. }
  651. private void save() {
  652. esCCBCurrentBankStatementMapper.insertBatch(cacheList);
  653. cacheList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  654. }
  655. };
  656. }
  657. private void readCompanyRegularDetails(File excelFile, Cells cells, int sheetNo) {
  658. Class<CCBRegularBankStatementEntity> headClazz = CCBRegularBankStatementEntity.class;
  659. String sourceFile = HelperUtil.getSourceFileName(excelFile.getAbsolutePath(),BANK_NAME);
  660. Cell startCell = null;
  661. Cell endCell = null;
  662. int startRow = 0;
  663. int endRow = 0;
  664. for (; ; ) {
  665. startCell = AsposeUtil.getCell(cells, "交易日期", startRow);
  666. if (startCell == null) {
  667. break;
  668. }
  669. startRow = startCell.getRow() + 1; // headRowNum
  670. endCell = AsposeUtil.getCell(cells, "根据查询条件", startRow);
  671. if (endCell == null) {
  672. // 设置最后一行
  673. endRow = cells.getMaxRow() + 1;
  674. } else {
  675. endRow = endCell.getRow() + 1;
  676. }
  677. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  678. ReadSheet rs = EasyExcel.readSheet(sheetNo)
  679. .head(headClazz)
  680. .headRowNumber(startRow)
  681. .registerReadListener(HelperUtil.getReadListener(
  682. esCCBRegularBankStatementMapper, headClazz, startRow, endRow,sourceFile))
  683. .build();
  684. r.read(rs);
  685. } catch (Exception e) {
  686. // if (e instanceof ExcelAnalysisStopException) {
  687. // continue;
  688. // }
  689. //
  690. // log.error("读取企业定期流水信息失败: " + e.getMessage(), e);
  691. // throw new ImportDataFailedException("读取企业定期流水信息失败: " + e.getMessage(), excelFile.getAbsolutePath());
  692. }
  693. startRow = endRow;
  694. }
  695. }
  696. // 读取活期明细
  697. private void readCompanyCurrentDetails(File excelFile, Cells cells, int sheetNo) {
  698. String sourceFile = HelperUtil.getSourceFileName(excelFile.getAbsolutePath(),BANK_NAME);
  699. Class<CCBCurrentBankStatementEntity> headClazz = CCBCurrentBankStatementEntity.class;
  700. Cell startCell = null;
  701. Cell endCell = null;
  702. int startRow = 0;
  703. int endRow = 0;
  704. for (; ; ) {
  705. startCell = AsposeUtil.getCell(cells, "交易日期", startRow);
  706. if (startCell == null) {
  707. break;
  708. }
  709. startRow = startCell.getRow() + 1; // headRowNum
  710. endCell = AsposeUtil.getCell(cells, "根据查询条件", startRow);
  711. if (endCell == null) {
  712. // 设置最后一行
  713. endRow = cells.getMaxRow() + 1;
  714. } else {
  715. endRow = endCell.getRow() + 1;
  716. }
  717. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  718. ReadSheet rs = EasyExcel.readSheet(sheetNo)
  719. .head(headClazz)
  720. .headRowNumber(startRow)
  721. .registerReadListener(HelperUtil.getReadListener(
  722. esCCBCurrentBankStatementMapper, headClazz, startRow, endRow,sourceFile))
  723. .build();
  724. r.read(rs);
  725. } catch (Exception e) {
  726. if (e instanceof ExcelAnalysisStopException) {
  727. continue;
  728. }
  729. log.error("读取企业活期流水信息失败: " + e.getMessage(), e);
  730. throw new ImportDataFailedException("读取企业活期流水信息失败: " + e.getMessage(), sourceFile);
  731. }
  732. startRow = endRow;
  733. }
  734. }
  735. private void xiangjiaoTemplate(File excelFile, int sheetNo , String sourceFile) throws Exception {
  736. List<AnalyzeItem> itemList = getAnalyzeItemList(excelFile.getAbsolutePath(), sheetNo);
  737. for (AnalyzeItem item : itemList) {
  738. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  739. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  740. .headRowNumber(item.headRowNumber)
  741. .head(CCBCurrentBankStatementEntity.class)
  742. .registerReadListener(getCurrentDetailListener(item,sourceFile))
  743. .build();
  744. r.read(readSheet);
  745. } catch (Exception e) {
  746. if (e instanceof ExcelAnalysisStopException) {
  747. continue;
  748. }
  749. // 停止继续读取需要抛出异常,这里不必处理
  750. log.error("读取个人活期明细信息失败: " + e.getMessage(), e);
  751. throw new AnalyzeDataFailedException("读取个人活期明细信息失败: " + e.getMessage(), e);
  752. }
  753. }
  754. }
  755. private void readCompanyAccountInfo(File excelFile, Cells cells, int sheetNo,String sourceFile) {
  756. // 关键字:企业活期账户信息
  757. Cell startCell = null;
  758. Cell endCell = null;
  759. int startRow = 0;
  760. int endRow = 0;
  761. Class<CCBCurrentAccountInfoEntity> headClazz = CCBCurrentAccountInfoEntity.class;
  762. String[] keys = {"企业活期账户信息", "企业定期账户信息"};
  763. for (String key : keys) {
  764. startCell = AsposeUtil.getCell(cells, key, startRow);
  765. if (startCell == null) {
  766. break;
  767. }
  768. startRow = startCell.getRow();
  769. Cell cell = AsposeUtil.getCell(cells, "开户日期", startRow );
  770. if (cell == null) {
  771. continue;
  772. }
  773. startRow = cell.getRow();
  774. // if (endCell != null) {
  775. // startRow = endCell.getRow();
  776. // }
  777. endCell = AsposeUtil.getCell(cells, "根据查询条件", startRow);
  778. if (endCell == null) {
  779. // 设置最后一行
  780. endRow = cells.getMaxRow() + 1;
  781. } else {
  782. endRow = endCell.getRow() + 1;
  783. }
  784. int headRowNumber = cell.getRow() + 1;
  785. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  786. ReadSheet rs = EasyExcel.readSheet(sheetNo)
  787. .head(headClazz)
  788. .headRowNumber(headRowNumber)
  789. .registerReadListener(
  790. HelperUtil.getReadListener(accountInfoMapper, headClazz, startRow, endRow,sourceFile))
  791. .build();
  792. r.read(rs);
  793. } catch (Exception e) {
  794. if (e instanceof ExcelAnalysisStopException) {
  795. continue;
  796. }
  797. log.error("读取企业活期账户信息失败: " + e.getMessage(), e);
  798. throw new ImportDataFailedException("读取企业活期账户信息失败: " + e.getMessage(), sourceFile);
  799. }
  800. }
  801. }
  802. // 读取定期数据,分为个人和企业两种数据
  803. private void readRegularDetailsV2(File excelFile, Cells cells, int sheetNo,String sourceFile) throws Exception {
  804. Cell cell = AsposeUtil.getCell(excelFile, sheetNo, "企业");
  805. if (cell != null) {
  806. readRegularDetailsForCompany(excelFile, sheetNo,sourceFile);
  807. } else {
  808. readRegularDetailsForPerson(excelFile, sheetNo,sourceFile);
  809. }
  810. }
  811. private void readRegularDetailsForCompany(File excelFile, int sheetNo,String sourceFile) throws Exception {
  812. List<AnalyzeItem> itemList = getAnalyzeItemListForCompany(excelFile.getAbsolutePath(), sheetNo);
  813. for (AnalyzeItem item : itemList) {
  814. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  815. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  816. .headRowNumber(item.headRowNumber)
  817. .head(CCBRegularBankStatementEntity.class)
  818. .registerReadListener(getRegularDetailListener(item,sourceFile))
  819. .build();
  820. r.read(readSheet);
  821. } catch (Exception e) {
  822. // 停止继续读取需要抛出异常,这里不必处理
  823. if (e instanceof ExcelAnalysisStopException) {
  824. continue;
  825. }
  826. log.error("读取公司定期流水文件失败: " + e.getMessage(), e);
  827. throw new ImportDataFailedException("读取公司定期流水文件失败: " + e.getMessage(), excelFile.getAbsolutePath());
  828. }
  829. }
  830. }
  831. private void readRegularDetailsForPerson(File excelFile, int sheetNo,String sourceFile) throws Exception {
  832. List<AnalyzeItem> itemList = getAnalyzeItemList(excelFile.getAbsolutePath(), sheetNo);
  833. for (AnalyzeItem item : itemList) {
  834. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  835. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  836. .headRowNumber(item.headRowNumber)
  837. .head(CCBRegularBankStatementEntity.class)
  838. .registerReadListener(getRegularDetailListener(item,sourceFile))
  839. .build();
  840. r.read(readSheet);
  841. } catch (Exception e) {
  842. // 停止继续读取需要抛出异常,这里不必处理
  843. log.error("读取_accounts_info文件失败", e);
  844. throw new AnalyzeDataFailedException("读取_accounts_info文件失败", e);
  845. }
  846. }
  847. }
  848. private ReadListener<CCBRegularBankStatementEntity> getRegularDetailListener(AnalyzeItem item,String sourceFile) {
  849. AtomicInteger cnt = new AtomicInteger(item.headRowNumber + 1);
  850. return new ReadListener<CCBRegularBankStatementEntity>() {
  851. private List<CCBRegularBankStatementEntity> docList =
  852. ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  853. @Override
  854. public void invoke(CCBRegularBankStatementEntity entity, AnalysisContext context) {
  855. String id = IdUtil.objectId();
  856. entity.setId(id);
  857. entity.setCardNumber(item.getCardNumber());
  858. entity.setCardHolderName(item.getCardHolderName());
  859. entity.setSourceFile(sourceFile);
  860. docList.add(entity);
  861. if (docList.size() >= Constants.BATCH_SIZE) {
  862. saveToMongo();
  863. docList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  864. }
  865. if (cnt.incrementAndGet() > item.endRowNumber) {
  866. saveToMongo();
  867. throw new ExcelAnalysisStopException("stop running.");
  868. }
  869. }
  870. private void saveToMongo() {
  871. if (!docList.isEmpty()) {
  872. esCCBRegularBankStatementMapper.insertBatch(docList);
  873. }
  874. }
  875. @Override
  876. public void doAfterAllAnalysed(AnalysisContext context) {
  877. if (!docList.isEmpty()) {
  878. saveToMongo();
  879. }
  880. }
  881. };
  882. }
  883. // 个人活期明细信息
  884. private void readCurrentDetailsV2(File excelFile, Cells cells, int sheetNo, String sourceFile) throws Exception {
  885. List<AnalyzeItem> itemList = getAnalyzeItemList(excelFile.getAbsolutePath(), sheetNo);
  886. for (AnalyzeItem item : itemList) {
  887. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  888. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  889. .headRowNumber(item.headRowNumber)
  890. .head(CCBCurrentBankStatementEntity.class)
  891. .registerReadListener(getCurrentDetailListener(item,sourceFile))
  892. .build();
  893. r.read(readSheet);
  894. } catch (Exception e) {
  895. if (e instanceof ExcelAnalysisStopException) {
  896. continue;
  897. }
  898. // 停止继续读取需要抛出异常,这里不必处理
  899. log.error("读取个人活期明细信息失败: " + e.getMessage(), e);
  900. throw new AnalyzeDataFailedException("读取个人活期明细信息失败: " + e.getMessage(), e);
  901. }
  902. }
  903. }
  904. private ReadListener<CCBCurrentBankStatementEntity> getCurrentDetailListener(AnalyzeItem item,String sourceFile) {
  905. AtomicInteger cnt = new AtomicInteger(item.headRowNumber + 1);
  906. return new ReadListener<CCBCurrentBankStatementEntity>() {
  907. private List<CCBCurrentBankStatementEntity> docList =
  908. ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  909. @Override
  910. public void invoke(CCBCurrentBankStatementEntity entity, AnalysisContext context) {
  911. if (HelperUtil.isContainsChinese(entity.getId())) {
  912. return;
  913. }
  914. String id = IdUtil.objectId();
  915. entity.setId(id);
  916. if(StrUtil.isEmpty(entity.getCardNumber())){
  917. entity.setCardNumber(item.getCardNumber());
  918. }
  919. entity.setSourceFile(sourceFile);
  920. entity.setCardHolderName(item.getCardHolderName());
  921. docList.add(entity);
  922. if (docList.size() >= Constants.BATCH_SIZE) {
  923. saveToMongo();
  924. docList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  925. }
  926. if (cnt.incrementAndGet() > item.endRowNumber) {
  927. saveToMongo();
  928. throw new ExcelAnalysisStopException("stop running.");
  929. }
  930. }
  931. private void saveToMongo() {
  932. if (!docList.isEmpty()) {
  933. esCCBCurrentBankStatementMapper.insertBatch(docList);
  934. }
  935. }
  936. @Override
  937. public void doAfterAllAnalysed(AnalysisContext context) {
  938. if (!docList.isEmpty()) {
  939. saveToMongo();
  940. }
  941. }
  942. };
  943. }
  944. /**
  945. * 读取电子现金明细
  946. */
  947. private void readElectronicCashDetails(File excelFile, Cells cells, int sheetNo,String sourceFile) throws Exception {
  948. List<AnalyzeItem> itemList = getAnalyzeItemList(excelFile.getAbsolutePath(), sheetNo);
  949. for (AnalyzeItem item : itemList) {
  950. try (ExcelReader r = EasyExcel.read(excelFile).build()) {
  951. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  952. .headRowNumber(item.headRowNumber)
  953. .head(CCBElectronicCashBankStatementEntity.class)
  954. .registerReadListener(getElectronicCashDetailListener(item,sourceFile))
  955. .build();
  956. r.read(readSheet);
  957. } catch (Exception e) {
  958. if (e instanceof ExcelAnalysisStopException) {
  959. // 停止继续读取需要抛出异常,这里不必处理
  960. continue;
  961. } else {
  962. // 打印日志,抛出异常
  963. log.error("读取电子现金明细异常", e);
  964. throw new ImportDataFailedException(e.getMessage(), excelFile.getAbsolutePath());
  965. }
  966. }
  967. }
  968. }
  969. private ReadListener<CCBElectronicCashBankStatementEntity> getElectronicCashDetailListener(AnalyzeItem item,String sourceFile) {
  970. AtomicInteger cnt = new AtomicInteger(item.headRowNumber + 1);
  971. return new ReadListener<CCBElectronicCashBankStatementEntity>() {
  972. private List<CCBElectronicCashBankStatementEntity> docList =
  973. ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  974. @Override
  975. public void invoke(CCBElectronicCashBankStatementEntity entity, AnalysisContext context) {
  976. String id = IdUtil.objectId();
  977. entity.setId(id);
  978. entity.setCardNumber(item.getCardNumber());
  979. entity.setCardHolderName(item.getCardHolderName());
  980. entity.setSourceFile(sourceFile);
  981. docList.add(entity);
  982. if (docList.size() >= Constants.BATCH_SIZE) {
  983. saveToMongo();
  984. docList = ListUtils.newArrayListWithExpectedSize(Constants.BATCH_SIZE);
  985. }
  986. if (cnt.incrementAndGet() > item.endRowNumber) {
  987. saveToMongo();
  988. throw new ExcelAnalysisStopException("stop running.");
  989. }
  990. }
  991. private void saveToMongo() {
  992. if (!docList.isEmpty()) {
  993. esCCBElectronicCashBankStatementMapper.insertBatch(docList);
  994. }
  995. }
  996. @Override
  997. public void doAfterAllAnalysed(AnalysisContext context) {
  998. if (!docList.isEmpty()) {
  999. saveToMongo();
  1000. }
  1001. }
  1002. @Override
  1003. public void onException(Exception exception, AnalysisContext context) throws Exception {
  1004. HelperUtil.handleException(exception);
  1005. ReadListener.super.onException(exception, context);
  1006. }
  1007. };
  1008. }
  1009. /**
  1010. * 读取账户信息
  1011. */
  1012. private void readAccountInfo(File excelFile, Cells cells, int sheetNo,String sourceFile) throws Exception {
  1013. // 三种账户信息
  1014. int currentStartRow = AsposeUtil.getRowNumber(excelFile, sheetNo, "活期账户信息", 0);
  1015. if (currentStartRow != -1) {
  1016. currentStartRow += 3;
  1017. // 根据查询条件
  1018. int currentEndRow = AsposeUtil.getRowNumber(excelFile, sheetNo, "根据查询条件", currentStartRow);
  1019. if (currentEndRow != -1) {
  1020. // 1、个人活期账户信息 个人活期账户信息
  1021. readCurrentAccountInfo(excelFile, sheetNo, currentStartRow, currentEndRow,sourceFile);
  1022. }
  1023. }
  1024. int regularStartRow = AsposeUtil.getRowNumber(excelFile, sheetNo, "定期账户信息", 0);
  1025. if (regularStartRow != -1) {
  1026. regularStartRow += 3;
  1027. int regularEndRow = AsposeUtil.getRowNumber(excelFile, sheetNo, "根据查询条件", regularStartRow);
  1028. if (regularEndRow != -1) {
  1029. // 2、个人定期账户信息
  1030. readRegularAccountInfo(excelFile, sheetNo, regularStartRow, regularEndRow,sourceFile);
  1031. }
  1032. }
  1033. int electronicCashStartRow = AsposeUtil.getRowNumber(excelFile, sheetNo, "个人电子现金账户信息", 0);
  1034. if (electronicCashStartRow != -1) {
  1035. electronicCashStartRow += 3;
  1036. int electronicCashEndRow =
  1037. AsposeUtil.getRowNumber(excelFile, sheetNo, "个人电子现金账户信息", electronicCashStartRow);
  1038. if (electronicCashEndRow != -1) {
  1039. // 3、个人电子现金账户信息
  1040. readElectronicCashAccountInfo(excelFile, sheetNo, electronicCashStartRow, electronicCashEndRow,sourceFile);
  1041. }
  1042. }
  1043. }
  1044. /**
  1045. * 读取电子现金账户信息
  1046. */
  1047. private void readElectronicCashAccountInfo(File excelFile, int sheetNo, int startRow, int endRow,String sourceFile) {
  1048. Class<CCBElectronicCashAccountInfoEntity> clazz = CCBElectronicCashAccountInfoEntity.class;
  1049. try (ExcelReader reader = EasyExcel.read(excelFile).build()) {
  1050. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  1051. .headRowNumber(startRow)
  1052. .head(clazz)
  1053. .registerReadListener(HelperUtil.getReadListener(
  1054. esCCBElectronicCashAccountInfoMapper, clazz, startRow, endRow,sourceFile))
  1055. .build();
  1056. reader.read(readSheet);
  1057. } catch (Exception e) {
  1058. if (e instanceof ExcelAnalysisStopException) {
  1059. return;
  1060. }
  1061. log.error("read current account info error", e);
  1062. throw new ImportDataFailedException(e.getMessage(), excelFile.getAbsolutePath());
  1063. }
  1064. }
  1065. /**
  1066. * 读取定期账户信息
  1067. */
  1068. private void readRegularAccountInfo(File excelFile, int sheetNo, int startRow, int endRow,String sourceFile) {
  1069. try (ExcelReader reader = EasyExcel.read(excelFile).build()) {
  1070. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  1071. .headRowNumber(startRow)
  1072. .head(CCBRegularAccountInfoEntity.class)
  1073. .registerReadListener(
  1074. HelperUtil.getReadListener(esCCBRegularAccountInfoMapper, CCBRegularAccountInfoEntity.class, startRow, endRow,sourceFile))
  1075. .build();
  1076. reader.read(readSheet);
  1077. } catch (Exception e) {
  1078. if (e instanceof ExcelAnalysisStopException) {
  1079. return;
  1080. }
  1081. log.error("read current account info error", e);
  1082. throw new ImportDataFailedException(e.getMessage(), excelFile.getAbsolutePath());
  1083. }
  1084. }
  1085. /**
  1086. * 读取活期账户信息
  1087. */
  1088. private void readCurrentAccountInfo(File excelFile, int sheetNo, int startRow, int endRow,String sourceFile) {
  1089. try (ExcelReader reader = EasyExcel.read(excelFile).build()) {
  1090. ReadSheet readSheet = EasyExcel.readSheet(sheetNo)
  1091. .headRowNumber(startRow)
  1092. .head(CCBCurrentAccountInfoEntity.class)
  1093. .registerReadListener(new ReadCCBCurrentAccountInfoListener(startRow, endRow, accountInfoMapper,sourceFile))
  1094. .build();
  1095. reader.read(readSheet);
  1096. } catch (Exception e) {
  1097. if (e instanceof ExcelAnalysisStopException) {
  1098. return;
  1099. }
  1100. log.error("read current account info error", e);
  1101. throw new ImportDataFailedException(e.getMessage(), excelFile.getAbsolutePath());
  1102. }
  1103. }
  1104. /**
  1105. * 通过读取汇总结果得到相关文件
  1106. */
  1107. private Set<String> readSummary(File f) {
  1108. List<CCBSummaryEntry> summaryList = new ArrayList<>();
  1109. Set<String> fileNameSet = new HashSet<>();
  1110. try (ExcelReader reader = EasyExcel.read(f).build()) {
  1111. ReadSheet sheet = EasyExcel.readSheet()
  1112. .headRowNumber(2)
  1113. .head(CCBSummaryEntry.class)
  1114. .registerReadListener(new ReadListener<CCBSummaryEntry>() {
  1115. @Override
  1116. public void invoke(CCBSummaryEntry entry, AnalysisContext context) {
  1117. summaryList.add(entry);
  1118. }
  1119. @Override
  1120. public void doAfterAllAnalysed(AnalysisContext context) {
  1121. // 读取文件结束
  1122. for (CCBSummaryEntry entry : summaryList) {
  1123. String resultFileName = entry.getResultFileName();
  1124. if (!com.inscloudtech.common.utils.StringUtils.isEmpty(resultFileName)) {
  1125. int idx = resultFileName.indexOf("_");
  1126. if (idx != -1) {
  1127. String fileName = resultFileName.substring(idx + 1);
  1128. Integer resultCount = entry.getResultCount();
  1129. if (resultCount != 0) {
  1130. fileNameSet.add(fileName);
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. })
  1137. .build();
  1138. // 读文件
  1139. reader.read(sheet);
  1140. }
  1141. return fileNameSet;
  1142. }
  1143. // ------------------------------------------------------------------------------------------------------------------
  1144. private List<AnalyzeItem> getAnalyzeItemListForCompany(String filename, int sheetNo) throws Exception {
  1145. Workbook wb = new Workbook(filename);
  1146. WorksheetCollection worksheets = wb.getWorksheets();
  1147. Worksheet ws = worksheets.get(sheetNo);
  1148. String mainKey = "根据查询条件";
  1149. final String key = "客户名称";
  1150. Cells cells = ws.getCells();
  1151. Cell roundStartCell = cells.find(mainKey, null);
  1152. List<AnalyzeItem> itemList = new ArrayList<>();
  1153. for (; ; ) {
  1154. if (roundStartCell == null) {
  1155. break;
  1156. }
  1157. Cell roundEndCell = cells.find(mainKey, roundStartCell);
  1158. Cell cell = cells.find(key, roundStartCell);
  1159. if (cell == null) {
  1160. break;
  1161. }
  1162. int roundEndRow;
  1163. if (roundEndCell == null) {
  1164. roundEndRow = cells.getMaxRow();
  1165. } else {
  1166. roundEndRow = roundEndCell.getRow();
  1167. }
  1168. int row = cell.getRow();
  1169. while (row < roundEndRow) {
  1170. AnalyzeItem ai = new AnalyzeItem();
  1171. // 说明这一轮有数据
  1172. // 客户名称:徐唯,客户编号:667190000103481964,客户账号:3860740150310007432,一本通账号或卡号:4340613860503177,存款种类:一户通,币别:人民币元,钞汇标志:钞,册号:0,笔号:1
  1173. String complexStr = cell.getStringValue(); // 解析客户名称和客户账号
  1174. if (StrUtil.isNotEmpty(complexStr)) {
  1175. String[] strArr = complexStr.split(",");
  1176. if (strArr.length > 3) {
  1177. String nameStr = strArr[0];
  1178. String[] nameArr = nameStr.split(":");
  1179. if (nameArr.length == 2) {
  1180. ai.setCardHolderName(nameArr[1]);
  1181. } else {
  1182. break;
  1183. }
  1184. String cardNumberStr = strArr[2];
  1185. String[] cardNumberArr = cardNumberStr.split(":");
  1186. if (cardNumberArr.length == 2) {
  1187. ai.setCardNumber(cardNumberArr[1]);
  1188. } else {
  1189. break;
  1190. }
  1191. }
  1192. } else {
  1193. break;
  1194. }
  1195. int headRowNumber = cell.getRow() + 2;
  1196. ai.setHeadRowNumber(headRowNumber);
  1197. cell = cells.find(key, cell);
  1198. if (cell == null) {
  1199. ai.setEndRowNumber(roundEndRow);
  1200. itemList.add(ai);
  1201. break;
  1202. }
  1203. row = cell.getRow();
  1204. ai.setEndRowNumber(Math.min(row, roundEndRow));
  1205. itemList.add(ai);
  1206. }
  1207. // 这一轮没有数据,开始下一轮
  1208. roundStartCell = roundEndCell;
  1209. }
  1210. return itemList;
  1211. }
  1212. private List<AnalyzeItem> getAnalyzeItemList(String filename, int sheetNo) throws Exception {
  1213. Workbook wb = new Workbook(filename);
  1214. WorksheetCollection worksheets = wb.getWorksheets();
  1215. Worksheet ws = worksheets.get(sheetNo);
  1216. String mainKey = "根据查询条件";
  1217. final String key = "客户名称";
  1218. Cells cells = ws.getCells();
  1219. Cell roundStartCell = cells.find(mainKey, null);
  1220. List<AnalyzeItem> itemList = new ArrayList<>();
  1221. for (; ; ) {
  1222. if (roundStartCell == null) {
  1223. break;
  1224. }
  1225. Cell roundEndCell = cells.find(mainKey, roundStartCell);
  1226. Cell cell = cells.find(key, roundStartCell);
  1227. if (cell == null) {
  1228. break;
  1229. }
  1230. int roundEndRow;
  1231. if (roundEndCell == null) {
  1232. roundEndRow = cells.getMaxRow() + 1;
  1233. } else {
  1234. roundEndRow = roundEndCell.getRow();
  1235. }
  1236. int row = cell.getRow();
  1237. while (row <= roundEndRow) {
  1238. AnalyzeItem ai = new AnalyzeItem();
  1239. // 说明这一轮有数据
  1240. // 客户名称:徐唯,客户编号:667190000103481964,客户账号:3860740150310007432,一本通账号或卡号:4340613860503177,存款种类:一户通,币别:人民币元,钞汇标志:钞,册号:0,笔号:1
  1241. String complexStr = cell.getStringValue(); // 解析客户名称和客户账号
  1242. if (StrUtil.isNotEmpty(complexStr)) {
  1243. String[] strArr = complexStr.split(",");
  1244. if (strArr.length > 3) {
  1245. String nameStr = strArr[0];
  1246. String[] nameArr = nameStr.split(":");
  1247. if (nameArr.length == 2) {
  1248. ai.setCardHolderName(nameArr[1]);
  1249. } else {
  1250. break;
  1251. }
  1252. String cardNumberStr = strArr[2];
  1253. String[] cardNumberArr = cardNumberStr.split(":");
  1254. if (cardNumberArr.length == 2) {
  1255. ai.setCardNumber(cardNumberArr[1]);
  1256. } else {
  1257. break;
  1258. }
  1259. }
  1260. } else {
  1261. break;
  1262. }
  1263. int headRowNumber = cell.getRow() + 2;
  1264. ai.setHeadRowNumber(headRowNumber);
  1265. cell = cells.find(key, cell);
  1266. if (cell == null) {
  1267. ai.setEndRowNumber(roundEndRow);
  1268. itemList.add(ai);
  1269. break;
  1270. }
  1271. row = cell.getRow();
  1272. ai.setEndRowNumber(Math.min(row, roundEndRow));
  1273. itemList.add(ai);
  1274. }
  1275. // 这一轮没有数据,开始下一轮
  1276. roundStartCell = roundEndCell;
  1277. }
  1278. return itemList;
  1279. }
  1280. @Data
  1281. public static class AnalyzeItem {
  1282. private int headRowNumber;
  1283. private int endRowNumber;
  1284. private String cardHolderName;
  1285. private String cardNumber;
  1286. }
  1287. }