统计修改

This commit is contained in:
zhangheng 2026-03-02 17:17:49 +08:00
parent 1d02f34424
commit bfbf27ea86
7 changed files with 220 additions and 61 deletions

View File

@ -2,6 +2,7 @@ package com.xinelu.manage.mapper.questionsubject;
import com.xinelu.manage.domain.questionsubject.QuestionSubject; import com.xinelu.manage.domain.questionsubject.QuestionSubject;
import com.xinelu.manage.vo.questionsubject.QuestionSubjectVO; import com.xinelu.manage.vo.questionsubject.QuestionSubjectVO;
import com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo;
import java.util.List; import java.util.List;
@ -84,4 +85,12 @@ public interface QuestionSubjectMapper {
* @return 结果 * @return 结果
*/ */
int deleteSubjectByQuestionInfoId(Long questionInfoId); int deleteSubjectByQuestionInfoId(Long questionInfoId);
/**
* 原问卷选项信息
*
* @param questionnaireId 问卷id
* @return QuestionnaireTaskStatisticsVo
*/
List<QuestionnaireTaskStatisticsVo> selectQuestionnaireByQuestionnaireId(Long questionnaireId);
} }

View File

@ -272,4 +272,12 @@ public interface SignPatientManageRouteNodeMapper {
* @return QuestionSubmitExportVo * @return QuestionSubmitExportVo
*/ */
List<QuestionSubmitExportVo> selectQuestionSubmit(List<Long> manageRouteNodeIds); List<QuestionSubmitExportVo> selectQuestionSubmit(List<Long> manageRouteNodeIds);
/**
* 管理任务节点数据根据问卷id
*
* @param questionnaireTaskStatisticsDto 信息
* @return int
*/
int selectRouteNodeCountByQuestionId(QuestionnaireTaskStatisticsDto questionnaireTaskStatisticsDto);
} }

View File

@ -4,6 +4,7 @@ import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.core.domain.entity.SysUser; import com.xinelu.common.core.domain.entity.SysUser;
import com.xinelu.common.enums.NodeTypeEnum; import com.xinelu.common.enums.NodeTypeEnum;
import com.xinelu.common.enums.PhoneDialMethodEnum; import com.xinelu.common.enums.PhoneDialMethodEnum;
import com.xinelu.common.enums.QuestionSubjectTypeEnum;
import com.xinelu.common.enums.QuestionTypeEnum; import com.xinelu.common.enums.QuestionTypeEnum;
import com.xinelu.common.utils.StringUtils; import com.xinelu.common.utils.StringUtils;
import com.xinelu.manage.domain.agency.Agency; import com.xinelu.manage.domain.agency.Agency;
@ -14,6 +15,7 @@ import com.xinelu.manage.dto.statistics.QuestionnaireTaskStatisticsDto;
import com.xinelu.manage.mapper.department.DepartmentMapper; import com.xinelu.manage.mapper.department.DepartmentMapper;
import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper; import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper;
import com.xinelu.manage.mapper.phonedialrecord.PhoneDialRecordMapper; import com.xinelu.manage.mapper.phonedialrecord.PhoneDialRecordMapper;
import com.xinelu.manage.mapper.questionsubject.QuestionSubjectMapper;
import com.xinelu.manage.mapper.shortmessagesendrecord.ShortMessageSendRecordMapper; import com.xinelu.manage.mapper.shortmessagesendrecord.ShortMessageSendRecordMapper;
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper; import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
import com.xinelu.manage.mapper.subscribemessagesendrecord.SubscribeMessageSendRecordMapper; import com.xinelu.manage.mapper.subscribemessagesendrecord.SubscribeMessageSendRecordMapper;
@ -27,26 +29,25 @@ import com.xinelu.manage.vo.signpatientmanageroutenode.UploadRobotPublishRecordV
import com.xinelu.manage.vo.statistics.*; import com.xinelu.manage.vo.statistics.*;
import com.xinelu.system.mapper.SysUserMapper; import com.xinelu.system.mapper.SysUserMapper;
import com.xinelu.system.service.ISysUserService; import com.xinelu.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
/** /**
* @description: 统计模块Service业务层处理 * @description: 统计模块Service业务层处理
* @author: haown * @author: haown
* @create: 2024-10-31 11:24 * @create: 2024-10-31 11:24
**/ **/
@Slf4j
@Service @Service
public class StatisticsServiceImpl implements IStatisticsService { public class StatisticsServiceImpl implements IStatisticsService {
@ -70,6 +71,8 @@ public class StatisticsServiceImpl implements IStatisticsService {
private DepartmentMapper departmentMapper; private DepartmentMapper departmentMapper;
@Resource @Resource
private SysUserMapper sysUserMapper; private SysUserMapper sysUserMapper;
@Resource
private QuestionSubjectMapper questionSubjectMapper;
/** /**
* @description 随访成功率统计 * @description 随访成功率统计
@ -317,23 +320,76 @@ public class StatisticsServiceImpl implements IStatisticsService {
*/ */
@Override @Override
public AjaxResult questionnaireTaskStatistics(QuestionnaireTaskStatisticsDto questionnaireTaskStatisticsDto) { public AjaxResult questionnaireTaskStatistics(QuestionnaireTaskStatisticsDto questionnaireTaskStatisticsDto) {
//查询问卷任务 List<QuestionnaireTaskStatisticsVo> output = new ArrayList<>();
List<QuestionnaireTaskStatisticsVo> questionnaireTaskStatisticsVos = signPatientManageRouteNodeMapper.questionnaireTaskStatistics(questionnaireTaskStatisticsDto); //查询原问卷信息
//遍历计算比例 List<QuestionnaireTaskStatisticsVo> subjectAndOptionVos = questionSubjectMapper.selectQuestionnaireByQuestionnaireId(questionnaireTaskStatisticsDto.getQuestionInfoId());
if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVos)){ //空数据组装返回
for (QuestionnaireTaskStatisticsVo questionnaireTaskStatisticsVo : questionnaireTaskStatisticsVos) { if (CollectionUtils.isEmpty(subjectAndOptionVos)) {
//除数不能为空或0 return AjaxResult.success();
if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos()) && Objects.nonNull(questionnaireTaskStatisticsVo.getTotal()) && questionnaireTaskStatisticsVo.getTotal() != 0){ }
questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos() //查询问卷任务
.forEach(item -> item.setChoiceProportion( List<QuestionnaireTaskStatisticsVo> questionnaireTaskStatisticsVos = signPatientManageRouteNodeMapper.questionnaireTaskStatistics(questionnaireTaskStatisticsDto);
new BigDecimal(item.getChoiceNumber()) //空数据返回原问卷信息
.divide(new BigDecimal(questionnaireTaskStatisticsVo.getTotal()),2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")))); List<Long> total = null;
} else if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos()) && (Objects.isNull(questionnaireTaskStatisticsVo.getTotal()) || questionnaireTaskStatisticsVo.getTotal() == 0)){ if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVos)) {
questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos().forEach(item -> item.setChoiceProportion(BigDecimal.ZERO)); questionnaireTaskStatisticsVos = questionnaireTaskStatisticsVos.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getQuestionSubjectOptionId())).collect(Collectors.toList());
} total = questionnaireTaskStatisticsVos.stream().filter(Objects::nonNull).map(QuestionnaireTaskStatisticsVo::getManageRouteNodeId).distinct().collect(Collectors.toList());
} }
} //遍历计算
return AjaxResult.success(questionnaireTaskStatisticsVos); List<QuestionnaireTaskOptionStatisticsVo> optionStatisticsVos = new ArrayList<>();
if (questionnaireTaskStatisticsVos.size() > 0 && total != null && total.size() > 0) {
for (QuestionnaireTaskStatisticsVo subjectAndOptionVo : subjectAndOptionVos) {
QuestionnaireTaskOptionStatisticsVo optionStatisticsVo = new QuestionnaireTaskOptionStatisticsVo();
//根据 题目序号选项已选择过滤
List<QuestionnaireTaskStatisticsVo> choice = questionnaireTaskStatisticsVos.stream().filter(Objects::nonNull)
.filter(item -> Objects.nonNull(item.getQuestionNumber()) && item.getQuestionNumber().equals(subjectAndOptionVo.getQuestionNumber())
&& Objects.equals(item.getQuestionSubjectOptionId(), subjectAndOptionVo.getQuestionSubjectOptionId())
&& item.getOptionChooseSign() == 0)
.collect(Collectors.toList());
if (choice.size() > 0) {
subjectAndOptionVo.setChoiceProportion(new BigDecimal(choice.size()).divide(new BigDecimal(total.size()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
optionStatisticsVo.setChoiceNumber((long) choice.size());
} else {
subjectAndOptionVo.setChoiceProportion(BigDecimal.ZERO);
optionStatisticsVo.setChoiceNumber(0L);
}
optionStatisticsVo.setQuestionSubjectOptionId(subjectAndOptionVo.getQuestionSubjectOptionId());
optionStatisticsVo.setQuestionInfoId(questionnaireTaskStatisticsDto.getQuestionInfoId());
optionStatisticsVo.setOptionName(subjectAndOptionVo.getOptionName());
optionStatisticsVo.setQuestionNumber(subjectAndOptionVo.getQuestionNumber());
optionStatisticsVo.setChoiceProportion(subjectAndOptionVo.getChoiceProportion());
optionStatisticsVos.add(optionStatisticsVo);
}
} else {
//如果没数据返回问卷模板
for (QuestionnaireTaskStatisticsVo subjectAndOptionVo : subjectAndOptionVos) {
QuestionnaireTaskOptionStatisticsVo optionStatisticsVo = new QuestionnaireTaskOptionStatisticsVo();
optionStatisticsVo.setQuestionInfoId(questionnaireTaskStatisticsDto.getQuestionInfoId());
optionStatisticsVo.setQuestionSubjectOptionId(subjectAndOptionVo.getQuestionSubjectOptionId());
optionStatisticsVo.setOptionName(subjectAndOptionVo.getOptionName());
optionStatisticsVo.setQuestionNumber(subjectAndOptionVo.getQuestionNumber());
optionStatisticsVo.setChoiceProportion(BigDecimal.ZERO);
optionStatisticsVo.setChoiceNumber(0L);
optionStatisticsVos.add(optionStatisticsVo);
}
}
//根据题号组装数据类型
List<BigDecimal> questionNumberList = subjectAndOptionVos.stream().filter(Objects::nonNull)
.filter(item -> item.getQuestionType().equals(QuestionSubjectTypeEnum.MULTIPLE_CHOICE.getInfo()) || item.getQuestionType().equals(QuestionSubjectTypeEnum.MULTIPLE_CHOICE_QUESTIONS.getInfo()))
.map(QuestionnaireTaskStatisticsVo::getQuestionNumber).distinct().collect(Collectors.toList());
for (BigDecimal questionNumber : questionNumberList) {
QuestionnaireTaskStatisticsVo questionnaireTaskStatisticsVo = new QuestionnaireTaskStatisticsVo();
List<QuestionnaireTaskOptionStatisticsVo> collect = optionStatisticsVos.stream().filter(Objects::nonNull).filter(item -> questionNumber.equals(item.getQuestionNumber())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(collect)) {
questionnaireTaskStatisticsVo.setQuestionnaireName(collect.get(0).getQuestionnaireName());
questionnaireTaskStatisticsVo.setCreateTime(collect.get(0).getCreateTime());
questionnaireTaskStatisticsVo.setQuestionName(collect.get(0).getQuestionName());
questionnaireTaskStatisticsVo.setQuestionNumber(collect.get(0).getQuestionNumber());
questionnaireTaskStatisticsVo.setQuestionnaireTaskOptionStatisticsVos(collect);
output.add(questionnaireTaskStatisticsVo);
}
}
return AjaxResult.success(output);
} }
/** /**

View File

@ -1,9 +1,11 @@
package com.xinelu.manage.vo.statistics; package com.xinelu.manage.vo.statistics;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* @description: 问卷任务统计选项返回值 * @description: 问卷任务统计选项返回值
@ -75,4 +77,20 @@ public class QuestionnaireTaskOptionStatisticsVo {
* 选择比例 * 选择比例
*/ */
private BigDecimal choiceProportion; private BigDecimal choiceProportion;
/**
* 题目序号
*/
private BigDecimal questionNumber;
/**
* 问卷标题(上层数据使用)
*/
private String questionnaireName;
/**
* 创建时间(上层数据使用)
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
} }

View File

@ -22,6 +22,12 @@ public class QuestionnaireTaskStatisticsVo {
@ApiModelProperty(value = "问卷提交结果信息表id") @ApiModelProperty(value = "问卷提交结果信息表id")
private Long questionSubmitResultId; private Long questionSubmitResultId;
/**
* 问卷选项id
*/
@ApiModelProperty(value = "问卷选项id")
private Long questionSubmitId;
/** /**
* 问卷表id * 问卷表id
*/ */
@ -48,6 +54,36 @@ public class QuestionnaireTaskStatisticsVo {
@ApiModelProperty(value = "题目名称") @ApiModelProperty(value = "题目名称")
private String questionName; private String questionName;
/**
* 问卷选项提交结果信息表id
*/
@ApiModelProperty(value = "问卷选项提交结果信息表id")
private Long patientQuestionOptionResult;
/**
* 问卷选项信息表id
*/
@ApiModelProperty(value = "问卷选项信息表id")
private Long questionSubjectOptionId;
/**
* 问卷选项名称
*/
@ApiModelProperty(value = "问卷选项名称")
private String optionName;
/**
* 问卷选项排序
*/
@ApiModelProperty(value = "问卷选项排序")
private Long optionSort;
/**
* 问卷选项是否选择
*/
@ApiModelProperty(value = "问卷选项是否选择")
private Integer optionChooseSign;
/** /**
* 填写问卷总数 * 填写问卷总数
*/ */
@ -69,4 +105,14 @@ public class QuestionnaireTaskStatisticsVo {
*/ */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime; private LocalDateTime createTime;
/**
* 填写问卷总数
*/
private Long manageRouteNodeId;
/**
* 选择比例
*/
private BigDecimal choiceProportion;
} }

View File

@ -369,4 +369,20 @@
from question_subject from question_subject
where question_info_id = #{questionInfoId} where question_info_id = #{questionInfoId}
</delete> </delete>
<select id="selectQuestionnaireByQuestionnaireId"
resultType="com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo">
select qs.question_info_id,
qs.id questionSubjectId,
qs.question_number,
qs.question_type,
qs.question_name,
qso.id questionSubjectOptionId,
qso.option_name,
qso.option_sort
from question_subject qs
LEFT JOIN question_subject_option qso ON qso.questionnaire_subject_id = qs.id
where qs.question_info_id = #{questionnaireId}
order by qs.question_number ASC, qso.id ASC
</select>
</mapper> </mapper>

View File

@ -1242,11 +1242,11 @@
</select> </select>
<select id="questionnaireTaskStatistics" <select id="questionnaireTaskStatistics"
resultType="com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo" resultType="com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo">
resultMap="QuestionnaireTaskStatisticsVoResult">
select select
qi.create_time, qi.create_time,
qi.questionnaire_name, qi.questionnaire_name,
spmrn.id manageRouteNodeId,
spmrn.question_info_id, spmrn.question_info_id,
pqsjr.question_subject_id, pqsjr.question_subject_id,
pqsjr.question_number, pqsjr.question_number,
@ -1256,39 +1256,7 @@
pqor.question_subject_option_id questionSubjectOptionId, pqor.question_subject_option_id questionSubjectOptionId,
pqor.option_name, pqor.option_name,
pqor.option_sort, pqor.option_sort,
( pqor.option_choose_sign
SELECT
count( f.option_choose_sign = 0 OR NULL )
FROM
sign_patient_manage_route_node a
LEFT JOIN sign_patient_manage_route b ON b.id = a.manage_route_id
LEFT JOIN patient_info c ON b.patient_id = c.id
LEFT JOIN patient_question_submit_result d ON a.id = d.manage_route_node_id
LEFT JOIN patient_question_subject_result e ON d.id = e.question_submit_result_id
LEFT JOIN patient_question_option_result f ON e.id = f.question_subject_result_id
WHERE
c.del_flag = 0
AND a.question_info_id = spmrn.question_info_id
AND e.question_subject_id = pqsjr.question_subject_id
AND f.question_subject_option_id = pqor.question_subject_option_id
<if test="taskStartTime != null"><!-- 开始时间检索 -->
AND date_format(a.node_finish_date,'%y%m%d') &gt;= date_format(#{taskStartTime},'%y%m%d')
</if>
<if test="taskEndTime != null"><!-- 结束时间检索 -->
AND date_format(a.node_finish_date,'%y%m%d') &lt;= date_format(#{taskEndTime},'%y%m%d')
</if>
<if test="visitStartTime != null and visitEndTime != null">
and( (date_format(c.visit_date, '%y%m%d') >= date_format(#{visitStartTime}, '%y%m%d')
and date_format(c.visit_date, '%y%m%d') &lt;= date_format(#{visitEndTime}, '%y%m%d'))
or (date_format(c.discharge_time,'%y%m%d') >= date_format(#{visitStartTime}, '%y%m%d') and
date_format(c.discharge_time,'%y%m%d') &lt;= date_format(#{visitEndTime}, '%y%m%d')))
</if>
) choiceNumber,
(
SELECT count( 1 ) FROM sign_patient_manage_route_node a
LEFT JOIN patient_question_submit_result d ON a.id = d.manage_route_node_id
WHERE a.question_info_id = spmrn.question_info_id
) total
from sign_patient_manage_route_node spmrn from sign_patient_manage_route_node spmrn
left join question_info qi on spmrn.question_info_id = qi.id left join question_info qi on spmrn.question_info_id = qi.id
left join sign_patient_manage_route spmr on spmr.id = spmrn.manage_route_id left join sign_patient_manage_route spmr on spmr.id = spmrn.manage_route_id
@ -1383,7 +1351,19 @@
WHERE WHERE
spmrn.del_flag = 0 spmrn.del_flag = 0
AND spmrn.question_info_id = #{questionInfoId} AND spmrn.question_info_id = #{questionInfoId}
AND pqor.question_subject_option_id = #{questionSubjectOptionId} <if test="questionSubjectOptionId != null">
AND pqor.question_subject_option_id = #{questionSubjectOptionId}
AND pi.del_flag = 0
AND spmrn.node_finish_status = 'SUCCESS'
AND pqsjr.question_type in
('MULTIPLE_CHOICE','MULTIPLE_CHOICE_QUESTIONS','COMBINATION_RADIO_SUBJECT','COMBINATION_MULTIPLE_SUBJECT')
</if>
<if test="startTime != null"><!-- 开始时间检索 -->
AND date_format(spmrn.node_finish_date,'%y%m%d') &gt;= date_format(#{startTime},'%y%m%d')
</if>
<if test="endTime != null"><!-- 结束时间检索 -->
AND date_format(spmrn.node_finish_date,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
</if>
AND pqor.option_choose_sign = #{optionChooseSign} AND pqor.option_choose_sign = #{optionChooseSign}
ORDER BY spmrn.create_time DESC ORDER BY spmrn.create_time DESC
</select> </select>
@ -1557,4 +1537,30 @@
</foreach> </foreach>
ORDER BY pqsm.create_time DESC ORDER BY pqsm.create_time DESC
</select> </select>
<select id="selectRouteNodeCountByQuestionId" resultType="java.lang.Integer">
SELECT
count(1)
FROM sign_patient_manage_route_node spmrn
LEFT JOIN sign_patient_manage_route spmr ON spmr.id = spmrn.manage_route_id
LEFT JOIN patient_info p ON spmr.patient_id = p.id
WHERE
p.del_flag = 0
AND spmrn.node_finish_status = 'SUCCESS'
<if test="questionInfoId != null">
and spmrn.question_info_id = #{questionInfoId}
</if>
<if test="taskStartTime != null"><!-- 开始时间检索 -->
AND date_format(spmrn.node_finish_date,'%y%m%d') &gt;= date_format(#{taskStartTime},'%y%m%d')
</if>
<if test="taskEndTime != null"><!-- 结束时间检索 -->
AND date_format(spmrn.node_finish_date,'%y%m%d') &lt;= date_format(#{taskEndTime},'%y%m%d')
</if>
<if test="visitStartTime != null and visitEndTime != null">
and( (date_format(p.visit_date, '%y%m%d') >= date_format(#{visitStartTime}, '%y%m%d')
and date_format(p.visit_date, '%y%m%d') &lt;= date_format(#{visitEndTime}, '%y%m%d'))
or (date_format(p.discharge_time,'%y%m%d') >= date_format(#{visitStartTime}, '%y%m%d') and
date_format(p.discharge_time,'%y%m%d') &lt;= date_format(#{visitEndTime}, '%y%m%d')))
</if>
</select>
</mapper> </mapper>