# WalkRoomApproveLogServiceImpl.java

    package cloud.wconnect.frontoffice.service.walkroomrequest.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.frontoffice.cons.ApproveStatusEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomApproveTypeEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomErrorI18nConstant;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.WalkRoomApproveConfig;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.WalkRoomApproveLevel;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.WalkRoomApproveLog;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.WalkRoomDateinOther;
    import cloud.wconnect.frontoffice.mapper.walkroomrequest.WalkRoomApproveLogMapper;
    import cloud.wconnect.frontoffice.pojo.dto.walkroomrequest.WalkRoomApproveLevelDTO;
    import cloud.wconnect.frontoffice.pojo.vo.walkroomrequest.WalkRoomApproveLevelVO;
    import cloud.wconnect.frontoffice.pojo.vo.walkroomrequest.WalkRoomApproveUserVO;
    import cloud.wconnect.frontoffice.service.walkroomrequest.IWalkRoomApproveConfigService;
    import cloud.wconnect.frontoffice.service.walkroomrequest.IWalkRoomApproveLevelService;
    import cloud.wconnect.frontoffice.service.walkroomrequest.IWalkRoomApproveLogService;
    import cloud.wconnect.frontoffice.service.walkroomrequest.IWalkRoomDateinOtherService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;

    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    import static java.util.stream.Collectors.groupingBy;
    import static java.util.stream.Collectors.toList;

    /**
     * <p>
     * walk room审批日志表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-07-08
     */
    @Service
    @DS("logbook")
    public class WalkRoomApproveLogServiceImpl extends ServiceImpl<WalkRoomApproveLogMapper, WalkRoomApproveLog> implements IWalkRoomApproveLogService {

        @Autowired
        @Lazy
        private IWalkRoomApproveLevelService approveLevelService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        @Lazy
        private IWalkRoomDateinOtherService walkRoomDateinOtherService;
        @Autowired
        private IWalkRoomApproveConfigService approveConfigService;

        /**
         * 查询入住明细的审批日志
         *
         * @param dateinOtherIds       入住明细id
         * @param walkRoomApproveLevel 审批级别数据
         * @return java.util.Map<java.lang.Long, java.util.List < cloud.wconnect.frontoffice.entity.walkroom.WalkRoomApproveLog>>
         * @author lichen
         * @date 2023/7/11
         */
        @Override
        public Map<Long, List<WalkRoomApproveLog>> listDateinOtherApproveLog(List<Long> dateinOtherIds, WalkRoomApproveLevel walkRoomApproveLevel) {
            //查询待审核数据 在当前节点下对应的审核日志信息
            LambdaQueryWrapper<WalkRoomApproveLog> approveLogQueryWrapper = new LambdaQueryWrapper<>();
            approveLogQueryWrapper.eq(WalkRoomApproveLog::getPropertyId, walkRoomApproveLevel.getPropertyId());
            approveLogQueryWrapper.in(WalkRoomApproveLog::getDateinOtherId, dateinOtherIds);
            approveLogQueryWrapper.eq(WalkRoomApproveLog::getLevelId, walkRoomApproveLevel.getId());
            approveLogQueryWrapper.eq(WalkRoomApproveLog::getIsApproved, true);
            List<WalkRoomApproveLog> approveLogList = list(approveLogQueryWrapper);
            //数据为空时，直接return
            if (CollectionUtils.isEmpty(approveLogList)) return Collections.emptyMap();
            //key = 业务数据id ; value = 审批日志集合
            return approveLogList.stream().collect(groupingBy(WalkRoomApproveLog::getDateinOtherId));
        }

        /**
         * 查询入住明细在某个审批级别上的审批日志
         *
         * @param walkRoomDateinOther 入住明细数据
         * @param approveType         审批类型1:Sent 2:Receive
         * @return java.util.List<cloud.wconnect.frontoffice.entity.walkroom.WalkRoomApproveLog>
         * @author lichen
         * @date 2023/7/11
         */
        @Override
        public List<WalkRoomApproveLog> listApproveIndexLogByDateinOther(WalkRoomDateinOther walkRoomDateinOther, Integer approveType) {
            //查询待审核数据 在当前节点下对应的审核日志信息
            LambdaQueryWrapper<WalkRoomApproveLog> approveLogQueryWrapper = new LambdaQueryWrapper<>();
            if (approveType.equals(WalkRoomApproveTypeEnum.SENT.getCode())) {
                approveLogQueryWrapper.eq(WalkRoomApproveLog::getPropertyId, walkRoomDateinOther.getFromPropertyId());
                approveLogQueryWrapper.eq(WalkRoomApproveLog::getApproveIndex, walkRoomDateinOther.getSentApproveIndex());
            } else {
                approveLogQueryWrapper.eq(WalkRoomApproveLog::getPropertyId, walkRoomDateinOther.getToPropertyId());
                approveLogQueryWrapper.eq(WalkRoomApproveLog::getApproveIndex, walkRoomDateinOther.getReceiveApproveIndex());
            }
            approveLogQueryWrapper.eq(WalkRoomApproveLog::getDateinOtherId, walkRoomDateinOther.getId());
            List<WalkRoomApproveLog> approveLogList = list(approveLogQueryWrapper);
            //数据为空时，直接return
            if (CollectionUtils.isEmpty(approveLogList)) return Collections.emptyList();
            return approveLogList;
        }

        /**
         * 校验在入住期间资产是否没有 审批通过 的日志
         *
         * @param id          walk room主键id
         * @param levelList   审批层级集合
         * @param propertyId  资产id
         * @param approveType 审批类型
         * @return void
         * @author lichen
         * @date 2023/7/21
         */
        @Override
        public void checkIsWithOutApprovedLog(Long id, List<WalkRoomApproveLevel> levelList, Integer propertyId, Integer approveType) {
            //查询入住记录id集合
            List<WalkRoomDateinOther> walkRoomDateinOthers = walkRoomDateinOtherService.listByReqIds(Arrays.asList(id));
            if (CollectionUtils.isEmpty(walkRoomDateinOthers)) return;

            //审批级别为空时，无需校验
            if (CollectionUtils.isEmpty(levelList)) return;

            //审批级别id集合
            List<Long> levelIds = levelList.stream().map(WalkRoomApproveLevel::getId).collect(toList());

            //入住记录主键id集合
            List<Long> dateinOtherIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getId).collect(toList());

            //查询入住记录在对应的审批级别上是否有审核通过的日志
            long count = count(new LambdaQueryWrapper<WalkRoomApproveLog>()
                    .eq(WalkRoomApproveLog::getPropertyId, propertyId)
                    .in(WalkRoomApproveLog::getDateinOtherId, dateinOtherIds)
                    .in(WalkRoomApproveLog::getLevelId, levelIds)
                    .eq(WalkRoomApproveLog::getIsApproved, true));
            if (count > 0) {
                if (approveType == WalkRoomApproveTypeEnum.SENT.getCode()) {
                    throw new BadRequestException(WalkRoomErrorI18nConstant.SENDER_ALREADY_APPROVED,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "The data cannot be modified because it has been approved by the sender, walkRoomId=" + id);
                } else {
                    throw new BadRequestException(WalkRoomErrorI18nConstant.RECEIVER_ALREADY_APPROVED,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "The data cannot be modified because it has been approved by the receiver, walkRoomId=" + id);
                }
            }
        }

        /**
         * 查询未审批过的入住记录的审批日志
         *
         * @param propertyDTO  资产对象
         * @param approveType 审批类型
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLevelVO>
         * @author lichen
         * @date 2023/8/14
         */
        @Override
        public List<WalkRoomApproveLevelVO> listUnApproveLevelLogs(PropertyDTO propertyDTO, Integer approveType) {
            //查询审批层级和对应的人员信息
            List<WalkRoomApproveLevelDTO> levelList = approveLevelService.list(propertyDTO, approveType);
            if (CollectionUtils.isEmpty(levelList)) return Collections.emptyList();

            List<WalkRoomApproveLevelVO> levelVoList = Lists.newArrayListWithExpectedSize(levelList.size());
            for (WalkRoomApproveLevelDTO approveLevelDTO : levelList) {
                //审批层级
                WalkRoomApproveLevelVO levelVo = beanMapper.map(approveLevelDTO, WalkRoomApproveLevelVO.class);
                //层级审批状态设置为0，未开始审核
                levelVo.setApproveStatus(BaseConstant.ZERO);
                //审批层级上的人员
                List<WalkRoomApproveUserVO> logVoList = beanMapper.mapList(approveLevelDTO.getUsers(), WalkRoomApproveUserVO.class, (user, logVo) -> {
                    //设置用户信息
                    logVo.setUserId(user.getId());
                    logVo.setApproveStatus(BaseConstant.ZERO);
                });
                levelVo.setUsers(logVoList);
                levelVoList.add(levelVo);
            }
            return levelVoList;
        }

        /**
         * 根据入住记录主键id查询审批日志
         *
         * @param otherIds 入住记录主键id
         * @return java.util.List<cloud.wconnect.frontoffice.entity.walkroom.WalkRoomApproveLog>
         * @author lichen
         * @date 2023/8/15
         */
        @Override
        public List<WalkRoomApproveLog> listByDateinOtherIds(List<Long> otherIds) {
            if (CollectionUtils.isEmpty(otherIds)) return Collections.emptyList();
            return list(new LambdaQueryWrapper<WalkRoomApproveLog>().in(WalkRoomApproveLog::getDateinOtherId, otherIds));
        }

        /**
         * 查询入住记录的审批日志树
         *
         * @param walkRoomDateinOthers 入住记录集合
         * @param propertyDTO          资产DTO
         * @param approveType          审批类型（发送方或接收方）
         * @return java.util.Map<java.lang.Long, java.util.List < cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLevelVO>>
         * @author lichen
         * @date 2023/9/22
         */
        @Override
        public Map<Long, List<WalkRoomApproveLevelVO>> listApproveLogTree(List<WalkRoomDateinOther> walkRoomDateinOthers, PropertyDTO propertyDTO, Integer approveType) {
            if (CollectionUtils.isEmpty(walkRoomDateinOthers)) return Collections.emptyMap();
            List<Long> dateinOtherIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getId).toList();

            //根据资产id和审批类型查询审批层级
            List<WalkRoomApproveLevel> levelList = approveLevelService.listByPropertyIdAndType(propertyDTO.getId(), approveType);
            List<Long> levelIds = levelList.stream().map(WalkRoomApproveLevel::getId).collect(toList());
            Map<Long, WalkRoomApproveLevel> levelId2ApproveLevel = levelList.stream().collect(Collectors.toMap(WalkRoomApproveLevel::getId, Function.identity()));

            /**
             * 查询入住记录的审批日志
             * 因为审批时发送方和接收方的资产id不一致，所以根据propertyId可以区分发送方或接收方的审批日志。
             * 一条入住记录作为发送方或接收方只有一批审批日志，因为某天的入住记录每次开始审核时，都会先清空审批日志数据。
             */
            List<WalkRoomApproveLog> approveLogs = listByPropertyIdAndDateinOtherIds(propertyDTO.getId(), dateinOtherIds);
            List<Integer> approveByList = approveLogs.stream().map(WalkRoomApproveLog::getApproveBy).collect(toList());
            Map<Long, List<WalkRoomApproveLog>> dateinOtherId2ApproveLog = approveLogs.stream()
                    .collect(Collectors.groupingBy(WalkRoomApproveLog::getDateinOtherId));

            //查询审批层级人员
            List<WalkRoomApproveConfig> approveConfigs = approveConfigService.listByLevelIds(levelIds);
            List<Integer> configApproveByList = approveConfigs.stream().map(WalkRoomApproveConfig::getUserId).toList();
            Map<Long, List<WalkRoomApproveConfig>> levelId2ApproveConfigs = approveConfigs.stream().collect(groupingBy(WalkRoomApproveConfig::getLevelId));

            //查询用户信息
            List<Integer> userIds = Lists.newArrayList(approveByList);
            userIds.addAll(configApproveByList);
            Map<Integer, UserDTO> userId2UserDto = userInternalService.getUserMapByIds(propertyDTO.getTenantId(), userIds);

            //循环入住记录，生成审批日志树
            HashMap<Long, List<WalkRoomApproveLevelVO>> resultMap = Maps.newHashMapWithExpectedSize(walkRoomDateinOthers.size());
            for (WalkRoomDateinOther walkRoomDateinOther : walkRoomDateinOthers) {
                //根据审批类型获取审批状态
                Integer approveStatus = WalkRoomApproveTypeEnum.SENT.getCode() == approveType ?
                        walkRoomDateinOther.getSentApproveStatus() : walkRoomDateinOther.getReceiveApproveStatus();

                //获取入住记录的审批日志
                List<WalkRoomApproveLog> approveLogsByDateinOtherId = dateinOtherId2ApproveLog.getOrDefault(walkRoomDateinOther.getId(), Collections.emptyList());

                List<WalkRoomApproveLevelVO> approveLevelVOList = Collections.emptyList();
                if (approveStatus == ApproveStatusEnum.APPROVED.getStatus()) {
                    approveLevelVOList = createApprovedLog(approveLogsByDateinOtherId, levelId2ApproveLevel, userId2UserDto);
                } else if (approveStatus == ApproveStatusEnum.REJECTED.getStatus()) {
                    approveLevelVOList = createRejectedLog(approveLogsByDateinOtherId, levelId2ApproveLevel, userId2UserDto);
                } else {
                    //审核中的审批树，walk room request功能比较特殊没有送审操作，所以审批中时审批日志也有可能为空
                    approveLevelVOList = createApprovingLog(walkRoomDateinOther, approveLogsByDateinOtherId, levelList,
                            levelId2ApproveLevel, levelId2ApproveConfigs, userId2UserDto, approveType);
                }
                resultMap.put(walkRoomDateinOther.getId(), approveLevelVOList);
            }
            return resultMap;
        }

        /**
         * 根据资产id和入住记录id集合查询审批日志
         *
         * @param propertyId     资产id
         * @param dateinOtherIds 入住记录id集合
         * @return java.util.List<cloud.wconnect.frontoffice.entity.walkroom.WalkRoomApproveLog>
         * @author lichen
         * @date 2023/9/22
         */
        @Override
        public List<WalkRoomApproveLog> listByPropertyIdAndDateinOtherIds(Integer propertyId, List<Long> dateinOtherIds) {
            if (CollectionUtils.isEmpty(dateinOtherIds)) return Collections.emptyList();
            return list(new LambdaQueryWrapper<WalkRoomApproveLog>()
                    .eq(WalkRoomApproveLog::getPropertyId, propertyId)
                    .in(WalkRoomApproveLog::getDateinOtherId, dateinOtherIds));
        }

        /**
         * 创建审批通过的审批树
         *
         * @param approvedLogs               审批日志集合
         * @param latestLevelId2ApproveLevel 资产配置的最新审批层级集合
         * @param userId2UserDto             用户集合
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLevelVO>
         * @author lichen
         * @date 2023/9/22
         */
        private List<WalkRoomApproveLevelVO> createApprovedLog(List<WalkRoomApproveLog> approvedLogs,
                                                               Map<Long, WalkRoomApproveLevel> latestLevelId2ApproveLevel, Map<Integer, UserDTO> userId2UserDto) {
            /**
             * 审批日志中出现过的所有审批层级集合
             */
            List<WalkRoomApproveLevel> levelList = approvedLogs.stream().map(log -> {
                //获取当前资产配置的最新审批层级
                WalkRoomApproveLevel latestApproveLevel = latestLevelId2ApproveLevel.get(log.getLevelId());
                if (Objects.nonNull(latestApproveLevel)) return latestApproveLevel;
                //审批层级被删除，生成审批层级对象
                return WalkRoomApproveLevel.builder()
                        .id(log.getLevelId())
                        .approveIndex(log.getApproveIndex())
                        .propertyId(log.getPropertyId())
                        .build();
                //去重：审批层级上有多个人时会重复
                //排序：页面需要按照顺序显示审批日志树
            }).distinct().sorted(Comparator.comparing(WalkRoomApproveLevel::getApproveIndex)).collect(toList());

            //审批日志按照审批层级id分组。key=审批层级id value=审批人
            Map<Long, List<WalkRoomApproveLog>> levelId2ApproveLog = approvedLogs.stream().collect(groupingBy(WalkRoomApproveLog::getLevelId));

            return beanMapper.mapList(levelList, WalkRoomApproveLevelVO.class, (entity, vo) -> {
                vo.setApproveStatus(ApproveStatusEnum.APPROVED.getStatus());
                vo.setUsers(convertApproveLogToVO(levelId2ApproveLog.get(entity.getId()), userId2UserDto));
            });
        }

        /**
         * 创建审批拒绝的审批树
         *
         * @param approvedLogs               审批日志集合
         * @param latestLevelId2ApproveLevel 资产配置的最新审批层级集合
         * @param userId2UserDto             用户集合
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLevelVO>
         * @author lichen
         * @date 2023/9/22
         */
        private List<WalkRoomApproveLevelVO> createRejectedLog(List<WalkRoomApproveLog> approvedLogs,
                                                               Map<Long, WalkRoomApproveLevel> latestLevelId2ApproveLevel, Map<Integer, UserDTO> userId2UserDto) {
            /**
             * 审批日志中出现过的所有审批层级集合
             */
            List<WalkRoomApproveLevel> levelList = approvedLogs.stream().map(log -> {
                //获取当前资产配置的最新审批层级
                WalkRoomApproveLevel latestApproveLevel = latestLevelId2ApproveLevel.get(log.getLevelId());
                if (Objects.nonNull(latestApproveLevel)) return latestApproveLevel;
                //审批层级被删除，生成审批层级对象
                return WalkRoomApproveLevel.builder()
                        .id(log.getLevelId())
                        .approveIndex(log.getApproveIndex())
                        .propertyId(log.getPropertyId())
                        .build();
                //去重：审批层级上有多个人时会重复
                //排序：页面需要按照顺序显示审批日志树
            }).distinct().sorted(Comparator.comparing(WalkRoomApproveLevel::getApproveIndex)).collect(toList());

            //审批日志按照审批层级id分组。key=审批层级id value=审批人
            Map<Long, List<WalkRoomApproveLog>> levelId2ApproveLog = approvedLogs.stream().collect(groupingBy(WalkRoomApproveLog::getLevelId));

            /**
             * 查询出审批拒绝的的层级
             */
            Integer rejectedApproveIndex = approvedLogs.stream().filter(log -> !log.getIsApproved()).findFirst().get().getApproveIndex();

            return beanMapper.mapList(levelList, WalkRoomApproveLevelVO.class, (entity, vo) -> {
                if (vo.getApproveIndex().equals(rejectedApproveIndex)) {
                    vo.setApproveStatus(ApproveStatusEnum.REJECTED.getStatus());
                } else {
                    vo.setApproveStatus(ApproveStatusEnum.APPROVED.getStatus());
                }
                vo.setUsers(convertApproveLogToVO(levelId2ApproveLog.get(entity.getId()), userId2UserDto));
            });
        }

        /**
         * 创建审批中的审批树
         *
         * @param walkRoomDateinOther    入住记录
         * @param approveLogs            审批日志集合
         * @param levelList              资产配置的最新审批层级集合
         * @param levelId2ApproveLevel   资产配置的最新审批层级集合
         * @param levelId2ApproveConfigs 审批人集合
         * @param userId2UserDto         用户集合
         * @param approveType            审批类型1：sent 2:receive
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLevelVO>
         * @author lichen
         * @date 2023/9/22
         */
        private List<WalkRoomApproveLevelVO> createApprovingLog(WalkRoomDateinOther walkRoomDateinOther, List<WalkRoomApproveLog> approveLogs,
                                                                List<WalkRoomApproveLevel> levelList, Map<Long, WalkRoomApproveLevel> levelId2ApproveLevel,
                                                                Map<Long, List<WalkRoomApproveConfig>> levelId2ApproveConfigs,
                                                                Map<Integer, UserDTO> userId2UserDto, Integer approveType) {
            List<WalkRoomApproveLevelVO> levelVOList = Lists.newArrayListWithCapacity(levelList.size());

            //根据审批类型获取当前审批索引
            Integer currentApproveIndex = WalkRoomApproveTypeEnum.SENT.getCode() == approveType ?
                    walkRoomDateinOther.getSentApproveIndex() : walkRoomDateinOther.getReceiveApproveIndex();
            //当前审批层级
            Optional<WalkRoomApproveLevel> currentApproveLevelOptional = levelList.stream()
                    .filter(item -> item.getApproveIndex().equals(currentApproveIndex)).findFirst();
            if (currentApproveLevelOptional.isPresent()) {
                WalkRoomApproveLevel currentApproveLevel = currentApproveLevelOptional.get();
                /**
                 * 过滤出小于当前审批索引的审批日志
                 * 这部分审批日志已经审批通过，生成审批通过的树
                 */
                List<WalkRoomApproveLog> approvedLogsByLessThanApproveIndex = approveLogs.stream().filter(log -> log.getApproveIndex() < currentApproveIndex).collect(toList());
                List<WalkRoomApproveLevelVO> approvedLogVOList = createApprovedLog(approvedLogsByLessThanApproveIndex, levelId2ApproveLevel, userId2UserDto);

                /**
                 * 当前审批层级的人包括:审批日志中的人 + 未审批的人
                 */
                List<WalkRoomApproveUserVO> approveingUserVOS = Lists.newArrayList();
                //过滤出等于当前审批索引的审批日志
                List<WalkRoomApproveLog> approveingLogs = approveLogs.stream().filter(log -> log.getApproveIndex().equals(currentApproveIndex)).collect(toList());
                List<Integer> currentApproveLevelalreadyApproveUser = approveingLogs.stream().map(WalkRoomApproveLog::getApproveBy).toList();//已经审批过的人
                approveingUserVOS.addAll(convertApproveLogToVO(approveingLogs, userId2UserDto));
                //当前审批层级未审批的人
                List<WalkRoomApproveConfig> currentApproveLevelUnApprover = levelId2ApproveConfigs.get(currentApproveLevel.getId())
                        .stream().filter(item -> !currentApproveLevelalreadyApproveUser.contains(item.getUserId())).collect(toList());
                approveingUserVOS.addAll(convertApproveConfigToVO(currentApproveLevelUnApprover, userId2UserDto, BaseConstant.ZERO));
                //生成当前审批层级的vo
                WalkRoomApproveLevelVO approveingLogVO = beanMapper.map(currentApproveLevel, WalkRoomApproveLevelVO.class, vo -> {
                    vo.setApproveStatus(ApproveStatusEnum.APPROVEING.getStatus());
                    vo.setUsers(approveingUserVOS);
                });
                levelVOList.addAll(approvedLogVOList);
                levelVOList.add(approveingLogVO);
            }

            /**
             * 未审批的审批层级：大于当前审批索引的审批层级集合
             */
            List<WalkRoomApproveLevel> unApproveLevelList = levelList.stream().filter(item -> item.getApproveIndex() > currentApproveIndex).collect(toList());
            List<WalkRoomApproveLevelVO> unApproveLevelVOList = beanMapper.mapList(unApproveLevelList, WalkRoomApproveLevelVO.class, (entity, vo) -> {
                vo.setApproveStatus(BaseConstant.ZERO);
                //获取审批配置人员
                List<WalkRoomApproveConfig> approveConfigsByLevelId = levelId2ApproveConfigs.get(entity.getId());
                //设置审批配置人员
                vo.setUsers(convertApproveConfigToVO(approveConfigsByLevelId, userId2UserDto, BaseConstant.ZERO));
            });
            levelVOList.addAll(unApproveLevelVOList);
            levelVOList.sort(Comparator.comparing(WalkRoomApproveLevelVO::getApproveIndex));
            return levelVOList;
        }

        /**
         * 把审批日志上的审批人转化成VO
         *
         * @param walkRoomApproveLogs 审批日志
         * @param userId2UserDto      用户集合
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveLogVO>
         * @author lichen
         * @date 2023/9/22
         */
        private List<WalkRoomApproveUserVO> convertApproveLogToVO(List<WalkRoomApproveLog> walkRoomApproveLogs, Map<Integer, UserDTO> userId2UserDto) {
            return walkRoomApproveLogs.stream().map(approveLog -> {
                WalkRoomApproveUserVO approveUserVO = new WalkRoomApproveUserVO();
                approveUserVO.setUserId(approveLog.getApproveBy());
                approveUserVO.setApproveStatus(approveLog.getIsApproved() ? ApproveStatusEnum.APPROVED.getStatus() : ApproveStatusEnum.REJECTED.getStatus());
                approveUserVO.setApproveOpinion(approveLog.getApproveOpinion());
                approveUserVO.setApproveTime(approveLog.getApproveTime());

                UserDTO userDTO = userId2UserDto.get(approveLog.getApproveBy());
                if (Objects.nonNull(userDTO)) {
                    approveUserVO.setName(userDTO.getName());
                    approveUserVO.setAccount(userDTO.getAccount());
                    approveUserVO.setEmail(userDTO.getEmail());
                    approveUserVO.setPhone(userDTO.getPhone());
                }
                return approveUserVO;
            }).collect(toList());
        }

        /**
         * 把审批配置人转化成VO
         *
         * @param approveConfigs 审批配置集合
         * @param userId2UserDto 用户集合
         * @param approveStatus  审批状态
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomApproveUserVO>
         * @author lichen
         * @date 2023/9/22
         */
        private List<WalkRoomApproveUserVO> convertApproveConfigToVO(List<WalkRoomApproveConfig> approveConfigs,
                                                                     Map<Integer, UserDTO> userId2UserDto, int approveStatus) {
            return approveConfigs.stream().map(approveConfig -> {
                WalkRoomApproveUserVO approveUserVO = new WalkRoomApproveUserVO();
                approveUserVO.setUserId(approveConfig.getUserId());
                approveUserVO.setApproveStatus(approveStatus);
                UserDTO userDTO = userId2UserDto.get(approveConfig.getUserId());
                if (Objects.nonNull(userDTO)) {
                    approveUserVO.setName(userDTO.getName());
                    approveUserVO.setAccount(userDTO.getAccount());
                    approveUserVO.setEmail(userDTO.getEmail());
                    approveUserVO.setPhone(userDTO.getPhone());
                }
                return approveUserVO;
            }).collect(toList());
        }

    }