package com.ruoyi.satisfaction.mapper;
|
|
import com.ruoyi.satisfaction.domain.ServiceSubtaskDetailRatioExport;
|
import com.ruoyi.satisfaction.domain.dto.MydTrendReqDTO;
|
import com.ruoyi.satisfaction.domain.dto.MzMydScoreRankDTO;
|
import com.ruoyi.satisfaction.domain.dto.QuestionCountKsOrBqDTO;
|
import com.ruoyi.satisfaction.domain.dto.ServiceSubtaskOptionStatDTO;
|
import com.ruoyi.satisfaction.domain.entity.SatisfactionStatQuery;
|
import com.ruoyi.satisfaction.domain.row.SatisfactionSubtaskQuery;
|
import com.ruoyi.satisfaction.domain.row.SatisfactionSubtaskRef;
|
import com.ruoyi.satisfaction.domain.row.SatisfactionTaskRow;
|
import com.ruoyi.satisfaction.domain.vo.MzMydScoreRankVO;
|
import com.ruoyi.satisfaction.domain.vo.PatSatisfactionReqVO;
|
import com.ruoyi.satisfaction.domain.vo.QuestionCountKsOrBqVO;
|
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Param;
|
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 满意度统计 Mapper 接口。
|
* <p>
|
* 迁移说明:方法原本散落在 {@code com.ruoyi.task.mapper.ServiceSubtaskMapper} 与
|
* {@code com.ruoyi.task.mapper.ServiceSubtaskDetailMapper} 中,满意度模块化后集中到此处。
|
* <p>
|
* 本模块自带 SQL,<b>直接查询</b> {@code service_subtask} / {@code service_subtask_detail},
|
* 以及模板分类表;不依赖任何其它模块的 Mapper。
|
* <p>
|
* 对应 XML:{@code ruoyi-satisfaction/src/main/resources/mapper/satisfaction/SatisfactionMapper.xml}
|
* <p>
|
* 已删除的死代码(搬迁时确认零调用点):
|
* <ul>
|
* <li>{@code selectSatisfactionSubtaskList} —— 被 {@code selectSatisfactionSubtaskTypes} 替代;</li>
|
* <li>{@code querySendCount} —— 被 {@code selectSatisfactionSendCount} 替代。</li>
|
* </ul>
|
*/
|
@Mapper
|
public interface SatisfactionMapper {
|
|
// ================================================================ 发送量统计
|
|
/**
|
* 满意度柱状图:一次性统计本次请求全部模板的发送量(按 libtemplateid 分组)。
|
*
|
* @param query 聚合查询条件
|
* @return 每行含 libtemplateid、cnt
|
*/
|
List<Map<String, Object>> selectSatisfactionSendCount(SatisfactionStatQuery query);
|
|
/**
|
* 满意度统计:只查本次条件下实际存在哪些 type(1 语音 / 2 问卷)。
|
*
|
* @param patSatisfactionReqVO 查询条件
|
* @return 去重后的 type 列表(可能为 null)
|
*/
|
List<String> selectSatisfactionSubtaskTypes(PatSatisfactionReqVO patSatisfactionReqVO);
|
|
// ================================================================ 填报量统计
|
|
/**
|
* 满意度柱状图:一次性统计本次请求全部模板的填报量(按 模板+问题+score 分组)。
|
*
|
* @param query 聚合查询条件
|
* @return 每行含 libtemplateid、questiontext、score、cnt
|
*/
|
List<Map<String, Object>> selectSatisfactionFillStat(SatisfactionStatQuery query);
|
|
/**
|
* 满意度统计:一次性统计本次请求全部问题的填报量(按 模板+问题+matchedtext+score 分组)。
|
*
|
* @param query 聚合查询条件
|
* @return 每行含 libtemplateid、questiontext、matchedtext、score、cnt、targetvalue
|
*/
|
List<Map<String, Object>> selectSatisfactionFillStatByMatchedtext(SatisfactionStatQuery query);
|
|
/**
|
* 满意度柱状图:一次性统计本次请求全部模板的「回收人数」。
|
* <p>
|
* 回收人数必须是人数口径(count distinct sub_id),不能按题目汇总答案行数(题量口径)。
|
*
|
* @param query 聚合查询条件
|
* @return 每行含 libtemplateid、cnt
|
*/
|
List<Map<String, Object>> selectSatisfactionFillPersonCount(SatisfactionStatQuery query);
|
|
/**
|
* 【按 模板 + 问题】统计答题人数({@code count(distinct ssd.sub_id)})。
|
* <p>
|
* <b>为什么单独加这一条</b>:{@code /statistics} 的「答题人数 / 未答题人数」必须与
|
* 「发送人数」({@link #selectSatisfactionSendCount},也是人数)同口径。
|
* 原实现误用 {@link #selectSatisfactionFillStatByMatchedtext} 的 {@code count(*)}(明细<b>行数</b>),
|
* 而一条 {@code (sub_id, questiontext)} 可能有多行明细(多选项 / 重复明细),
|
* 导致「未答题人数 = 发送人数 − 明细行数」出现负数(实测 -120)。
|
* <p>
|
* ⚠️ 平均分 / 最高分 / 最低分 / 各选项占比仍使用明细行数(那些口径本来就按行计),未改动。
|
* <p>
|
* 除聚合键与 {@code distinct} 外,from/where 与 {@link #selectSatisfactionFillStatByMatchedtext}
|
* 完全一致,保证两者统计的是同一批数据。
|
*
|
* @param query 聚合查询条件
|
* @return 每行含 libtemplateid、questiontext、cnt(人数)
|
*/
|
List<Map<String, Object>> selectSatisfactionFillPersonCountByQuestion(SatisfactionStatQuery query);
|
|
// ================================================================ 省立同德:趋势与维度
|
|
/**
|
* 省立同德患者满意度趋势。
|
*
|
* @param startFinishTime 开始时间
|
* @param endFinishTime 结束时间
|
* @param type 粒度:week / month / year / day
|
* @return 趋势数据
|
*/
|
List<MydTrendReqDTO> mydTrend(@Param("startFinishTime") Date startFinishTime,
|
@Param("endFinishTime") Date endFinishTime,
|
@Param("type") String type);
|
|
/**
|
* 省立同德患者满意度——按科室维度统计。
|
*/
|
List<MydTrendReqDTO> sltdMydTotalByDimension(@Param("startFinishTime") Date startFinishTime,
|
@Param("endFinishTime") Date endFinishTime,
|
@Param("type") String type);
|
|
/**
|
* 省立同德患者满意度——按院区维度统计。
|
*/
|
List<MydTrendReqDTO> sltdMydTotalByYQ(@Param("startFinishTime") Date startFinishTime,
|
@Param("endFinishTime") Date endFinishTime,
|
@Param("type") String type);
|
|
// ================================================================ 选项占比
|
|
/**
|
* 统计满意度选项的百分比。
|
*
|
* @param taskIds 任务 ID 列表
|
* @param subtaskIds 子任务 ID 列表(非空时只统计这些子任务;为空则统计这些任务下的全部子任务)
|
* @param startOutHospTime 出院开始时间
|
* @param endOutHospTime 出院结束时间
|
* @param startFinishTime 完成开始时间
|
* @param endFinishTime 完成结束时间
|
* @param scoreStart 分值下限
|
* @param scoreEnd 分值上限
|
* @param questiontext 题目内容(模糊匹配)
|
* @param valueType 题型(2=多选)
|
*/
|
List<ServiceSubtaskDetailRatioExport> statQuestionOption(
|
@Param("taskIds") List<Long> taskIds,
|
@Param("startOutHospTime") Date startOutHospTime,
|
@Param("endOutHospTime") Date endOutHospTime,
|
@Param("startFinishTime") Date startFinishTime,
|
@Param("endFinishTime") Date endFinishTime,
|
@Param("scoreStart") Double scoreStart,
|
@Param("scoreEnd") Double scoreEnd,
|
@Param("questiontext") String questiontext,
|
@Param("valueType") String valueType,
|
@Param("subtaskIds") List<Long> subtaskIds);
|
|
/**
|
* 满意度导出:选项占比。
|
* <p>
|
* 项数 = 选了该选项的患者数(同一人同一题只取最新一条明细);分数 = 该选项所有明细 score 之和。
|
*
|
* @param subtaskIds 本次导出的子任务 ID
|
* @param questiontext 题目内容(可选,模糊匹配)
|
*/
|
List<ServiceSubtaskOptionStatDTO> statMydQuestionOptionForExport(
|
@Param("subtaskIds") List<Long> subtaskIds,
|
@Param("questiontext") String questiontext);
|
|
/**
|
* 根据子任务 ID 统计满意度选项的百分比(用于满意度统计 serviceType=6/14)。
|
*/
|
List<ServiceSubtaskDetailRatioExport> statQuestionOptionBySubtaskIds(
|
@Param("subtaskIds") List<Long> subtaskIds,
|
@Param("startOutHospTime") Date startOutHospTime,
|
@Param("endOutHospTime") Date endOutHospTime,
|
@Param("startFinishTime") Date startFinishTime,
|
@Param("endFinishTime") Date endFinishTime,
|
@Param("scoreStart") Double scoreStart,
|
@Param("scoreEnd") Double scoreEnd,
|
@Param("questiontext") String questiontext,
|
@Param("valueType") String valueType);
|
|
/**
|
* 按科室/病区对满意度题目做归类统计。
|
*/
|
List<QuestionCountKsOrBqDTO> statQuestionOptionByKsOrBq(QuestionCountKsOrBqVO questionCountKsOrBqVO);
|
|
// ================================================================ 综合得分排名
|
|
/**
|
* 门诊满意度综合得分排名(按科室或病区)。
|
* <p>
|
* 综合满意度 = Σ(评分明细权重) / 评分明细条数 × 100%;权重只取 1、0.8、0.6、0.4、0.2 五档。
|
*
|
* @param mzMydScoreRankVO 查询条件(dimensionType、serviceType、时间区间、科室/病区编号、orgid/campusid)
|
* @return 每行科室/病区的综合得分,已按综合得分降序
|
*/
|
List<MzMydScoreRankDTO> selectMzMydScoreRank(MzMydScoreRankVO mzMydScoreRankVO);
|
// ================================================================ 重复明细清理(满意度统计前置)
|
|
/**
|
* 找出「同一 sub_id + questiontext」下除最新一条之外的重复明细 id。
|
* <p>
|
* 原属 {@code ServiceSubtaskDetailMapper},只有满意度统计调用(已核实),故一并搬入。
|
* <p>
|
* ⚠️ 注意:调用它的 {@code statQuestionOption} / {@code statQuestionOptionBySubtaskIds}
|
* 会先执行本查询再执行 {@link #deleteRepeatDetailByIds},<b>这是会写库的行为</b>(原实现即如此)。
|
*
|
* @return 需要清理的明细 id
|
*/
|
List<Long> selectRepeatDetailIds();
|
|
/**
|
* 按 id 逻辑删除重复明细({@code del_flag = 1})。
|
*/
|
Integer deleteRepeatDetailByIds(@Param("ids") List<Long> ids);
|
// ================================================================ 子任务(满意度统计取数)
|
|
/**
|
* 按机构/院区/服务类型/出院时间/科室病区取子任务,<b>只返回 id 与 taskid</b>。
|
* <p>
|
* 对应原实现 {@code ServiceSubtaskServiceImpl.getServiceSubtasks(ServiceSubtaskEntity)}
|
* 中 {@code sltdMydTotalByScore} 实际用到的口径。原方法基于
|
* {@code selectServiceSubtaskList}(近百个可选条件 + 返回全表字段),
|
* 满意度只需要上述条件与两个 id 列,因此这里专写一条精简查询。
|
* <p>
|
* <b>条件与原文逐字一致</b>(均「非空才拼」):
|
* {@code del_flag = 0}、{@code orgid}、{@code campusid}、{@code service_type}、
|
* {@code endtime} 的日期区间、{@code deptOrDistrict==1} 时的病区 IN、
|
* {@code leaveldeptcodes} 的科室 IN。
|
* <p>
|
* ⚠️ 原文无默认排序、无默认分页({@code sort}/{@code pageSize} 未设置即不生效),
|
* 本查询同样不加排序,保证结果顺序行为一致。
|
*/
|
List<SatisfactionSubtaskRef> selectMydSubtaskRefs(@Param("q") SatisfactionSubtaskQuery query);
|
|
// ================================================================ 随访「满意度指数」取数
|
// 以下 5 个方法服务于 getSatisfactionIndex(随访统计页的「满意度题目总量/填报量/完成比例」),
|
// 原本散落在 smartor 的 ServiceTaskMapper / IvrTaskTemplateScriptMapper /
|
// SvyTaskTemplateScriptMapper / ServiceSubtaskMapper / ServiceSubtaskDetailMapper 中,
|
// 由 ServiceSubtaskServiceImpl#getSatisfactionIndex 逐个调用。
|
|
/**
|
* 按科室 <b>或</b> 病区取随访任务(只取统计用到的 4 列)。
|
* <p>
|
* 对应原实现 {@code ServiceTaskMapper.selectServiceTaskList},调用方按 type 二选一传参:
|
* <ul>
|
* <li>{@code deptcode} 非空 → 拼 {@code deptcode REGEXP CONCAT('(^|,)', #{deptcode}, '(,|$)')};</li>
|
* <li>{@code leavehospitaldistrictcode} 非空 → 拼同形态的 REGEXP;</li>
|
* </ul>
|
* 两者只会有一个非空,因此本方法一条 SQL 即可覆盖原实现的两个分支。
|
* <p>
|
* <b>口径逐字一致</b>:{@code del_flag = 0}、{@code orgid}、{@code order by update_time desc, taskid desc}。
|
*/
|
List<SatisfactionTaskRow> selectSatisfactionServiceTasks(
|
@Param("orgid") String orgid,
|
@Param("deptcode") String deptcode,
|
@Param("leavehospitaldistrictcode") String leavehospitaldistrictcode);
|
|
/**
|
* 统计某模板下的语音满意度题目数量。
|
* <p>
|
* 对应原实现 {@code IvrTaskTemplateScriptMapper.selectIvrTaskTemplateScriptList}
|
* 在 {@code templateID + orgid + scriptAssortid} 三个条件下的 {@code size()}。
|
* <p>
|
* <b>口径注意</b>:{@code scriptAssortid} 为 {@code null} 时<b>不拼</b>该条件
|
* (等于统计该模板全部题目)——与原文 {@code <if test="scriptAssortid != null">} 一致。
|
*/
|
int countIvrTaskTemplateScripts(@Param("templateID") Long templateID,
|
@Param("orgid") String orgid,
|
@Param("scriptAssortid") Long scriptAssortid);
|
|
/**
|
* 统计某模板下的问卷满意度题目数量。
|
* <p>
|
* 对应原实现 {@code SvyTaskTemplateScriptMapper.selectSvyTaskTemplateScriptList}
|
* 在 {@code templateID + orgid + categoryid} 三个条件下的 {@code size()}。
|
* <p>
|
* <b>口径注意</b>:{@code categoryid} 为 {@code null} 时<b>不拼</b>该条件(与原文一致)。
|
*/
|
int countSvyTaskTemplateScripts(@Param("templateID") Long templateID,
|
@Param("orgid") String orgid,
|
@Param("categoryid") Long categoryid);
|
|
/**
|
* 统计某任务下指定发送状态的子任务数量。
|
* <p>
|
* 对应原实现 {@code ServiceSubtaskMapper.selectServiceSubtaskBySendstate}
|
* 在 {@code taskid + sendstates(3,5,6)} 两个条件下的 {@code size()}。
|
* 原调用没有设置 {@code orgid},故本方法也不含该条件。
|
* <p>
|
* <b>口径注意</b>:含 {@code del_flag = 0};{@code sendstates} 为 {@code null} 时不拼 IN 条件。
|
*/
|
int countSubtaskBySendstates(@Param("taskid") Long taskid,
|
@Param("sendstates") List<Long> sendstates);
|
|
/**
|
* 统计某任务下的满意度明细数量。
|
* <p>
|
* 对应原实现 {@code ServiceSubtaskDetailMapper.selectServiceSubtaskDetailList}
|
* 在 {@code taskid + categoryid + orgid} 三个条件下的 {@code size()}。
|
* <p>
|
* <b>口径注意</b>:原文<b>没有</b> {@code del_flag} 条件,本查询同样不加;
|
* {@code categoryid} 为 {@code null} 时不拼该条件(保留原文的"按任务类型决定是否设 categoryid"行为)。
|
*/
|
int countSubtaskDetail(@Param("taskid") Long taskid,
|
@Param("categoryid") Long categoryid,
|
@Param("orgid") String orgid);
|
}
|