| | |
| | | import com.smartor.domain.DTO.MzMydScoreRankDTO; |
| | | import com.smartor.domain.DTO.QuestionCountKsOrBqDTO; |
| | | import com.smartor.domain.DTO.ServiceSubtaskDetailDTO; |
| | | import com.smartor.domain.DTO.ServiceSubtaskOptionStatDTO; |
| | | import com.smartor.domain.*; |
| | | import com.smartor.domain.VO.*; |
| | | import com.smartor.domain.entity.ServiceSubtaskEntity; |
| | |
| | | result.putIfAbsent("wxsf", 0); |
| | | result.putIfAbsent("xsf", 0); |
| | | result.putIfAbsent("dsf", 0); |
| | | result.putIfAbsent("ywc", 0); |
| | | result.putIfAbsent("yc", 0); |
| | | result.putIfAbsent("jg", 0); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 统计任务各种状态的数量(已优化) |
| | | * 优化说明: |
| | | * 1. 使用数据库层聚合计算,替代应用层遍历 |
| | | * 2. 性能提升 10-100 倍(取决于数据量) |
| | | * 3. 降低内存占用和网络传输 |
| | | * |
| | | * @param serviceSubtaskEntity 查询条件 |
| | | * @return 各状态统计结果 |
| | | */ |
| | | @Override |
| | | public Map<String, Object> countByCondition(ServiceSubtaskEntity serviceSubtaskEntity) { |
| | | // 直接调用数据库统计方法,在数据库层完成聚合计算 |
| | | Map<String, Object> result = serviceSubtaskMapper.countByCondition(serviceSubtaskEntity); |
| | | // 处理空异常 |
| | | if (MapUtils.isEmpty(result)) { |
| | | result = new HashMap<>(); |
| | | // 确保所有 key 都有值,避免空指针异常 |
| | | // MyBatis 的 SUM 在没有匹配行时会返回 null |
| | | result.putIfAbsent("wzx", 0); |
| | | result.putIfAbsent("ysf", 0); |
| | | result.putIfAbsent("fssb", 0); |
| | | result.putIfAbsent("yfs", 0); |
| | | result.putIfAbsent("blq", 0); |
| | | result.putIfAbsent("total", 0); |
| | | result.putIfAbsent("wxsf", 0); |
| | | result.putIfAbsent("xsf", 0); |
| | | result.putIfAbsent("dsf", 0); |
| | | result.putIfAbsent("dfs", 0); |
| | | result.putIfAbsent("yfs", 0); |
| | | result.putIfAbsent("ywc", 0); |
| | | result.putIfAbsent("yc", 0); |
| | | result.putIfAbsent("jg", 0); |
| | |
| | | * @return |
| | | */ |
| | | @Override |
| | | @Cacheable(value = "sfStatistics", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()") |
| | | // @Cacheable(value = "sfStatistics", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()") |
| | | public List<ServiceSubtaskStatistic> getSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq) { |
| | | log.info("getSfStatistics的入参为:{}", serviceSubtaskCountReq); |
| | | String drcode = "drcode"; |
| | |
| | | return resultMap; |
| | | } |
| | | @Override |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startFinishTime, Date endFinishTime, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) { |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startFinishTime, Date endFinishTime, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType, List<Long> subtaskIds) { |
| | | //先清理一下重复数据 |
| | | List<Long> repeatIds = serviceSubtaskDetailMapper.selectRepeatDetailIds(); |
| | | if (!CollectionUtils.isEmpty(repeatIds)) { |
| | | serviceSubtaskDetailMapper.deleteRepeatDetailByIds(repeatIds); |
| | | } |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOption(taskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType); |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOption(taskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType, subtaskIds); |
| | | |
| | | // 处理 targetvalue:按 & 分割成多条记录 |
| | | List<ServiceSubtaskDetailRatioExport> result = new ArrayList<>(); |
| | |
| | | // 如果有多条目标值,拆分成多行 |
| | | for (String value : values) { |
| | | //先去 result 中查一下,有没有这个 questiontext 和对应的 targetvalue |
| | | ServiceSubtaskDetailRatioExport existingExport = result.stream().filter(e -> e.getQuestiontext().equals(export.getQuestiontext()) && value.trim().equals(e.getTargetvalue())).findFirst().orElse(null); |
| | | //注意必须带上 taskid 一起匹配:否则会把别的任务的数据填到本任务的行上, |
| | | //导致导出的「数量/比例」和该行的「任务名称/任务编号」对不上(同一任务同一题出现两个不同分母) |
| | | ServiceSubtaskDetailRatioExport existingExport = result.stream().filter(e -> Objects.equals(e.getTaskid(), export.getTaskid()) && e.getQuestiontext().equals(export.getQuestiontext()) && value.trim().equals(e.getTargetvalue())).findFirst().orElse(null); |
| | | if (existingExport != null && existingExport.getRatio().equals("0") && existingExport.getCount().equals("0")) { |
| | | //如果存在,则将 result 里的这个问题所对应的 Targetvalue=value 这条数据更新成当前这条数据 |
| | | if (value.equals(export.getOptionresult())) { |
| | |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<ServiceSubtaskDetailRatioExport> statMydQuestionOptionForExport(List<Long> subtaskIds, String questiontext) { |
| | | List<ServiceSubtaskDetailRatioExport> result = new ArrayList<>(); |
| | | if (CollectionUtils.isEmpty(subtaskIds)) { |
| | | return result; |
| | | } |
| | | List<ServiceSubtaskOptionStatDTO> statList = serviceSubtaskMapper.statMydQuestionOptionForExport(subtaskIds, questiontext); |
| | | if (CollectionUtils.isEmpty(statList)) { |
| | | return result; |
| | | } |
| | | return buildMydOptionRows(statList); |
| | | } |
| | | |
| | | /** |
| | | * 把「任务+题目+选项」的作答统计拼成导出的「问题详情占比」行 |
| | | * <ul> |
| | | * <li>选项清单:题目配置过的选项在 targetvalue(用 & 连接)里,全部列出,没人选的显示 0</li> |
| | | * <li>数量:患者选中的选项在 asrtext 里(多选题是「A&B」),每个选中项各记一次人数,一个患者只算一条明细</li> |
| | | * <li>比例:数量 / 该题作答患者数,所以单选题各选项数量之和 = 该题作答患者数</li> |
| | | * <li>分数:该选项明细的 score 之和;多选行按选中项份数均分,保证各选项分数之和 = 明细分数之和</li> |
| | | * </ul> |
| | | */ |
| | | private static List<ServiceSubtaskDetailRatioExport> buildMydOptionRows(List<ServiceSubtaskOptionStatDTO> statList) { |
| | | List<ServiceSubtaskDetailRatioExport> result = new ArrayList<>(); |
| | | |
| | | // 按「任务 + 题目」分组,保持 SQL 的顺序(先题目后任务) |
| | | Map<String, List<ServiceSubtaskOptionStatDTO>> grouped = new LinkedHashMap<>(); |
| | | for (ServiceSubtaskOptionStatDTO stat : statList) { |
| | | String key = stat.getTaskid() + "\u0001" + stat.getQuestiontext(); |
| | | grouped.computeIfAbsent(key, k -> new ArrayList<>()).add(stat); |
| | | } |
| | | |
| | | for (List<ServiceSubtaskOptionStatDTO> group : grouped.values()) { |
| | | ServiceSubtaskOptionStatDTO first = group.get(0); |
| | | // 选项 -> 人数(long[1] 便于累加),顺序即出现顺序 |
| | | Map<String, long[]> countMap = new LinkedHashMap<>(); |
| | | Map<String, BigDecimal> scoreMap = new LinkedHashMap<>(); |
| | | |
| | | for (ServiceSubtaskOptionStatDTO stat : group) { |
| | | // targetvalue = 本题所有选项的清单,没人选的也要列出来 |
| | | List<String> options = splitOptions(stat.getTargetvalue()); |
| | | // asrtext = 患者实际选中的选项,多选题会是「选中项1&选中项2」 |
| | | List<String> chosenOptions = splitOptions(stat.getOptionresult()); |
| | | for (String option : options) { |
| | | countMap.computeIfAbsent(option, k -> new long[1]); |
| | | scoreMap.computeIfAbsent(option, k -> BigDecimal.ZERO); |
| | | } |
| | | |
| | | long patientCount = stat.getPatientCount() == null ? 0L : stat.getPatientCount(); |
| | | BigDecimal scoreSum = stat.getScoreSum() == null ? BigDecimal.ZERO : stat.getScoreSum(); |
| | | |
| | | if (!chosenOptions.isEmpty()) { |
| | | BigDecimal[] scoreParts = splitScore(scoreSum, chosenOptions.size()); |
| | | for (int i = 0; i < chosenOptions.size(); i++) { |
| | | String chosen = chosenOptions.get(i); |
| | | // 选中的选项可能不在配置清单里(历史数据),补一行 |
| | | countMap.computeIfAbsent(chosen, k -> new long[1]); |
| | | scoreMap.computeIfAbsent(chosen, k -> BigDecimal.ZERO); |
| | | countMap.get(chosen)[0] += patientCount; |
| | | scoreMap.put(chosen, scoreMap.get(chosen).add(scoreParts[i])); |
| | | } |
| | | } else if (options.size() == 1) { |
| | | // 没有 asrtext(未答/无应答)时,只有唯一选项才能确定归属 |
| | | countMap.get(options.get(0))[0] += patientCount; |
| | | scoreMap.put(options.get(0), scoreMap.get(options.get(0)).add(scoreSum)); |
| | | } |
| | | } |
| | | |
| | | long total = 0L; |
| | | for (long[] count : countMap.values()) total += count[0]; |
| | | |
| | | for (Map.Entry<String, long[]> entry : countMap.entrySet()) { |
| | | long count = entry.getValue()[0]; |
| | | ServiceSubtaskDetailRatioExport row = new ServiceSubtaskDetailRatioExport(); |
| | | row.setQuestiontext(first.getQuestiontext()); |
| | | row.setOptionresult(entry.getKey()); |
| | | row.setTargetvalue(entry.getKey()); |
| | | row.setCount(String.valueOf(count)); |
| | | row.setRatio(formatRatio(count, total)); |
| | | row.setScore(formatScore(scoreMap.get(entry.getKey()))); |
| | | row.setTaskname(first.getTaskName()); |
| | | row.setTaskid(first.getTaskid()); |
| | | row.setValueType(first.getValueType()); |
| | | result.add(row); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 把一条明细的分数按选中项份数均分,余数补给第一个,保证各份之和 = 原分数 |
| | | */ |
| | | private static BigDecimal[] splitScore(BigDecimal total, int parts) { |
| | | BigDecimal[] result = new BigDecimal[parts]; |
| | | if (parts <= 0) { |
| | | return result; |
| | | } |
| | | BigDecimal each = total.divide(BigDecimal.valueOf(parts), 2, RoundingMode.HALF_UP); |
| | | for (int i = 0; i < parts; i++) { |
| | | result[i] = each; |
| | | } |
| | | result[0] = result[0].add(total.subtract(each.multiply(BigDecimal.valueOf(parts)))); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 拆分题目配置的选项(多个选项用 & 连接),顺带去掉全角/半角空白 |
| | | */ |
| | | private static List<String> splitOptions(String targetvalue) { |
| | | List<String> options = new ArrayList<>(); |
| | | if (StringUtils.isEmpty(targetvalue)) { |
| | | return options; |
| | | } |
| | | for (String part : targetvalue.split("&")) { |
| | | String option = trimAll(part); |
| | | if (StringUtils.isNotEmpty(option) && !options.contains(option)) { |
| | | options.add(option); |
| | | } |
| | | } |
| | | return options; |
| | | } |
| | | |
| | | /** |
| | | * 比例:数量 / 该题作答患者数,保留两位小数 |
| | | */ |
| | | private static String formatRatio(long count, long total) { |
| | | if (total <= 0) { |
| | | return "0.00%"; |
| | | } |
| | | return BigDecimal.valueOf(count * 100.0 / total).setScale(2, RoundingMode.HALF_UP).toPlainString() + "%"; |
| | | } |
| | | |
| | | /** |
| | | * 分数之和:去掉多余的小数位(0.00 -> 0) |
| | | */ |
| | | private static String formatScore(BigDecimal score) { |
| | | if (score == null) { |
| | | return "0"; |
| | | } |
| | | BigDecimal value = score.stripTrailingZeros(); |
| | | if (value.scale() < 0) { |
| | | value = value.setScale(0); |
| | | } |
| | | return value.toPlainString(); |
| | | } |
| | | |
| | | /* |
| | |
| | | String voiceText = phoneCallReqYQVO.getAsrtext(); |
| | | String questionText = StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent(); |
| | | Integer matched = -1; |
| | | log.info("AI匹配:url = {},questionText = {},voiceText = {},options = {},uuid ={}", |
| | | url,questionText,voiceText,options,uuid); |
| | | matched = matchOptionIndex(url, questionText, voiceText, options, uuid); |
| | | //说明匹配正确了 |
| | | if (matched != null && matched >= 0) { |
| | |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy()); |
| | | //记录状态 |
| | | setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9"); |
| | | return phoneCallBackYQVO; |
| | | back = phoneCallBackYQVO; |
| | | return back; |
| | | } |
| | | |
| | | flag = 1; |
| | |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop"); |
| | | // //获取下一题 |
| | | log.error("获取下一题的信息:{}", ivrTaskTemplateScriptVO); |
| | | if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1") || ivrTaskTemplateScriptVO.getBranchFlag().equals("0") && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) { |
| | | //branchFlag为null时按分支0处理,避免NPE |
| | | if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) { |
| | | Long nextQuestion = null; |
| | | if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1")) { |
| | | if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag())) { |
| | | nextQuestion = chosenOption.getNextQuestion(); |
| | | //更新分数 |
| | | double score = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES); |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy()); |
| | | //将结果写进detail表 |
| | | ServiceSubTaskDetailReq ssdReq = new ServiceSubTaskDetailReq(); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetailList2 = new ArrayList<>(); |
| | | serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate)); |
| | | serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList2); |
| | | ssdReq.setGuid(phoneCallReqYQVO.getGuid()); |
| | | ssdReq.setOrgid(phoneCallReqYQVO.getOrgid()); |
| | | saveQuestionAnswerPhone(ssdReq); |
| | | return phoneCallBackYQVO; |
| | | //明细在本题匹配成功时已落库(见上方 saveQuestionAnswerPhone),这里不再重复保存 |
| | | back = phoneCallBackYQVO; |
| | | return back; |
| | | } |
| | | |
| | | for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) { |
| | |
| | | redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid()); |
| | | } |
| | | } |
| | | //下一题脚本没找到时,兜底重问当前题,避免调用方误判为未处理而退回正则识别 |
| | | if (StringUtils.isEmpty(phoneCallBackYQVO.getValue())) { |
| | | log.error("下一题脚本未找到,重问当前题,nextQuestion:{}", nextQuestion); |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue()); |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, questionText)); |
| | | } |
| | | back = phoneCallBackYQVO; |
| | | return back; |
| | | } else if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) { |
| | | ServiceTask serviceTask1 = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | phoneCallBackYQVO.setType("text"); |
| | |
| | | //在redis中保存一下结束语,在调用挂电话的方法时删除 |
| | | ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES); |
| | | // return phoneCallBackYQVO; |
| | | //结束语已拼进返回值,挂机由平台按返回值执行 |
| | | back = phoneCallBackYQVO; |
| | | return back; |
| | | |
| | | } |
| | | } else { |
| | | log.info("没有匹配上----------------------------"); |
| | | //flag=0,说明没 匹配上,也要把患者说的话记录下来 |
| | | if (matched == ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().size() - 1 && flag == 0) { |
| | | ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq(); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>(); |
| | | ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate); |
| | | //修改一下语音路径(改成前端可以访问的,存到数据库中) |
| | | if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) { |
| | | String questionvoice = serviceSubtaskDetail.getQuestionvoice(); |
| | | String[] split = questionvoice.split("\\\\"); |
| | | if (split.length > 0) { |
| | | String lastPart = split[split.length - 1]; |
| | | serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart); |
| | | //AI没有匹配上:由AI分支自己按"没问清就重问"的次数处理,不再退回正则识别 |
| | | log.info("ai没有匹配上----------------------------"); |
| | | //没匹配上也要把患者说的话记录下来(matchedtext置空,与正则路径口径一致) |
| | | ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq(); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>(); |
| | | ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate); |
| | | //修改一下语音路径(改成前端可以访问的,存到数据库中) |
| | | if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) { |
| | | String questionvoice = serviceSubtaskDetail.getQuestionvoice(); |
| | | String[] split = questionvoice.split("\\\\"); |
| | | if (split.length > 0) { |
| | | String lastPart = split[split.length - 1]; |
| | | serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart); |
| | | } |
| | | } |
| | | serviceSubtaskDetailList.add(serviceSubtaskDetail); |
| | | //如果没有 匹配上,这个必须为null |
| | | serviceSubtaskDetailList.get(0).setMatchedtext(""); |
| | | serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList); |
| | | serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid()); |
| | | serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid()); |
| | | saveQuestionAnswerPhone(serviceSubTaskDetailReq); |
| | | |
| | | String mateKey = phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid(); |
| | | Integer count = null; |
| | | Object countObj = redisCache.getCacheObject(mateKey); |
| | | if (ObjectUtils.isNotEmpty(countObj)) count = (Integer) countObj; |
| | | if (count != null && count >= ivrTaskTemplate.getMateNum()) { |
| | | //没匹配次数已经用满,不能再重问了 |
| | | boolean noNextQuestion = ("0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "1".equals(ivrTaskTemplateScriptVO.getBranchFlag())) |
| | | && (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0); |
| | | if (noNextQuestion) { |
| | | //已经是最后一题,直接挂机 |
| | | ServiceTask serviceTask1 = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue()); |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy()); |
| | | //更新一下分数 |
| | | Double score = null; |
| | | Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | | if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj; |
| | | serviceSubtask.setScore(String.valueOf(score)); |
| | | serviceSubtask.setFinishtime(new Date()); |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtask.setRemark("电话拨打已完成"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | //记录状态 |
| | | setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9"); |
| | | //在redis中保存一下结束语,在调用挂电话的方法时删除 |
| | | ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES); |
| | | //去redis中,把该子任务ID删除 |
| | | Long id = serviceSubtask.getId(); |
| | | Map<String, String> map = delRedisValue(null, id.toString()); |
| | | if (ObjectUtils.isNotEmpty(map)) { |
| | | redisCache.setCacheObject(map.get("cacheName"), map.get("val")); |
| | | redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone()); |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | | } |
| | | } else { |
| | | //还有下一题,按nextScriptno继续提问 |
| | | for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) { |
| | | if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) { |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue()); |
| | | String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent(); |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent)); |
| | | //将该患者的Redis中的题目ID,进行修改 |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES); |
| | | //更新一下分数 |
| | | Double score = null; |
| | | Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | | if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj; |
| | | score = BigDecimal.valueOf(score).add(new BigDecimal(script.getScore())).doubleValue(); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES); |
| | | //换题成功,没匹配次数清零 |
| | | redisCache.deleteObject(mateKey); |
| | | } |
| | | } |
| | | } |
| | | serviceSubtaskDetailList.add(serviceSubtaskDetail); |
| | | //如果没有 匹配上,这个必须为null |
| | | serviceSubtaskDetailList.get(0).setMatchedtext(""); |
| | | serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList); |
| | | serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid()); |
| | | serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid()); |
| | | saveQuestionAnswerPhone(serviceSubTaskDetailReq); |
| | | } else { |
| | | //还没问满次数,用noMatchText引导患者重答 |
| | | redisCache.setCacheObject(mateKey, count == null ? 1 : count + 1, 120, TimeUnit.MINUTES); |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue()); |
| | | phoneCallBackYQVO.setValue(ivrTaskTemplateScriptVO.getNoMatchText() + getObject(serviceSubtask, StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent())); |
| | | } |
| | | back = phoneCallBackYQVO; |
| | | return back; |
| | | } |
| | | return back; |
| | | } |
| | |
| | | if (hasFollowUp) { |
| | | //获取serviceSubtaskList中的所有taskid |
| | | List<Long> taskIds = serviceSubtaskRes.stream().map(ServiceSubtaskRes::getTaskid).filter(ObjectUtils::isNotEmpty).distinct().collect(Collectors.toList()); |
| | | serviceSubtaskDetailRatioExports = statQuestionOption(taskIds, sltdMydTotalVO.getStartFinishTime(), sltdMydTotalVO.getEndFinishTime(), sltdMydTotalVO.getStartOutHospTime(), sltdMydTotalVO.getEndOutHospTime(), sltdMydTotalVO.getQuestionContent(), sltdMydTotalVO.getStartScore(), sltdMydTotalVO.getEndScore(), sltdMydTotalVO.getValueType()); |
| | | //同时带上本次导出的子任务 id:让「问题详情占比」只统计这批患者,与「患者随访信息表单」口径一致 |
| | | List<Long> subtaskIds = serviceSubtaskRes.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).distinct().collect(Collectors.toList()); |
| | | serviceSubtaskDetailRatioExports = statQuestionOption(taskIds, sltdMydTotalVO.getStartFinishTime(), sltdMydTotalVO.getEndFinishTime(), sltdMydTotalVO.getStartOutHospTime(), sltdMydTotalVO.getEndOutHospTime(), sltdMydTotalVO.getQuestionContent(), sltdMydTotalVO.getStartScore(), sltdMydTotalVO.getEndScore(), sltdMydTotalVO.getValueType(), subtaskIds); |
| | | } else if (hasSatisfaction) { |
| | | //满意度统计 (通过 subtask 的 id 去统计) |
| | | List<Long> subtaskIds = serviceSubtaskRes.stream().map(ServiceSubtaskRes::getId).collect(Collectors.toList()); |