diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/security/user/LoginUserUtil.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/security/user/LoginUserUtil.java index ce92400ae0..220ac403a8 100644 --- a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/security/user/LoginUserUtil.java +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/security/user/LoginUserUtil.java @@ -2,6 +2,7 @@ package com.epmet.commons.tools.security.user; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.utils.EpmetRequestHolder; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; diff --git a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java index 2108042cd6..64cceb765a 100644 --- a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java +++ b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java @@ -23,6 +23,10 @@ public interface ImportTaskConstants { String BIZ_TYPE_IC_ENTERPRISE="ic_enterprise"; String IC_POINT_NUCLEIC_MONITORING = "ic_point_nucleic_monitoring"; String IC_POINT_VACCINES_INOCULATION = "ic_point_vaccines_inoculation"; + /** + * 工作日志导入 + */ + String BIZ_TYPE_WORK_DIARY_IMPORT = "work_diary_import"; /** * 核酸检测 */ diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/controller/WorkdiaryServiceController.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/controller/WorkdiaryServiceController.java index 1b73a301a4..31a9b61af6 100755 --- a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/controller/WorkdiaryServiceController.java +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/controller/WorkdiaryServiceController.java @@ -1,29 +1,52 @@ package com.epmet.controller; import com.epmet.commons.tools.aop.NoRepeatSubmit; +import com.epmet.commons.tools.constant.ServiceConstant; 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.feign.ResultDataResolver; import com.epmet.commons.tools.page.PageData; +import com.epmet.commons.tools.utils.EpmetRequestHolder; import com.epmet.commons.tools.utils.ExcelUtils; +import com.epmet.commons.tools.utils.FileUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.commons.tools.validator.AssertUtils; import com.epmet.commons.tools.validator.ValidatorUtils; import com.epmet.commons.tools.validator.group.AddGroup; -import com.epmet.commons.tools.validator.group.UpdateGroup; import com.epmet.commons.tools.validator.group.DefaultGroup; +import com.epmet.commons.tools.validator.group.UpdateGroup; +import com.epmet.constants.ImportTaskConstants; import com.epmet.dto.WorkdiaryServiceTypeDTO; import com.epmet.dto.form.workdiaryservice.WorkdiaryServiceQueryFormDTO; +import com.epmet.dto.result.ImportTaskCommonResultDTO; import com.epmet.dto.result.WorkdiaryServiceRecordDTO; import com.epmet.entity.WorkdiaryServiceTypeExcel; import com.epmet.service.WorkdiaryServiceRecordService; import com.epmet.service.WorkdiaryServiceTypeService; +import com.epmet.utils.ImportTaskUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.validation.constraints.NotNull; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.file.Path; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; /** @@ -32,9 +55,10 @@ import java.util.Map; * @author generator generator@elink-cn.com * @since v1.0.0 2022-08-23 */ +@Slf4j @RestController @RequestMapping("workdiaryService") -public class WorkdiaryServiceController { +public class WorkdiaryServiceController implements ResultDataResolver { @Autowired private WorkdiaryServiceRecordService workdiaryServiceRecordService; @@ -42,6 +66,9 @@ public class WorkdiaryServiceController { @Autowired private WorkdiaryServiceTypeService workdiaryServiceTypeService; + @Autowired + private ExecutorService executorService; + /** * 记录-分页 * @return @@ -127,6 +154,75 @@ public class WorkdiaryServiceController { workdiaryServiceRecordService.export(gridId, serviceType, applicantName, applicantAddress, serviceContent, applicantMobile, response); } + /** + * 下载模板 + * @return + */ + @RequestMapping("downloadTemplate") + public void downloadTemplate(HttpServletResponse response) throws UnsupportedEncodingException { + response.setCharacterEncoding("UTF-8"); + response.addHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Content-Disposition"); + response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("工作日志导入模板", "UTF-8") + ".xlsx"); + + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("templates/workdiary_service_import.xlsx"); + ServletOutputStream os = response.getOutputStream()) { + IOUtils.copy(is, os); + } catch (IOException e) { + log.error("【工作日志】下载模板-IO错误:{}", ExceptionUtils.getErrorStackTrace(e)); + } + } + + /** + * 记录导入 + * @param file + */ + @PostMapping("/record/import") + public Result recordImport(MultipartFile file) { + + if (file == null) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), null, "请选择文件"); + } + + // 格式校验 + // 只接受如下两种格式后缀 + String originFileName = file.getOriginalFilename(); + String suffix = originFileName.substring(originFileName.lastIndexOf(".")); + if (StringUtils.isBlank(suffix) || (!".xlsx".equals(suffix) && !".xls".equals(suffix))) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), null, "只支持.xls和.xlsx两种格式"); + } + + // 创建保存目录 + Path fileSavePath = null; + try { + Path saveDir = FileUtils.getAndCreateDirUnderEpmetFilesDir("workdiary", "import", EpmetRequestHolder.getLoginUserId()); + fileSavePath = saveDir.resolve(System.currentTimeMillis() + suffix); + } catch (IOException e) { + e.printStackTrace(); + } + + // 将文件保存到本地 + try (FileOutputStream fos = new FileOutputStream(fileSavePath.toString()); + InputStream is = file.getInputStream()) { + IOUtils.copy(is, fos); + } catch (Exception e) { + log.error("【书记日志】上传-保存文件到本地失败:{}", ExceptionUtils.getErrorStackTrace(e)); + throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode()); + } + + // 创建导入记录 + ImportTaskCommonResultDTO itResult = getResultDataOrThrowsException(ImportTaskUtils.createImportTask(originFileName, ImportTaskConstants.BIZ_TYPE_WORK_DIARY_IMPORT), + ServiceConstant.EPMET_COMMON_SERVICE, EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "有导入操作正在进行", "有导入操作正在进行"); + + // 执行异步导入 + Path finalFileSavePath = fileSavePath; + CompletableFuture.runAsync(() -> { + workdiaryServiceRecordService.createImportTaskAndExecuteImport(finalFileSavePath, originFileName, itResult.getTaskId()); + }, executorService); + + return new Result(); + } + /** * 服务类型-分页 * @return diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/entity/WorkdiaryServiceRecordEntity.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/entity/WorkdiaryServiceRecordEntity.java index 4b74496fd6..16db6c8bc5 100755 --- a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/entity/WorkdiaryServiceRecordEntity.java +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/entity/WorkdiaryServiceRecordEntity.java @@ -3,8 +3,10 @@ package com.epmet.entity; import com.baomidou.mybatisplus.annotation.TableName; import com.epmet.commons.mybatis.entity.BaseEpmetEntity; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import java.util.Date; @@ -17,6 +19,8 @@ import java.util.Date; @Data @EqualsAndHashCode(callSuper=false) @TableName("workdiary_service_record") +@NoArgsConstructor +@AllArgsConstructor public class WorkdiaryServiceRecordEntity extends BaseEpmetEntity { private static final long serialVersionUID = 1L; diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/WorkdiaryServiceRecordExcel.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/WorkdiaryServiceRecordExcel.java index 7da0010c82..631c3ed943 100755 --- a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/WorkdiaryServiceRecordExcel.java +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/WorkdiaryServiceRecordExcel.java @@ -4,6 +4,9 @@ import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.epmet.dto.result.WorkdiaryServiceRecordDTO; import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; /** * 工作日志(服务)-记录 excel @@ -12,16 +15,20 @@ import lombok.Data; * @since v1.0.0 2022-08-23 */ @Data +@NoArgsConstructor public class WorkdiaryServiceRecordExcel { + @NotBlank(message = "所属网格必填") @ColumnWidth(25) @ExcelProperty(value = "所属网格") private String gridName; + @NotBlank(message = "服务类型必填") @ColumnWidth(15) @ExcelProperty(value = "服务类型") private String serviceTypeName; + @NotBlank(message = "申请人必填") @ColumnWidth(10) @ExcelProperty(value = "申请人") private String applicantName; @@ -30,6 +37,7 @@ public class WorkdiaryServiceRecordExcel { @ExcelProperty(value = "住址") private String applicantAddress; + @NotBlank(message = "服务内容必填") @ColumnWidth(25) @ExcelProperty(value = "服务内容") private String serviceContent; @@ -42,6 +50,7 @@ public class WorkdiaryServiceRecordExcel { @ExcelProperty(value = "负责人") private String principal; + @NotBlank(message = "服务时间必填") @ColumnWidth(10) @ExcelProperty(value = "服务时间") private String serviceTime; diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/listener/WorkdiaryServiceImportListener.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/listener/WorkdiaryServiceImportListener.java new file mode 100644 index 0000000000..bc09d401d0 --- /dev/null +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/excel/listener/WorkdiaryServiceImportListener.java @@ -0,0 +1,54 @@ +package com.epmet.excel.listener; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.excel.WorkdiaryServiceRecordExcel; +import com.epmet.service.WorkdiaryServiceRecordService; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +/** + * 工作日志-导入-监听器 + */ +@Slf4j +public class WorkdiaryServiceImportListener implements ReadListener { + + /** + * 200 一批执行导入 + */ + public static final Integer BATCH_SIZE = 2; + + /** + * 数据列表 + */ + private List datas = new ArrayList<>(); + + private WorkdiaryServiceRecordService workdiaryServiceRecordService; + + public WorkdiaryServiceImportListener(WorkdiaryServiceRecordService workdiaryServiceRecordService) { + this.workdiaryServiceRecordService = workdiaryServiceRecordService; + } + + @Override + public void invoke(WorkdiaryServiceRecordExcel data, AnalysisContext context) { + datas.add(data); + if (datas.size() >= BATCH_SIZE) { + // 达到批量阈值,执行一次导入 + try { + workdiaryServiceRecordService.executeBatchImport(datas); + } catch (Exception e) { + log.error("【工作日志】导入-发生未知错误:{}", ExceptionUtils.getErrorStackTrace(e)); + } finally { + datas.clear(); + } + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + workdiaryServiceRecordService.executeBatchImport(datas); + } +} diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/WorkdiaryServiceRecordService.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/WorkdiaryServiceRecordService.java index e6ed7578f4..4dfc2f3cb5 100755 --- a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/WorkdiaryServiceRecordService.java +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/WorkdiaryServiceRecordService.java @@ -5,8 +5,10 @@ import com.epmet.commons.tools.page.PageData; import com.epmet.dto.form.workdiaryservice.WorkdiaryServiceQueryFormDTO; import com.epmet.dto.result.WorkdiaryServiceRecordDTO; import com.epmet.entity.WorkdiaryServiceRecordEntity; +import com.epmet.excel.WorkdiaryServiceRecordExcel; import javax.servlet.http.HttpServletResponse; +import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -85,4 +87,8 @@ public interface WorkdiaryServiceRecordService extends BaseService datas); } \ No newline at end of file diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/WorkdiaryServiceRecordServiceImpl.java b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/WorkdiaryServiceRecordServiceImpl.java index 64505ae54a..ea0966c7a0 100755 --- a/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/WorkdiaryServiceRecordServiceImpl.java +++ b/epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/WorkdiaryServiceRecordServiceImpl.java @@ -1,7 +1,11 @@ package com.epmet.service.impl; +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.write.metadata.WriteSheet; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -9,41 +13,61 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.epmet.commons.mybatis.service.impl.BaseServiceImpl; import com.epmet.commons.tools.constant.FieldConstant; import com.epmet.commons.tools.constant.ServiceConstant; +import com.epmet.commons.tools.dto.result.OptionResultDTO; 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.ValidateException; import com.epmet.commons.tools.feign.ResultDataResolver; import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.redis.common.CustomerOrgRedis; -import com.epmet.commons.tools.utils.ConvertUtils; -import com.epmet.commons.tools.utils.EpmetRequestHolder; -import com.epmet.commons.tools.utils.ExcelUtils; -import com.epmet.commons.tools.utils.SpringContextUtils; +import com.epmet.commons.tools.security.user.LoginUserUtil; +import com.epmet.commons.tools.utils.*; +import com.epmet.commons.tools.validator.ValidatorUtils; +import com.epmet.constants.ImportTaskConstants; import com.epmet.dao.WorkdiaryServiceRecordDao; import com.epmet.dao.WorkdiaryServiceTypeDao; -import com.epmet.dto.IcResiUserDTO; -import com.epmet.dto.WorkdiaryServiceTypeDTO; -import com.epmet.dto.result.WorkdiaryServiceRecordDTO; +import com.epmet.dto.*; +import com.epmet.dto.form.GridOptionFormDTO; +import com.epmet.dto.form.LoginUserDetailsFormDTO; +import com.epmet.dto.form.resi.IcResiPageNonDynamicFormDTO; +import com.epmet.dto.result.*; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.entity.WorkdiaryServiceRecordEntity; import com.epmet.excel.WorkdiaryServiceRecordExcel; +import com.epmet.excel.listener.WorkdiaryServiceImportListener; import com.epmet.feign.EpmetUserOpenFeignClient; +import com.epmet.feign.GovOrgOpenFeignClient; +import com.epmet.feign.OssFeignClient; import com.epmet.redis.WorkdiaryServiceRecordRedis; import com.epmet.service.WorkdiaryServiceRecordService; import com.epmet.service.WorkdiaryServiceTypeService; +import com.epmet.utils.ImportTaskUtils; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; +import org.apache.poi.ss.usermodel.Workbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -64,6 +88,34 @@ public class WorkdiaryServiceRecordServiceImpl extends BaseServiceImpl> importResultDescTl = new ThreadLocal<>(); + + /** + * 导入结果描述 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ImportResultDesc { + @ColumnWidth(20) + @ExcelProperty(value = "申请人") + private String applicantName; + + @ColumnWidth(30) + @ExcelProperty(value = "服务内容") + private String serviceContent; + + @ColumnWidth(30) + @ExcelProperty(value = "描述") + private String desc; + } + @Override public PageData page(Map params) { IPage page = baseDao.selectPage( @@ -77,14 +129,18 @@ public class WorkdiaryServiceRecordServiceImpl extends BaseServiceImpl page(String gridId, Short serviceType, String applicantName, String applicantAddress, String serviceContent, String applicantMobile, Integer pageNo, Integer pageSize) { + LoginUserDetailsResultDTO currentStaff = getResultDataOrThrowsException(userOpenFeignClient.getLoginUserDetails(new LoginUserDetailsFormDTO( + EpmetRequestHolder.getLoginUserApp(), EpmetRequestHolder.getLoginUserClient(), EpmetRequestHolder.getLoginUserId() + )), ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "查询工作人员信息失败", "查询工作人员信息失败"); + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(StringUtils.isNotBlank(gridId), WorkdiaryServiceRecordEntity::getGridId, gridId); query.eq(serviceType != null, WorkdiaryServiceRecordEntity::getServiceType, serviceType); - query.eq(WorkdiaryServiceRecordEntity::getCreatedBy, EpmetRequestHolder.getLoginUserId()); query.like(StringUtils.isNotBlank(applicantName), WorkdiaryServiceRecordEntity::getApplicantName, applicantName); query.like(StringUtils.isNotBlank(applicantAddress), WorkdiaryServiceRecordEntity::getApplicantAddress, applicantAddress); query.like(StringUtils.isNotBlank(serviceContent), WorkdiaryServiceRecordEntity::getServiceContent, serviceContent); query.like(StringUtils.isNotBlank(applicantMobile), WorkdiaryServiceRecordEntity::getApplicantMobile, applicantMobile); + query.likeRight(WorkdiaryServiceRecordEntity::getOrgIdPath, currentStaff.getOrgIdPath()); // 查找类型列表 List stList = SpringContextUtils.getBean(WorkdiaryServiceTypeService.class).list(null, 1, 100); @@ -246,4 +302,189 @@ public class WorkdiaryServiceRecordServiceImpl extends BaseServiceImpl()); + WorkdiaryServiceImportListener listener = new WorkdiaryServiceImportListener(this); + EasyExcel.read(fileSavePath.toFile(), WorkdiaryServiceRecordExcel.class,listener).headRowNumber(1).sheet(0).doRead(); + } catch (Exception e) { + logger.error("【工作日志】-导入-未知错误:{}", ExceptionUtils.getErrorStackTrace(e)); + } finally { + // 清理临时文件 + try { + Files.deleteIfExists(fileSavePath); + } catch (IOException e) { + logger.error("【书记日志】-导入-删除导入临时文件失败,staffId:{}, 文件名称:{}, 错误信息:{}", + EpmetRequestHolder.getLoginUserId(), fileSavePath.toString(), ExceptionUtils.getErrorStackTrace(e)); + } + + // 上传错误描述文件 + try { + resultDescFileUtl = buildAndUploadResultDescFile(importResultDescTl.get()); + } catch (IOException e) { + logger.error("【工作日志】导入-生成和上传错误描述文件失败:{}", ExceptionUtils.getErrorStackTrace(e)); + } + + // 清理错误结果描述缓存 + importResultDescTl.remove(); + } + + + + // 修改导入记录状态为已完成 + ImportTaskUtils.finishImportTask(taskId, ImportTaskConstants.PROCESS_STATUS_FINISHED_SUCCESS, resultDescFileUtl, ""); + } + + /** + * 生成和上传错误描述文件 + * @return + */ + private String buildAndUploadResultDescFile(List descs) throws IOException { + if(CollectionUtils.isEmpty(descs)) { + return null; + } + //Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("导入失败的数据列表","导入失败的数据列表"), + // ImportResultDesc.class, descs); + + String fileName = System.currentTimeMillis() + "_" + EpmetRequestHolder.getLoginUserId() + ".xlsx"; + + FileItem fileItem = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, FileUtils.getAndCreateDirUnderEpmetFilesDir("workdiary", "result_desc").toFile()) + .createItem("file", ContentType.APPLICATION_OCTET_STREAM.toString(), false, fileName); + + // 为了自动关闭流 + try (OutputStream os = fileItem.getOutputStream()) { + EasyExcel.write(os, ImportResultDesc.class).sheet("失败列表").doWrite(descs); + } + + UploadImgResultDTO result = getResultDataOrThrowsException(ossFeignClient.uploadImportTaskDescFile(new CommonsMultipartFile(fileItem)), + ServiceConstant.EPMET_OSS_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "上传结果描述文件失败", "上传结果描述文件失败"); + + if (!fileItem.isInMemory()) { + fileItem.delete(); + } + return result.getUrl(); + } + + /** + * 执行批量插入 + * @param datas + */ + @Override + public void executeBatchImport(List datas) { + if (CollectionUtils.isEmpty(datas)) { + return; + } + + // 当前登录人 + LoginUserDetailsResultDTO currentStaff = getResultDataOrThrowsException(userOpenFeignClient.getLoginUserDetails( + new LoginUserDetailsFormDTO(EpmetRequestHolder.getLoginUserApp(), EpmetRequestHolder.getLoginUserClient(), EpmetRequestHolder.getLoginUserId())), + ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "【工作日志】-导入-没有找到当前登录人信息", "【工作日志】-导入-没有找到当前登录人信息"); + + // 服务类型字典。key:养老 value:object + List serviceTypes = SpringContextUtils.getBean(WorkdiaryServiceTypeService.class).page(null, 1, 100).getList(); + Map serviceTypeMap = serviceTypes.stream().collect(Collectors.toMap(WorkdiaryServiceTypeDTO::getServiceTypeName, Function.identity())); + + ArrayList diaryRecordList = new ArrayList<>(); + + // 循环校验和填充数据 + for (WorkdiaryServiceRecordExcel row : datas) { + + String gridName = row.getGridName(); + String serviceTypeName = row.getServiceTypeName(); + String applicantName = row.getApplicantName(); + + try { + // 校验必填 + ValidatorUtils.validateEntity(row); + + // 检查服务类型 + WorkdiaryServiceTypeDTO serviceType = serviceTypeMap.get(serviceTypeName); + if (serviceType == null || serviceType.getEnabled().shortValue() == 0) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "所选服务类型不存在或已禁用", "所选服务类型不存在或已禁用"); + } + + // 检查网格 + OptionResultDTO grid = findGrid(currentStaff.getAgencyId(), gridName); + if (grid == null) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "网格不存在,或不在您所属的组织下", "网格不存在,或不在您所属的组织下"); + } + + // 查找居民 + IcResiNonDynamicResultDTO resi = findResi(grid.getValue(), row.getApplicantName(), row.getApplicantMobile()); + + if (StringUtils.isBlank(row.getApplicantMobile())) { + row.setApplicantMobile(resi.getMobile()); + } + + // 没填写住址的,到系统查询 + if (StringUtils.isBlank(row.getApplicantAddress())) { + + HouseAgencyInfoResultDTO house = getResultDataOrThrowsException(govOrgOpenFeignClient.getHouseAgencyInfo(resi.getHomeId()), + ServiceConstant.GOV_ORG_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "查询房屋失败", "查询房屋失败"); + + if (house == null) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "居民住址未找到", "居民未找到"); + } + + row.setApplicantAddress(house.getFullName()); + } + // 填充到entity + WorkdiaryServiceRecordEntity record = new WorkdiaryServiceRecordEntity(EpmetRequestHolder.getLoginUserCustomerId(), serviceType.getServiceType(), currentStaff.getAgencyId(), + grid.getValue(), currentStaff.getOrgIdPath().concat(":").concat(grid.getValue()), resi.getId(), row.getApplicantName(), + row.getApplicantAddress(), row.getApplicantMobile(), row.getServiceContent(), row.getServiceTime(), row.getPrincipal(), row.getRemark()); + + diaryRecordList.add(record); + } catch (ValidateException ve) { + importResultDescTl.get().add(new ImportResultDesc(applicantName, row.getServiceContent(), ve.getMsg())); + } catch (EpmetException ee) { + importResultDescTl.get().add(new ImportResultDesc(applicantName, row.getServiceContent(), ee.getMsg())); + } catch (Throwable t) { + logger.error(ExceptionUtils.getThrowableErrorStackTrace(t)); + importResultDescTl.get().add(new ImportResultDesc(applicantName, row.getServiceContent(), "未知错误")); + } + } + + // 批量持久化 + insertBatch(diaryRecordList, 50); + } + + private IcResiNonDynamicResultDTO findResi(String gridId, String applicantName, String mobile) { + PageData page = getResultDataOrThrowsException(userOpenFeignClient.listResiNonDynamic(new IcResiPageNonDynamicFormDTO(gridId, applicantName, mobile, false)), + ServiceConstant.EPMET_USER_SERVER, EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "居民未找到", "居民未找到"); + + List list = page.getList(); + + if (page == null || CollectionUtils.isEmpty(page.getList())) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "居民未找到", "居民未找到"); + } + + return list.get(0); + } + + /** + * 从组织下查找指定的网格名称,得到网格数据 + * @param agencyId + * @param gridName + * @return + */ + private OptionResultDTO findGrid(String agencyId, String gridName) { + List gridOptions = getResultDataOrThrowsException(govOrgOpenFeignClient.getGridOption(new GridOptionFormDTO(agencyId, "saveOrUpdate")), + ServiceConstant.GOV_ORG_SERVER, EpmetErrorCode.SERVER_ERROR.getCode(), "【工作日志】-导入-网格查询失败", "【工作日志】-导入-网格查询失败"); + + for (OptionResultDTO grid : gridOptions) { + if (gridName.equals(grid.getLabel())) { + return grid; + } + } + + return null; + } +} diff --git a/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/templates/workdiary_service_import.xlsx b/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/templates/workdiary_service_import.xlsx new file mode 100644 index 0000000000..06bf284e8b Binary files /dev/null and b/epmet-module/epmet-heart/epmet-heart-server/src/main/resources/templates/workdiary_service_import.xlsx differ diff --git a/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/form/GridOptionFormDTO.java b/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/form/GridOptionFormDTO.java index e6fae52bc9..434af5aed4 100644 --- a/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/form/GridOptionFormDTO.java +++ b/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/form/GridOptionFormDTO.java @@ -1,6 +1,8 @@ package com.epmet.dto.form; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; import java.io.Serializable; @@ -11,6 +13,8 @@ import java.io.Serializable; * @Date 2021/11/12 10:54 上午 */ @Data +@NoArgsConstructor +@AllArgsConstructor public class GridOptionFormDTO implements Serializable { /** * 部门Id diff --git a/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/result/HouseAgencyInfoResultDTO.java b/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/result/HouseAgencyInfoResultDTO.java index d5734e2791..eff5a441d8 100644 --- a/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/result/HouseAgencyInfoResultDTO.java +++ b/epmet-module/gov-org/gov-org-client/src/main/java/com/epmet/dto/result/HouseAgencyInfoResultDTO.java @@ -21,6 +21,7 @@ public class HouseAgencyInfoResultDTO implements Serializable { private String neighborHoodId; private String buildingId; private String buildingUnitId; + private String fullName; public HouseAgencyInfoResultDTO() { this.agencyId = ""; diff --git a/epmet-module/gov-org/gov-org-server/src/main/resources/mapper/IcHouseDao.xml b/epmet-module/gov-org/gov-org-server/src/main/resources/mapper/IcHouseDao.xml index 8b900c90dd..6098775330 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/resources/mapper/IcHouseDao.xml +++ b/epmet-module/gov-org/gov-org-server/src/main/resources/mapper/IcHouseDao.xml @@ -393,6 +393,7 @@ h.BUILDING_UNIT_ID, nh.AGENCY_ID, nh.GRID_ID, + h.FULL_NAME, nh.AGENCY_PIDS AS pids FROM ic_house h INNER JOIN ic_neighbor_hood nh ON (nh.ID = h.NEIGHBOR_HOOD_ID AND nh.DEL_FLAG = '0') diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/resi/IcResiPageNonDynamicFormDTO.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/resi/IcResiPageNonDynamicFormDTO.java new file mode 100644 index 0000000000..e5453cda85 --- /dev/null +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/form/resi/IcResiPageNonDynamicFormDTO.java @@ -0,0 +1,25 @@ +package com.epmet.dto.form.resi; + +import com.epmet.commons.tools.dto.form.PageFormDTO; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class IcResiPageNonDynamicFormDTO extends PageFormDTO { + + private String gridId; + + private String name; + + private String mobile; + + /** + * 是否模糊。true:模糊,false:精确 + */ + private Boolean fuzzy = false; + +} diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/result/resi/IcResiNonDynamicResultDTO.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/result/resi/IcResiNonDynamicResultDTO.java new file mode 100644 index 0000000000..52da33987e --- /dev/null +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/dto/result/resi/IcResiNonDynamicResultDTO.java @@ -0,0 +1,23 @@ +package com.epmet.dto.result.resi; + +import lombok.Data; + +/** + * 居民基础信息V2 + */ +@Data +public class IcResiNonDynamicResultDTO { + private String id; + private String name; + private String customerId; + private String agencyId; + private String gridId; + private String villageId; + private String buildId; + private String unitId; + private String homeId; + private String mobile; + private String idCard; + private String gender; + private String idCardType; +} diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java index e37454ed35..47a67e5fbd 100644 --- a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/EpmetUserOpenFeignClient.java @@ -3,12 +3,15 @@ package com.epmet.feign; import com.epmet.commons.tools.constant.ServiceConstant; import com.epmet.commons.tools.dto.result.OptionDataResultDTO; +import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.commons.tools.utils.Result; import com.epmet.dto.*; import com.epmet.dto.form.*; import com.epmet.dto.form.patrol.PatrolQueryFormDTO; +import com.epmet.dto.form.resi.IcResiPageNonDynamicFormDTO; import com.epmet.dto.result.*; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.feign.fallback.EpmetUserOpenFeignClientFallbackFactory; import com.epmet.resi.partymember.dto.partymember.IcPartyMemberDTO; import org.springframework.cloud.openfeign.FeignClient; @@ -871,4 +874,12 @@ public interface EpmetUserOpenFeignClient { @PostMapping("/epmetuser/customerstaff/customerstaff") Result> customerStaff(@RequestBody GridStaffUploadtFormDTO formDTO); + + /** + * 居民列表,非动态 + * @param input + * @return + */ + @PostMapping("/epmetuser/icresiuser/nonDynamic/listResi") + Result> listResiNonDynamic(@RequestBody IcResiPageNonDynamicFormDTO input); } diff --git a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java index 71711e66a8..7c9cc3b2a4 100644 --- a/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java +++ b/epmet-user/epmet-user-client/src/main/java/com/epmet/feign/fallback/EpmetUserOpenFeignClientFallback.java @@ -2,13 +2,16 @@ package com.epmet.feign.fallback; import com.epmet.commons.tools.constant.ServiceConstant; import com.epmet.commons.tools.dto.result.OptionDataResultDTO; +import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.commons.tools.utils.ModuleUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.dto.*; import com.epmet.dto.form.*; import com.epmet.dto.form.patrol.PatrolQueryFormDTO; +import com.epmet.dto.form.resi.IcResiPageNonDynamicFormDTO; import com.epmet.dto.result.*; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.feign.EpmetUserOpenFeignClient; import com.epmet.resi.partymember.dto.partymember.IcPartyMemberDTO; import org.springframework.web.bind.annotation.RequestBody; @@ -671,4 +674,8 @@ public class EpmetUserOpenFeignClientFallback implements EpmetUserOpenFeignClien return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "customerStaff", formDTO); } + @Override + public Result> listResiNonDynamic(IcResiPageNonDynamicFormDTO input) { + return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "listResiNonDynamic", input); + } } 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 7604ebc5c7..9b0fe3324c 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 @@ -55,8 +55,10 @@ import com.epmet.constant.SystemMessageType; import com.epmet.constants.ImportTaskConstants; import com.epmet.dto.IcResiUserDTO; import com.epmet.dto.form.*; +import com.epmet.dto.form.resi.IcResiPageNonDynamicFormDTO; import com.epmet.dto.result.*; import com.epmet.dto.result.demand.OptionDTO; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.enums.IcResiUserTableEnum; import com.epmet.excel.PartyMemberAgeExportExcel; import com.epmet.excel.PartyMemberEducationExportExcel; @@ -1371,4 +1373,23 @@ public class IcResiUserController implements ResultDataResolver { return new Result().ok(icResiUserService.icUserMatchGrid(formDTO)); } + /** + * 居民列表分页查询 非动态 + * @param input + * @return + */ + @PostMapping("/nonDynamic/listResi") + public Result> listResiNonDynamic(@RequestBody IcResiPageNonDynamicFormDTO input) { + + String gridId = input.getGridId(); + String name = input.getName(); + Integer pageNo = input.getPageNo(); + Integer pageSize = input.getPageSize(); + Boolean fuzzy = input.getFuzzy(); + String mobile = input.getMobile(); + + PageData page = icResiUserService.listResiNonDynamic(fuzzy, gridId, name, mobile, pageNo, pageSize); + return new Result>().ok(page); + } + } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserService.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserService.java index 37cf258e14..8975e06443 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserService.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/IcResiUserService.java @@ -26,6 +26,7 @@ import com.epmet.dto.IcResiUserDTO; import com.epmet.dto.form.*; import com.epmet.dto.result.*; import com.epmet.dto.result.demand.OptionDTO; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.entity.IcResiUserEntity; import com.epmet.excel.support.ExportResiUserItemDTO; import com.epmet.resi.partymember.dto.partymember.IcPartyMemberDTO; @@ -505,4 +506,5 @@ public interface IcResiUserService extends BaseService { */ IcUserMatchGridResultDTO icUserMatchGrid(IcUserMatchGridFormDTO formDTO); + PageData listResiNonDynamic(Boolean fuzzy, String gridId, String name, String mobile, Integer pageNo, Integer pageSize); } diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java index d8f57e4e81..ce30430738 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java @@ -63,6 +63,7 @@ import com.epmet.dto.form.demand.UserDemandNameQueryFormDTO; import com.epmet.dto.result.*; import com.epmet.dto.result.demand.IcResiDemandDictDTO; import com.epmet.dto.result.demand.OptionDTO; +import com.epmet.dto.result.resi.IcResiNonDynamicResultDTO; import com.epmet.entity.*; import com.epmet.excel.support.ExportResiUserItemDTO; import com.epmet.feign.*; @@ -3312,4 +3313,21 @@ public class IcResiUserServiceImpl extends BaseServiceImpl" + customer); return customer; } + + @Override + public PageData listResiNonDynamic(Boolean fuzzy, String gridId, String name, String mobile, Integer pageNo, Integer pageSize) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(IcResiUserEntity::getCustomerId, EpmetRequestHolder.getLoginUserCustomerId()); + query.eq(StringUtils.isNotBlank(gridId), IcResiUserEntity::getGridId, gridId); + // 一个模糊一个精确 + query.eq((!fuzzy && StringUtils.isNotBlank(name)), IcResiUserEntity::getName, name); + query.like((fuzzy && StringUtils.isNotBlank(name)), IcResiUserEntity::getName, name); + + query.eq((!fuzzy && StringUtils.isNotBlank(mobile)), IcResiUserEntity::getMobile, mobile); + query.like((fuzzy && StringUtils.isNotBlank(mobile)), IcResiUserEntity::getMobile, mobile); + + PageHelper.startPage(pageNo, pageSize); + List list = baseDao.selectList(query).stream().map((e) -> ConvertUtils.sourceToTarget(e, IcResiNonDynamicResultDTO.class)).collect(Collectors.toList()); + return new PageData(list, new PageInfo<>(list).getTotal(), pageSize); + } }