统计修改

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.vo.questionsubject.QuestionSubjectVO;
import com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo;
import java.util.List;
@ -84,4 +85,12 @@ public interface QuestionSubjectMapper {
* @return 结果
*/
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
*/
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.enums.NodeTypeEnum;
import com.xinelu.common.enums.PhoneDialMethodEnum;
import com.xinelu.common.enums.QuestionSubjectTypeEnum;
import com.xinelu.common.enums.QuestionTypeEnum;
import com.xinelu.common.utils.StringUtils;
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.patientvisitrecord.PatientVisitRecordMapper;
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.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
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.system.mapper.SysUserMapper;
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.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
/**
* @description: 统计模块Service业务层处理
* @author: haown
* @create: 2024-10-31 11:24
**/
@Slf4j
@Service
public class StatisticsServiceImpl implements IStatisticsService {
@ -70,6 +71,8 @@ public class StatisticsServiceImpl implements IStatisticsService {
private DepartmentMapper departmentMapper;
@Resource
private SysUserMapper sysUserMapper;
@Resource
private QuestionSubjectMapper questionSubjectMapper;
/**
* @description 随访成功率统计
@ -317,23 +320,76 @@ public class StatisticsServiceImpl implements IStatisticsService {
*/
@Override
public AjaxResult questionnaireTaskStatistics(QuestionnaireTaskStatisticsDto questionnaireTaskStatisticsDto) {
//查询问卷任务
List<QuestionnaireTaskStatisticsVo> questionnaireTaskStatisticsVos = signPatientManageRouteNodeMapper.questionnaireTaskStatistics(questionnaireTaskStatisticsDto);
//遍历计算比例
if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVos)){
for (QuestionnaireTaskStatisticsVo questionnaireTaskStatisticsVo : questionnaireTaskStatisticsVos) {
//除数不能为空或0
if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos()) && Objects.nonNull(questionnaireTaskStatisticsVo.getTotal()) && questionnaireTaskStatisticsVo.getTotal() != 0){
questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos()
.forEach(item -> item.setChoiceProportion(
new BigDecimal(item.getChoiceNumber())
.divide(new BigDecimal(questionnaireTaskStatisticsVo.getTotal()),2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))));
} else if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos()) && (Objects.isNull(questionnaireTaskStatisticsVo.getTotal()) || questionnaireTaskStatisticsVo.getTotal() == 0)){
questionnaireTaskStatisticsVo.getQuestionnaireTaskOptionStatisticsVos().forEach(item -> item.setChoiceProportion(BigDecimal.ZERO));
}
}
}
return AjaxResult.success(questionnaireTaskStatisticsVos);
List<QuestionnaireTaskStatisticsVo> output = new ArrayList<>();
//查询原问卷信息
List<QuestionnaireTaskStatisticsVo> subjectAndOptionVos = questionSubjectMapper.selectQuestionnaireByQuestionnaireId(questionnaireTaskStatisticsDto.getQuestionInfoId());
//空数据组装返回
if (CollectionUtils.isEmpty(subjectAndOptionVos)) {
return AjaxResult.success();
}
//查询问卷任务
List<QuestionnaireTaskStatisticsVo> questionnaireTaskStatisticsVos = signPatientManageRouteNodeMapper.questionnaireTaskStatistics(questionnaireTaskStatisticsDto);
//空数据返回原问卷信息
List<Long> total = null;
if (CollectionUtils.isNotEmpty(questionnaireTaskStatisticsVos)) {
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());
}
//遍历计算
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;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @description: 问卷任务统计选项返回值
@ -75,4 +77,20 @@ public class QuestionnaireTaskOptionStatisticsVo {
* 选择比例
*/
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")
private Long questionSubmitResultId;
/**
* 问卷选项id
*/
@ApiModelProperty(value = "问卷选项id")
private Long questionSubmitId;
/**
* 问卷表id
*/
@ -48,6 +54,36 @@ public class QuestionnaireTaskStatisticsVo {
@ApiModelProperty(value = "题目名称")
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")
private LocalDateTime createTime;
/**
* 填写问卷总数
*/
private Long manageRouteNodeId;
/**
* 选择比例
*/
private BigDecimal choiceProportion;
}

View File

@ -369,4 +369,20 @@
from question_subject
where question_info_id = #{questionInfoId}
</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>

View File

@ -1242,11 +1242,11 @@
</select>
<select id="questionnaireTaskStatistics"
resultType="com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo"
resultMap="QuestionnaireTaskStatisticsVoResult">
resultType="com.xinelu.manage.vo.statistics.QuestionnaireTaskStatisticsVo">
select
qi.create_time,
qi.questionnaire_name,
spmrn.id manageRouteNodeId,
spmrn.question_info_id,
pqsjr.question_subject_id,
pqsjr.question_number,
@ -1256,39 +1256,7 @@
pqor.question_subject_option_id questionSubjectOptionId,
pqor.option_name,
pqor.option_sort,
(
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
pqor.option_choose_sign
from sign_patient_manage_route_node spmrn
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
@ -1383,7 +1351,19 @@
WHERE
spmrn.del_flag = 0
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}
ORDER BY spmrn.create_time DESC
</select>
@ -1557,4 +1537,30 @@
</foreach>
ORDER BY pqsm.create_time DESC
</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>