| | |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.*; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import javax.annotation.Resource; |
| | | |
| | | import cn.lihu.jh.module.ecg.Utils; |
| | | import cn.lihu.jh.module.ecg.controller.admin.room.vo.MonitorInfoVO; |
| | | import cn.lihu.jh.module.ecg.dal.dataobject.devrent.DevRentDO; |
| | | import cn.lihu.jh.module.ecg.dal.mysql.call.CallMapper; |
| | | import cn.lihu.jh.module.ecg.dal.mysql.devrent.DevRentMapper; |
| | | import cn.lihu.jh.module.ecg.enums.DevRentStateEnum; |
| | | import cn.lihu.jh.module.system.api.oauth2.OAuth2TokenApi; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import cn.lihu.jh.framework.common.exception.enums.GlobalErrorCodeConstants; |
| | | import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO; |
| | | import cn.lihu.jh.framework.common.exception.ErrorCode; |
| | | import cn.lihu.jh.framework.common.pojo.CommonResult; |
| | | import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomRespVO; |
| | | import cn.lihu.jh.module.ecg.dal.dataobject.queue.BedQueueStatisticDO; |
| | | import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueStatisticDO; |
| | | import cn.lihu.jh.module.ecg.dal.mysql.room.RoomMapper; |
| | | import cn.lihu.jh.module.ecg.enums.BedStatusEnum; |
| | | import cn.lihu.jh.module.ecg.enums.QueueStatusEnum; |
| | | import cn.lihu.jh.module.ecg.controller.admin.queue.vo.*; |
| | | import cn.lihu.jh.module.ecg.dal.dataobject.queue.QueueDO; |
| | | import cn.lihu.jh.framework.common.pojo.PageResult; |
| | | import cn.lihu.jh.framework.common.util.object.BeanUtils; |
| | | import cn.lihu.jh.module.ecg.dal.mysql.queue.queueMapper; |
| | | import cn.lihu.jh.module.ecg.dal.mysql.queue.QueueMapper; |
| | | import static cn.lihu.jh.module.ecg.enums.ErrorCodeConstants.*; |
| | | import static cn.lihu.jh.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.lihu.jh.framework.common.pojo.CommonResult.error; |
| | |
| | | public class QueueServiceImpl implements QueueService { |
| | | |
| | | @Resource |
| | | private queueMapper queueMapper; |
| | | QueueServiceTxFunctions queueServiceTxFunctions; |
| | | |
| | | @Resource |
| | | private OAuth2TokenApi oAuth2TokenApi; |
| | | |
| | | @Resource |
| | | private QueueMapper queueMapper; |
| | | |
| | | @Resource |
| | | private RoomMapper roomMapper; |
| | |
| | | @Resource |
| | | private DevRentMapper devRentMapper; |
| | | |
| | | AtomicInteger openingFlag = new AtomicInteger(0); |
| | | AtomicInteger curSeqNum = new AtomicInteger(0); |
| | | |
| | | PriorityBlockingQueue<BedQueueBO> priorityQueue = new PriorityBlockingQueue<>(); |
| | | ConcurrentHashMap<String, BedQueueBO > mapBedVsQueue = new ConcurrentHashMap<>(); |
| | | |
| | | ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); |
| | | |
| | | Integer queueReadyMax = 0; |
| | | |
| | | Integer bigScrenWaitingSize = 5; |
| | | Integer bigScrenPassedSize = 5; |
| | | Integer bigScrenWaitingFrom = 0; |
| | | Integer bigScrenPassedFrom = 0; |
| | | ConcurrentHashMap<String, RoomDO> mapRoomBed = new ConcurrentHashMap<>(); |
| | | |
| | | @Override |
| | | public Integer createqueue(QueueSaveReqVO createReqVO) { |
| | |
| | | |
| | | @Override |
| | | public ErrorCode startBedOpen(Long roomId, String roomName, String bedNo) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( new BedOpenCallable(this, roomId, roomName, bedNo)); |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( new BedOpenCallable(queueServiceTxFunctions, roomId, roomName, bedNo)); |
| | | |
| | | try { |
| | | ErrorCode ret = future.get(); |
| | |
| | | |
| | | @Override |
| | | public ErrorCode startBedClose(Long roomId, String bedNo) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( new BedCloseCallable(this, roomId, bedNo)); |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( new BedCloseCallable(queueServiceTxFunctions, roomId, bedNo)); |
| | | |
| | | try { |
| | | ErrorCode ret = future.get(); |
| | |
| | | @Override |
| | | public ErrorCode startBedDoctorPause(Long roomId, String bedNo, Long docId, String docName) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorPauseCallable(this, roomId, bedNo, docId, docName) |
| | | new BedDoctorPauseCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName) |
| | | ); |
| | | |
| | | try { |
| | |
| | | @Override |
| | | public ErrorCode startBedDoctorResume(Long roomId, String bedNo, Long docId, String docName) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorResumeCallable(this, roomId, bedNo, docId, docName) |
| | | new BedDoctorResumeCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName) |
| | | ); |
| | | |
| | | try { |
| | |
| | | @Override |
| | | public ErrorCode startBedDoctorOn(Long roomId, String bedNo, Long docId, String docName) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorOnCallable(this, roomId, bedNo, docId, docName) |
| | | new BedDoctorOnCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName) |
| | | ); |
| | | |
| | | try { |
| | |
| | | @Override |
| | | public ErrorCode startBedDoctorOff(Long roomId, String bedNo, Long docId, String docName) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorOffCallable(this, roomId, bedNo, docId, docName) |
| | | new BedDoctorOffCallable(queueServiceTxFunctions, roomId, bedNo, docId, docName) |
| | | ); |
| | | |
| | | try { |
| | |
| | | @Override |
| | | public ErrorCode startNextPatient(Long roomId, String bedNo) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorNextPatientCallable(this, roomId, bedNo) |
| | | new BedDoctorNextPatientCallable(queueServiceTxFunctions, roomId, bedNo) |
| | | ); |
| | | |
| | | try { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void startHurryUp() { |
| | | public ErrorCode startNextInstallPatient(Long roomId, String bedNo) { |
| | | Future<ErrorCode> future = singleThreadExecutor.submit( |
| | | new BedDoctorNextInstallPatientCallable(queueServiceTxFunctions, roomId, bedNo) |
| | | ); |
| | | |
| | | try { |
| | | ErrorCode ret = future.get(); |
| | | return ret; |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } catch (ExecutionException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | System.out.println("startNextInstallPatient ========"); |
| | | return ECG_INNER_ERROR; |
| | | } |
| | | |
| | | @Override |
| | | public void startHurryUpOneBed(Long roomId, String bedNo) { |
| | | singleThreadExecutor.execute( () -> { |
| | | hurryup(); |
| | | queueServiceTxFunctions.hurryupOneBed(roomId, bedNo); |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | public void startHurryUpOneCheckType(Integer checkType) { |
| | | singleThreadExecutor.execute( () -> { |
| | | queueServiceTxFunctions.hurryupOneCheckType( checkType ); |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | public void startBedReload() { |
| | | singleThreadExecutor.execute( () -> { |
| | | bedReload(); |
| | | hurryup(); |
| | | monitorInfo(); |
| | | queueServiceTxFunctions.bedReload(); |
| | | queueServiceTxFunctions.hurryupAllBed(); |
| | | queueServiceTxFunctions.monitorInfo(); |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | public void startResetRoom(Boolean needCloseBed) { |
| | | singleThreadExecutor.execute( () -> { |
| | | queueServiceTxFunctions.resetRoom(needCloseBed); |
| | | queueServiceTxFunctions.bedReload(); |
| | | queueServiceTxFunctions.monitorInfo(); |
| | | }); |
| | | } |
| | | |
| | | @Override |
| | | public MonitorInfoVO getMonitorInfo() { |
| | | MonitorInfoVO monitorInfoVO = new MonitorInfoVO(); |
| | | monitorInfoVO.setOpeningFlag( openingFlag.get() ); |
| | | monitorInfoVO.setQueueNum( mapBedVsQueue.size() ); |
| | | monitorInfoVO.setActiveQueueNum( priorityQueue.size() ); |
| | | return monitorInfoVO; |
| | | } |
| | | |
| | | /** |
| | | * 已关闭 或者 关闭中,可以开通工位 |
| | | * @param roomId |
| | | * @param bedNo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public ErrorCode bedOpen(Long roomId, String roomName, String bedNo) { |
| | | BedQueueBO bedQueueBO2 = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null != bedQueueBO2) { |
| | | log.error("bedOpen mapBedVsQueue has existed. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_EXIST; |
| | | } |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.CLOSED); |
| | | Integer updateNum = roomMapper.setBedOpeningOpening(roomId, bedNo, BedStatusEnum.OPENING, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedOpen DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | List<Byte> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.READY.getStatus()); |
| | | List<QueueDO> queueDOList = queueMapper.getDoctorQueueByStatus(roomId, bedNo, queueStatusList); |
| | | |
| | | // 新增工位 优先队列 |
| | | BedQueueBO bedQueueBO = new BedQueueBO(); |
| | | bedQueueBO.setRoomId(roomId); |
| | | bedQueueBO.setRoomName(roomName); |
| | | bedQueueBO.setBedNo(bedNo); |
| | | bedQueueBO.setMaxQueueNum(queueReadyMax); |
| | | bedQueueBO.setQueueNum(new AtomicInteger(queueDOList.size())); |
| | | bedQueueBO.setStatus(BedStatusEnum.OPENING.getStatus()); |
| | | priorityQueue.offer(bedQueueBO); |
| | | mapBedVsQueue.put(String.format("%09d%s", roomId, bedNo), bedQueueBO); |
| | | |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | @Override |
| | | public ErrorCode bedClose(Long roomId, String bedNo) { |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null == bedQueueBO) { |
| | | log.error("bedClose mapBedVsQueue DONOT existed. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_NOT_EXIST; |
| | | } |
| | | |
| | | // 除了判断 准备候诊中 的人数,还需要 判断 过号的人数 |
| | | //if (bedQueueBO.getQueueNum().get() >0) |
| | | // return QUEUE_HAVE_PATIENT; |
| | | List<Byte> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.READY.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.PASSED.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.RECALLED.getStatus()); |
| | | List<QueueDO> queueDOList = queueMapper.getDoctorQueueByStatus(roomId, bedNo, queueStatusList); |
| | | if (queueDOList.size() > 0) |
| | | return QUEUE_HAVE_PATIENT; |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.OPENING); |
| | | statusList.add(BedStatusEnum.DOCTOR_ON); |
| | | statusList.add(BedStatusEnum.PAUSE); |
| | | Integer updateNum = roomMapper.setBedOpeningClosed(roomId, bedNo, |
| | | BedStatusEnum.CLOSED, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedClose DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | mapBedVsQueue.remove(String.format("%09d%s", roomId, bedNo)); |
| | | priorityQueue.remove(bedQueueBO); |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | return queueServiceTxFunctions.getMonitorInfo(); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<RoomRespVO> getRoom(Long roomId, String bedNo, Long docId) { |
| | | RoomDO roomDO = roomMapper.getRoom(roomId, bedNo, docId); |
| | | RoomDO roomDO = roomMapper.getRoomByRoomBedDoc(roomId, bedNo, docId); |
| | | if (null == roomDO) { |
| | | return error(ROOM_NOT_SIT); |
| | | } |
| | | |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | BedQueueBO bedQueueBO = queueServiceTxFunctions.getBedQueueBO(roomId, bedNo); |
| | | if (null == bedQueueBO) { |
| | | log.error("getRoom mapBedVsQueue DONOT existed. " + roomId + " " + bedNo); |
| | | return error(QUEUE_BED_NOT_EXIST); |
| | |
| | | |
| | | RoomRespVO roomRespVO = BeanUtils.toBean(roomDO, RoomRespVO.class); |
| | | return success(roomRespVO); |
| | | } |
| | | |
| | | @Override |
| | | public ErrorCode bedDoctorPause(Long roomId, String bedNo, Long docId, String docName) { |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null == bedQueueBO) { |
| | | log.error("bedDoctorPause mapBedVsQueue DONOT existed. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_NOT_EXIST; |
| | | } |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.DOCTOR_ON); |
| | | Integer updateNum = roomMapper.setBedDoctorStatus(roomId, bedNo, docId, BedStatusEnum.PAUSE, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedDoctorPause DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | bedQueueBO.setStatus(BedStatusEnum.PAUSE.getStatus()); |
| | | priorityQueue.remove(bedQueueBO); |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | @Override |
| | | public ErrorCode bedDoctorResume(Long roomId, String bedNo, Long docId, String docName) { |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null == bedQueueBO || !bedQueueBO.getStatus().equals(BedStatusEnum.PAUSE.getStatus())) { |
| | | log.error("bedDoctorResume mapBedVsQueue DONOT existed OR NOT Paused. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_NOT_EXIST; |
| | | } |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.PAUSE); |
| | | Integer updateNum = roomMapper.setBedDoctorStatus(roomId, bedNo, docId, |
| | | BedStatusEnum.DOCTOR_ON, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedDoctorResume DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | bedQueueBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus()); |
| | | if (!priorityQueue.contains(bedQueueBO)) { |
| | | priorityQueue.offer(bedQueueBO); |
| | | } else { |
| | | log.error("bedDoctorResume priorityQueue still exist!. " + roomId + " " + bedNo); |
| | | return ECG_INNER_ERROR; |
| | | } |
| | | |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | @Override |
| | | public ErrorCode bedDoctorOn(Long roomId, String bedNo, Long docId, String docName) { |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null == bedQueueBO) { |
| | | log.error("bedDoctorOn mapBedVsQueue DONOT existed. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_NOT_EXIST; |
| | | } |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.OPENING); |
| | | Integer updateNum = roomMapper.setBedDoctorOn(roomId, bedNo, docId, docName, BedStatusEnum.DOCTOR_ON, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedDoctorOn DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | bedQueueBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus()); |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | @Override |
| | | public ErrorCode bedDoctorOff(Long roomId, String bedNo, Long docId, String docName) { |
| | | BedQueueBO bedQueueBO = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | if (null == bedQueueBO) { |
| | | log.error("bedDoctorOff mapBedVsQueue DONOT existed. " + roomId + " " + bedNo); |
| | | return QUEUE_BED_NOT_EXIST; |
| | | } |
| | | |
| | | // DB update |
| | | List statusList = new ArrayList<BedStatusEnum>(); |
| | | statusList.add(BedStatusEnum.DOCTOR_ON); |
| | | statusList.add(BedStatusEnum.PAUSE); |
| | | Integer updateNum = roomMapper.setBedDoctorOff(roomId, bedNo, docId, BedStatusEnum.OPENING, statusList); |
| | | if ( null==updateNum || 0 == updateNum ) { |
| | | log.error("bedDoctorOff DB invalid status. " + roomId + " " + bedNo); |
| | | return ROOM_INVALID_STATUS; |
| | | } |
| | | |
| | | // 如果是在 PAUSE 状态离座的,需要重新加回 优先队列 |
| | | if (bedQueueBO.getStatus().equals(BedStatusEnum.PAUSE.getStatus())) { |
| | | if (!priorityQueue.contains(bedQueueBO)) { |
| | | priorityQueue.offer(bedQueueBO); |
| | | } else { |
| | | log.error("bedDoctorResume priorityQueue still exist!. " + roomId + " " + bedNo); |
| | | return ECG_INNER_ERROR; |
| | | } |
| | | } |
| | | |
| | | bedQueueBO.setStatus(BedStatusEnum.OPENING.getStatus()); |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | private void validatequeueExists(Integer id) { |
| | |
| | | return queueMapper.selectPage(pageReqVO); |
| | | } |
| | | |
| | | /** |
| | | * !!开诊期间,不能执行这个方法,否则会有 P0 问题 |
| | | * 1. 每天开诊前 从DB同步工位的患者队列数据到 工位优先队列 |
| | | * 2. 服务运维重启时 |
| | | */ |
| | | @Override |
| | | public ErrorCode bedReload() { |
| | | priorityQueue.clear(); |
| | | mapBedVsQueue.clear(); |
| | | |
| | | // 清除非当天的排队人员 |
| | | queueMapper.clearQueue(); |
| | | // 清除非当天的语音叫号记录 |
| | | callMapper.clearCall(); |
| | | |
| | | // 从DB 获取 工位列表 |
| | | List<BedStatusEnum> bedStatusEnumList = new ArrayList<BedStatusEnum>(); |
| | | bedStatusEnumList.add(BedStatusEnum.OPENING); |
| | | bedStatusEnumList.add(BedStatusEnum.DOCTOR_ON); |
| | | bedStatusEnumList.add(BedStatusEnum.PAUSE); |
| | | List<RoomDO> roomDOList = roomMapper.simpleRoomList(bedStatusEnumList); |
| | | List<BedQueueBO> bedQueueBOList = roomDOList.stream().map(item -> BeanUtils.toBean(item, BedQueueBO.class)).toList(); |
| | | |
| | | // 从DB 获取 队列中 就诊准备中人员统计 列表 |
| | | List<Byte> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.READY.getStatus()); |
| | | List<QueueStatisticDO> queueStatisticDOList = queueMapper.queueStatistic(queueStatusList); |
| | | |
| | | bedQueueBOList.forEach(item -> { |
| | | item.maxQueueNum = queueReadyMax; |
| | | Optional<QueueStatisticDO> queueStatisticDOOptional = queueStatisticDOList.stream().filter(it->it.getRoomId()==item.roomId && it.getBedNo().equals(item.getBedNo())).findFirst(); |
| | | int queueNum = queueStatisticDOOptional.isPresent() ? queueStatisticDOOptional.get().getTotalInStatus() : 0; |
| | | if ( queueReadyMax < queueNum ) |
| | | throw new RuntimeException("init: exceed max queue number!"); |
| | | |
| | | item.queueNum.set( queueNum ); |
| | | mapBedVsQueue.put(String.format("%09d%s", item.roomId, item.bedNo), item); |
| | | if (BedStatusEnum.PAUSE.getStatus() != item.getStatus()) { |
| | | priorityQueue.offer(item); |
| | | } |
| | | }); |
| | | |
| | | Integer num = queueMapper.getMaxSeqNum(); |
| | | curSeqNum = new AtomicInteger(null == num ? 0 : num); |
| | | |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | public void hurryup() { |
| | | if (0 == openingFlag.get()) |
| | | return; |
| | | |
| | | // 处理 过号-回来 的人 |
| | | for (BedQueueBO bedQueueBO : mapBedVsQueue.values()) { |
| | | while (bedQueueBO.queueNum.get() < bedQueueBO.maxQueueNum) { |
| | | // 查看 当前工位 是否有过号-回来的患者 |
| | | Integer updateNum = queueMapper.queueRecalledPatient( |
| | | bedQueueBO.getRoomId(), |
| | | bedQueueBO.getRoomName(), |
| | | bedQueueBO.getBedNo(), |
| | | curSeqNum.get() + 1, |
| | | QueueStatusEnum.RECALLED.getStatus(), |
| | | QueueStatusEnum.READY.getStatus()); |
| | | if (null == updateNum || 0 == updateNum) |
| | | break; |
| | | |
| | | curSeqNum.getAndIncrement(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了值 |
| | | bedQueueBO.queueNum.incrementAndGet(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了优先队列顺序 |
| | | priorityQueue.remove(bedQueueBO); |
| | | priorityQueue.offer(bedQueueBO); |
| | | } |
| | | } |
| | | |
| | | // 处理 排队中 患者 |
| | | while (true) { |
| | | BedQueueBO bedQueueBO = priorityQueue.peek(); |
| | | if (null == bedQueueBO) |
| | | return; |
| | | |
| | | int curQueueNum = bedQueueBO.queueNum.get(); |
| | | if (curQueueNum > bedQueueBO.maxQueueNum) |
| | | throw new RuntimeException("hurryup: exceed max queue number!"); |
| | | |
| | | if (curQueueNum == bedQueueBO.maxQueueNum) |
| | | return; |
| | | |
| | | // 查看 是否有排队中的患者 |
| | | Integer updateNum = queueMapper.preemptPatient( |
| | | bedQueueBO.getRoomId(), |
| | | bedQueueBO.getRoomName(), |
| | | bedQueueBO.getBedNo(), |
| | | curSeqNum.get() + 1, |
| | | QueueStatusEnum.WAITING.getStatus(), |
| | | QueueStatusEnum.READY.getStatus()); |
| | | |
| | | // 没有抢到排队患者 |
| | | if (null == updateNum || 0 == updateNum) { |
| | | return; |
| | | } |
| | | |
| | | curSeqNum.getAndIncrement(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了值 |
| | | bedQueueBO.queueNum.incrementAndGet(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了优先队列顺序 |
| | | priorityQueue.remove(bedQueueBO); |
| | | priorityQueue.offer(bedQueueBO); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 预约确认后的排队 |
| | |
| | | |
| | | DevRentDO devRent = BeanUtils.toBean(queueSaveReqVO, DevRentDO.class); |
| | | devRent.setState( DevRentStateEnum.FREE.getState() ); |
| | | devRent.setPatDetails( queueSaveReqVO.getPatDetails() ); |
| | | devRentMapper.insert(devRent); |
| | | |
| | | startHurryUp(); |
| | | startHurryUpOneCheckType( queue.getBookCheckType() ); |
| | | } |
| | | |
| | | // 常规检查 叫号 |
| | | @Override |
| | | public ErrorCode nextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 序号最小的 就诊准备中的人 设置为就诊中 |
| | | Integer updateNum = queueMapper.updateQueueStatus(roomId, bedNo, |
| | | QueueStatusEnum.READY.getStatus(), QueueStatusEnum.ONSTAGE.getStatus()); |
| | | // 该工位 没有 就诊准备中 人员 |
| | | if (null == updateNum || 0 == updateNum) { |
| | | return QUEUE_NOT_READY_PATIENT; |
| | | } |
| | | |
| | | // 优先队列中 该工位 就诊准备中人的数量 减一 |
| | | BedQueueBO bo = mapBedVsQueue.get(String.format("%09d%s", roomId, bedNo)); |
| | | bo.queueNum.getAndDecrement(); // 可能已经【并发的】在 hurry-up 中改变了值 |
| | | priorityQueue.remove(bo); |
| | | priorityQueue.offer(bo); |
| | | |
| | | return GlobalErrorCodeConstants.SUCCESS; |
| | | } |
| | | |
| | | public void finishNextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 就诊中的人 设置为就诊完成 |
| | | Integer ret = queueMapper.updateQueueStatus(roomId, bedNo, |
| | | QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.FINISH.getStatus()); |
| | | //Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, |
| | | // QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.FINISH.getStatus()); |
| | | |
| | | // 从 DB 检查 该工位 是否有 [就诊中] 人员,若有就.放弃取下一位 |
| | | List<Integer> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.ONSTAGE.getStatus()); |
| | | Integer num = queueMapper.bedQueueStatisticByStatus(roomId, bedNo, queueStatusList); |
| | | if ( num != null && num > 0) |
| | | return; |
| | | |
| | | startNextPatient(roomId, bedNo); |
| | | } |
| | | |
| | | // 领用 叫号 |
| | | @Override |
| | | public void finishReceiveNextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 [就诊中] 的人 设置为 【已领用】 |
| | | //Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, |
| | | // QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.RECEIVED.getStatus()); |
| | | |
| | | // 从 DB 检查 该工位 是否有 [就诊中] 人员,若有就.放弃取下一位 |
| | | List<Integer> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.ONSTAGE.getStatus()); |
| | | Integer num = queueMapper.bedQueueStatisticByStatus(roomId, bedNo, queueStatusList); |
| | | if ( num != null && num > 0) |
| | | return; |
| | | |
| | | startNextPatient(roomId, bedNo); |
| | | } |
| | | |
| | | // 装机 叫号 |
| | | @Override |
| | | public void finishInstallNextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 [安装中] 的人 设置为 [已就诊] |
| | | //Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, |
| | | // QueueStatusEnum.INSTALLING.getStatus(), QueueStatusEnum.FINISH.getStatus()); |
| | | |
| | | // 从 DB 检查 该工位 是否有 [就诊中] 人员,若有就.放弃取下一位 |
| | | List<Integer> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.INSTALLING.getStatus()); |
| | | Integer num = queueMapper.bedQueueStatisticByStatus(roomId, bedNo, queueStatusList); |
| | | if ( num != null && num > 0) |
| | | return; |
| | | |
| | | startNextInstallPatient(roomId, bedNo); |
| | | } |
| | | |
| | | public void passNextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 就诊中的人 设置为过号 |
| | | Integer ret = queueMapper.updateQueueStatus(roomId, bedNo, |
| | | Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, |
| | | QueueStatusEnum.ONSTAGE.getStatus(), QueueStatusEnum.PASSED.getStatus()); |
| | | |
| | | startNextPatient(roomId, bedNo); |
| | | } |
| | | |
| | | public List<QueueDO> getDoctorQueueByStatus(Long roomId, String bedNo, List<Byte> statusList) { |
| | | List<QueueDO> queueDOList = queueMapper.getDoctorQueueByStatus(roomId, bedNo, statusList); |
| | | @Override |
| | | public void passInstallNextPatient(Long roomId, String bedNo) { |
| | | // 从 DB 把 [安装中]的人 设置为 [过号-安装] |
| | | Integer ret = queueMapper.updateBedQueueStatus(roomId, bedNo, |
| | | QueueStatusEnum.INSTALLING.getStatus(), QueueStatusEnum.PASSED_INSTALL.getStatus()); |
| | | |
| | | startNextPatient(roomId, bedNo); |
| | | } |
| | | |
| | | public List<QueueDO> getBedQueueByStatus(Long roomId, String bedNo, List<Integer> statusList) { |
| | | List<QueueDO> queueDOList = queueMapper.getBedQueueByStatus(roomId, bedNo, statusList); |
| | | return queueDOList; |
| | | } |
| | | |
| | | @Override |
| | | public List<QueueDO> getRoomQueueByStatus(Long roomId, List<Integer> statusList) { |
| | | List<QueueDO> queueDOList = queueMapper.getRoomQueueByStatus(roomId, statusList); |
| | | return queueDOList; |
| | | } |
| | | |
| | | // 常规检查 医生界面的统计信息 |
| | | public PatientStatisticVO getPatientStatistic(Long roomId, String bedNo) { |
| | | PatientStatisticVO patientStatisticVO = new PatientStatisticVO(); |
| | | List<BedQueueStatisticDO> bedQueueStatisticDOList = queueMapper.bedQueueStatistic(roomId, bedNo); |
| | |
| | | } |
| | | }); |
| | | |
| | | List<Byte> statusList = new ArrayList<>(); |
| | | // 统计 该工位类型的【排队中】人员数量 |
| | | RoomDO roomDO = getRoomDO(roomId, bedNo); |
| | | Integer[] checkTypes = roomDO.getCheckTypes(); |
| | | List<Integer> statusList = new ArrayList<>(); |
| | | statusList.add(QueueStatusEnum.WAITING.getStatus()); |
| | | Integer num = queueMapper.statusStatistic(statusList); |
| | | Integer num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList); |
| | | patientStatisticVO.setQueuingNum(num); |
| | | |
| | | return patientStatisticVO; |
| | | } |
| | | |
| | | @Override |
| | | public void setQueueReadyMax(Integer max) { |
| | | queueReadyMax = max; |
| | | public PatientStatisticVO getBedDevInstallStatistic(Long roomId, String bedNo) { |
| | | PatientStatisticVO patientStatisticVO = new PatientStatisticVO(); |
| | | List<BedQueueStatisticDO> bedQueueStatisticDOList = queueMapper.bedQueueStatistic(roomId, bedNo); |
| | | bedQueueStatisticDOList.forEach(item -> { |
| | | // } else if (QueueStatusEnum.INSTALLING.getStatus() == item.getStatus()) { |
| | | // patientStatisticVO.setReceivedNum( patientStatisticVO.getReceivedNum() + item.getTotalInStatus() ); |
| | | if (QueueStatusEnum.FINISH.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setFinishedNum(item.getTotalInStatus()); |
| | | } |
| | | }); |
| | | |
| | | // 装机界面:统计 该诊室 [已领用] 的数量, 因为安装工位看不到 [已领用] 患者,所以无法根据装机工位来统计,只能按诊室统计 |
| | | patientStatisticVO.setReceivedNum( 0 ); |
| | | List<BedQueueStatisticDO> roomQueueStatisticDOList = queueMapper.roomQueueStatistic(roomId); |
| | | roomQueueStatisticDOList.forEach(item -> { |
| | | if (QueueStatusEnum.RECEIVED.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setReceivedNum( patientStatisticVO.getReceivedNum() + item.getTotalInStatus() ); |
| | | } |
| | | }); |
| | | |
| | | return patientStatisticVO; |
| | | } |
| | | |
| | | public PatientStatisticVO getBedDevReadyStatistic(Long roomId, String bedNo) { |
| | | PatientStatisticVO patientStatisticVO = new PatientStatisticVO(); |
| | | List<BedQueueStatisticDO> bedQueueStatisticDOList = queueMapper.bedQueueStatistic(roomId, bedNo); |
| | | bedQueueStatisticDOList.forEach(item -> { |
| | | if (QueueStatusEnum.READY.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setReadyNum(item.getTotalInStatus()); |
| | | } else if (QueueStatusEnum.PASSED.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setPassedNum(item.getTotalInStatus()); |
| | | } |
| | | }); |
| | | |
| | | // 领用界面:统计 该诊室 [已领用] 的数量, 因为安装时患者归属工位从领用工位变更到安装工位,所以无法根据领用工位来统计,只能按诊室统计 |
| | | patientStatisticVO.setReceivedNum( 0 ); |
| | | List<BedQueueStatisticDO> roomQueueStatisticDOList = queueMapper.roomQueueStatistic(roomId); |
| | | roomQueueStatisticDOList.forEach(item -> { |
| | | if (QueueStatusEnum.RECEIVED.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setReceivedNum( patientStatisticVO.getReceivedNum() + item.getTotalInStatus() ); |
| | | } else if (QueueStatusEnum.INSTALLING.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setReceivedNum( patientStatisticVO.getReceivedNum() + item.getTotalInStatus() ); |
| | | } else if (QueueStatusEnum.FINISH.getStatus() == item.getStatus()) { |
| | | patientStatisticVO.setReceivedNum(patientStatisticVO.getReceivedNum() + item.getTotalInStatus() ); |
| | | } |
| | | }); |
| | | |
| | | // 统计 该工位类型的【排队中】人员数量 |
| | | RoomDO roomDO = getRoomDO(roomId, bedNo); |
| | | Integer[] checkTypes = roomDO.getCheckTypes(); |
| | | List<Integer> statusList = new ArrayList<>(); |
| | | statusList.add(QueueStatusEnum.WAITING.getStatus()); |
| | | Integer num = queueMapper.checkTypeAndStatusStatistic(checkTypes, statusList); |
| | | patientStatisticVO.setQueuingNum(num); |
| | | |
| | | return patientStatisticVO; |
| | | } |
| | | |
| | | public void initCheckType() { |
| | | queueServiceTxFunctions.initCheckType( ); |
| | | } |
| | | |
| | | public void startBiz() { |
| | | if (1 == openingFlag.get()) |
| | | if (1 == queueServiceTxFunctions.getOpeningFlag()) |
| | | return; |
| | | |
| | | openingFlag.set(1); |
| | | queueServiceTxFunctions.setOpeningFlag(1); |
| | | startBedReload(); |
| | | } |
| | | |
| | | public void closeBiz() { |
| | | openingFlag.set(0); |
| | | queueServiceTxFunctions.setOpeningFlag(0); |
| | | startBedReload(); |
| | | } |
| | | |
| | |
| | | public Integer recallPatient(Long roomId, String bedNo, String patId) { |
| | | Integer updateNum = queueMapper.recallPassedPatient(roomId, bedNo, patId, |
| | | QueueStatusEnum.PASSED.getStatus(), QueueStatusEnum.RECALLED.getStatus()); |
| | | startHurryUp(); |
| | | startHurryUpOneBed(roomId, bedNo); |
| | | return updateNum; |
| | | } |
| | | |
| | | @Override |
| | | public Integer recallInstallPatient(Long roomId, String bedNo, String patId) { |
| | | Integer updateNum = queueMapper.recallPassedInstallPatient(roomId, bedNo, patId, |
| | | QueueStatusEnum.PASSED_INSTALL.getStatus(), QueueStatusEnum.RECALLED_INSTALL.getStatus()); |
| | | // 安装工位 不设计 优先队列 |
| | | //startHurryUpOneBed(roomId, bedNo); |
| | | return updateNum; |
| | | } |
| | | |
| | | @Override |
| | | public Integer patientJump(String patId, Byte jumped) { |
| | | Integer updateNum = queueMapper.queueJump(patId, QueueStatusEnum.WAITING.getStatus(), jumped); |
| | | startHurryUp(); |
| | | |
| | | QueueDO queueDO = queueMapper.getQueueByPatId(patId); |
| | | startHurryUpOneCheckType(Integer.valueOf(queueDO.getBookCheckType())); |
| | | return updateNum; |
| | | } |
| | | |
| | | @Override |
| | | public void monitorInfo() { |
| | | log.info("map " + mapBedVsQueue.size() + " priority " + priorityQueue.size() |
| | | + " opening " + openingFlag.get()); |
| | | public RoomDO getDocRoomInfo(Long docId) { |
| | | return roomMapper.getRoomByDocId(docId); |
| | | } |
| | | |
| | | /** |
| | | * 获取 指定工位 待检查|待领用的人 |
| | | * @param roomId |
| | | * @param bedNo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<QueueDO> getToBeCheckedPatient(Long roomId, String bedNo) { |
| | | List<Integer> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.RECALLED.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.READY.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.ONSTAGE.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.PASSED.getStatus()); |
| | | List<QueueDO> queueDOList = getBedQueueByStatus(roomId, bedNo, queueStatusList); |
| | | return queueDOList; |
| | | } |
| | | |
| | | @Override |
| | | public List<QueueDO> getToBeInstalledPatient(Long roomId, String bedNo) { |
| | | List<Integer> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.RECEIVED.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.PASSED_INSTALL.getStatus()); |
| | | List<QueueDO> queueDOList = getRoomQueueByStatus(roomId, queueStatusList); |
| | | |
| | | queueStatusList.clear(); |
| | | queueStatusList.add(QueueStatusEnum.INSTALLING.getStatus()); |
| | | queueStatusList.add(QueueStatusEnum.RECALLED_INSTALL.getStatus()); |
| | | queueDOList.addAll(0, getBedQueueByStatus(roomId, bedNo, queueStatusList) ); |
| | | return queueDOList; |
| | | } |
| | | |
| | | private RoomDO getRoomDO(Long roomId, String bedNo) { |
| | | RoomDO roomDO = mapRoomBed.get( Utils.formatRoomBed(roomId, bedNo) ); |
| | | if ( null == roomDO) |
| | | roomDO = roomMapper.getRoom(roomId, bedNo); |
| | | |
| | | return roomDO; |
| | | } |
| | | |
| | | } |