陈昶聿
7 天以前 839e23b23b2bfb13282e9e5f621d32a1c55186ea
fix: 调整随访及时率基准

非任务组按出院时间+发送天数+补偿天数+1天;任务组按 schedule_benchmark 解析基准时间+day_offset+发送天数+补偿天数+1天,完成时间不晚于基准计为及时。
已修改2个文件
61 ■■■■■ 文件已修改
ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskMapper.java
@@ -126,10 +126,14 @@
    /**
     * 随访及时率(按 groupKey 分组批量统计)
     * <p>
     * rate:出院时间(endtime)起 rateDay + 补偿天数 内完成随访的占比。
     * rate:完成时间(finishtime) 不晚于及时率基准的占比,分母为应随访数。
     * 非任务组(appltype != 5):endtime + send_day(缺省1) + Σ补偿天数 + 1 天;
     * 任务组(appltype = 5):按 schedule_benchmark 解析基准时间
     * (1-入院 2-出院 3-就诊 4-入组 0/其它-自定义时间) + day_offset
     * + send_day(缺省1) + Σ补偿天数 + 1 天。
     * 补偿天数取自 service_subtask_preachform.compensate_time 按子任务求和,
     * 用子任务快照而非 service_task.preachform_desc,保证历史数据不随任务改配置而变动。
     * rateDay 为空时 rate 返回 NULL。
     * rateDay 参数不再参与该口径。
     * <p>
     * finishRate:应随访时间(visit_time) &lt;= 实际完成时间(finishtime) 的占比,当前未被随访统计使用。
     *
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
@@ -940,16 +940,50 @@
        </if>
        SUM(CASE WHEN ss.finishtime IS NOT NULL AND DATE(ss.visit_time) &lt;= DATE(ss.finishtime) THEN 1 ELSE 0 END) /
        COUNT(*) AS finishRate,
        <if test="rateDay != null">
            SUM(CASE WHEN ss.finishtime IS NOT NULL
            AND DATEDIFF(ss.finishtime, ss.endtime) &lt;= #{rateDay} + COALESCE(cp.compensate_days, 0)
            THEN 1 ELSE 0 END) / COUNT(*) AS rate
        </if>
        <if test="rateDay == null">
            NULL AS rate
        </if>
        <!-- 及时率基准:
             1) 非任务组(appltype != 5):endtime + send_day(缺省1) + Σ补偿天数 + 1 天;
             2) 任务组(appltype = 5):按 schedule_benchmark 解析基准时间
                (1-入院时间 2-出院时间 3-就诊时间 4-入组时间 0/其它-自定义时间)
                + day_offset + send_day(缺省1) + Σ补偿天数 + 1 天;
             完成时间 finishtime <= 基准时间计为及时,分母仍为应随访数。
             补偿天数只取 service_subtask_preachform.compensate_time 的汇总值一次,
             避免与补偿明细相加造成重复补偿或一对多放大分母。 -->
        SUM(CASE
            WHEN ss.finishtime IS NOT NULL
             AND COALESCE(st.appltype, '') != '5'
             AND ss.endtime IS NOT NULL
             AND ss.finishtime &lt;= DATE_ADD(
                   DATE_ADD(ss.endtime, INTERVAL COALESCE(st.send_day, 1) DAY),
                   INTERVAL (COALESCE(cp.compensate_days, 0) + 1) DAY)
            THEN 1
            WHEN ss.finishtime IS NOT NULL
             AND st.appltype = '5'
             AND std.day_offset IS NOT NULL
             AND ss.finishtime &lt;= DATE_ADD(
                   DATE_ADD(
                     DATE_ADD(
                       CASE sts.schedule_benchmark
                         WHEN 1 THEN ss.starttime
                         WHEN 2 THEN ss.endtime
                         WHEN 3 THEN ss.admindate
                         WHEN 4 THEN ss.create_time
                         ELSE sts.schedule_benchmark_custom_time
                       END, INTERVAL std.day_offset DAY),
                     INTERVAL COALESCE(st.send_day, 1) DAY),
                   INTERVAL (COALESCE(cp.compensate_days, 0) + 1) DAY)
            THEN 1
            ELSE 0
        END) / COUNT(*) AS rate
        FROM service_subtask ss
        <if test="rateDay != null">
        <!-- 这里按 taskid / 历史 schedule 快照关联,不按 del_flag 过滤:
             任务或计划被编辑后旧 schedule/detail 会置为 del_flag=1,
             但历史 subtask 仍引用旧 ID,过滤会丢失历史及时率基准。 -->
        LEFT JOIN service_task st
               ON st.taskid = ss.taskid
        LEFT JOIN service_task_schedule sts
               ON sts.id = ss.schedule_id
        LEFT JOIN service_task_schedule_detail std
               ON std.id = ss.schedule_detail_id
            <!-- 补偿时间:先按子任务聚合成一行再关联,避免一对多放大 COUNT(*) 分母。
                 compensate_time 是 varchar 且可能存成空串,需先置空再转数字 -->
            LEFT JOIN (
@@ -959,7 +993,6 @@
            WHERE del_flag = 0
            GROUP BY subid
            ) cp ON cp.subid = ss.id
        </if>
        WHERE ss.del_flag = 0
        AND ss.visit_time IS NOT NULL
        AND ss.sendstate != 4