| | |
| | | patTaskRelevance.setDiagname(serviceSubtask1.getLeavediagname()); |
| | | patTaskRelevance.setPatid(serviceSubtask1.getPatid()); |
| | | patTaskRelevance.setSendStatus(serviceSubtask1.getSendstate()); |
| | | patTaskRelevance.setDeptcode(serviceSubtask1.getDeptcode()); |
| | | patTaskRelevance.setDeptName(serviceSubtask1.getDeptname()); |
| | | patTaskRelevance.setDeptcode(serviceSubtask1.getLeaveldeptcode()); |
| | | patTaskRelevance.setDeptName(serviceSubtask1.getLeaveldeptname()); |
| | | patTaskRelevance.setLeavehospitaldistrictcode(serviceSubtask1.getLeavehospitaldistrictcode()); |
| | | patTaskRelevance.setLeavehospitaldistrictname(serviceSubtask1.getLeavehospitaldistrictname()); |
| | | patTaskRelevance.setInhosptime(serviceSubtask1.getInhosptime()); |
| | |
| | | patTaskRelevance.setTelcode(serviceSubtask1.getPhone()); |
| | | patTaskRelevance.setFinishtime(serviceSubtask1.getFinishtime()); |
| | | patTaskRelevance.setAddr(serviceSubtask1.getAddr()); |
| | | patTaskRelevance.setDeptName(serviceSubtask1.getDeptname()); |
| | | patTaskRelevance.setDeptcode(serviceSubtask1.getDeptcode()); |
| | | patTaskRelevance.setDeptName(serviceSubtask1.getLeaveldeptname()); |
| | | patTaskRelevance.setDeptcode(serviceSubtask1.getLeaveldeptcode()); |
| | | patTaskRelevance.setBedNo(serviceSubtask1.getBedNo()); |
| | | patTaskRelevance.setDiagname(serviceSubtask1.getLeavediagname()); |
| | | patTaskRelevance.setPatid(serviceSubtask1.getPatid()); |
| | |
| | | List<ServiceSubtask> selectServiceSubtaskList = getServiceSubtasks(serviceSubtaskEntity); |
| | | |
| | | List<ServiceSubtaskRes> serviceSubtaskResList = new ArrayList<>(); |
| | | // 同一次请求(列表分页 / 全量导出)里,inhospid 与 patid 高度重复 |
| | | // (再次随访、同一患者多任务都会指向同一条住院记录/同一份档案)。 |
| | | // 原来每行都要 2 次单条查询,导出几千行就是几千×2 次往返;这里按 id 做进程内缓存, |
| | | // 把「每行 2 次」压成「每个不同 id 1 次」,取数语义不变。 |
| | | Map<Long, PatMedInhosp> inhospCache = new HashMap<>(); |
| | | Map<Long, PatArchive> archiveCache = new HashMap<>(); |
| | | for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) { |
| | | ServiceSubtaskRes serviceSubtaskRes = DtoConversionUtils.sourceToTarget(serviceSubtask, ServiceSubtaskRes.class); |
| | | if (ObjectUtils.isNotEmpty(serviceSubtask.getContinueContent())) { |
| | |
| | | serviceSubtaskRes.setCurrentPreachform(serviceSubtask.getPreachform().split(",")[0]); |
| | | } |
| | | } |
| | | PatMedInhosp inhosp = inhospVisitFacade.selectPatMedInhospByInhospid(serviceSubtask.getInhospid()); |
| | | PatMedInhosp inhosp = loadInhospCached(inhospCache, serviceSubtask.getInhospid()); |
| | | if (ObjectUtils.isNotEmpty(inhosp)) { |
| | | PatArchive patArchive = taskArchivePort.findByPatid(inhosp.getPatid()); |
| | | PatArchive patArchive = loadArchiveCached(archiveCache, inhosp.getPatid()); |
| | | if (ObjectUtils.isNotEmpty(patArchive)) { |
| | | Map<String, String> stringStringMap = calculateAge(patArchive.getBirthdate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalDate.now()); |
| | | serviceSubtaskRes.setAge(StringUtils.isNotEmpty(stringStringMap.get("age")) ? Long.valueOf(stringStringMap.get("age")) : null); |
| | |
| | | serviceSubtaskResList.add(serviceSubtaskRes); |
| | | } |
| | | return serviceSubtaskResList; |
| | | } |
| | | |
| | | /** |
| | | * 按 inhospid 取住院记录(带进程内缓存)。 |
| | | * <p> |
| | | * 只是把「同一次请求内同一个 id 只查一次」这件事收口,<b>不改变取数语义</b>: |
| | | * 查不到(null)也会缓存,避免同一批数据里对不存在的 id 反复打库。 |
| | | * 缓存生命周期 = 单次 {@code patItem} 调用,不跨请求、不共享。 |
| | | */ |
| | | private PatMedInhosp loadInhospCached(Map<Long, PatMedInhosp> cache, Long inhospid) { |
| | | if (inhospid == null) { |
| | | return null; |
| | | } |
| | | if (!cache.containsKey(inhospid)) { |
| | | cache.put(inhospid, inhospVisitFacade.selectPatMedInhospByInhospid(inhospid)); |
| | | } |
| | | return cache.get(inhospid); |
| | | } |
| | | |
| | | /** |
| | | * 按 patid 取患者档案(带进程内缓存),语义同 {@link #loadInhospCached}。 |
| | | */ |
| | | private PatArchive loadArchiveCached(Map<Long, PatArchive> cache, Long patid) { |
| | | if (patid == null) { |
| | | return null; |
| | | } |
| | | if (!cache.containsKey(patid)) { |
| | | cache.put(patid, taskArchivePort.findByPatid(patid)); |
| | | } |
| | | return cache.get(patid); |
| | | } |
| | | |
| | | public List<ServiceSubtask> getServiceSubtasks(ServiceSubtaskEntity serviceSubtaskEntity) { |
| | |
| | | } |
| | | } |
| | | } |
| | | List<ServiceSubtask> selectServiceSubtaskList = this.selectServiceSubtaskList(serviceSubtaskEntity); |
| | | return selectServiceSubtaskList; |
| | | // 分页请求走「两阶段」:先只取当页 id,再按 id 回表。 |
| | | // 列表 select 约 100 列,深翻页时被 offset 跳过的每一行原本都要回表读整行; |
| | | // 只取 id 的查询能走覆盖索引并提前截断,代价小得多。 |
| | | if (serviceSubtaskEntity.getPageNum() != null && serviceSubtaskEntity.getPageSize() != null) { |
| | | return selectServiceSubtaskPage(serviceSubtaskEntity); |
| | | } |
| | | return this.selectServiceSubtaskList(serviceSubtaskEntity); |
| | | } |
| | | |
| | | /** |
| | | * 两阶段分页:① 只查 id(覆盖索引 + limit offset)② 按 id 回表取整行。 |
| | | * <p> |
| | | * 第二阶段复用 {@code selectServiceSubtaskList} 的 subIdList 条件回表, |
| | | * 必须把 pageNum/pageSize 摘掉 —— 否则会在「当页 id 集合」上再翻一次页。 |
| | | * <p> |
| | | * 统计缓存(Controller 的 {@code getPatItemCountWithCache})用 ReflectUtils 比对整个 |
| | | * entity 作为缓存命中条件,{@code subIdList} 参与比对,所以用完必须原样还原, |
| | | * 否则缓存永远不命中,每次请求都要重算一次聚合。 |
| | | */ |
| | | private List<ServiceSubtask> selectServiceSubtaskPage(ServiceSubtaskEntity serviceSubtaskEntity) { |
| | | List<Long> pageIds = serviceSubtaskMapper.selectServiceSubtaskIdsPage(serviceSubtaskEntity); |
| | | if (CollectionUtils.isEmpty(pageIds)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | Integer pageNum = serviceSubtaskEntity.getPageNum(); |
| | | Integer pageSize = serviceSubtaskEntity.getPageSize(); |
| | | List<Long> originSubIdList = serviceSubtaskEntity.getSubIdList(); |
| | | serviceSubtaskEntity.setPageNum(null); |
| | | serviceSubtaskEntity.setPageSize(null); |
| | | serviceSubtaskEntity.setSubIdList(pageIds); |
| | | List<ServiceSubtask> rows; |
| | | try { |
| | | rows = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity); |
| | | } finally { |
| | | serviceSubtaskEntity.setPageNum(pageNum); |
| | | serviceSubtaskEntity.setPageSize(pageSize); |
| | | serviceSubtaskEntity.setSubIdList(originSubIdList); |
| | | } |
| | | if (CollectionUtils.isEmpty(rows)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | // 以第一阶段的 id 顺序为准重排:第二阶段的 order by 只保证「同一页内」有序, |
| | | // 遇到排序字段值相同的行时相对顺序不一定与第一阶段一致。 |
| | | Map<Long, ServiceSubtask> byId = new HashMap<>(Math.max(16, rows.size() * 2)); |
| | | for (ServiceSubtask row : rows) { |
| | | if (row.getId() != null) { |
| | | byId.put(row.getId(), row); |
| | | } |
| | | } |
| | | List<ServiceSubtask> ordered = new ArrayList<>(pageIds.size()); |
| | | for (Long id : pageIds) { |
| | | ServiceSubtask row = byId.get(id); |
| | | if (row != null) { |
| | | ordered.add(row); |
| | | } |
| | | } |
| | | return ordered; |
| | | } |
| | | |
| | | @Override |
| | |
| | | serviceSubtask.setInhospid(patTaskRelevance.getHospid()); |
| | | //新建完成就是待发送状态 |
| | | serviceSubtask.setSendstate(2L); |
| | | serviceSubtask.setDeptcode(StringUtils.isNotEmpty(patTaskRelevance.getDeptcode()) ? patTaskRelevance.getDeptcode() : serviceTaskVO.getDeptcode()); |
| | | serviceSubtask.setDeptname(StringUtils.isNotEmpty(patTaskRelevance.getDeptName()) ? patTaskRelevance.getDeptName() : serviceTaskVO.getDeptname()); |
| | | serviceSubtask.setLeaveldeptcode(StringUtils.isNotEmpty(patTaskRelevance.getDeptcode()) ? patTaskRelevance.getDeptcode() : serviceTaskVO.getDeptcode()); |
| | | serviceSubtask.setLeaveldeptname(StringUtils.isNotEmpty(patTaskRelevance.getDeptName()) ? patTaskRelevance.getDeptName() : serviceTaskVO.getDeptname()); |
| | | serviceSubtask.setLeavehospitaldistrictcode(patTaskRelevance.getLeavehospitaldistrictcode()); |
| | | serviceSubtask.setLeavehospitaldistrictname(patTaskRelevance.getLeavehospitaldistrictname()); |
| | | serviceSubtask.setType(serviceTaskVO.getType()); |
| | |
| | | serviceSubtask.setAddr(patTaskRelevance.getAddr()); |
| | | serviceSubtask.setPatid(patTaskRelevance.getPatid()); |
| | | serviceSubtask.setOpenid(patTaskRelevance.getOpenid()); |
| | | serviceSubtask.setDeptcode(patTaskRelevance.getDeptcode()); |
| | | serviceSubtask.setLeaveldeptcode(patTaskRelevance.getDeptcode()); |
| | | serviceSubtask.setLeavehospitaldistrictname(patTaskRelevance.getLeavehospitaldistrictname()); |
| | | serviceSubtask.setLeavehospitaldistrictcode(patTaskRelevance.getLeavehospitaldistrictcode()); |
| | | serviceSubtask.setDeptname(patTaskRelevance.getDeptName()); |
| | | serviceSubtask.setLeaveldeptname(patTaskRelevance.getDeptName()); |
| | | serviceSubtask.setType(serviceTaskVO.getType()); |
| | | serviceSubtask.setCreateTime(DateUtils.getNowDate()); |
| | | serviceSubtask.setDrname(patTaskRelevance.getDrname()); |
| | |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getManagementDoctorCode()).orElse("Unknown"))); |
| | | break; |
| | | case "deptcode": |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptcode()).orElse("Unknown"))); |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeaveldeptcode()).orElse("Unknown"))); |
| | | break; |
| | | case "leavehospitaldistrictcode": |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown"))); |
| | |
| | | * @return |
| | | */ |
| | | public Map<String, Map<String, Object>> getSsRateForSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq, Map<String, List<ServiceSubtask>> collect) { |
| | | if (ObjectUtils.isEmpty(serviceSubtaskCountReq) || ObjectUtils.isEmpty(collect)) { |
| | | return null; |
| | | } |
| | | return getSsRateForSfStatistics(serviceSubtaskCountReq, new ArrayList<>(collect.keySet())); |
| | | } |
| | | |
| | | /** |
| | | * 随访统计-及时率统计(分组键直接传值的重载) |
| | | * <p> |
| | | * 统计下推到 SQL 的 {@code getSfStatisticsScript} 不再把明细行捞回内存,拿不到 |
| | | * {@code Map<分组, List<明细>>},因此直接传分组键集合;查询语句与原来完全同一个。 |
| | | * |
| | | * @param groupKeyList 分组键集合(drcode / leaveldeptcode / leavehospitaldistrictcode 的实际取值) |
| | | */ |
| | | public Map<String, Map<String, Object>> getSsRateForSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq, List<String> groupKeyList) { |
| | | if (ObjectUtils.isEmpty(serviceSubtaskCountReq)) { |
| | | return null; |
| | | } |
| | |
| | | if (StringUtils.isEmpty(groupKey)) { |
| | | return null; |
| | | } |
| | | List<String> groupKeyList = new ArrayList<>(collect.keySet()); |
| | | if (ObjectUtils.isEmpty(groupKeyList)) { |
| | | return null; |
| | | } |
| | |
| | | ssRate.setGroupKey(groupKey); |
| | | ssRate.setGroupKeyList(groupKeyList); |
| | | ssRate.setRateDay(serviceSubtaskCountReq.getRateDay()); |
| | | Map<String, Map<String, Object>> jsRates = new HashMap<>(); |
| | | if (!collect.isEmpty()) { |
| | | jsRates = serviceSubtaskMapper.selectTimelyRateBatch(ssRate); |
| | | } |
| | | return jsRates; |
| | | return serviceSubtaskMapper.selectTimelyRateBatch(ssRate); |
| | | } |
| | | |
| | | /** |
| | | * 空值兜底:SUM(CASE ...) 理论上不会是 null,这里只做防御,避免拆箱 NPE。 |
| | | */ |
| | | private long nvlLong(Long value) { |
| | | return value == null ? 0L : value; |
| | | } |
| | | |
| | | /** |
| | | * 把数据库聚合值(BigDecimal / Long / Integer 等)转成 int。 |
| | | */ |
| | | private int toIntValue(Object value) { |
| | | return value instanceof Number ? ((Number) value).intValue() : 0; |
| | | } |
| | | |
| | | public List<ServiceSubtaskStatistic> getSfStatisticsExport(ServiceSubtaskCountReq serviceSubtaskCountReq) { |
| | |
| | | if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) { |
| | | collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrname()).orElse("Unknown"))); |
| | | } else { |
| | | collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptname()).orElse("Unknown"))); |
| | | collect = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq).stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeaveldeptname()).orElse("Unknown"))); |
| | | } |
| | | } |
| | | List<ServiceSubtaskCount> joySubCount = serviceSubtaskMapper.getSfStatisticsJoy(serviceSubtaskCountReq); |
| | |
| | | if (CollectionUtils.isNotEmpty(serviceSubtaskCountReq.getLeavehospitaldistrictcodes())) { |
| | | ss.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | } else if (CollectionUtils.isNotEmpty(serviceSubtaskCountReq.getDeptcodes())) { |
| | | ss.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | ss.setLeaveldeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | } |
| | | } |
| | | |
| | |
| | | } else { |
| | | //格式化为两位小数的百分比 |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode()); |
| | |
| | | ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic(); |
| | | //格式化为两位小数的百分比 |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode()); |
| | |
| | | ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic(); |
| | | //格式化为两位小数的百分比 |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode()); |
| | |
| | | ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic(); |
| | | //格式化为两位小数的百分比 |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode()); |
| | |
| | | ServiceSubtaskStatistic serviceSubtaskStatistic = new ServiceSubtaskStatistic(); |
| | | //格式化为两位小数的百分比 |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getDeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getDeptcode()); |
| | | serviceSubtaskStatistic.setDeptname(serviceSubtaskList.get(0).getLeaveldeptname()); |
| | | serviceSubtaskStatistic.setDeptcode(serviceSubtaskList.get(0).getLeaveldeptcode()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictname(serviceSubtaskList.get(0).getLeavehospitaldistrictname()); |
| | | serviceSubtaskStatistic.setLeavehospitaldistrictcode(serviceSubtaskList.get(0).getLeavehospitaldistrictcode()); |
| | | serviceSubtaskStatistic.setDrcode(serviceSubtaskList.get(0).getDrcode()); |
| | |
| | | log.info("getSfStatisticsScript的入参为:{}", serviceSubtaskCountReq); |
| | | List<ServiceSubtaskStatistic> serviceSubtaskStatistics = new ArrayList<>(); |
| | | |
| | | // 根据条件进行分组 |
| | | Map<String, List<ServiceSubtask>> collect = new HashMap<>(); |
| | | // 根据条件决定分组维度:离院维度按 leaveldeptcode / leavehospitaldistrictcode(含历史 deptcodes 入参), |
| | | // 在院维度按 deptcode / hospitaldistrictcode |
| | | String groupKey = "drcode"; |
| | | boolean hasDrcode = serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty(); |
| | | if (serviceSubtaskCountReq.getLeavehospitaldistrictcodes() != null && !serviceSubtaskCountReq.getLeavehospitaldistrictcodes().isEmpty()) { |
| | | if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) { |
| | | groupKey = "drcode"; |
| | | } else { |
| | | groupKey = "leavehospitaldistrictcode"; |
| | | } |
| | | groupKey = hasDrcode ? "drcode" : "leavehospitaldistrictcode"; |
| | | } else if (serviceSubtaskCountReq.getLeaveldeptcodes() != null && !serviceSubtaskCountReq.getLeaveldeptcodes().isEmpty()) { |
| | | groupKey = hasDrcode ? "drcode" : "leaveldeptcode"; |
| | | } else if (serviceSubtaskCountReq.getHospitaldistrictcodes() != null && !serviceSubtaskCountReq.getHospitaldistrictcodes().isEmpty()) { |
| | | // 在院满意度:按在院病区分组(hospitaldistrictcode) |
| | | groupKey = hasDrcode ? "drcode" : "hospitaldistrictcode"; |
| | | } else if (serviceSubtaskCountReq.getHospitaldeptcodes() != null && !serviceSubtaskCountReq.getHospitaldeptcodes().isEmpty()) { |
| | | // 在院满意度:按在院科室分组(deptcode) |
| | | groupKey = hasDrcode ? "drcode" : "deptcode"; |
| | | } else if (serviceSubtaskCountReq.getDeptcodes() != null && !serviceSubtaskCountReq.getDeptcodes().isEmpty()) { |
| | | if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) { |
| | | groupKey = "drcode"; |
| | | } else { |
| | | groupKey = "deptcode"; |
| | | } |
| | | // 历史入参 deptcodes 表示离院科室 |
| | | groupKey = hasDrcode ? "drcode" : "leaveldeptcode"; |
| | | } |
| | | serviceSubtaskCountReq.setGroupKey(groupKey); |
| | | // 分组列与过滤列保持一致:离院科室 leaveldeptcode、在院科室 deptcode |
| | | serviceSubtaskCountReq.setGroupColumn(groupKey); |
| | | //分组键集合:这一步保持不变(分页参数照旧作用在该查询上),保证“参与统计的分组”与改造前一致 |
| | | List<String> groupKeyList = serviceSubtaskMapper.getSfStatisticsGroupKey(serviceSubtaskCountReq); |
| | | /* |
| | | * 分组列可能为 NULL:满意度子任务(service_type 6/14/15/16)的 leavehospitaldistrictcode |
| | | * 大量为 NULL,getSfStatisticsGroupKey 会把 NULL 原样带回来, |
| | | * 拼进 SQL 就变成 `AND xxx IN (null)`(恒不成立),整张统计表直接空。 |
| | | * 这里统一成 'Unknown',与聚合 SQL 的 GROUP BY IFNULL(列,'Unknown') 对齐。 |
| | | */ |
| | | if (groupKeyList != null) { |
| | | groupKeyList = groupKeyList.stream() |
| | | .map(key -> key == null ? "Unknown" : key) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | } |
| | | serviceSubtaskCountReq.setGroupKeyList(groupKeyList); |
| | | List<ServiceSubtask> rawData = serviceSubtaskMapper.getSfStatistics(serviceSubtaskCountReq); |
| | | switch (groupKey) { |
| | | case "deptcode": |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDeptcode()).orElse("Unknown"))); |
| | | break; |
| | | case "drcode": |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown"))); |
| | | break; |
| | | case "leavehospitaldistrictcode": |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getLeavehospitaldistrictcode()).orElse("Unknown"))); |
| | | break; |
| | | default: |
| | | collect = rawData.stream().collect(Collectors.groupingBy(subtask -> Optional.ofNullable(subtask.getDrcode()).orElse("Unknown"))); |
| | | break; |
| | | |
| | | /* |
| | | * 统计下推到数据库:一次 GROUP BY 只返回“分组数”行。 |
| | | * 改造前是 serviceSubtaskMapper.getSfStatistics() 把命中的全部明细行(39 个字段, |
| | | * 含 continue_content 等大字段)捞回 JVM 后逐行累加,几千行时传输和遍历都很慢。 |
| | | * 这里的聚合口径与原 getStatisticCategory 逐条对齐(见 Mapper 中 getSfStatisticsScriptSum 的注释)。 |
| | | */ |
| | | List<ServiceSubtaskStatistic> sumStatistics = serviceSubtaskMapper.getSfStatisticsScriptSum(serviceSubtaskCountReq); |
| | | if (CollectionUtils.isEmpty(sumStatistics)) { |
| | | return serviceSubtaskStatistics; |
| | | } |
| | | //获取及时率统计合集 |
| | | Map<String, Map<String, Object>> jsRates = getSsRateForSfStatistics(serviceSubtaskCountReq, collect); |
| | | //一次性查询所有分组的题目统计,避免每个分组一次SQL(N+1) |
| | | List<Long> allSubTaskIds = rawData.stream().map(ServiceSubtask::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); |
| | | List<ServiceSubtaskCount> subCounts = new ArrayList<>(); |
| | | if (CollectionUtils.isNotEmpty(allSubTaskIds)) { |
| | | serviceSubtaskCountReq.setSubTaskIds(allSubTaskIds); |
| | | subCounts = serviceSubtaskMapper.getSfStatisticsCategory(serviceSubtaskCountReq); |
| | | } |
| | | for (String collectKey : collect.keySet()) { |
| | | List<ServiceSubtask> serviceSubtaskList = collect.get(collectKey); |
| | | if (CollectionUtils.isEmpty(serviceSubtaskList)) { |
| | | continue; |
| | | } |
| | | ServiceSubtaskStatistic statistic = getStatisticCategory(serviceSubtaskList, serviceSubtaskCountReq, subCounts); |
| | | if (ObjectUtils.isNotEmpty(jsRates)) { |
| | | Map<String, Object> jsRateMap = jsRates.get(collectKey); |
| | | BigDecimal jsRate = new BigDecimal("0"); |
| | | if (ObjectUtils.isNotEmpty(jsRateMap) && ObjectUtils.isNotEmpty(jsRateMap.get("rate"))) { |
| | | jsRate = new BigDecimal(jsRateMap.get("rate").toString()); |
| | | |
| | | /* |
| | | * 满意度题目量:也改成按分组在库里聚合。 |
| | | * 改造前是先把本次命中的全部子任务 id 灌进 getSfStatisticsCategory 的 IN 列表查一遍, |
| | | * 再在内存里对每个子任务做一次 subCounts.stream().filter(...)(N*M 次比较)。 |
| | | */ |
| | | Map<String, Integer> joyCountMap = new HashMap<>(); |
| | | Map<String, Integer> joyAllCountMap = new HashMap<>(); |
| | | if (StringUtils.isNotEmpty(serviceSubtaskCountReq.getConfigValue())) { |
| | | List<Map<String, Object>> joySums = serviceSubtaskMapper.getSfStatisticsScriptJoySum(serviceSubtaskCountReq); |
| | | if (CollectionUtils.isNotEmpty(joySums)) { |
| | | for (Map<String, Object> joySum : joySums) { |
| | | String joyGroupCode = joySum.get("groupCode") == null ? "Unknown" : joySum.get("groupCode").toString(); |
| | | joyCountMap.put(joyGroupCode, toIntValue(joySum.get("joyCount"))); |
| | | joyAllCountMap.put(joyGroupCode, toIntValue(joySum.get("joyAllCount"))); |
| | | } |
| | | Double jsRateDouble = (jsRate.setScale(4, RoundingMode.HALF_UP)).doubleValue(); |
| | | statistic.setRate(jsRateDouble); |
| | | } |
| | | if (ObjectUtils.isNotEmpty(statistic)) { |
| | | serviceSubtaskStatistics.add(statistic); |
| | | } |
| | | |
| | | //随访率:口径与原 getStatisticCategory 一致(首次率的判断沿用原来的 needFollowUp、再次率沿用原来的分母) |
| | | DecimalFormat percentFormat = new DecimalFormat("##.##%"); |
| | | List<String> statisticsGroupKeys = new ArrayList<>(); |
| | | for (ServiceSubtaskStatistic statistic : sumStatistics) { |
| | | String statisticGroupCode = statistic.getGroupCode() == null ? "Unknown" : statistic.getGroupCode(); |
| | | statistic.setJoyCount(joyCountMap.getOrDefault(statisticGroupCode, 0)); |
| | | statistic.setJoyAllCount(joyAllCountMap.getOrDefault(statisticGroupCode, 0)); |
| | | //首次随访率:只有该分组存在首次随访记录时才会被赋值(不存在则是 null,与改造前一致) |
| | | if (statistic.getFirstVisitCount() != null && statistic.getFirstVisitCount() > 0) { |
| | | if (statistic.getNeedFollowUp() != null && statistic.getNeedFollowUp() > 0) { |
| | | double rate = (double) (nvlLong(statistic.getFollowUpSuccess()) + nvlLong(statistic.getFollowUpFail())) / statistic.getNeedFollowUp(); |
| | | statistic.setFollowUpRate(percentFormat.format(rate)); |
| | | } else { |
| | | statistic.setFollowUpRate("0.00%"); |
| | | } |
| | | } |
| | | //再次随访率:判断条件与原实现一致(原来判断的是 needFollowUp,这里照搬以免口径变化) |
| | | if (statistic.getAgainVisitCount() != null && statistic.getAgainVisitCount() > 0) { |
| | | if (statistic.getNeedFollowUp() != null && statistic.getNeedFollowUp() > 0) { |
| | | double rateAgain = (double) (nvlLong(statistic.getFollowUpSuccessAgain()) + nvlLong(statistic.getFollowUpFailAgain())) / nvlLong(statistic.getNeedFollowUpAgain()); |
| | | statistic.setFollowUpRateAgain(percentFormat.format(rateAgain)); |
| | | } else { |
| | | statistic.setFollowUpRateAgain("0.00%"); |
| | | } |
| | | } |
| | | statisticsGroupKeys.add(statisticGroupCode); |
| | | serviceSubtaskStatistics.add(statistic); |
| | | } |
| | | |
| | | //获取及时率统计合集(一次批量查询,不按分组循环查) |
| | | Map<String, Map<String, Object>> jsRates = getSsRateForSfStatistics(serviceSubtaskCountReq, statisticsGroupKeys); |
| | | for (ServiceSubtaskStatistic statistic : serviceSubtaskStatistics) { |
| | | String statisticGroupCode = statistic.getGroupCode() == null ? "Unknown" : statistic.getGroupCode(); |
| | | Map<String, Object> jsRateMap = jsRates == null ? null : jsRates.get(statisticGroupCode); |
| | | BigDecimal jsRate = new BigDecimal("0"); |
| | | if (ObjectUtils.isNotEmpty(jsRateMap) && ObjectUtils.isNotEmpty(jsRateMap.get("rate"))) { |
| | | jsRate = new BigDecimal(jsRateMap.get("rate").toString()); |
| | | } |
| | | statistic.setRate((jsRate.setScale(4, RoundingMode.HALF_UP)).doubleValue()); |
| | | } |
| | | |
| | | //统计随访题目分类 |
| | |
| | | diagname.setPhone(subtask.getPhone()); |
| | | diagname.setNurseName(subtask.getNurseName()); |
| | | diagname.setDrname(subtask.getDrname()); |
| | | diagname.setDeptname(subtask.getDeptname()); |
| | | diagname.setDeptname(subtask.getLeaveldeptname()); |
| | | diagname.setLeavehospitaldistrictname(subtask.getLeavehospitaldistrictname()); |
| | | diagname.setTemplatename(subtask.getTemplatename()); |
| | | diagname.setPreachform(subtask.getPreachform()); |
| | |
| | | //3.如果查出来的集合不为空,则进行循环 |
| | | for (ServiceSubtask serviceSubtask : serviceSubtasks) { |
| | | Integer preachformSize = 0; |
| | | Boolean flag = false; |
| | | ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform(); |
| | | serviceSubtaskPreachform.setSubid(serviceSubtask.getId()); |
| | | List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = taskPreachformPort.selectServiceSubtaskPreachformList(serviceSubtaskPreachform); |
| | |
| | | preachformSize = serviceSubtaskPreachforms.size(); |
| | | if (serviceSubtask.getUpdateTime() != null && DateUtils.differentDaysByMillisecond(new Date(), serviceSubtask.getUpdateTime()) >= failDay) { |
| | | //3.1 判断当前serviceSubtask的updateTime是不是为空,如果不为空,则判断当前时间是不是与updateTime差距大于等于failDay |
| | | flag = saveServiceSubtaskDetail(serviceSubtask); |
| | | log.debug("【失败任务默认值】子任务 {} 达到失败天数(updateTime)", serviceSubtask.getId()); |
| | | } else if (serviceSubtask.getVisitTime() != null && DateUtils.differentDaysByMillisecond(new Date(), serviceSubtask.getVisitTime()) >= failDay + preachformSize) { |
| | | //3.2 如果当前serviceSubtask的updateTime为空,根据当前serviceSubtask的subid去查service_subtask_preachform得到size(如果size为空,则默认0),则根据当前时间是不是与当前serviceSubtask的visitTime差距大于等于failDay + size |
| | | flag = saveServiceSubtaskDetail(serviceSubtask); |
| | | log.debug("【失败任务默认值】子任务 {} 达到失败天数(visitTime+preachformSize)", serviceSubtask.getId()); |
| | | } else { |
| | | //3.3 如果2.1且2.2都为false,则continue |
| | | continue; |
| | | } |
| | | |
| | | //4.如果flag为true,则更新service_subtask表中的sendstate为6,preachform为1 |
| | | if (flag) { |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtask.setPreachform("1"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | //4. ⚠️ 2026-10-21 加固:先"算完"再"落库",彻底去掉"先插入、失败再删除"的写法。 |
| | | // 旧逻辑是边插边判断,只要有一题没配默认值,就把这个 sub_id 下**所有**明细(含患者真实作答、 |
| | | // 甚至刚插进去的那批)统统置 del_flag='1' —— nhfy 2026-09-08 那 10 位患者的满意度作答 |
| | | // 就是这样被删掉、导致导出「问题详情占比」370 而「随访信息表单」380 的。 |
| | | // 现在:① 清单为空(=有题没配默认值)→ 整份跳过,不写也不删; |
| | | // ② 清单齐全 → 统一落库(存在则更新并复活,不存在则插入)。 |
| | | List<ServiceSubtaskDetail> defaultDetails = buildDefaultDetails(serviceSubtask); |
| | | if (CollectionUtils.isEmpty(defaultDetails)) { |
| | | log.info("【失败任务默认值】任务 {} 子任务 {} 有题目未配置默认值,整份跳过(不插入、不删除任何明细)", |
| | | serviceSubtask.getTaskid(), serviceSubtask.getId()); |
| | | continue; |
| | | } |
| | | persistDefaultDetails(defaultDetails); |
| | | |
| | | //5.全部落库成功后再把任务置为已完成 |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtask.setPreachform("1"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 按模板构造"默认值明细"清单(<b>只计算、不落库</b>) |
| | | * <p> |
| | | * 2026-10-21 新增:把原来的 {@code saveServiceSubtaskDetail}(边算边插、失败再删)拆成 |
| | | * 「build(本方法)」+「persist({@link #persistDefaultDetails})」两步, |
| | | * 保证"默认值不全"时**一个字节都不会写、更不会删**。 |
| | | * |
| | | * @param serviceSubtask 子任务 |
| | | * @return 明细清单;任一题没配默认值(或模板为空)时返回 {@code null},表示整份不处理 |
| | | */ |
| | | private List<ServiceSubtaskDetail> buildDefaultDetails(ServiceSubtask serviceSubtask) { |
| | | if (serviceSubtask.getType() == null) { |
| | | return null; |
| | | } |
| | | List<ServiceSubtaskDetail> details = new ArrayList<>(); |
| | | if (serviceSubtask.getType().equals("1")) { |
| | | //3.3.1 如果type是 1,则用当前serviceSubtask的templateid去ivr_task_temaplate_script中获取问题和选项 |
| | | IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript(); |
| | | ivrTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid()); |
| | | List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript); |
| | | if (CollectionUtils.isEmpty(ivrTaskTemplateScripts)) return null; |
| | | for (IvrTaskTemplateScript its : ivrTaskTemplateScripts) { |
| | | IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(its, IvrTaskTemplateScriptVO.class); |
| | | IvrTaskTemplateTargetoption ivrTaskTemplateTargetoption = new IvrTaskTemplateTargetoption(); |
| | | ivrTaskTemplateTargetoption.setScriptid(ivrTaskTemplateScriptVO.getId()); |
| | | List<IvrTaskTemplateTargetoption> ivrTaskTemplateTargetoptions = iIvrTaskTemplateTargetoptionService.selectIvrTaskTemplateTargetoptionList(ivrTaskTemplateTargetoption); |
| | | ivrTaskTemplateScriptVO.setIvrTaskScriptTargetoptionList(ivrTaskTemplateTargetoptions); |
| | | ServiceSubtaskDetail detail = buildSFDetail(ivrTaskTemplateScriptVO, serviceSubtask); |
| | | if (detail == null) return null; |
| | | details.add(detail); |
| | | } |
| | | } else if (serviceSubtask.getType().equals("2")) { |
| | | //3.3.2 如果type是 2,则用当前serviceSubtask的templateid去svy_task_temaplate_script中获取问题和选项 |
| | | SvyTaskTemplateScript svyTaskTemplateScript = new SvyTaskTemplateScript(); |
| | | svyTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid()); |
| | | List<SvyTaskTemplateScript> svyTaskTemplateScripts = svyTaskTemplateScriptService.selectSvyTaskTemplateScriptList(svyTaskTemplateScript); |
| | | if (CollectionUtils.isEmpty(svyTaskTemplateScripts)) return null; |
| | | for (SvyTaskTemplateScript taskTemplateScript : svyTaskTemplateScripts) { |
| | | SvyTaskTemplateScriptVO svyTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(taskTemplateScript, SvyTaskTemplateScriptVO.class); |
| | | SvyTaskTemplateScriptVO svyTaskTemplateScriptVO1 = svyTaskTemplateScriptService.selectInfoByCondition(svyTaskTemplateScriptVO); |
| | | ServiceSubtaskDetail detail = buildWJDetail(svyTaskTemplateScriptVO1, serviceSubtask); |
| | | if (detail == null) return null; |
| | | details.add(detail); |
| | | } |
| | | } else { |
| | | return null; |
| | | } |
| | | return details; |
| | | } |
| | | |
| | | /** |
| | | * 落库"默认值明细":存在则更新并复活,不存在则插入(<b>只增不删</b>) |
| | | */ |
| | | private void persistDefaultDetails(List<ServiceSubtaskDetail> details) { |
| | | for (ServiceSubtaskDetail detail : details) { |
| | | ServiceSubtaskDetailDTO exist = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(detail.getSubId(), detail.getScriptid()); |
| | | if (ObjectUtils.isNotEmpty(exist)) { |
| | | detail.setId(exist.getId()); |
| | | detail.setUpdateTime(new Date()); |
| | | serviceSubtaskDetailMapper.updateServiceSubtaskDetail(detail); |
| | | //命中历史被删副本时置回 del_flag='0',避免再插一份新副本 |
| | | serviceSubtaskDetailMapper.reviveServiceSubtaskDetail(exist.getId()); |
| | | } else { |
| | | //删除误新增detail里的数据 |
| | | ServiceSubtaskDetail serviceSubtaskDetail = new ServiceSubtaskDetail(); |
| | | serviceSubtaskDetail.setSubId(serviceSubtask.getId()); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetails = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(serviceSubtaskDetail); |
| | | if (CollectionUtils.isNotEmpty(serviceSubtaskDetails)) { |
| | | for (ServiceSubtaskDetail serviceSubtaskDetail1 : serviceSubtaskDetails) { |
| | | serviceSubtaskDetail1.setDelFlag("1"); |
| | | serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail1); |
| | | } |
| | | } |
| | | serviceSubtaskDetailMapper.insertServiceSubtaskDetail(detail); |
| | | } |
| | | } |
| | | } |
| | |
| | | return resultMap; |
| | | } |
| | | |
| | | private Boolean saveServiceSubtaskDetail(ServiceSubtask serviceSubtask) { |
| | | Boolean result = true; |
| | | //3.4 如果3.1或3.2为true的话,根据type判断什么类型 |
| | | if (serviceSubtask.getType().equals("1")) { |
| | | //3.3.1 如果type是 1 ,则用当前serviceSubtask的templateid去ivr_task_temaplate_script中获取问题和选项,将问题和选项的默认值放到service_detail中 |
| | | IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript(); |
| | | ivrTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid()); |
| | | List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript); |
| | | for (IvrTaskTemplateScript its : ivrTaskTemplateScripts) { |
| | | IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(its, IvrTaskTemplateScriptVO.class); |
| | | IvrTaskTemplateTargetoption ivrTaskTemplateTargetoption = new IvrTaskTemplateTargetoption(); |
| | | ivrTaskTemplateTargetoption.setScriptid(ivrTaskTemplateScriptVO.getId()); |
| | | List<IvrTaskTemplateTargetoption> ivrTaskTemplateTargetoptions = iIvrTaskTemplateTargetoptionService.selectIvrTaskTemplateTargetoptionList(ivrTaskTemplateTargetoption); |
| | | ivrTaskTemplateScriptVO.setIvrTaskScriptTargetoptionList(ivrTaskTemplateTargetoptions); |
| | | Integer integer = setSFDetailInfo(ivrTaskTemplateScriptVO, serviceSubtask); |
| | | if (Objects.isNull(integer) || integer == 0) result = false; |
| | | } |
| | | /* |
| | | * 2026-10-21 已删除 saveServiceSubtaskDetail(...)。 |
| | | * 它原来的语义是"边算默认值边落库,最后返回布尔值",调用方在返回 false 时把该 sub_id 下的 |
| | | * 全部明细置 del_flag='1'(连患者真实作答一起删)。 |
| | | * 现在拆成 buildDefaultDetails(...)(只算不写) + persistDefaultDetails(...)(只增不删), |
| | | * 任何一题缺默认值就整份跳过,不会再产生"删除"动作。 |
| | | */ |
| | | |
| | | } else if (serviceSubtask.getType().equals("2")) { |
| | | //3.3.2 如果type是 2,则用当前serviceSubtask的templateid去svy_task_temaplate_script中获取问题和选项,将问题和选项的默认值放到service_detail中 |
| | | SvyTaskTemplateScript svyTaskTemplateScript = new SvyTaskTemplateScript(); |
| | | svyTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid()); |
| | | List<SvyTaskTemplateScript> svyTaskTemplateScripts = svyTaskTemplateScriptService.selectSvyTaskTemplateScriptList(svyTaskTemplateScript); |
| | | for (SvyTaskTemplateScript taskTemplateScript : svyTaskTemplateScripts) { |
| | | SvyTaskTemplateScriptVO svyTaskTemplateScriptVO = DtoConversionUtils.sourceToTarget(taskTemplateScript, SvyTaskTemplateScriptVO.class); |
| | | SvyTaskTemplateScriptVO svyTaskTemplateScriptVO1 = svyTaskTemplateScriptService.selectInfoByCondition(svyTaskTemplateScriptVO); |
| | | Integer integer = setWJDetailInfo(svyTaskTemplateScriptVO1, serviceSubtask); |
| | | if (Objects.isNull(integer) || integer == 0) result = false; |
| | | } |
| | | /** |
| | | * 按「问卷模板」构造一条"默认值明细"(<b>只计算、不落库</b>) |
| | | * <p> |
| | | * 2026-10-21 由 {@code setWJDetailInfo}(算完就直接 insert/update,失败返回 0)改造而来: |
| | | * 现在只负责把实体拼出来,由 {@link #persistDefaultDetails} 统一落库。 |
| | | * |
| | | * @return 明细;该题没配默认值(单/多选题一个默认选项都没有)时返回 {@code null},表示整份问卷不处理 |
| | | */ |
| | | private ServiceSubtaskDetail buildWJDetail(SvyTaskTemplateScriptVO svyTaskTemplateScriptVO, ServiceSubtask serviceSubtask) { |
| | | if (svyTaskTemplateScriptVO == null) { |
| | | return null; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Integer setWJDetailInfo(SvyTaskTemplateScriptVO svyTaskTemplateScriptVO, ServiceSubtask serviceSubtask) { |
| | | log.info("-----setWJDetailInfo的入参为:{}", svyTaskTemplateScriptVO); |
| | | log.info("-----buildWJDetail的入参为:{}", svyTaskTemplateScriptVO); |
| | | |
| | | ServiceSubtaskDetailVO serviceSubtaskDetailVO = new ServiceSubtaskDetailVO(); |
| | | if (svyTaskTemplateScriptVO.getScriptType().equals("1") || svyTaskTemplateScriptVO.getScriptType().equals("2")) { |
| | | if ("1".equals(svyTaskTemplateScriptVO.getScriptType()) || "2".equals(svyTaskTemplateScriptVO.getScriptType())) { |
| | | //1、2为单选或多选 |
| | | for (SvyTaskTemplateTargetoption svyTaskTemplateTargetoption : svyTaskTemplateScriptVO.getSvyTaskTemplateTargetoptions()) { |
| | | //将问题选项记录下来 |
| | |
| | | } |
| | | |
| | | } |
| | | //如果asrtext和matchedtext都为空,则没有默认值,则不进行处理 |
| | | //如果asrtext和matchedtext都为空,则没有默认值,则不进行处理(返回 null = 整份问卷跳过) |
| | | if (StringUtils.isEmpty(serviceSubtaskDetailVO.getAsrtext()) && StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext())) { |
| | | return 0; |
| | | return null; |
| | | } |
| | | } |
| | | ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | |
| | | } |
| | | serviceSubtaskDetailVO.setSubId(serviceSubtask.getId()); |
| | | serviceSubtaskDetailVO.setTemplatequestionnum(svyTaskTemplateScriptVO.getId()); |
| | | ServiceSubtaskDetail serviceSubtaskDetail = DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class); |
| | | |
| | | //先用subid和scriptid查询一下是否存在,如果存在则更新,不存在则插入 |
| | | ServiceSubtaskDetailDTO existServiceSubtaskDetail = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(serviceSubtaskDetailVO.getSubId(), serviceSubtaskDetailVO.getScriptid()); |
| | | if (ObjectUtils.isNotEmpty(existServiceSubtaskDetail)) { |
| | | serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId()); |
| | | serviceSubtaskDetail.setUpdateTime(new Date()); |
| | | return serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } else { |
| | | return serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } |
| | | return DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class); |
| | | } |
| | | |
| | | private Integer setSFDetailInfo(IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask) { |
| | | |
| | | /** |
| | | * 按「电话模板」构造一条"默认值明细"(<b>只计算、不落库</b>),语义同 {@link #buildWJDetail} |
| | | */ |
| | | private ServiceSubtaskDetail buildSFDetail(IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask) { |
| | | if (ivrTaskTemplateScriptVO == null) { |
| | | return null; |
| | | } |
| | | ServiceSubtaskDetailVO serviceSubtaskDetailVO = new ServiceSubtaskDetailVO(); |
| | | if (ivrTaskTemplateScriptVO.getScriptType() != null && (ivrTaskTemplateScriptVO.getScriptType().equals("1") || ivrTaskTemplateScriptVO.getScriptType().equals("2"))) { |
| | | //1、2为单选或多选 |
| | |
| | | serviceSubtaskDetailVO.setMatchedtext(StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext()) ? ivrTaskTemplateTargetoption.getTargetvalue() : serviceSubtaskDetailVO.getMatchedtext() + "&" + ivrTaskTemplateTargetoption.getTargetvalue()); |
| | | } |
| | | } |
| | | //如果asrtext和matchedtext都为空,则没有默认值,不进行处理 |
| | | //如果asrtext和matchedtext都为空,则没有默认值,不进行处理(返回 null = 整份问卷跳过) |
| | | if (StringUtils.isEmpty(serviceSubtaskDetailVO.getAsrtext()) && StringUtils.isEmpty(serviceSubtaskDetailVO.getMatchedtext())) { |
| | | return 0; |
| | | return null; |
| | | } |
| | | } else if (ivrTaskTemplateScriptVO.getScriptType() == null) { |
| | | return null; |
| | | } |
| | | |
| | | serviceSubtaskDetailVO.setTargetid(ivrTaskTemplateScriptVO.getTargetid() != null ? ivrTaskTemplateScriptVO.getTargetid().intValue() : null); |
| | |
| | | serviceSubtaskDetailVO.setTemplateType(1); |
| | | serviceSubtaskDetailVO.setTemplateid(ivrTaskTemplateScriptVO.getTemplateID() == null ? null : ivrTaskTemplateScriptVO.getTemplateID().toString()); |
| | | serviceSubtaskDetailVO.setLibTemplateid(serviceSubtask.getLibtemplateid() != null ? serviceSubtask.getLibtemplateid().intValue() : null); |
| | | ServiceSubtaskDetail serviceSubtaskDetail = DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class); |
| | | //先用subid和scriptid查询一下是否存在,如果存在则更新,不存在则插入 |
| | | ServiceSubtaskDetailDTO existServiceSubtaskDetail = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(serviceSubtaskDetailVO.getSubId(), serviceSubtaskDetailVO.getScriptid()); |
| | | if (ObjectUtils.isNotEmpty(existServiceSubtaskDetail)) { |
| | | serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId()); |
| | | serviceSubtaskDetail.setUpdateTime(new Date()); |
| | | return serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } else { |
| | | return serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } |
| | | return DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class); |
| | | } |
| | | |
| | | |
| | | public String scanGenerateSubtask(ServiceTask serviceTaskVo) { |
| | | String content = ""; |
| | |
| | | // serviceSubtask.setDrcode(patMedInhosp1.getDrcode()); |
| | | // serviceSubtask.setDrname(patMedInhosp1.getDrname()); |
| | | if (StringUtils.isNotEmpty(serviceTaskdept.getDeptType()) && serviceTaskdept.getDeptType().equals("1")) { |
| | | serviceSubtask.setDeptcode(serviceTaskdept.getDeptCode()); |
| | | serviceSubtask.setDeptname(serviceTaskdept.getDeptName()); |
| | | serviceSubtask.setLeaveldeptcode(serviceTaskdept.getDeptCode()); |
| | | serviceSubtask.setLeaveldeptname(serviceTaskdept.getDeptName()); |
| | | } else { |
| | | serviceSubtask.setLeavehospitaldistrictcode(serviceTaskdept.getDeptCode()); |
| | | serviceSubtask.setLeavehospitaldistrictname(serviceTaskdept.getDeptName()); |
| | |
| | | // 这里用任务配置的病区(其次科室)反查 sys_dept.campusid 落库,保证问卷统计能按院区取到。 |
| | | String campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getLeavehospitaldistrictcode(), serviceTask.getOrgid()); |
| | | if (StringUtils.isEmpty(campusIdByDept)) { |
| | | campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getDeptcode(), serviceTask.getOrgid()); |
| | | campusIdByDept = queryCampusIdByDeptCode(serviceSubtask.getLeaveldeptcode(), serviceTask.getOrgid()); |
| | | } |
| | | if (StringUtils.isNotEmpty(campusIdByDept)) { |
| | | serviceSubtask.setCampusid(campusIdByDept); |
| | |
| | | if (StringUtils.isEmpty(serviceSubtask.getLeavehospitaldistrictcode()) |
| | | && ("6".equals(serviceSubtask.getServiceType()) || "14".equals(serviceSubtask.getServiceType()))) { |
| | | log.warn("【扫码生成任务】满意度子任务没有病区,按病区筛选的报表将统计不到该答卷:taskid={}, deptcode={}, campusid={}", |
| | | serviceSubtask.getTaskid(), serviceSubtask.getDeptcode(), serviceSubtask.getCampusid()); |
| | | serviceSubtask.getTaskid(), serviceSubtask.getLeaveldeptcode(), serviceSubtask.getCampusid()); |
| | | } |
| | | return serviceSubtask; |
| | | } |