From 8c2ea4f97613d892a4de789b6139cc2fed4b593d Mon Sep 17 00:00:00 2001 From: guoshengxiong <1923636941@qq.com> Date: Sun, 27 Apr 2025 18:01:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=85=E5=A4=B4bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/WorkerAdmissionController.java | 130 +++++++++++++----- .../impl/WorkerAdmissionServiceImpl.java | 5 - .../car/controller/CarInfoController.java | 12 +- .../com/zhgd/xmgl/util/FlowSeviceUtil.java | 31 ++++- .../resources/excel/人员入场导入模板.xlsx | Bin 18994 -> 18961 bytes 5 files changed, 134 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/zhgd/xmgl/modules/baotou/controller/WorkerAdmissionController.java b/src/main/java/com/zhgd/xmgl/modules/baotou/controller/WorkerAdmissionController.java index 2f36b6b14..8b8bc8f9e 100644 --- a/src/main/java/com/zhgd/xmgl/modules/baotou/controller/WorkerAdmissionController.java +++ b/src/main/java/com/zhgd/xmgl/modules/baotou/controller/WorkerAdmissionController.java @@ -8,7 +8,9 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.*; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ZipUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.gexin.fastjson.JSON; @@ -28,7 +30,6 @@ import com.zhgd.xmgl.modules.basicdata.service.IDictionariesRecordService; import com.zhgd.xmgl.modules.basicdata.service.IDictionaryItemService; import com.zhgd.xmgl.modules.basicdata.service.ISystemUserService; import com.zhgd.xmgl.modules.basicdata.service.impl.NoticeServiceImpl; -import com.zhgd.xmgl.modules.exam.entity.ExamTrainRecord; import com.zhgd.xmgl.modules.exam.service.IExamTrainRecordService; import com.zhgd.xmgl.modules.project.service.IProjectEnterpriseService; import com.zhgd.xmgl.modules.worker.entity.EnterpriseInfo; @@ -620,8 +621,16 @@ public class WorkerAdmissionController { FileUtil.writeFromStream(zipFile.getInputStream(), zip); File unzip = ZipUtil.unzip(zip, Charset.forName("gbk")); File[] files = unzip.listFiles(); - if (!CollUtil.newArrayList(files).stream().anyMatch(o -> StringUtils.endsWith(o.getAbsolutePath(), ".xlsx"))) { - unzip = files[0]; + if (files == null || files.length == 0) { + throw new OpenAlertException("压缩文件为空"); + } + while (CollUtil.newArrayList(files).stream().noneMatch(o -> StringUtils.endsWith(o.getAbsolutePath(), ".xlsx"))) { + List dirList = Arrays.stream(files).filter(File::isDirectory).collect(Collectors.toList()); + if (dirList.size() != 1) { + throw new OpenAlertException("压缩文件目录结构有误,请检查"); + } + unzip = dirList.get(0); + files = unzip.listFiles(); } //设置一个压缩包,里面分别有人员信息excel,【人脸采集图片】文件夹、【身份证人像面文件夹】、【身份证国徽面】文件夹、【劳动合同】文件夹、【保险】文件夹、【体检报告】文件夹、【人员资质】文件夹、【人员资质验证】文件夹,文件夹中文件分别以姓名_身份证格式名称 List vos = parseUploadExcelWorkAdmission(unzip.getAbsolutePath(), projectSn); @@ -720,45 +729,65 @@ public class WorkerAdmissionController { throw new OpenAlertException(MessageUtil.get("excelNotDataErr")); } this.checkParams(list); + List absentWorkerTypes = new ArrayList<>(); + List absentGroups = new ArrayList<>(); + List absentEpcs = new ArrayList<>(); + List absentEdus = new ArrayList<>(); + List absentPolitics = new ArrayList<>(); + List absentBranchs = new ArrayList<>(); List enterpriseInfos = projectEnterpriseService.queryPageList(new MapBuilder() .put("projectSn", projectSn) .put(Cts.PAGE_SIZE, -1) .build()).getRecords(); - List deviceUnits = deviceUnitService.list(new LambdaQueryWrapper() - .eq(DeviceUnit::getProjectSn, projectSn).last(Cts.IGNORE_DATA_SCOPE_CONDITION)); List workerTypeList = postWorkTypeService.list(new LambdaQueryWrapper() .eq(PostWorkType::getProjectSn, projectSn)); Map groupMap = projectGroupService.list(new LambdaQueryWrapper() .eq(ProjectGroup::getProjectSn, projectSn)).stream().collect(Collectors.toMap(ProjectGroup::getProjectGroupName, Function.identity(), (o1, o2) -> o1)); - Map certTypeMap = dictionariesRecordService.selectCertTypeList(new MapBuilder() - .put("type", 1) - .build()).stream().collect(Collectors.toMap(DictionariesRecord::getDictionaryName, Function.identity(), (o1, o2) -> o1)); List isc = Arrays.asList("市场监督管理局", "应急管理局", "住房和城乡建设厅", "人力资源和社会保障部(厅)"); Map orgMap = partyConstructionOrganizationService.list(new LambdaQueryWrapper() .eq(PartyConstructionOrganization::getProjectSn, projectSn)).stream().collect(Collectors.toMap(PartyConstructionOrganization::getClassificationName, Function.identity(), (o1, o2) -> o1)); for (Map importInfo : list) { UploadZipWorkAdmissionVo detail = new UploadZipWorkAdmissionVo(); - detail.setNum(importInfo.get("*编号")); - detail.setWorkerName(importInfo.get("*姓名")); + String num = StrUtil.trim(importInfo.get("*编号")); + detail.setNum(num); + String workerName = StrUtil.trim(importInfo.get("*姓名")); + detail.setWorkerName(workerName); detail.setEnterpriseId(enterpriseInfos.stream().filter(o -> o.getEnterpriseName().equals(importInfo.get("单位"))).findFirst().map(EnterpriseInfo::getId).orElse(null)); detail.setWorkAreaName(importInfo.get("*工作区域")); - detail.setPostWorkType(workerTypeList.stream().filter(o -> o.getPostWorkTypeName().equals(importInfo.get("*岗位(工种)"))).findFirst().map(o -> o.getId()).orElse(null)); - //detail.setTeam(""); - Map idCardInfoMap = IdCardUtils.getBirthdayAgeSex(importInfo.get("*身份证号")); + String idCardNo = importInfo.get("*身份证号"); + String workerType = importInfo.get("*岗位(工种)"); + Optional workType = workerTypeList.stream().filter(o -> o.getPostWorkTypeName().equals(workerType)).findFirst(); + Long postWorkTypeId = workType.map(PostWorkType::getId).orElse(null); + if (postWorkTypeId == null) { + absentWorkerTypes.add(StrUtil.format("{}的岗位(工种)({})", workerName, workerType)); + } + detail.setPostWorkType(postWorkTypeId); + Map idCardInfoMap = IdCardUtils.getBirthdayAgeSex(idCardNo); detail.setSex(MapUtils.getInteger(idCardInfoMap, "sex")); detail.setAge(idCardInfoMap.get("age")); - detail.setIdCard(importInfo.get("*身份证号")); + detail.setIdCard(idCardNo); detail.setEntryDeadline(importInfo.get("*计划截止时间")); detail.setRemark(importInfo.get("备注")); detail.setProjectSn(projectSn); - detail.setPersonType(NumberUtil.compare(detail.getPostWorkType(), 200) >= 0 ? 1 : 2); + detail.setPersonType(workType.map(PostWorkType::getWorkerType).orElse(null)); detail.setBirthday(idCardInfoMap.get("birthday")); - detail.setPhone(importInfo.get("电话")); - detail.setEpcCbs(enterpriseInfos.stream().filter(o -> o.getEnterpriseName().equals(importInfo.get("EPC承包商"))).findFirst().map(o -> o.getId()).orElse(null)); + String phone = StrUtil.trim(importInfo.get("电话")); + detail.setPhone(phone); + String epcName = StrUtil.trim(importInfo.get("EPC承包商")); + Long epcCbs = enterpriseInfos.stream().filter(o -> o.getEnterpriseName().equals(epcName)).findFirst().map(EnterpriseInfo::getId).orElse(null); + if (epcCbs == null && StrUtil.isNotBlank(epcName)) { + absentEpcs.add(StrUtil.format("{}的EPC承包商({})", workerName, epcName)); + } + detail.setEpcCbs(epcCbs); //项目组 资格证号 资质类型 发证机关 取证日期 截止日期 - detail.setProjectGroup(Optional.ofNullable(groupMap.get(importInfo.get("*项目组"))).map(m -> Convert.toLong(m.getId())).orElse(null)); - detail.setCertificateNumber(importInfo.get("资格证号")); - detail.setCertificateType(Optional.ofNullable(certTypeMap.get(importInfo.get("资质类型"))).map(m -> Convert.toStr(m.getId())).orElse(null)); + String groupName = StrUtil.trim(importInfo.get("*项目组")); + Long projectGroup = Optional.ofNullable(groupMap.get(groupName)).map(m -> Convert.toLong(m.getId())).orElse(null); + if (projectGroup == null) { + absentGroups.add(StrUtil.format("{}的项目组({})", workerName, groupName)); + } + detail.setProjectGroup(projectGroup); + String certificateNumber = StrUtil.trim(importInfo.get("资格证号")); + detail.setCertificateNumber(certificateNumber); int issueCompany = isc.indexOf(importInfo.get("发证机关")); detail.setIssueCompany(issueCompany != -1 ? issueCompany + 1 : null); String issueTime = importInfo.get("取证日期"); @@ -771,9 +800,14 @@ public class WorkerAdmissionController { List ps = Arrays.asList("群众", "正式党员", "预备党员"); - int p = ps.indexOf(importInfo.get("政治面貌")); + String readPolitics = StrUtil.trim(importInfo.get("政治面貌")); + int p = ps.indexOf(readPolitics); + if (p == -1 && StrUtil.isNotBlank(readPolitics)) { + absentPolitics.add(StrUtil.format("{}的政治面貌({})", workerName, readPolitics)); + } detail.setPoliticsStatus(p != -1 ? p + 1 : null); - detail.setPoliticsStatusStr(importInfo.get("政治面貌")); + detail.setPoliticsStatusStr(readPolitics); + String readEdu = StrUtil.trim(importInfo.get("学历")); List edus = Arrays.asList("小学", "初中", "中专", @@ -783,18 +817,53 @@ public class WorkerAdmissionController { "研究生", "博士", "博士后"); - int edu = edus.indexOf(importInfo.get("学历")); + int edu = edus.indexOf(readEdu); + if (edu == -1 && StrUtil.isNotBlank(readEdu)) { + absentEdus.add(StrUtil.format("{}的学历({})", workerName, readEdu)); + } detail.setEducational(edu != -1 ? edu + 1 : null); - detail.setEducationalStr(importInfo.get("学历")); - PartyConstructionOrganization organization = orgMap.get(importInfo.get("支部名称")); + detail.setEducationalStr(readEdu); + String readBranch = StrUtil.trim(importInfo.get("支部名称")); + PartyConstructionOrganization organization = orgMap.get(readBranch); if (organization != null) { List ids = StrUtil.split(organization.getAncestors(), ","); ids.remove("0"); ids.add(organization.getId() + ""); detail.setBranchIdStr(StrUtil.join("-", ids)); + } else { + if (StrUtil.isNotBlank(readBranch)) { + absentBranchs.add(StrUtil.format("{}的支部名称({})", workerName, readBranch)); + } } admissionVos.add(detail); } + if (absentWorkerTypes.size() > 0 || + absentGroups.size() > 0 || + absentEpcs.size() > 0 || + absentEdus.size() > 0 || + absentPolitics.size() > 0 || + absentBranchs.size() > 0) { + ArrayList lists = new ArrayList<>(); + if (absentWorkerTypes.size() > 0) { + lists.add(StrUtil.join("、", absentWorkerTypes) + "不存在"); + } + if (absentGroups.size() > 0) { + lists.add(StrUtil.join("、", absentGroups) + "不存在"); + } + if (absentEpcs.size() > 0) { + lists.add(StrUtil.join("、", absentEpcs) + "不存在"); + } + if (absentEdus.size() > 0) { + lists.add(StrUtil.join("、", absentEdus) + "不存在"); + } + if (absentPolitics.size() > 0) { + lists.add(StrUtil.join("、", absentPolitics) + "不存在"); + } + if (absentBranchs.size() > 0) { + lists.add(StrUtil.join("、", absentBranchs) + "不存在"); + } + throw new OpenAlertException(StrUtil.join("。", lists)); + } return admissionVos; } @@ -807,15 +876,6 @@ public class WorkerAdmissionController { if (StringUtils.isBlank(importInfo.get("*姓名"))) { throw new OpenAlertException("有姓名未填写"); } -// if (StringUtils.isBlank(importInfo.get("*电话"))) { -// throw new OpenAlertException("有电话未填写"); -// } - //if (StringUtils.isBlank(importInfo.get("EPC承包商"))) { - // throw new OpenAlertException("有EPC承包商未填写"); - //} - //if (StringUtils.isBlank(importInfo.get("单位"))) { - // throw new OpenAlertException("有单位未填写"); - //} if (StringUtils.isBlank(importInfo.get("*工作区域"))) { throw new OpenAlertException("有工作区域未填写"); } diff --git a/src/main/java/com/zhgd/xmgl/modules/baotou/service/impl/WorkerAdmissionServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/baotou/service/impl/WorkerAdmissionServiceImpl.java index 34ca918ca..37c182895 100644 --- a/src/main/java/com/zhgd/xmgl/modules/baotou/service/impl/WorkerAdmissionServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/baotou/service/impl/WorkerAdmissionServiceImpl.java @@ -428,11 +428,6 @@ public class WorkerAdmissionServiceImpl extends ServiceImpl postWorkTypes = postWorkTypeService.list(new LambdaQueryWrapper() .eq(PostWorkType::getProjectSn, projectSn)); - //List epcIds = deviceUnits.stream().map(DeviceUnit::getEpcContractorIds).collect(Collectors.toList()).stream().flatMap(o -> StrUtil.split(o, ",").stream()).distinct().collect(Collectors.toList()); - //List epcInfos = new ArrayList<>(); - //if (CollUtil.isNotEmpty(epcIds)) { - // epcInfos = enterpriseInfos.stream().filter(o -> epcIds.contains(o.getId() + "")).collect(Collectors.toList()); - //} List epcInfos = deviceUnitService.getEpcList(new MapBuilder() .put("projectSn", projectSn) .build()); diff --git a/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java b/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java index f6533300b..a73a96067 100644 --- a/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java +++ b/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java @@ -465,8 +465,16 @@ public class CarInfoController { FileUtil.writeFromStream(zipFile.getInputStream(), zip); File unzip = ZipUtil.unzip(zip, Charset.forName("gbk")); File[] files = unzip.listFiles(); - if (!CollUtil.newArrayList(files).stream().anyMatch(o -> StringUtils.endsWith(o.getAbsolutePath(), ".xlsx"))) { - unzip = files[0]; + if (files == null || files.length == 0) { + throw new OpenAlertException("压缩文件为空"); + } + while (CollUtil.newArrayList(files).stream().noneMatch(o -> StringUtils.endsWith(o.getAbsolutePath(), ".xlsx"))) { + List dirList = Arrays.stream(files).filter(File::isDirectory).collect(Collectors.toList()); + if (dirList.size() != 1) { + throw new OpenAlertException("压缩文件目录结构有误,请检查"); + } + unzip = dirList.get(0); + files = unzip.listFiles(); } Result result = carInfoService.uploadExcelCar(unzip, projectSn); if (result.isSuccess()) { diff --git a/src/main/java/com/zhgd/xmgl/util/FlowSeviceUtil.java b/src/main/java/com/zhgd/xmgl/util/FlowSeviceUtil.java index 1447677d5..c721a7ac8 100644 --- a/src/main/java/com/zhgd/xmgl/util/FlowSeviceUtil.java +++ b/src/main/java/com/zhgd/xmgl/util/FlowSeviceUtil.java @@ -42,6 +42,7 @@ import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.runtime.Execution; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstanceQuery; import org.flowable.task.api.Task; @@ -451,9 +452,35 @@ public class FlowSeviceUtil { HistoricProcessInstanceQuery instanceQuery = historyService.createHistoricProcessInstanceQuery(); instanceQuery.processInstanceTenantId(TenantContextHolder.getTenantId()); if (Objects.equals(customStatus, 1)) { - instanceQuery.or().startedBy(userId + "").involvedUser(userId + "").endOr(); + HistoricProcessInstanceQuery baseQuery = historyService.createHistoricProcessInstanceQuery() + .or().startedBy(userId) + .involvedUser(userId) + .endOr() + .unfinished(); + List processInstanceIds = baseQuery.list() + .stream() + .map(HistoricProcessInstance::getId) + .collect(Collectors.toList()); + // 获取当前用户待处理任务的流程实例ID + TaskQuery taskQuery = taskService.createTaskQuery(); + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery(); + Set stringSet = processInstanceQuery.list().stream().map(Execution::getProcessInstanceId).collect(Collectors.toSet()); + taskQuery.active().taskTenantId(TenantContextHolder.getTenantId()) + .processInstanceIdIn(stringSet) + .taskCandidateOrAssigned(userId); + List activeTaskProcessIds = taskQuery.list() + .stream() + .map(Task::getProcessInstanceId) + .collect(Collectors.toList()); + // 排除待处理的流程实例ID + processInstanceIds.removeAll(activeTaskProcessIds); + if (processInstanceIds.isEmpty()) { + processInstanceIds.add("-100"); + } + // 构造最终查询并分页 + instanceQuery.processInstanceIds(new HashSet<>(processInstanceIds)); } else if (Objects.equals(customStatus, 2)) { - instanceQuery.or().startedBy(userId + "").involvedUser(userId + "").endOr(); + instanceQuery.or().startedBy(userId).involvedUser(userId).endOr(); instanceQuery.finished(); } Executor.builder() diff --git a/src/main/resources/excel/人员入场导入模板.xlsx b/src/main/resources/excel/人员入场导入模板.xlsx index 2477a695b8af3d79361b65f1f21a6736ac29c466..787008fb858ced45922ae1c5059bfaa90d651804 100644 GIT binary patch delta 5221 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 R0EmMEs`21i%KdfizW~E)ep3Jd delta 5195 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 I^YBmp2cz(4!~g&Q