package cn.lihu.jh.module.ecg.service.jobrecord;
|
|
import cn.lihu.jh.module.ecg.controller.admin.appointment.vo.AppointmentRespVO;
|
import cn.lihu.jh.module.ecg.dal.dataobject.appointment.AppointmentDO;
|
import cn.lihu.jh.module.ecg.dal.dataobject.devrent.DevRentDO;
|
import cn.lihu.jh.module.ecg.dal.dataobject.jobrecord.JobRecordStatisticDO;
|
import cn.lihu.jh.module.ecg.dal.mysql.appointment.AppointmentMapper;
|
import cn.lihu.jh.module.ecg.dal.mysql.devrent.DevRentMapper;
|
import org.springframework.stereotype.Service;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import cn.lihu.jh.module.ecg.controller.admin.jobrecord.vo.*;
|
import cn.lihu.jh.module.ecg.dal.dataobject.jobrecord.JobRecordDO;
|
import cn.lihu.jh.framework.common.pojo.PageResult;
|
import cn.lihu.jh.framework.common.pojo.PageParam;
|
import cn.lihu.jh.framework.common.util.object.BeanUtils;
|
|
import cn.lihu.jh.module.ecg.dal.mysql.jobrecord.JobRecordMapper;
|
import cn.lihu.jh.module.ecg.dal.mysql.queue.QueueMapper;
|
import cn.lihu.jh.module.ecg.enums.QueueStatusEnum;
|
import lombok.extern.slf4j.Slf4j;
|
|
import javax.annotation.Resource;
|
|
import static cn.lihu.jh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.lihu.jh.framework.common.pojo.CommonResult.success;
|
import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*;
|
|
/**
|
* 工作记录 Service 实现类
|
*
|
* @author 芋道源码
|
*/
|
@Service
|
@Validated
|
@Slf4j
|
public class JobRecordServiceImpl implements JobRecordService {
|
|
@Resource
|
private JobRecordMapper jobRecordMapper;
|
|
/** 【撤销标识】读当日队列状态,判断"完成是否被撤销过" */
|
@Resource
|
private QueueMapper queueMapper;
|
|
@Resource
|
private DevRentMapper devRentMapper;
|
|
@Resource
|
private AppointmentMapper appointmentMapper;
|
|
@Override
|
public Long createJobRecord(JobRecordSaveReqVO createReqVO) {
|
// 插入
|
JobRecordDO jobRecord = BeanUtils.toBean(createReqVO, JobRecordDO.class);
|
jobRecordMapper.insert(jobRecord);
|
// 返回
|
return jobRecord.getId();
|
}
|
|
@Override
|
public void updateJobRecord(JobRecordSaveReqVO updateReqVO) {
|
// 校验存在
|
validateJobRecordExists(updateReqVO.getId());
|
// 更新
|
JobRecordDO updateObj = BeanUtils.toBean(updateReqVO, JobRecordDO.class);
|
jobRecordMapper.updateById(updateObj);
|
}
|
|
@Override
|
public void deleteJobRecord(Long id) {
|
// 校验存在
|
validateJobRecordExists(id);
|
// 删除
|
jobRecordMapper.deleteById(id);
|
}
|
|
private void validateJobRecordExists(Long id) {
|
if (jobRecordMapper.selectById(id) == null) {
|
throw exception(JOB_RECORD_NOT_EXISTS);
|
}
|
}
|
|
@Override
|
public JobRecordDO getJobRecord(Long id) {
|
JobRecordDO jobRecordDO = jobRecordMapper.selectById(id);
|
if (null != jobRecordDO) {
|
fillPatientInfo(java.util.Collections.singletonList(jobRecordDO));
|
}
|
return jobRecordDO;
|
}
|
|
@Override
|
public PageResult<JobRecordDO> getJobRecordPage(JobRecordPageReqVO pageReqVO) {
|
PageResult<JobRecordDO> pageResult = jobRecordMapper.selectPage(pageReqVO);
|
|
List<JobRecordDO> jobRecordDOList = pageResult.getList();
|
if ( !jobRecordDOList.isEmpty() ) {
|
List<Long> rentIdList = jobRecordDOList.stream().map(item -> item.getRentId()).toList();
|
List<Integer> paidInfoList = devRentMapper.getPaidInfo(rentIdList);
|
for (int i = 0; i < jobRecordDOList.size(); i++) {
|
jobRecordDOList.get(i).setPaid(paidInfoList.get(i));
|
}
|
// 需求1:回填患者信息(批量,避免 N+1)
|
fillPatientInfo(jobRecordDOList);
|
// 【撤销标识】标记"完成被撤销过、还没重新完成"的记录
|
fillUndoneFlag(jobRecordDOList);
|
}
|
|
return pageResult;
|
}
|
|
/**
|
* 【撤销标识】给"已完成记录"补上 {@code undone}。
|
*
|
* <p>撤销「检查完成」只是把队列行 40(已就诊) 改回 20(准备中),**不碰 job_record**;
|
* 因此判断规则是:该患者**今日**对应检查项目的队列行存在、且状态 ≠ 40 → 已被撤销。
|
* 患者再次完成后队列行会回到 40 → 自动恢复成"已完成",无需写库、也不会漏清标记。
|
*
|
* <p>一次批量查询解决整页(按 patId 取当日队列状态,再在内存里按 patId+checkType 匹配)。
|
*/
|
private void fillUndoneFlag(List<JobRecordDO> jobRecordDOList) {
|
List<String> patIdList = jobRecordDOList.stream()
|
.map(JobRecordDO::getPatId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.toList();
|
if (patIdList.isEmpty()) {
|
return;
|
}
|
Map<String, Integer> statusMap = new HashMap<>();
|
try {
|
for (Map<String, Object> row : queueMapper.selectTodayStatusByPatIds(patIdList)) {
|
Object patId = row.get("patId");
|
Object checkType = row.get("checkType");
|
Object status = row.get("status");
|
if (null != patId && null != checkType && status instanceof Number) {
|
statusMap.put(patId + "#" + checkType, ((Number) status).intValue());
|
}
|
}
|
} catch (Exception e) {
|
log.warn("[fillUndoneFlag] 读取当日队列状态失败,撤销标识按【未撤销】处理", e);
|
return;
|
}
|
for (JobRecordDO row : jobRecordDOList) {
|
if (null == row.getPatId() || null == row.getCheckType()) {
|
row.setUndone(false);
|
continue;
|
}
|
Integer status = statusMap.get(row.getPatId() + "#" + row.getCheckType());
|
// 队列行不存在(历史记录/已清理)→ 视为未撤销;存在且不是 40 → 已撤销
|
row.setUndone(null != status && QueueStatusEnum.FINISH.getStatus() != status);
|
}
|
}
|
|
// ==================== 需求1:回填患者信息 18 项 ====================
|
// 回填链路(三级):
|
// job_record.rentId → dev_rent.applyNo → appointment
|
// 之所以不用逐条 getByApplyNo:job_record 列表页一次可能返回几十条,
|
// 逐条查会形成 N+1。这里改为「批量取 dev_rent」+「批量取 appointment」。
|
|
private void fillPatientInfo(List<JobRecordDO> jobRecordDOList) {
|
if (null == jobRecordDOList || jobRecordDOList.isEmpty()) {
|
return;
|
}
|
// 1) 批量取 dev_rent,拿到 applyNo
|
List<Long> rentIdList = jobRecordDOList.stream()
|
.map(JobRecordDO::getRentId)
|
.filter(java.util.Objects::nonNull)
|
.distinct()
|
.toList();
|
if (rentIdList.isEmpty()) {
|
return;
|
}
|
Map<Long, String> applyNoByRentId = new HashMap<>();
|
// 一次 IN 查询取全部 applyNo(原先逐条 selectById → N 次查询)
|
List<DevRentDO> devRentDOList = devRentMapper.getApplyNoByIdList(rentIdList);
|
if (null != devRentDOList) {
|
devRentDOList.forEach(d -> {
|
if (null != d && null != d.getId()
|
&& org.springframework.util.StringUtils.hasText(d.getApplyNo())) {
|
applyNoByRentId.put(d.getId(), d.getApplyNo());
|
}
|
});
|
}
|
if (applyNoByRentId.isEmpty()) {
|
return;
|
}
|
|
// 2) 批量取 appointment(一次 IN 查询)
|
List<String> applyNoList = applyNoByRentId.values().stream().distinct().toList();
|
Map<String, AppointmentDO> appointmentByApplyNo = new HashMap<>();
|
List<AppointmentDO> appointmentDOList = appointmentMapper.getByApplyNoList(applyNoList);
|
if (null != appointmentDOList) {
|
appointmentDOList.forEach(a -> {
|
if (null != a && org.springframework.util.StringUtils.hasText(a.getApplyNo())) {
|
appointmentByApplyNo.put(a.getApplyNo(), a);
|
}
|
});
|
}
|
|
// 3) 回填
|
jobRecordDOList.forEach(jobRecordDO -> {
|
if (null == jobRecordDO || null == jobRecordDO.getRentId()) {
|
return;
|
}
|
String applyNo = applyNoByRentId.get(jobRecordDO.getRentId());
|
if (null == applyNo) {
|
return;
|
}
|
AppointmentDO appointment = appointmentByApplyNo.get(applyNo);
|
if (null == appointment) {
|
return;
|
}
|
jobRecordDO.setApplyNo(applyNo);
|
jobRecordDO.setEpisodeId(appointment.getEpisodeId());
|
jobRecordDO.setPatGender(appointment.getPatGender());
|
jobRecordDO.setPatBirthday(appointment.getPatBirthday());
|
jobRecordDO.setRegisterDate(appointment.getRegisterDate());
|
jobRecordDO.setDoctor(appointment.getDoctor());
|
jobRecordDO.setDoctorTime(appointment.getDoctorTime());
|
jobRecordDO.setPatSrc(appointment.getPatSrc());
|
jobRecordDO.setPatMobile(appointment.getPatMobile());
|
jobRecordDO.setPatPhone(appointment.getPatPhone());
|
jobRecordDO.setPatWardDesc(appointment.getPatWardDesc());
|
jobRecordDO.setPatBedNo(appointment.getPatBedNo());
|
jobRecordDO.setMedicalCard(appointment.getMedicalCard());
|
jobRecordDO.setDoctorAdviceNo(appointment.getDoctorAdviceNo());
|
jobRecordDO.setOutpatientNo(appointment.getOutpatientNo());
|
jobRecordDO.setPatIdentityId(appointment.getPatIdentityId());
|
jobRecordDO.setTolerance(appointment.getTolerance());
|
});
|
}
|
|
@Override
|
public List<JobRecordStatisticDO> getJobStatistic(LocalDateTime jobTimeFrom, LocalDateTime jobTimeTo) {
|
|
return jobRecordMapper.getJobStatistic(jobTimeFrom, jobTimeTo);
|
}
|
|
}
|