| | |
| | | |
| | | public List<ServiceSubtask> getServiceSubtasks(ServiceSubtaskEntity serviceSubtaskEntity) { |
| | | if (serviceSubtaskEntity.getSendstateView() != null) { |
| | | // 1:待随访(1 被领取、2 待发送、3 已发送、5 发送失败、7、超时);2:已完成( 6 已完成)、3:无需随访(4 不执行) |
| | | // 1:待随访(1 被领取、2 待发送、3 已发送、7 超时;发送失败(5) 单独统计);2:已完成( 6 已完成)、3:无需随访(4 不执行) |
| | | if (serviceSubtaskEntity.getSendstateView() == 1) |
| | | serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(1L, 2L, 3L, 5L, 7L))); |
| | | serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(1L, 2L, 3L, 7L))); |
| | | if (serviceSubtaskEntity.getSendstateView() == 2) |
| | | serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(6L))); |
| | | if (serviceSubtaskEntity.getSendstateView() == 3) |
| | |
| | | } |
| | | |
| | | /** |
| | | * 统一「随访病区」口径:一律以【出院记录】{@code pat_med_inhosp} 为准(2026-10-29 业务确认)。 |
| | | * |
| | | * <h3>为什么需要它</h3> |
| | | * 出院随访子任务的科室/病区本应来自出院记录,但「再次随访 / 手工新增」这两个入口是 |
| | | * <b>直接按前端传来的字段落库</b>的:前端不带这些字段时 |
| | | * {@code leaveldeptcode} / {@code leavehospitaldistrictcode} / {@code campusid} 就是空。 |
| | | * 而随访列表是按科室/病区过滤的({@code and leavehospitaldistrictcode = #{...}}), |
| | | * 空值不匹配任何值 → 这些任务"生成了但页面上查不到"(线上 2026-10 实测 314 条)。 |
| | | * |
| | | * <p>口径:<b>病区只认出院记录</b> —— 不按患者档案反推、也不用前端传的值。 |
| | | * 只对出院随访({@code service_type='2'})且能定位到出院记录({@code inhospid} 非空)的行生效; |
| | | * 其余情况原样放行,对满意度(6)/宣教/门诊等其它类型没有任何影响。 |
| | | * |
| | | * @param serviceSubtask 待落库的子任务(就地修改) |
| | | */ |
| | | private void alignDischargeWardFromInhosp(ServiceSubtask serviceSubtask) { |
| | | if (serviceSubtask == null || serviceSubtask.getInhospid() == null) { |
| | | return; |
| | | } |
| | | if (!"2".equals(serviceSubtask.getServiceType())) { |
| | | return; |
| | | } |
| | | PatMedInhosp inhosp; |
| | | try { |
| | | inhosp = inhospVisitFacade.selectPatMedInhospByInhospid(serviceSubtask.getInhospid()); |
| | | } catch (Exception e) { |
| | | log.warn("【随访任务】按 inhospid={} 取出院记录失败,病区沿用入参:{}", |
| | | serviceSubtask.getInhospid(), e.toString()); |
| | | return; |
| | | } |
| | | if (inhosp == null) { |
| | | log.warn("【随访任务】inhospid={} 查不到出院记录,病区沿用入参", serviceSubtask.getInhospid()); |
| | | return; |
| | | } |
| | | serviceSubtask.setLeaveldeptcode(inhosp.getLeaveldeptcode()); |
| | | serviceSubtask.setLeaveldeptname(inhosp.getLeaveldeptname()); |
| | | serviceSubtask.setLeavehospitaldistrictcode(inhosp.getLeavehospitaldistrictcode()); |
| | | serviceSubtask.setLeavehospitaldistrictname(inhosp.getLeavehospitaldistrictname()); |
| | | if (StringUtils.isNotEmpty(inhosp.getCampusid())) { |
| | | serviceSubtask.setCampusid(inhosp.getCampusid()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 新增单一任务(随访) |
| | | * |
| | | * @param serviceSubtask 单一任务(随访) |
| | |
| | | } |
| | | |
| | | serviceSubtask.setCreateTime(DateUtils.getNowDate()); |
| | | // 口径(2026-10-29 业务确认):出院随访的科室/病区一律以出院记录为准 |
| | | alignDischargeWardFromInhosp(serviceSubtask); |
| | | serviceSubtaskMapper.insertServiceSubtask(serviceSubtask); |
| | | //修改住院满意度状态(避免重复查询) |
| | | if (serviceSubtask.getServiceType() != null && "6".equals(serviceSubtask.getServiceType())) { |
| | |
| | | serviceSubtask2.setVisitType(serviceSubtask.getVisitType()); |
| | | serviceSubtask2.setVisitDeptCode(serviceSubtask.getVisitDeptCode()); |
| | | serviceSubtask2.setVisitDeptName(serviceSubtask.getVisitDeptName()); |
| | | // 口径(2026-10-29 业务确认):随访病区一律取出院记录的 |
| | | // ① 再次随访是从请求 DTO 复制出来的,出院记录ID 不在请求里 → 先用原任务的上; |
| | | // ② 再按出院记录把科室/病区/院区统一过来(取不到就保持不变)。 |
| | | if (serviceSubtask2.getInhospid() == null) { |
| | | serviceSubtask2.setInhospid(serviceSubtask1.getInhospid()); |
| | | } |
| | | alignDischargeWardFromInhosp(serviceSubtask2); |
| | | int i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask2); |
| | | if (i == 1) { |
| | | //新增成功后,需要将之前的任务设置为不要再随访(防止重复点,然后重复生成) |
| | |
| | | serviceSubtaskCountReq.setGroupKey(groupKey); |
| | | // 分组列与过滤列保持一致:离院科室 leaveldeptcode、在院科室 deptcode |
| | | serviceSubtaskCountReq.setGroupColumn(groupKey); |
| | | /* |
| | | * 满意度「病区统计」(离院维度):出院病区为空则回退到在院病区。 |
| | | * 满意度子任务(service_type 6/14/15/16)的 leavehospitaldistrictcode 约三成为空, |
| | | * 之前为了“查得到数据”把病区条件写成 `xxx IS NULL OR xxx IN (...)`, |
| | | * 于是选了 A 病区也会把空病区的全量数据带进来,再统一归到 'Unknown' 组, |
| | | * 该组的病区名又是 MAX(hospitaldistrictname) 随便挑的 —— 表现就是 |
| | | * “选了血液内科病区,却查出一行显示骨科中心三病区”。 |
| | | * 用“有效病区”列过滤 + 分组后:筛选真正生效,空病区的记录也回到它真实的在院病区。 |
| | | */ |
| | | if ("leavehospitaldistrictcode".equals(groupKey)) { |
| | | String districtColumn = "IFNULL(leavehospitaldistrictcode, hospitaldistrictcode)"; |
| | | serviceSubtaskCountReq.setGroupColumn(districtColumn); |
| | | serviceSubtaskCountReq.setDistrictColumn(districtColumn); |
| | | } |
| | | //分组键集合:这一步保持不变(分页参数照旧作用在该查询上),保证“参与统计的分组”与改造前一致 |
| | | List<String> groupKeyList = serviceSubtaskMapper.getSfStatisticsGroupKey(serviceSubtaskCountReq); |
| | | /* |
| | |
| | | serviceSubtaskStatistics.add(statistic); |
| | | } |
| | | |
| | | /* |
| | | * 病区统计:这一行的病区就是分组键本身,展示名取该组自己的病区名。 |
| | | * 聚合 SQL 里原来的 MAX(hospitaldistrictname) 在“一个组混了多个病区”时会挑出 |
| | | * 一个毫不相干的病区名(选血液内科病区显示成骨科中心三病区就是这么来的)。 |
| | | * 这里把分组键回填到在院/离院两套病区字段,保证前端不论读哪一列都是同一个病区, |
| | | * 也让“查看详情”带上来的病区编码能查回同一批数据。 |
| | | */ |
| | | if (StringUtils.isNotEmpty(serviceSubtaskCountReq.getDistrictColumn())) { |
| | | for (ServiceSubtaskStatistic statistic : serviceSubtaskStatistics) { |
| | | String districtCode = statistic.getGroupCode() == null ? "Unknown" : statistic.getGroupCode(); |
| | | String districtName = StringUtils.isNotEmpty(statistic.getGroupName()) ? statistic.getGroupName() : districtCode; |
| | | statistic.setLeavehospitaldistrictcode(districtCode); |
| | | statistic.setLeavehospitaldistrictname(districtName); |
| | | statistic.setHospitaldistrictcode(districtCode); |
| | | statistic.setHospitaldistrictname(districtName); |
| | | } |
| | | } |
| | | |
| | | //获取及时率统计合集(一次批量查询,不按分组循环查) |
| | | Map<String, Map<String, Object>> jsRates = getSsRateForSfStatistics(serviceSubtaskCountReq, statisticsGroupKeys); |
| | | for (ServiceSubtaskStatistic statistic : serviceSubtaskStatistics) { |
| | |
| | | sum = new BigDecimal(serviceSubtaskStatistic.getJoyAllCount()); |
| | | } |
| | | if (sum.intValue() != 0) { |
| | | finishedPercentage = finishedSum.divide(sum, 2, RoundingMode.HALF_UP).doubleValue(); |
| | | // 原来只保留 2 位小数(23634/26106 会被截成 0.91),前端再 ×100 |
| | | // 就显示成 91.00%,与实际的 90.53% 差了半个百分点。这里保留 4 位。 |
| | | finishedPercentage = finishedSum.divide(sum, 4, RoundingMode.HALF_UP).doubleValue(); |
| | | } |
| | | serviceSubtaskStatistic.setJoyAllCount(sum.intValue()); |
| | | serviceSubtaskStatistic.setJoyCount(finishedSum.intValue()); |