diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java index fcf79a3c89..57b2461c1e 100644 --- a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java @@ -29,10 +29,10 @@ public enum DictTypeEnum { IC_DANGER_TYPE("ic_danger_type","危化品种类",24), POLICY_LEVEL("policy_level","政策级别",25), LOG_TYPE("log_type", "日志类型", 33), - TRAFFIC_TYPE("traffic_type", "日志类型", 36), - SOJOURN_HISTORY("sojourn_history", "日志类型", 37), - ISOLATE_TYPE("isolate_type", "日志类型", 38), - TRIP_DATA_TYPE("trip_data_type", "日志类型", 39), + TRAFFIC_TYPE("traffic_type", "交通方式", 36), + SOJOURN_HISTORY("sojourn_history", "7天内旅居史情况", 37), + ISOLATE_TYPE("isolate_type", "隔离状态", 38), + TRIP_DATA_TYPE("trip_data_type", "行程记录类型", 39), ; private final String code; diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java index aea630040c..74139ac33d 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java @@ -13,6 +13,7 @@ import com.epmet.commons.tools.dto.form.PageFormDTO; import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetException; import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.feign.ResultDataResolver; import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.security.dto.TokenDto; @@ -31,11 +32,13 @@ import com.epmet.feign.EpmetCommonServiceOpenFeignClient; import com.epmet.service.IcTripReportRecordService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -246,7 +249,6 @@ public class IcTripReportRecordController implements ResultDataResolver { } } - /** * 导入excel * @return @@ -300,4 +302,71 @@ public class IcTripReportRecordController implements ResultDataResolver { icTripReportRecordService.execAsyncExcelImport(fileSavePath, rstData.getTaskId(),tokenDto.getCustomerId(),tokenDto.getUserId()); return new Result(); } + + /** + * pc:磐石-行程上报-下载模板 + * @param response + * @throws IOException + */ + @RequestMapping(value = "psdownloadtemplate", method = {RequestMethod.GET, RequestMethod.POST}) + public void psDownloadTemplate(HttpServletResponse response) throws IOException { + response.setCharacterEncoding("UTF-8"); + response.addHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Content-Disposition"); + //response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-excel"); + response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("行程上报导入模板", "UTF-8") + ".xlsx"); + + InputStream is = this.getClass().getClassLoader().getResourceAsStream("excel/ps_trip_report_import_template.xlsx"); + try { + ServletOutputStream os = response.getOutputStream(); + IOUtils.copy(is, os); + } finally { + if (is != null) { + is.close(); + } + } + } + + /** + * 磐石-导入excel + * @return + */ + @PostMapping("psimport") + @Transactional(rollbackFor = Exception.class) + public Result psImportExcel(@LoginUser TokenDto tokenDto, HttpServletResponse response, @RequestPart("file") MultipartFile file) throws Exception { + if (file.isEmpty()) { + throw new RenException("请上传文件"); + } + + // 校验文件类型 + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (!"xls".equals(extension) && !"xlsx".equals(extension)) { + throw new RenException("文件类型不匹配"); + } + //1.查询当前工作人员是否有再导入的党员先锋数据,有则不允许导入,没有则进行新的导入 + ImportTaskCommonFormDTO importTaskForm = new ImportTaskCommonFormDTO(); + importTaskForm.setOriginFileName(file.getOriginalFilename()); + importTaskForm.setOperatorId(tokenDto.getUserId()); + importTaskForm.setBizType(ImportTaskConstants.PS_BIZ_TYPE_IC_TRIP_REPORT); + Result result = commonServiceOpenFeignClient.createImportTask(importTaskForm); + if (!result.success()) { + throw new RenException(result.getInternalMsg()); + } + InputStream inputStream = null; + try { + inputStream = file.getInputStream(); + }catch (Exception e){ + ImportTaskCommonFormDTO input = new ImportTaskCommonFormDTO(); + input.setOperatorId(tokenDto.getUserId()); + input.setTaskId(result.getData().getTaskId()); + input.setProcessStatus(ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL); + commonServiceOpenFeignClient.finishImportTask(input); + log.error("读取文件失败"); + } + //2.执行导入程序 + icTripReportRecordService.psExecAsyncExcelImport(tokenDto, response, inputStream, result.getData().getTaskId()); + + return new Result(); + } + } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/IcPsTripReportRecordExcel.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/IcPsTripReportRecordExcel.java new file mode 100644 index 0000000000..011757b7d6 --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/IcPsTripReportRecordExcel.java @@ -0,0 +1,109 @@ +package com.epmet.excel; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import cn.afterturn.easypoi.excel.annotation.ExcelCollection; +import com.epmet.commons.tools.utils.ExcelVerifyInfo; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * 磐石-行程上报信息 + * + */ +@Data +public class IcPsTripReportRecordExcel extends ExcelVerifyInfo { + + @Excel(name = "姓名", needMerge = true) + @NotBlank(message = "不能为空") + private String name; + + @Excel(name = "年龄", needMerge = true) + //@NotNull(message = "不能为空") + private Integer age; + + @Excel(name = "证件号", needMerge = true) + @NotBlank(message = "不能为空") + private Integer idCard; + + @Excel(name = "户籍地(省市县区)", needMerge = true) + @NotBlank(message = "不能为空") + private String presentAddress; + + @Excel(name = "手机号", needMerge = true) + @NotBlank(message = "不能为空") + private String mobile; + + @ExcelCollection(name = "来源地") + private List source; + + @Excel(name = "来曹事由(100字以内)", needMerge = true) + @NotBlank(message = "不能为空") + private String describe; + + @Excel(name = "48小时核酸检测", needMerge = true) + @NotBlank(message = "不能为空") + private String natOutcome; + + @Excel(name = "来到本地时间(2022-01-01)", needMerge = true) + @NotBlank(message = "不能为空") + private String arriveDate; + + @ExcelCollection(name = "在曹居住地点") + private List present; + + @ExcelCollection(name = "返回方式") + private List traffic; + + @Excel(name = "7天内旅居史情况", needMerge = true) + private String sojournHistory; + + @Excel(name = "隔离状态", needMerge = true) + private String isolateType; + + @Excel(name = "备注(500字以内)", needMerge = true) + private String remark; + + @Excel(name = "是否落实“落地检”", needMerge = true) + private String isArriveCheck; + + @Excel(name = "是否达到曹县", needMerge = true) + private String isArrive; + + @Excel(name = "上报时间(2022-01-01)", needMerge = true) + private String reportingTime; + + @Excel(name = "管控措施(500字以内)", needMerge = true) + private String controlMeasures; + + @Excel(name = "类型(省内、省外、市内、县内)", needMerge = true) + private String tripDataType; + + + @Data + public class Source { + @Excel(name = "社区(省-市-区-街道-社区)") + @NotBlank(message = "不能为空") + private String sourceAddress; + @Excel(name = "详细地址", width = 20) + private String sourceDetailAddress; + } + @Data + public class Present { + @Excel(name = "村/居") + @NotBlank(message = "不能为空") + private String presentAddress; + @Excel(name = "详细地址", width = 20) + private String detailAddress; + } + @Data + public class Traffic { + @Excel(name = "返回方式") + @NotBlank(message = "不能为空") + private String trafficType; + @Excel(name = "其他返回方式", width = 20) + private String trafficTypeExplain; + } + +} \ No newline at end of file diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/error/IcPsTripReportRecordErrorExcel.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/error/IcPsTripReportRecordErrorExcel.java new file mode 100644 index 0000000000..a330e40462 --- /dev/null +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/excel/error/IcPsTripReportRecordErrorExcel.java @@ -0,0 +1,32 @@ +package com.epmet.excel.error; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.Date; + +/** + * 磐石-行程上报信息 + * + */ +@Data +public class IcPsTripReportRecordErrorExcel { + + @Excel(name = "姓名", width = 20) + private String name; + + @Excel(name = "证件号", width = 25) + private Integer idCard; + + @Excel(name = "户籍地(省市县区)", width = 40) + private String presentAddress; + + @Excel(name = "手机号", width = 20) + private String mobile; + + @Excel(name = "社会自组织名称", width = 40) + private String errorInfo; + + +} \ No newline at end of file diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcTripReportRecordService.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcTripReportRecordService.java index 32447f2d74..998e942b3d 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcTripReportRecordService.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcTripReportRecordService.java @@ -2,6 +2,7 @@ package com.epmet.service; import com.epmet.commons.mybatis.service.BaseService; import com.epmet.commons.tools.page.PageData; +import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.dto.IcTripReportRecordDTO; import com.epmet.dto.form.IcTripReportFormDTO; import com.epmet.dto.form.MyReportedTripFormDTO; @@ -9,6 +10,8 @@ import com.epmet.dto.form.PageTripReportFormDTO; import com.epmet.dto.result.TripListDTO; import com.epmet.entity.IcTripReportRecordEntity; +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -102,4 +105,6 @@ public interface IcTripReportRecordService extends BaseService fileList = new ArrayList<>(); + IcPsTripReportRecordErrorExcel excel = null; + //1.读取Excel数据 + ExcelImportResult testExcelImportResult = ExcelPoiUtils.importExcel1(inputStream, 0, 3, IcPsTripReportRecordExcel.class); + //2.存在错误行数据时存入错误数据集合中 + if (CollectionUtils.isNotEmpty(testExcelImportResult.getFailList())) { + for (IcPsTripReportRecordExcel entity : testExcelImportResult.getFailList()) { + //打印失败的行 和失败的信息 + log.warn("第{}行,{}", entity.getRowNum(), entity.getErrorMsg()); + excel = new IcPsTripReportRecordErrorExcel(); + excel.setName(entity.getName()); + excel.setIdCard(entity.getIdCard()); + excel.setPresentAddress(entity.getPresentAddress()); + excel.setMobile(entity.getMobile()); + excel.setErrorInfo(entity.getErrorMsg()); + fileList.add(excel); + } + } + //3.正确行数据集合 + List list = testExcelImportResult.getList(); + if (CollectionUtils.isNotEmpty(list)) { + //3-1.校验数据值,把填写不对的数据剔除 + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + AtomicBoolean bl = new AtomicBoolean(false); + StringBuffer errMsg = new StringBuffer(""); + IcPsTripReportRecordExcel obj = iterator.next(); + //返回方式为其他时需要填写"其他返回方式" + if (CollectionUtils.isEmpty(obj.getTraffic()) || + ("其他".equals(obj.getTraffic().get(0).getTrafficType()) && StringUtils.isBlank(obj.getTraffic().get(0).getTrafficTypeExplain()))) { + errMsg.append("返回方式为其他时,请补充“其他返回方式”;"); + bl.set(true); + } + if (bl.get()) { + excel = new IcPsTripReportRecordErrorExcel(); + excel.setName(obj.getName()); + excel.setIdCard(obj.getIdCard()); + excel.setPresentAddress(obj.getPresentAddress()); + excel.setMobile(obj.getMobile()); + excel.setErrorInfo(errMsg.toString()); + fileList.add(excel); + iterator.remove(); + } + } + //3-2.获取需要的字典表数据 + //交通方式 + Result> trafficTypeMap = adminOpenFeignClient.dictMap(DictTypeEnum.TRAFFIC_TYPE.getCode()); + //7天内旅居史情况 + Result> sojournHistoryMap = adminOpenFeignClient.dictMap(DictTypeEnum.SOJOURN_HISTORY.getCode()); + //隔离状态 + Result> isolateTypeMap = adminOpenFeignClient.dictMap(DictTypeEnum.ISOLATE_TYPE.getCode()); + //行程记录类型 + Result> tripDataTypeMap = adminOpenFeignClient.dictMap(DictTypeEnum.TRIP_DATA_TYPE.getCode()); + //获取当前登录用户所属组织id + CustomerStaffInfoCacheResult staffInfo = queryCurrentStaff(tokenDto.getCustomerId(), tokenDto.getUserId()); + //风险地区数据 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(IcDangerAreaEntity::getCustomerId, tokenDto.getCustomerId()); + wrapper.eq(IcDangerAreaEntity::getDelFlag, DelFlagEnum.NORMAL.value()); + List areaList = icDangerAreaDao.selectList(wrapper); + Map map1 = areaList.stream().collect(Collectors.toMap(IcDangerAreaEntity::getDistrict, IcDangerAreaEntity::getDangerLevel)); + Map map2 = areaList.stream().collect(Collectors.toMap(IcDangerAreaEntity::getCity, IcDangerAreaEntity::getDangerLevel)); + Map map3 = areaList.stream().collect(Collectors.toMap(IcDangerAreaEntity::getProvince, IcDangerAreaEntity::getDangerLevel)); + + list.forEach(l -> { + //3-3.数据赋值 + AtomicBoolean bl = new AtomicBoolean(false); + StringBuffer errMsg = new StringBuffer(""); + IcTripReportRecordEntity e = ConvertUtils.sourceToTarget(l, IcTripReportRecordEntity.class); + e.setCustomerId(tokenDto.getCustomerId()); + e.setAgencyId(staffInfo.getAgencyId()); + e.setPids(staffInfo.getAgencyPIds()); + e.setUserType(IcResiUserConstant.USER_TYPE_IMPORT); + if (!CollectionUtils.isEmpty(l.getSource())) { + e.setSourceAddress(l.getSource().get(0).getSourceAddress()); + e.setSourceDetailAddress(l.getSource().get(0).getSourceDetailAddress()); + } + if (!CollectionUtils.isEmpty(l.getPresent())) { + e.setPresentAddress(l.getPresent().get(0).getPresentAddress()); + e.setDetailAddress(l.getPresent().get(0).getDetailAddress()); + } + if (!CollectionUtils.isEmpty(l.getTraffic()) && trafficTypeMap.getData().containsKey(l.getTraffic().get(0).getTrafficType())) { + e.setTrafficType(trafficTypeMap.getData().get(l.getTraffic().get(0).getTrafficType())); + e.setTrafficTypeExplain(l.getTraffic().get(0).getTrafficTypeExplain()); + } + if (StringUtils.isNotBlank(l.getSojournHistory())) { + e.setSojournHistory(sojournHistoryMap.getData().get(l.getSojournHistory())); + } else { + String[] str = e.getSourceAddress().split("-"); + if (str.length < 3) { + bl.set(true); + errMsg.append("数据不完整,‘来源地’信息填写格式错误;"); + } + e.setSojournHistory("4"); + if (map1.containsKey(str[2])) { + e.setSojournHistory(map1.get(str[2]).equals("2") ? "1" : ("1".equals(map1.get(str[2])) ? "2" : ("0".equals(map1.get(str[2])) ? "3" : "4"))); + } + if (map2.containsKey(str[1])) { + e.setSojournHistory(map2.get(str[1]).equals("2") ? "1" : ("1".equals(map2.get(str[1])) ? "2" : ("0".equals(map2.get(str[1])) ? "3" : "4"))); + } + if (map3.containsKey(str[0])) { + e.setSojournHistory(map3.get(str[0]).equals("2") ? "1" : ("1".equals(map3.get(str[0])) ? "2" : ("0".equals(map3.get(str[0])) ? "3" : "4"))); + } + } + if (StringUtils.isNotBlank(l.getIsolateType())) { + e.setIsolateType(isolateTypeMap.getData().get(l.getIsolateType())); + } + if (StringUtils.isNotBlank(l.getTripDataType())) { + e.setTripDataType(tripDataTypeMap.getData().get(l.getTripDataType())); + } + e.setIsArriveCheck("是".equals(l.getIsArriveCheck()) ? "1" : "0"); + e.setIsArrive("是".equals(l.getIsArrive()) ? "1" : "0"); + //必要字段没值的 + if (StringUtils.isEmpty(e.getSourceAddress()) || StringUtils.isEmpty(e.getPresentAddress()) + || StringUtils.isEmpty(e.getTrafficType())) { + errMsg.append("数据不完整,请检查‘来源地’、‘在曹居住地点’、‘返回方式’信息是否填写完整;"); + bl.set(true); + } + if (bl.get()) { + IcPsTripReportRecordErrorExcel el = new IcPsTripReportRecordErrorExcel(); + el.setName(l.getName()); + el.setIdCard(l.getIdCard()); + el.setPresentAddress(l.getPresentAddress()); + el.setMobile(l.getMobile()); + el.setErrorInfo(errMsg.toString()); + fileList.add(el); + return; + } + //3-4.保存数据 + baseDao.insert(e); + }); + } + + //4.错误数据生成文件,修改导入任务状态 + String url = erroeImport(fileList); + upImportTask(url, taskId, tokenDto.getUserId(), true); + } catch (Exception e) { + String errorMsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【行程上报数据导入】程序错误:{}", errorMsg); + upImportTask(null, taskId, tokenDto.getUserId(), false); + } + } + + /** + * @Author sun + * @Description 行程上报数据导入,错误数据生成导入失败文件存到阿里云,修改导入任务为已结束 + **/ + private String erroeImport(List fileList) throws IOException { + String url = ""; + //1.有错误数据则生成错误数据存放文件传到阿里云服务 + if (!org.springframework.util.CollectionUtils.isEmpty(fileList)) { + Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("导入失败的数据列表", "导入失败的数据列表"), + IcPsTripReportRecordErrorExcel.class, fileList); + + // 文件名 + String resultDescFileName = UUID.randomUUID().toString().concat(".xlsx"); + FileItemFactory factory = new DiskFileItemFactory(16, null); + FileItem fileItem = factory.createItem("file", ContentType.APPLICATION_OCTET_STREAM.toString(), true, resultDescFileName); + OutputStream os = fileItem.getOutputStream(); + Result uploadResult = null; + try { + workbook.write(os); + uploadResult = ossFeignClient.uploadImportTaskDescFile(new CommonsMultipartFile(fileItem)); + } catch (Exception e) { + String errormsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【行程上报数据导入】上传错误描述文件:{}", errormsg); + } finally { + try { + os.close(); + } catch (IOException e) { + String errormsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【行程上报数据导入】上传错误描述文件关闭输出流:{}", errormsg); + } + try { + fileItem.delete(); + } catch (Exception e) { + String errormsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【行程上报数据导入】上传错误描述文件删除临时文件:{}", errormsg); + } + } + + if (uploadResult == null || !uploadResult.success()) { + log.error("【行程上报数据导入】调用OSS上传结果描述文件失败"); + } + url = uploadResult.getData().getUrl(); + } + return url; + } + + /** + * @Author sun + * @Description 行程上报数据导入修改导入任务状态 + **/ + private void upImportTask(String url, String importTaskId, String staffId, Boolean status) { + //2.更新导入任务数据 + ImportTaskCommonFormDTO importTaskForm = new ImportTaskCommonFormDTO(); + importTaskForm.setOperatorId(staffId); + importTaskForm.setBizType(ImportTaskConstants.PS_BIZ_TYPE_IC_TRIP_REPORT); + importTaskForm.setTaskId(importTaskId); + importTaskForm.setResultDescFilePath(url); + if (status && StringUtils.isBlank(url)) { + importTaskForm.setProcessStatus(ImportTaskConstants.PROCESS_STATUS_FINISHED_SUCCESS); + } else { + importTaskForm.setProcessStatus(ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL); + importTaskForm.setResultDesc("行程上报数据导入存在程序错误"); + } + Result result = commonServiceOpenFeignClient.finishImportTask(importTaskForm); + if (!result.success()) { + throw new RenException(result.getInternalMsg()); + } + } + + }