diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/constant/ImportTaskConstants.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/constant/ImportTaskConstants.java new file mode 100644 index 0000000000..685e80a39a --- /dev/null +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/constant/ImportTaskConstants.java @@ -0,0 +1,26 @@ +package com.epmet.constant; + +/** + * 导入任务的业务类型常量 + */ +public interface ImportTaskConstants { + /** + * 居民 + */ + String BIZ_TYPE_RESI = "resi"; + + /** + * 处理状态:处理中 + */ + String PROCESS_STATUS_PROCESSING = "processing"; + + /** + * 处理状态:成功 + */ + String PROCESS_STATUS_FINISHED_SUCCESS = "finished_success"; + + /** + * 处理状态:完成,但未完全成功 + */ + String PROCESS_STATUS_FINISHED_FAIL = "finished_fail"; +} diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java index 1350ce159f..7624198dfb 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java @@ -38,11 +38,13 @@ import com.epmet.commons.tools.redis.RedisKeys; import com.epmet.commons.tools.redis.RedisUtils; import com.epmet.commons.tools.redis.common.CustomerStaffRedis; import com.epmet.commons.tools.security.dto.TokenDto; +import com.epmet.commons.tools.security.user.LoginUserUtil; import com.epmet.commons.tools.utils.ExcelUtils; import com.epmet.commons.tools.utils.HttpClientManager; import com.epmet.commons.tools.utils.IpUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.commons.tools.validator.ValidatorUtils; +import com.epmet.constant.ImportTaskConstants; import com.epmet.constant.SystemMessageType; import com.epmet.dto.IcResiUserDTO; import com.epmet.dto.form.*; @@ -54,6 +56,7 @@ import com.epmet.feign.OperCustomizeOpenFeignClient; import com.epmet.feign.OssFeignClient; import com.epmet.service.IcResiUserImportService; import com.epmet.service.IcResiUserService; +import com.epmet.service.ImportTaskService; import jodd.io.FileUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; @@ -118,6 +121,11 @@ public class IcResiUserController { private RedisUtils redisUtils; @Autowired private EpmetMessageOpenFeignClient epmetMessageOpenFeignClient; + @Autowired + private LoginUserUtil loginUserUtil; + @Autowired + private ImportTaskService importTaskService; + /** * 模板枚举 @@ -431,6 +439,18 @@ public class IcResiUserController { throw new RenException("文件类型不匹配"); } + String operatorId = loginUserUtil.getLoginUserId(); + String importTaskId; + + // 记录导入任务 + if (importTaskService.existsProcessingTask(operatorId, ImportTaskConstants.BIZ_TYPE_RESI)) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), + "已存在执行中的导入任务,请等待执行完成。", + "已存在执行中的导入任务,请等待执行完成。"); + } else { + importTaskId = importTaskService.createProcessTask(operatorId, ImportTaskConstants.BIZ_TYPE_RESI); + } + Path savePath = null; try { String fileName = UUID.randomUUID().toString().concat(".").concat(extension); @@ -438,10 +458,14 @@ public class IcResiUserController { IOUtils.copy(file.getInputStream(), new FileOutputStream(savePath.toString())); List formItemList = icResiUserService.listFormItems(customerId,IcFormCodeEnum.RESI_BASE_INFO.getCode()); - icResiUserImportService.importIcResiInfoFromExcel(formItemList, savePath.toString(), response); - } catch (IOException e) { - String errorMsg = ExceptionUtils.getErrorStackTrace(e); + + icResiUserImportService.importIcResiInfoFromExcel(importTaskId, formItemList, savePath.toString(), response); + } catch (Throwable e) { + String errorMsg = ExceptionUtils.getThrowableErrorStackTrace(e); log.error("【导入居民信息失败】导入失败:{}", errorMsg); + + // 要将导入任务状态设置为结束但不成功 + importTaskService.finish(importTaskId, ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL, operatorId, null, e.getMessage()); throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode()); } finally { try { diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/ImportTaskDao.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/ImportTaskDao.java new file mode 100644 index 0000000000..1306b7e3cd --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/dao/ImportTaskDao.java @@ -0,0 +1,31 @@ +package com.epmet.dao; + +import com.epmet.commons.mybatis.dao.BaseDao; +import com.epmet.entity.ImportTaskEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2022-02-15 + */ +@Mapper +public interface ImportTaskDao extends BaseDao { + + /** + * 完成导入 + * @param taskId 任务id + * @param processStatus 处理状态 + * @param operatorId 操作者id + * @param resultDesc 结果文字描述 + * @param resultDescFile 结果描述文件 + * @return + */ + int finish(@Param("taskId") String taskId, + @Param("process_status") String processStatus, + @Param("operatorId") String operatorId, + @Param("resultDesc") String resultDesc, + @Param("resultDescFile") String resultDescFile); +} \ No newline at end of file diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/entity/ImportTaskEntity.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/entity/ImportTaskEntity.java new file mode 100644 index 0000000000..742c6cc93e --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/entity/ImportTaskEntity.java @@ -0,0 +1,48 @@ +package com.epmet.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import com.epmet.commons.mybatis.entity.BaseEpmetEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2022-02-15 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("import_task") +public class ImportTaskEntity extends BaseEpmetEntity { + + private static final long serialVersionUID = 1L; + + /** + * 业务类型。resi:居民;楼栋:building;房屋:house。依次补充 + */ + private String bizType; + + /** + * 处理状态。processing:处理中;finished:完成; + */ + private String processStatus; + + /** + * 谁导入的 + */ + private String operatorId; + + /** + * 开始导入的时间 + */ + private Date startTime; + + private String resultDescFile; + + private String resultDesc; + +} diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserImportService.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserImportService.java index 7f3d0bdca0..35748c9ddc 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserImportService.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserImportService.java @@ -12,5 +12,5 @@ import java.util.List; */ public interface IcResiUserImportService { - void importIcResiInfoFromExcel(List formItemList, String excelPathName, HttpServletResponse response); + void importIcResiInfoFromExcel(String importTaskId, List formItemList, String excelPathName, HttpServletResponse response); } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/ImportTaskService.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/ImportTaskService.java new file mode 100644 index 0000000000..65245abd98 --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/ImportTaskService.java @@ -0,0 +1,35 @@ +package com.epmet.service; + + +/** + * + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2022-02-15 + */ +public interface ImportTaskService { + + /** + * 检查指定类型该用户是否存在处理中的导入任务 + * @param operatorId 操作者ID + * @param bizType 业务类型。resi:居民 + * @return + */ + boolean existsProcessingTask(String operatorId, String bizType); + + /** + * 创建处理任务 + * @param operatorId + * @param bizType + */ + String createProcessTask(String operatorId, String bizType); + + /** + * 结束导入 + * @param taskId 任务id + * @param processStatus 处理状态 + * @param resultDescFile 结果描述文件 + * @param resultDesc 结果描述文本 + */ + Boolean finish(String taskId, String processStatus, String operatorId, String resultDescFile, String resultDesc); +} \ No newline at end of file diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserImportServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserImportServiceImpl.java index 32314bff9b..4ff0a8abaa 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserImportServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserImportServiceImpl.java @@ -24,6 +24,7 @@ import com.epmet.commons.tools.redis.common.CustomerStaffRedis; import com.epmet.commons.tools.security.user.LoginUserUtil; import com.epmet.commons.tools.utils.ConvertUtils; import com.epmet.commons.tools.utils.Result; +import com.epmet.constant.ImportTaskConstants; import com.epmet.dao.IcResiUserDao; import com.epmet.dao.IcUserChangeDetailedDao; import com.epmet.dao.IcUserChangeRecordDao; @@ -72,7 +73,6 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res // 错误和跳过excel行暂存 public static final ThreadLocal>> errorRows = new ThreadLocal<>(); - public static final ThreadLocal>> skipedRows = new ThreadLocal<>(); /** * 导入的居民中,新增或者变动的居民 @@ -126,6 +126,9 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res @Autowired private RedisUtils redisUtils; + @Autowired + private ImportTaskService importTaskService; + /** * 字表中不需要的列 @@ -212,11 +215,13 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res /** * 导入居民信息 - * 导入主表和所有子表信息 - * @return + * @param importTaskId 导入任务id + * @param formItemList item列表 + * @param excelPathName excel缓存路径 + * @param response 响应对象 */ @Override - public void importIcResiInfoFromExcel(List formItemList, String excelPathName, HttpServletResponse response) { + public void importIcResiInfoFromExcel(String importTaskId, List formItemList, String excelPathName, HttpServletResponse response) { String loginUserId = loginUserUtil.getLoginUserId(); String loginUserApp = loginUserUtil.getLoginUserApp(); @@ -235,6 +240,8 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res CustomerAgencyDTO agencyInfo = getResultDataOrThrowsException(govOrgOpenFeignClient.getAgencyById(currUserAgencyId), ServiceConstant.GOV_ORG_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), null, null); String customerId = agencyInfo.getCustomerId(); + boolean hasErrorRows = false; + try { initImportThreadLocal(customerId); @@ -273,11 +280,27 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res saveResiCategoryChangedRecord(categoryChangedResis); saveTransferedResiRecord(transferedResis); + hasErrorRows = hasErrorRows(); + try { - downLoadResults(response); + // todo 做了导入记录之后,这里就要判断,没有错误就不生成文件了 + downLoadResults(hasErrorRows, response); } catch (IOException e) { log.error("【导入IC居民附加信息】下载导入结果信息失败:{}", ExceptionUtils.getErrorStackTrace(e)); } + + // 更新上传记录 + if (hasErrorRows) { + importTaskService.finish(importTaskId, ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL, loginUserId, + null, null); + } else { + importTaskService.finish(importTaskId, ImportTaskConstants.PROCESS_STATUS_FINISHED_SUCCESS, loginUserId, + null, null); + } + + } catch (Exception e) { + // 抛出,让外层捕获处理,记录 + throw e; } finally { // 清空rediskey try { @@ -289,7 +312,6 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res } // 清空线程变量 - skipedRows.remove(); errorRows.remove(); newlyOrChangedResi.remove(); resiCategoryColumnNameAndLabel.remove(); @@ -297,6 +319,22 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res } } + /** + * 是否有错误行 + * @return + */ + private Boolean hasErrorRows() { + boolean hasError = false; + Map> tableAndErrorRows = errorRows.get(); + for (Map.Entry> entry:tableAndErrorRows.entrySet()) { + if (entry.getValue().size() != 0) { + hasError = true; + } + } + + return hasError; + } + /** * threadLocal初始化 */ @@ -310,7 +348,6 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res for (IcResiUserTableEnum e : IcResiUserTableEnum.values()) { skipedRowsMap.put(e.getTableName(), new LinkedList<>()); } - skipedRows.set(skipedRowsMap); // 错误信息 Map> errorRowsMap = new LinkedHashMap<>(); @@ -1000,19 +1037,11 @@ public class IcResiUserImportServiceImpl implements IcResiUserImportService, Res * @param response * @throws IOException */ - public void downLoadResults(HttpServletResponse response) throws IOException { + public void downLoadResults(Boolean hasErrorRows, HttpServletResponse response) throws IOException { String fileName; // 判断是否有错误信息,以确定文件名 - boolean hasError = false; - Map> tableAndErrorRows = errorRows.get(); - for (Map.Entry> entry:tableAndErrorRows.entrySet()) { - if (entry.getValue().size() != 0) { - hasError = true; - } - } - - if (hasError) { + if (hasErrorRows) { fileName = "导入失败条目清单.xls"; } else { fileName = "导入成功.xls"; diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/ImportTaskServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/ImportTaskServiceImpl.java new file mode 100644 index 0000000000..d80ee5d9a6 --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/ImportTaskServiceImpl.java @@ -0,0 +1,57 @@ +package com.epmet.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.epmet.constant.ImportTaskConstants; +import com.epmet.dao.ImportTaskDao; +import com.epmet.entity.ImportTaskEntity; +import com.epmet.service.ImportTaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; + +/** + * + * + * @author generator generator@elink-cn.com + * @since v1.0.0 2022-02-15 + */ +@Service +public class ImportTaskServiceImpl implements ImportTaskService { + + @Autowired + private ImportTaskDao importRecordDao; + + /** + * 该用户,该业务类型,是否有正在处理的导入任务 + * @param operatorId 操作者ID + * @param bizType 业务类型。resi:居民 + * @return + */ + @Override + public boolean existsProcessingTask(String operatorId, String bizType) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(ImportTaskEntity::getOperatorId, operatorId); + query.eq(ImportTaskEntity::getBizType, bizType); + query.eq(ImportTaskEntity::getProcessStatus, ImportTaskConstants.PROCESS_STATUS_PROCESSING); + + return importRecordDao.selectCount(query) > 0; + } + + @Override + public String createProcessTask(String operatorId, String bizType) { + ImportTaskEntity importRecord = new ImportTaskEntity(); + importRecord.setProcessStatus(ImportTaskConstants.PROCESS_STATUS_PROCESSING); + importRecord.setOperatorId(operatorId); + importRecord.setBizType(bizType); + importRecord.setStartTime(new Date()); + + importRecordDao.insert(importRecord); + return importRecord.getId(); + } + + @Override + public Boolean finish(String taskId, String processStatus, String operatorId, String resultDescFile, String resultDesc) { + return importRecordDao.finish(taskId, processStatus, operatorId, resultDesc, resultDescFile) > 0; + } +} \ No newline at end of file diff --git a/epmet-user/epmet-user-server/src/main/resources/mapper/ImportTaskDao.xml b/epmet-user/epmet-user-server/src/main/resources/mapper/ImportTaskDao.xml new file mode 100644 index 0000000000..edc56fa5c7 --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/resources/mapper/ImportTaskDao.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + update import_task + set PROCESS_STATUS = #{process_status}, + RESULT_DESC = #{resultDesc}, + RESULT_DESC_FILE = #{resultDescFile}, + UPDATED_BY=#{operatorId}, + UPDATED_TIME=NOW() + where ID=#{taskId} + and PROCESS_STATUS = 'processing' + + \ No newline at end of file