# WalkRoomController.java

    package cloud.wconnect.frontoffice.controller.walkroomrequest;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.CommonFieldI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.jsonview.Views;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.service.RoleInternalService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.frontoffice.cons.ApproveStatusEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomApproveTypeEnum;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomErrorI18nConstant;
    import cloud.wconnect.frontoffice.cons.walkroomrequest.WalkRoomStatusEnum;
    import cloud.wconnect.frontoffice.entity.walkroomrequest.*;
    import cloud.wconnect.frontoffice.pojo.dto.walkroomrequest.*;
    import cloud.wconnect.frontoffice.pojo.query.walkroomrequest.WalkRoomDailySummaryQuery;
    import cloud.wconnect.frontoffice.pojo.query.walkroomrequest.WalkRoomQuery;
    import cloud.wconnect.frontoffice.pojo.vo.walkroomrequest.*;
    import cloud.wconnect.frontoffice.service.walkroomrequest.*;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.fasterxml.jackson.annotation.JsonView;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;

    import jakarta.validation.Valid;
    import java.math.BigDecimal;
    import java.text.MessageFormat;
    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;

    /**
     * <p>
     * Walk Room Requests 功能 前端控制器
     * </p>
     *
     * @author lichen
     * @date 2023/7/12
     */
    @RestController
    @RequestMapping("/walk-room-request")
    public class WalkRoomController {

        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private IWalkRoomRequestService walkRoomRequestService;
        @Autowired
        private IWalkRoomDateinOtherService walkRoomDateinOtherService;
        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IWalkRoomApproveLogService walkRoomApproveLogService;
        @Autowired
        private IWalkRoomDateinRateService walkRoomDateinRateService;
        @Autowired
        private IWalkRoomRequestLogService walkRoomRequestLogService;
        @Autowired
        private RoleInternalService roleInternalService;
        @Autowired
        private IWalkRoomApproveLevelService approveLevelService;
        @Autowired
        private IWalkRoomRateService walkRoomRateService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询walkRoom列表
         *
         * @param property      资产标识
         * @param walkRoomQuery 查询条件
         * @return cloud.wconnect.commonlib.pojo.dto.ListPagedDTO<cloud.wconnect.frontoffice.pojo.view.walkroom.WalkRoomVO>
         * @author lichen
         * @date 2023/7/12
         */
        @ApiId(462)
        @GetMapping
        @JsonView({Views.ListView.class})
        public ListPagedDTO<WalkRoomVO> list(String property, @Valid WalkRoomQuery walkRoomQuery) {
            //日期查询条件
            Integer checkInDateStart = walkRoomQuery.getCheckInDateStart();
            Integer checkInDateEnd = walkRoomQuery.getCheckInDateEnd();
            Integer checkOutDateStart = walkRoomQuery.getCheckOutDateStart();
            Integer checkOutDateEnd = walkRoomQuery.getCheckOutDateEnd();

            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();
            //查询类型
            Integer type = walkRoomQuery.getType();
            //构建查询条件
            LambdaQueryWrapper<WalkRoomRequest> walkRoomRequestQueryWrapper = new LambdaQueryWrapper<>();
            if (type.equals(WalkRoomQuery.TYPE_SENT)) {
                walkRoomRequestQueryWrapper.eq(WalkRoomRequest::getFromPropertyId, propertyId);
                walkRoomRequestQueryWrapper.in(CollectionUtils.isNotEmpty(walkRoomQuery.getReceivePropertyIds()),
                        WalkRoomRequest::getToPropertyId, walkRoomQuery.getReceivePropertyIds());
            } else {
                walkRoomRequestQueryWrapper.eq(WalkRoomRequest::getToPropertyId, propertyId);
            }
            walkRoomRequestQueryWrapper.between(Objects.nonNull(checkInDateStart) && Objects.nonNull(checkInDateEnd), WalkRoomRequest::getCheckInDate, checkInDateStart, checkInDateEnd);
            walkRoomRequestQueryWrapper.between(Objects.nonNull(checkOutDateStart) && Objects.nonNull(checkOutDateEnd), WalkRoomRequest::getCheckOutDate, checkOutDateStart, checkOutDateEnd);
            walkRoomRequestQueryWrapper.and(StringUtils.isNotBlank(walkRoomQuery.getGuestName()), queryWrapper ->
                    queryWrapper.like(WalkRoomRequest::getFirstName, walkRoomQuery.getGuestName())
                            .or()
                            .like(WalkRoomRequest::getLastName, walkRoomQuery.getGuestName()));
            walkRoomRequestQueryWrapper.orderByDesc(WalkRoomRequest::getId);

            //查询walkRoomRequest数据
            Page<WalkRoomRequest> resultPage = walkRoomRequestService.page(new Page<>(walkRoomQuery.getPage(), walkRoomQuery.getSize()),
                    walkRoomRequestQueryWrapper);
            if (resultPage.getTotal() == 0) return new ListPagedDTO<>();

            List<WalkRoomRequest> records = resultPage.getRecords();

            //资产集合
            Set<Integer> propertyIds = records.stream().flatMap(item -> Stream.of(item.getFromPropertyId(), item.getToPropertyId())).collect(Collectors.toSet());
            Map<Integer, String> propertyId2PropertyName = propertyI18nRedisService.list(propertyIds)
                    .stream().collect(Collectors.toMap(PropertyDTO::getId, PropertyDTO::getName));

            //用户集合
            Set<Integer> uids = records.stream().flatMap(item -> Stream.of(item.getLastSentBy(), item.getAgentUserId())).collect(Collectors.toSet());
            Map<Integer, String> userId2UserName = userInternalService.getNameMapByIds(tenantId, uids);

            //查询walk room的final other id 对应的 other 信息
            List<Long> otherIds = records.stream().map(WalkRoomRequest::getFinalOtherId).collect(Collectors.toList());
            Map<Long, WalkRoomDateinOther> finalOtherId2WalkRoomDateinOther = walkRoomDateinOtherService.listByIds(otherIds)
                    .stream().collect(Collectors.toMap(WalkRoomDateinOther::getId, Function.identity()));

            //查询入住记录对应的审批日志
            Map<String, Long> otherIdAndPropertyId2ApproveLogCount = walkRoomApproveLogService.listByDateinOtherIds(otherIds).stream()
                    .collect(Collectors.groupingBy(item -> WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getDateinOtherId(), item.getPropertyId()),
                            Collectors.counting()));

            //List<WalkRoomRequest> -> List<WalkRoomVO
            List<WalkRoomVO> walkRoomVOS = beanMapper.mapList(records, WalkRoomVO.class, (record, vo) -> {
                //设置发送和接受方的资产名称
                vo.setFromPropertyName(propertyId2PropertyName.get(vo.getFromPropertyId()));
                vo.setToPropertyName(propertyId2PropertyName.get(vo.getToPropertyId()));
                //设置邮件发送人
                vo.setLastSentName(userId2UserName.get(vo.getLastSentBy()));
                //设置责任人
                vo.setAgentUserName(userId2UserName.get(vo.getAgentUserId()));

                //设置入住记录
                WalkRoomDateinOther walkRoomDateinOther = finalOtherId2WalkRoomDateinOther.get(record.getFinalOtherId());
                if (Objects.nonNull(walkRoomDateinOther)) {
                    vo.setSentApproveIndex(walkRoomDateinOther.getSentApproveIndex());
                    vo.setSentApproveStatus(walkRoomDateinOther.getSentApproveStatus());
                    vo.setReceiveApproveIndex(walkRoomDateinOther.getReceiveApproveIndex());
                    vo.setReceiveApproveStatus(walkRoomDateinOther.getReceiveApproveStatus());
                    //设置发送方是否开始审批
                    if (walkRoomDateinOther.getSentApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                        String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(walkRoomDateinOther.getId(), vo.getFromPropertyId());
                        Long approveLogCount = otherIdAndPropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                        if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                            vo.setSentIsStartApprove(false);
                        } else {
                            vo.setSentIsStartApprove(true);
                        }
                    }
                    //设置接受方是否开始审批
                    if (walkRoomDateinOther.getReceiveApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                        String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(walkRoomDateinOther.getId(), vo.getToPropertyId());
                        Long approveLogCount = otherIdAndPropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                        if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                            vo.setReceiveIsStartApprove(false);
                        } else {
                            vo.setReceiveIsStartApprove(true);
                        }
                    }
                    //设置入住日
                    vo.setApproveDate(walkRoomDateinOther.getDate());
                    //设置CRS.NO
                    vo.setCrsNumber(walkRoomDateinOther.getCrsNumber());
                    //设置入住记录的comment
                    vo.setDateinComment(walkRoomDateinOther.getComment());
                    //设置入住记录的状态
                    vo.setStatus(walkRoomDateinOther.getStatus());
                }
            });
            return new ListPagedDTO<>(resultPage.getTotal(), walkRoomVOS);
        }

        /**
         * 查询详情
         *
         * @param property 资产标识
         * @param id       walk room主键id
         * @param type     查询类型 1:Sent or 2:Receive
         * @param date     入住日期，格式yyyyMMdd
         * @return cloud.wconnect.frontoffice.pojo.vo.walkroom.WalkRoomVO
         * @author lichen
         * @date 2023/8/15
         */
        @ApiId(463)
        @GetMapping("/{id:\\d+}")
        @JsonView({Views.DetailsView.class})
        public WalkRoomVO detail(String property, @PathVariable Long id, @RequestParam("type") Integer type, @RequestParam(required = false) Integer date) {
            if (!Lists.newArrayList(1, 2).contains(type)) {
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("type", List.of(1, 2)),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The type must be 1:Sent 2: Receive");
            }
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();

            //校验walk room数据是否存在 且 归属于当前资产
            WalkRoomRequest walkRoomRequest = checkIsExistAndAffiliation(id, propertyId, type);

            //查询资产集合
            List<Integer> propertyIds = Arrays.asList(walkRoomRequest.getFromPropertyId(), walkRoomRequest.getToPropertyId());
            Map<Integer, String> propertyId2PropertyName = propertyInternalService.listPropertyName(propertyIds);

            WalkRoomDateinOther walkRoomDateinOther;
            if (Objects.isNull(date)) {
                //查询finalOther对应的入住记录信息
                walkRoomDateinOther = walkRoomDateinOtherService.getById(walkRoomRequest.getFinalOtherId());
            } else {
                //查询入住日对应的入住记录信息
                walkRoomDateinOther = walkRoomDateinOtherService.getByReqIdAndDate(id, date);
            }

            //用户集合
            ArrayList<Integer> userIds = Lists.newArrayList(walkRoomRequest.getLastSentBy(), walkRoomRequest.getAgentUserId());
            if (Objects.nonNull(walkRoomDateinOther)) {
                userIds.add(walkRoomDateinOther.getUpdateBy());
            }
            Map<Integer, String> userId2UserName = userInternalService.getNameMapByIds(tenantId, userIds);

            return beanMapper.map(walkRoomRequest, WalkRoomVO.class, vo -> {
                //设置发送方资产名称
                vo.setFromPropertyName(propertyId2PropertyName.get(walkRoomRequest.getFromPropertyId()));
                //设置接收方资产名称
                vo.setToPropertyName(propertyId2PropertyName.get(walkRoomRequest.getToPropertyId()));
                //设置邮件发送人
                vo.setLastSentName(userId2UserName.get(walkRoomRequest.getLastSentBy()));
                //设置责任人姓名
                vo.setAgentUserName(userId2UserName.get(walkRoomRequest.getAgentUserId()));

                /**
                 * 当walk room request的入住日期范围只有1天时，walkRoomDateinOther等于null
                 */
                if (Objects.nonNull(walkRoomDateinOther)) {
                    vo.setSentApproveIndex(walkRoomDateinOther.getSentApproveIndex());
                    vo.setSentApproveStatus(walkRoomDateinOther.getSentApproveStatus());
                    vo.setReceiveApproveIndex(walkRoomDateinOther.getReceiveApproveIndex());
                    vo.setReceiveApproveStatus(walkRoomDateinOther.getReceiveApproveStatus());

                    //设置确认人
                    vo.setConfirmUserId(walkRoomDateinOther.getUpdateBy());
                    //设置确认人姓名
                    vo.setConfirmUserName(userId2UserName.get(walkRoomDateinOther.getUpdateBy()));
                    //设置确认时间
                    vo.setConfirmTime(walkRoomDateinOther.getUpdateTime());

                    //设置CRS.NO
                    vo.setCrsNumber(walkRoomDateinOther.getCrsNumber());
                    //设置入住记录的comment
                    vo.setDateinComment(walkRoomDateinOther.getComment());
                    //设置入住记录的状态
                    vo.setStatus(walkRoomDateinOther.getStatus());

                    //查询审批日志记录
                    List<WalkRoomApproveLevelVO> approveLevelLogList = walkRoomApproveLogService.listApproveLogTree(List.of(walkRoomDateinOther), propertyDTO, type)
                            .getOrDefault(walkRoomDateinOther.getId(), Collections.emptyList());
                    //设置审批记录
                    vo.setApproveLevelLog(approveLevelLogList);
                    //设置审批状态对应的入住日
                    vo.setApproveDate(walkRoomDateinOther.getDate());
                }
            });
        }

        /**
         * 查询walk room的log
         *
         * @param property 资产标识
         * @param id       walk room 主键id
         * @return void
         * @author lichen
         * @date 2023/7/13
         */
        @ApiId(464)
        @GetMapping("/{id:\\d+}/log")
        public List<WalkRoomLogDTO> listLog(String property, @PathVariable Long id) {
            //校验walk room是否存在
            WalkRoomRequest walkRoomRequest = checkIsExist(id);
            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();

            //校验当前资产id是否是 发送方或接收方
            List<Integer> propertyIds = Arrays.asList(walkRoomRequest.getFromPropertyId(), walkRoomRequest.getToPropertyId());
            if (!propertyIds.contains(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("Currently property is neither the receiver nor the sender, No permission to view data. currentPropertyId:{0}, receiver:{1}, sender:{2}",
                                propertyId, walkRoomRequest.getToPropertyId(), walkRoomRequest.getFromPropertyId()));
            }
            //查询log
            return walkRoomRequestLogService.listByReqId(tenantId, walkRoomRequest.getId());
        }

        /**
         * 查询入住记录
         *
         * @param property 资产标识
         * @param id       walk room主键id
         * @param type     查询类型1:Sent 2:Receive
         * @return 入住记录集合
         */
        @ApiId(465)
        @GetMapping("/{id:\\d+}/datein")
        public List<WalkRoomDateinVO> listDatein(String property, @PathVariable Long id, @RequestParam("type") Integer type) {
            if (!Lists.newArrayList(1, 2).contains(type)) {
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("type", List.of(1, 2)),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The type must be 1:Sent 2: Receive");
            }
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            //校验walk room数据是否存在 且 归属于当前资产
            WalkRoomRequest walkRoomRequest = checkIsExistAndAffiliation(id, propertyId, type);

            //查询入住记录集合
            List<WalkRoomDateinOther> walkRoomDateinOthers = walkRoomDateinOtherService.listByReqIds(Collections.singletonList(walkRoomRequest.getId()));
            List<Long> dateinOtherIds = walkRoomDateinOthers.stream().map(WalkRoomDateinOther::getId).collect(Collectors.toList());
            Map<Integer, WalkRoomDateinOther> date2DateinOther = walkRoomDateinOthers.stream().collect(Collectors.toMap(WalkRoomDateinOther::getDate, Function.identity()));

            //查询入住记录的rate集合
            Map<Integer, BigDecimal> date2Rate = walkRoomDateinRateService.listDateMapByReqIdAndDate(walkRoomRequest.getId(), Collections.emptyList());

            List<WalkRoomDateinVO> walkRoomDateinVOS = new ArrayList<>();
            //使用接收方资产的时区，获取当前日期
            String timezone = propertyI18nRedisService.get(walkRoomRequest.getToPropertyId()).getTimezone();
            LocalDate currentLocalDate = LocalDate.now(ZoneId.of(timezone));

            //入住日期转换为localDate
            LocalDate checkInLocalDate = DateTimeUtils.strToLocalDate(walkRoomRequest.getCheckInDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
            LocalDate checkOutLocalDate = DateTimeUtils.strToLocalDate(walkRoomRequest.getCheckOutDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD);
            //判断客人是否提前退房
            if (walkRoomRequest.getInvalidDate() != 0) {
                /**
                 * 如果客人提前退房，则checkOutDate = invalidDate + 1天
                 * 加1天的原因是为了显示出invalidDate（提前退房）的入住记录
                 */
                checkOutLocalDate = DateTimeUtils.strToLocalDate(walkRoomRequest.getInvalidDate().toString(), BaseConstant.DATE_FORMAT_YYYYMMDD)
                        .plusDays(1);
            }

            //查询审批层级
            Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2ApproveLevel = approveLevelService.listByPropertyIds(
                            Lists.newArrayList(walkRoomRequest.getFromPropertyId(), walkRoomRequest.getToPropertyId()))
                    .stream().collect(Collectors.groupingBy(item -> WalkRoomApproveLevel.generateKey(item.getPropertyId(), item.getType())));

            //查询入住记录对应的审批日志
            Map<String, Long> otherIdAndpropertyId2ApproveLogCount = walkRoomApproveLogService.listByDateinOtherIds(dateinOtherIds).stream()
                    .collect(Collectors.groupingBy(item -> WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getDateinOtherId(), item.getPropertyId()),
                            Collectors.counting()));

            /**
             * checkInDate ~ checkOutDate范围内，按照日期生成每日的入住记录
             * 循环截止条件：localDate.isBefore(checkOutLocalDate)，最后一天的数据不显示。
             */
            for (LocalDate localDate = checkInLocalDate; localDate.isBefore(checkOutLocalDate); localDate = localDate.plusDays(1)) {
                Integer itemDate = Integer.valueOf(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));

                WalkRoomDateinVO walkRoomDateinVO = new WalkRoomDateinVO();
                walkRoomDateinVO.setDate(itemDate);

                //获取循环当日的入住记录
                WalkRoomDateinOther dateinOther = date2DateinOther.get(itemDate);
                if (Objects.isNull(dateinOther)) {
                    /**
                     * 循环的变量日期，小于等于当前时间时，才需要生成入住记录
                     */
                    if (!localDate.isAfter(currentLocalDate)) {
                        /**
                         * 当天未填写 crs number 信息时，延续当天之前填写的 crs number
                         */
                        String earlyCrsNumber = walkRoomDateinOtherService.getEarlyCrsNumber(walkRoomDateinOthers, itemDate);
                        walkRoomDateinVO.setCrsNumber(earlyCrsNumber);
                        /**
                         * 状态直接设置为check-in。
                         * 原因：当前循环的日历面板截止日期是退房日，所以小于当前时间的未填写CRS.NO的数据都是check-in
                         */
                        walkRoomDateinVO.setStatus(WalkRoomStatusEnum.CHECKED_IN.getCode());

                        //发送方的审批字段
                        String sentKey = WalkRoomApproveLevel.generateKey(walkRoomRequest.getFromPropertyId(), WalkRoomApproveTypeEnum.SENT.getCode());
                        List<WalkRoomApproveLevel> walkRoomApproveLevelsBySent = propertyIdAndType2ApproveLevel.get(sentKey);
                        if (CollectionUtils.isEmpty(walkRoomApproveLevelsBySent)) {
                            //审批层级索引设置为0
                            walkRoomDateinVO.setSentApproveIndex(0);
                            //审批状态设置为审批通过
                            walkRoomDateinVO.setSentApproveStatus(ApproveStatusEnum.APPROVED.getStatus());
                        } else {//有审批层级
                            WalkRoomApproveLevel walkRoomApproveLevel = walkRoomApproveLevelsBySent.stream()
                                    .min(Comparator.comparing(WalkRoomApproveLevel::getApproveIndex)).get();
                            walkRoomDateinVO.setSentApproveIndex(walkRoomApproveLevel.getApproveIndex());
                            //审批状态设置为审批中
                            walkRoomDateinVO.setSentApproveStatus(ApproveStatusEnum.APPROVEING.getStatus());
                            //未开始审批
                            walkRoomDateinVO.setSentIsStartApprove(false);
                        }

                        //接收方的审批字段
                        String receiveKey = WalkRoomApproveLevel.generateKey(walkRoomRequest.getToPropertyId(), WalkRoomApproveTypeEnum.RECEIVE.getCode());
                        List<WalkRoomApproveLevel> walkRoomApproveLevelsByReceive = propertyIdAndType2ApproveLevel.get(receiveKey);
                        if (CollectionUtils.isEmpty(walkRoomApproveLevelsByReceive)) {
                            //审批层级索引设置为0
                            walkRoomDateinVO.setReceiveApproveIndex(0);
                            //审批状态设置为审批通过
                            walkRoomDateinVO.setReceiveApproveStatus(ApproveStatusEnum.APPROVED.getStatus());
                        } else {//有审批层级
                            WalkRoomApproveLevel walkRoomApproveLevel = walkRoomApproveLevelsByReceive.stream()
                                    .min(Comparator.comparing(WalkRoomApproveLevel::getApproveIndex)).get();
                            walkRoomDateinVO.setReceiveApproveIndex(walkRoomApproveLevel.getApproveIndex());
                            //审批状态设置为审批中
                            walkRoomDateinVO.setReceiveApproveStatus(ApproveStatusEnum.APPROVEING.getStatus());
                            //未开始审批
                            walkRoomDateinVO.setReceiveIsStartApprove(false);
                        }
                    }
                } else {
                    walkRoomDateinVO.setId(dateinOther.getId());
                    walkRoomDateinVO.setComment(dateinOther.getComment());
                    walkRoomDateinVO.setStatus(dateinOther.getStatus());
                    walkRoomDateinVO.setCrsNumber(dateinOther.getCrsNumber());

                    if (StringUtils.isEmpty(dateinOther.getCrsNumber())) {
                        /**
                         * 当天未填写 crs number 信息时，延续当天之前填写的 crs number
                         */
                        String earlyCrsNumber = walkRoomDateinOtherService.getEarlyCrsNumber(walkRoomDateinOthers, itemDate);
                        walkRoomDateinVO.setCrsNumber(earlyCrsNumber);
                        /**
                         * 状态直接设置为check-in
                         */
                        walkRoomDateinVO.setStatus(WalkRoomStatusEnum.CHECKED_IN.getCode());
                    }

                    //设置审批相关字段
                    walkRoomDateinVO.setSentApproveIndex(dateinOther.getSentApproveIndex());
                    walkRoomDateinVO.setSentApproveStatus(dateinOther.getSentApproveStatus());
                    walkRoomDateinVO.setReceiveApproveIndex(dateinOther.getReceiveApproveIndex());
                    walkRoomDateinVO.setReceiveApproveStatus(dateinOther.getReceiveApproveStatus());
                    //设置发送方是否开始审批
                    if (dateinOther.getSentApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                        String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(dateinOther.getId(), dateinOther.getFromPropertyId());
                        Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                        if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                            walkRoomDateinVO.setSentIsStartApprove(false);
                        } else {
                            walkRoomDateinVO.setSentIsStartApprove(true);
                        }
                    }
                    //设置接收方是否开始审批
                    if (dateinOther.getReceiveApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                        String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(dateinOther.getId(), dateinOther.getToPropertyId());
                        Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                        if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                            walkRoomDateinVO.setReceiveIsStartApprove(false);
                        } else {
                            walkRoomDateinVO.setReceiveIsStartApprove(true);
                        }
                    }
                }

                //设置walk rate
                walkRoomDateinVO.setRate(date2Rate.get(itemDate));
                walkRoomDateinVOS.add(walkRoomDateinVO);
            }
            //查询审批日志
            Map<Long, List<WalkRoomApproveLevelVO>> dateinOtherId2LevelVOS = walkRoomApproveLogService.listApproveLogTree(walkRoomDateinOthers, propertyDTO, type);

            //是否需要设置未审批的日志
            boolean isNeedSetUnApproveLevelLog = walkRoomDateinVOS.stream().anyMatch(item -> Objects.isNull(item.getId()));
            List<WalkRoomApproveLevelVO> unApproveLevelVOS = Collections.emptyList();
            if (isNeedSetUnApproveLevelLog) {
                unApproveLevelVOS = walkRoomApproveLogService.listUnApproveLevelLogs(propertyDTO, type);
            }

            //设置审批日志
            for (WalkRoomDateinVO vo : walkRoomDateinVOS) {
                if (Objects.nonNull(vo.getId())) {
                    //设置审批日志
                    vo.setApproveLevelLog(dateinOtherId2LevelVOS.getOrDefault(vo.getId(), Collections.emptyList()));
                } else {
                    //设置审批日志
                    vo.setApproveLevelLog(unApproveLevelVOS);
                }
            }
            return walkRoomDateinVOS;
        }

        /**
         * 保存walk room信息
         *
         * @param property           资产标识
         * @param tenant             租户标识
         * @param id                 walk room主键id(0表示新增)
         * @param walkRoomRequestDTO walk room 信息
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/20
         */
        @ApiId(466)
        @PostMapping("/{id:\\d+}")
        public Map save(String property, String tenant, @PathVariable Long id, @Valid @RequestBody WalkRoomRequestDTO walkRoomRequestDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();
            //设置发送方资产
            walkRoomRequestDTO.setFromPropertyId(propertyId);
            //校验toProperty是否归属于当前租户下
            if (propertyInternalService.getPropertyByTenant(tenant).stream().noneMatch(item -> item.getId().equals(walkRoomRequestDTO.getToPropertyId()))) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The toProperty must be owned by the current tenant. toProperty:{0}, tenantAbbr:{1}",
                                walkRoomRequestDTO.getToPropertyId(), tenant));
            }

            if (id > BaseConstant.LONG_ZERO) {
                //设置主键id
                walkRoomRequestDTO.setId(id);
                //校验数据是否存在
                WalkRoomRequest oriWalkRoomRequest = checkIsExist(id);
                //只有发送方才可以修改数据，校验当前资产是否发送方
                checkCurrentPropertyIsSent(oriWalkRoomRequest, propertyId);

                //查询发送方和接收方的审批层级
                Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels = approveLevelService
                        .listByPropertyIds(Arrays.asList(oriWalkRoomRequest.getFromPropertyId(), oriWalkRoomRequest.getToPropertyId(), walkRoomRequestDTO.getToPropertyId()))
                        .stream()
                        .collect(Collectors.groupingBy(item -> WalkRoomApproveLevel.generateKey(item.getPropertyId(), item.getType())));

                if (!oriWalkRoomRequest.getToPropertyId().equals(walkRoomRequestDTO.getToPropertyId())) {
                    //校验是否可以修改接收方
                    checkIsCanUpdateReceiver(oriWalkRoomRequest, propertyIdAndType2Levels);
                    //修改
                    walkRoomRequestService.updateReceiver(walkRoomRequestDTO, propertyIdAndType2Levels, loginUserId);
                } else {
                    //修改
                    walkRoomRequestService.update(walkRoomRequestDTO, propertyIdAndType2Levels, loginUserId);
                }
                return ImmutableMap.of("id", oriWalkRoomRequest.getId());
            } else {
                //校验toProperty不能等于当前资产
                if (walkRoomRequestDTO.getToPropertyId().equals(propertyId)) {
                    throw new BadRequestException(CommonErrorI18nConstant.SENDER_AND_RECEIVER_CANNOT_SAME,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the to property not the same from property;from property:"
                            + propertyId + ",to property:" + walkRoomRequestDTO.getToPropertyId());
                }
                //查询发送方和接收方的审批层级
                Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels = approveLevelService
                        .listByPropertyIds(Arrays.asList(walkRoomRequestDTO.getFromPropertyId(), walkRoomRequestDTO.getToPropertyId()))
                        .stream()
                        .collect(Collectors.groupingBy(item -> WalkRoomApproveLevel.generateKey(item.getPropertyId(), item.getType())));

                //新增
                return walkRoomRequestService.save(walkRoomRequestDTO, propertyIdAndType2Levels, loginUserId);
            }
        }

        /**
         * 保存walk room数据时，给接收方资产发送通知
         *
         * @param property 资产标识
         * @param id       walk room主键id
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/18
         */
        @ApiId(467)
        @PostMapping("/{id:\\d+}/send-email")
        public Map sendNotify(String property, @PathVariable Long id) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();
            String username = sessionContext.getUsername();
            //校验数据是否存在
            WalkRoomRequest walkRoomRequest = checkIsExist(id);
            //只有发送方才可以发送通知，校验当前资产是否发送方
            checkCurrentPropertyIsSent(walkRoomRequest, propertyId);
            //给接收方资产发送通知
            walkRoomRequestService.sendNotifyToReceiver(walkRoomRequest, loginUserId, username);
            return Collections.emptyMap();
        }

        /**
         * 审批
         *
         * @param property   资产标识
         * @param id         walk room主键id
         * @param date       入住日期（yyyyMMdd）
         * @param approveDTO 审批dto
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/18
         */
        @ApiId(468)
        @PostMapping("/{id:\\d+}/approve/datein/{date:\\d+}")
        public Map approve(String property, @PathVariable Long id, @PathVariable Integer date,
                           @Validated @RequestBody WalkRoomApproveDTO approveDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();

            approveDTO.setApproveBy(loginUserId);

            //校验walk room数据是否存在
            WalkRoomRequest walkRoomRequest = checkIsExist(id);
            //审批类型是发送方时，校验fromProperty是否等于当前资产
            if (approveDTO.getApproveType() == WalkRoomApproveTypeEnum.SENT.getCode()
                    && walkRoomRequest.getFromPropertyId().compareTo(propertyId) != 0) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        "When the approveType equal to sent, propertyId must equal to fromProperty. fromProperty = "
                                + walkRoomRequest.getFromPropertyId() + ", propertyId = " + propertyId);
            }
            //审批类型是接收方时，校验toProperty是否等于当前资产
            if (approveDTO.getApproveType() == WalkRoomApproveTypeEnum.RECEIVE.getCode()
                    && walkRoomRequest.getToPropertyId().compareTo(propertyId) != 0) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        "When the approveType equal to receive, propertyId must equal to toProperty. toProperty = "
                                + walkRoomRequest.getToPropertyId() + ", propertyId = " + propertyId);
            }

            //审批入住记录
            walkRoomDateinOtherService.approve(walkRoomRequest, date, approveDTO);
            return Collections.emptyMap();
        }

        /**
         * 设置walk rate
         *
         * @param property    资产标识
         * @param id          walk room主键id
         * @param date        入住日期（yyyyMMdd）
         * @param walkRateDTO walk rate dto类
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/19
         */
        @ApiId(469)
        @PutMapping("/{id:\\d+}/walk-rate/{date:\\d+}")
        public Map setWalkRate(String property, @PathVariable Long id, @PathVariable Integer date,
                               @Valid @RequestBody WalkRateDTO walkRateDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();

            walkRateDTO.setDate(date);
            walkRateDTO.setPropertyId(propertyId);

            if (walkRateDTO.getIsBatchSet()) {
                //批量设置接收方某日的walk rate
                walkRoomRateService.batchSetReceiverWalkRate(walkRateDTO,loginUserId);
            } else {
                //校验walk room数据是否存在
                WalkRoomRequest walkRoomRequest = checkIsExist(id);
                //校验资产是否接收方
                checkCurrentPropertyIsReceive(walkRoomRequest, propertyId);
                //设置walk room某日的walk rate
                walkRoomDateinRateService.setWalkRate(walkRoomRequest, walkRateDTO);
            }
            return Collections.emptyMap();
        }

        /**
         * 接收方确认客人入住信息
         *
         * @param property   资产标识
         * @param id         walk room主键id
         * @param date       入住日期（yyyyMMdd）
         * @param confirmDTO 确认信息
         * @return java.util.Map
         * @author lichen
         * @date 2023/7/20
         */
        @ApiId(470)
        @PutMapping("/{id:\\d+}/confirm/{date:\\d+}")
        public Map confirm(String property, @PathVariable Long id, @PathVariable Integer date,
                           @Valid @RequestBody ConfirmDTO confirmDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();

            //接收方确认客人入住信息
            confirmDTO.setDate(date);
            confirmDTO.setPropertyId(propertyId);
            confirmDTO.setConfirmUserId(loginUserId);

            //校验walk room数据是否存在
            WalkRoomRequest walkRoomRequest = checkIsExist(id);

            //校验资产是否接收方
            checkCurrentPropertyIsReceive(walkRoomRequest, propertyId);

            Integer status = confirmDTO.getStatus();
            List<Integer> statuses = Lists.newArrayList(WalkRoomStatusEnum.NO_SHOW.getCode(), WalkRoomStatusEnum.CANCELLED.getCode());
            //入住第二天及往后，不能选择 no-show/cancelled
            if (confirmDTO.getDate() > walkRoomRequest.getCheckInDate() && statuses.contains(status)) {
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.STATUS,
                                List.of(WalkRoomStatusEnum.EARLY_CHECK_OUT.getI18nCode(), WalkRoomStatusEnum.CHECKED_IN.getI18nCode())),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The second day of stay and beyond,the status can not be " +
                        "2(no-show) or 3(cancelled);status:" + status);
            }
            walkRoomDateinOtherService.confirm(walkRoomRequest, confirmDTO, loginUserId);
            return Collections.emptyMap();
        }

        /**
         * Daily Summary列表
         *
         * @param property          资产标识
         * @param dailySummaryQuery 查询条件
         * @return java.util.List
         * @author lichen
         * @date 2023/7/26
         */
        @ApiId(471)
        @GetMapping("/daily-summary")
        @JsonView({Views.ListView.class})
        public List<WalkRoomVO> dailySummary(String property, @Valid WalkRoomDailySummaryQuery dailySummaryQuery) {
            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();

            Integer date = dailySummaryQuery.getDate();
            Integer approveStatus = dailySummaryQuery.getApproveStatus();
            Boolean confirm = dailySummaryQuery.getConfirm();
            //构造查询对象
            LambdaQueryWrapper<WalkRoomDateinOther> queryWrapperByWalkRoomDateinOther;
            //是否发送方
            boolean isSent = dailySummaryQuery.getType() == WalkRoomApproveTypeEnum.SENT.getCode();
            if (isSent) {
                queryWrapperByWalkRoomDateinOther = new LambdaQueryWrapper<WalkRoomDateinOther>()
                        //发送方时，根据fromPropertyId查询
                        .eq(WalkRoomDateinOther::getFromPropertyId, propertyId)
                        .in(CollectionUtils.isNotEmpty(dailySummaryQuery.getReceivePropertyIds()), WalkRoomDateinOther::getToPropertyId, dailySummaryQuery.getReceivePropertyIds())
                        .eq(WalkRoomDateinOther::getDate, date)
                        //updateBy 大于0 表示接受方资产已确认数据
                        .gt(Objects.nonNull(confirm) && confirm, WalkRoomDateinOther::getUpdateBy, 0)
                        //updateBy 等于0 表示接受方资产未确认的数据
                        .eq(Objects.nonNull(confirm) && !confirm, WalkRoomDateinOther::getUpdateBy, 0)
                        //根据发送方的审批状态查询
                        .eq(Objects.nonNull(approveStatus), WalkRoomDateinOther::getSentApproveStatus, approveStatus);
            } else {
                queryWrapperByWalkRoomDateinOther = new LambdaQueryWrapper<WalkRoomDateinOther>()
                        //接收方时，根据toPropertyId查询
                        .eq(WalkRoomDateinOther::getToPropertyId, propertyId)
                        .eq(WalkRoomDateinOther::getDate, date)
                        //updateBy 大于0 表示接受方资产已确认数据
                        .gt(Objects.nonNull(confirm) && confirm, WalkRoomDateinOther::getUpdateBy, 0)
                        //updateBy 等于0 表示接受方资产未确认的数据
                        .eq(Objects.nonNull(confirm) && !confirm, WalkRoomDateinOther::getUpdateBy, 0)
                        //根据接收到的审批状态查询
                        .eq(Objects.nonNull(approveStatus), WalkRoomDateinOther::getReceiveApproveStatus, approveStatus);
            }
            //查询入住记录
            List<WalkRoomDateinOther> dateinOtherList = walkRoomDateinOtherService.list(queryWrapperByWalkRoomDateinOther);
            if (CollectionUtils.isEmpty(dateinOtherList)) return Collections.emptyList();

            //查询还未离店的walkRoom数据
            List<WalkRoomRequest> walkRoomRequests = walkRoomRequestService.list(new LambdaQueryWrapper<WalkRoomRequest>()
                    .in(WalkRoomRequest::getId, dateinOtherList.stream().map(WalkRoomDateinOther::getReqId).toList())
                    //失效日等于0 或者 失效日大于等于查询日期 的数据
                    .and(queryWrapper -> queryWrapper.eq(WalkRoomRequest::getInvalidDate, 0).or().ge(WalkRoomRequest::getInvalidDate, date)));
            if (CollectionUtils.isEmpty(walkRoomRequests)) return Collections.emptyList();
            List<Long> reqIds = walkRoomRequests.stream().map(WalkRoomRequest::getId).collect(Collectors.toList());

            //过滤出有效的入住记录集合
            Map<String, WalkRoomDateinOther> reqIdAndDate2DateinOther = dateinOtherList.stream()
                    .filter(item -> reqIds.contains(item.getReqId()))
                    .collect(Collectors.toMap(other -> WalkRoomDateinOther.generateKey(other.getReqId(), other.getDate()), Function.identity()));

            //资产集合
            Set<Integer> propertyIds = walkRoomRequests.stream().flatMap(item -> Stream.of(item.getFromPropertyId(), item.getToPropertyId())).collect(Collectors.toSet());
            Map<Integer, String> propertyId2PropertyName = propertyInternalService.listPropertyName(propertyIds);

            //用户集合
            Set<Integer> uids = walkRoomRequests.stream().flatMap(item -> Stream.of(item.getLastSentBy(), item.getAgentUserId())).collect(Collectors.toSet());
            Map<Integer, String> userId2UserName = userInternalService.getNameMapByIds(tenantId, uids);

            //查询入住日的walk rate集合
            Map<String, BigDecimal> reqIdAndDate2Rate = walkRoomDateinRateService.listReqIdAndDateMapByReqIdAndDate(reqIds, Collections.singletonList(date));

            //查询入住日之前天的入住记录集合
            Map<Long, List<WalkRoomDateinOther>> early_reqId2DateinOthers = walkRoomDateinOtherService.listEarlyByReqidsAndDate(reqIds, date);

            //查询入住记录对应的审批日志
            List<Long> dateinOtherIds = dateinOtherList.stream().filter(item -> reqIds.contains(item.getReqId()))
                    .map(WalkRoomDateinOther::getId).toList();
            Map<String, Long> otherIdAndpropertyId2ApproveLogCount = walkRoomApproveLogService.listByDateinOtherIds(dateinOtherIds).stream()
                    .collect(Collectors.groupingBy(item -> WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(item.getDateinOtherId(), item.getPropertyId()),
                            Collectors.counting()));

            //List<WalkRoomRequest> -> List<WalkRoomVO>
            return beanMapper.mapList(walkRoomRequests, WalkRoomVO.class, (entity, vo) -> {
                //设置发送和接受方的资产名称
                vo.setFromPropertyName(propertyId2PropertyName.get(vo.getFromPropertyId()));
                vo.setToPropertyName(propertyId2PropertyName.get(vo.getToPropertyId()));
                //设置邮件发送人
                vo.setLastSentName(userId2UserName.get(vo.getLastSentBy()));
                //设置责任人
                vo.setAgentUserName(userId2UserName.get(vo.getAgentUserId()));
                //设置walk rate
                vo.setRate(reqIdAndDate2Rate.get(WalkRoomDateinRate.generateKey(vo.getId(), date)));

                //设置审批状态对应的入住日
                vo.setApproveDate(date);

                //获取入住日的入住记录
                WalkRoomDateinOther dateinOther = reqIdAndDate2DateinOther.get(WalkRoomDateinOther.generateKey(vo.getId(), date));
                vo.setSentApproveIndex(dateinOther.getSentApproveIndex());
                vo.setSentApproveStatus(dateinOther.getSentApproveStatus());
                vo.setReceiveApproveIndex(dateinOther.getReceiveApproveIndex());
                vo.setReceiveApproveStatus(dateinOther.getReceiveApproveStatus());
                //设置CRS.NO
                vo.setCrsNumber(dateinOther.getCrsNumber());
                //设置入住记录的comment
                vo.setDateinComment(dateinOther.getComment());
                //设置入住记录的状态
                vo.setStatus(dateinOther.getStatus());

                //入住记录的CRS.NO为空时
                if (StringUtils.isBlank(dateinOther.getCrsNumber())) {
                    //获取当前日期之前的入住记录
                    List<WalkRoomDateinOther> earlyDateinOthers = early_reqId2DateinOthers.get(vo.getId());
                    if (CollectionUtils.isNotEmpty(earlyDateinOthers)) {
                        //用当前日期之前 离当前日期最近入住记录的CRS.NO填充
                        String crsNumber = walkRoomDateinOtherService.getEarlyCrsNumber(earlyDateinOthers, date);
                        vo.setCrsNumber(crsNumber);
                        //因为当前日期等于退房日的数据不在审批页面显示，所以状态填充为check-in
                        vo.setStatus(WalkRoomStatusEnum.CHECKED_IN.getCode());
                    }
                }

                //设置发送方是否开始审批
                if (dateinOther.getSentApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                    String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(dateinOther.getId(), dateinOther.getFromPropertyId());
                    Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                    if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                        vo.setSentIsStartApprove(false);
                    } else {
                        vo.setSentIsStartApprove(true);
                    }
                }
                //设置接收方是否开始审批
                if (dateinOther.getReceiveApproveStatus() == ApproveStatusEnum.APPROVEING.getStatus()) {
                    String otherIdAndPropertyId = WalkRoomApproveLog.otherIdAndPropertyIdGenerateKey(dateinOther.getId(), dateinOther.getToPropertyId());
                    Long approveLogCount = otherIdAndpropertyId2ApproveLogCount.get(otherIdAndPropertyId);
                    if (Objects.isNull(approveLogCount) || approveLogCount == BaseConstant.LONG_ZERO) {
                        vo.setReceiveIsStartApprove(false);
                    } else {
                        vo.setReceiveIsStartApprove(true);
                    }
                }
            });
        }

        /**
         * 查询拥有walk room维护权限的用户集合
         *
         * @param property 资产标识
         * @return java.util.List<cloud.wconnect.commonlib.pojo.dto.UserDTO>
         * @author lichen
         * @date 2023/7/15
         */
        @ApiId(472)
        @GetMapping("/user")
        public List<UserDTO> user(String property) {
            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();
            return roleInternalService.getUsers(tenantId, propertyId, BaseConstant.WALK_ROOM_ROLE);
        }

        /**
         * 删除walk room request
         *
         * @param property 资产标识
         * @param id       walk room request主键ID
         * @return java.util.Map
         * @author lichen
         * @date 2024/6/25
         */
        @ApiId(1226)
        @DeleteMapping("/{id:\\d+}")
        public Map delete(String property, @PathVariable Long id) {
            int propertyId = sessionContext.getPropertyId(property);
            //校验walk room request是否存在 且 发送方酒店归属于当前资产
            WalkRoomRequest walkRoomRequest = checkIsExistAndAffiliation(id, propertyId, WalkRoomQuery.TYPE_SENT);
            //删除walk room request数据
            walkRoomRequestService.remove(walkRoomRequest);
            return Collections.emptyMap();
        }

        /**
         * 校验walk room数据是否存在 且 归属于当前资产
         *
         * @param id         walk room数据主键id
         * @param propertyId 资产id
         * @param type       查询类型1:Sent or 2:Receive
         * @return cloud.wconnect.frontoffice.entity.walkroom.WalkRoomRequest
         * @author lichen
         * @date 2023/7/12
         */
        private WalkRoomRequest checkIsExistAndAffiliation(Long id, Integer propertyId, Integer type) {
            WalkRoomRequest walkRoomRequest = checkIsExist(id);
            //查询类型是发送方时，校验fromProperty是否等于当前资产
            if (type.equals(WalkRoomQuery.TYPE_SENT) && walkRoomRequest.getFromPropertyId().compareTo(propertyId) != 0) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        "When the queryType equal to sent sender, fromProperty must equal to propertyId. fromProperty = "
                                + walkRoomRequest.getFromPropertyId() + ", propertyId = " + propertyId);
            }
            //查询类型是接收方时，校验toProperty是否等于当前资产
            if (type.equals(WalkRoomQuery.TYPE_RECEIVE) && walkRoomRequest.getToPropertyId().compareTo(propertyId) != 0) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        "When the queryType equal to receiver, toProperty must equal to propertyId. toProperty = "
                                + walkRoomRequest.getToPropertyId() + ", propertyId = " + propertyId);
            }
            return walkRoomRequest;
        }

        /**
         * 查询walk room数据是否存在
         *
         * @param id walk room主键id
         * @return cloud.wconnect.frontoffice.entity.walkroom.WalkRoomRequest
         * @author lichen
         * @date 2023/7/13
         */
        private WalkRoomRequest checkIsExist(Long id) {
            WalkRoomRequest walkRoomRequest = walkRoomRequestService.getById(id);
            if (Objects.isNull(walkRoomRequest)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Walk Room Requests not found");
            }
            return walkRoomRequest;
        }

        /**
         * 校验当前资产是否发送方
         *
         * @param walkRoomRequest walk room数据
         * @param propertyId      当前资产id
         */
        private void checkCurrentPropertyIsSent(WalkRoomRequest walkRoomRequest, Integer propertyId) {
            if (!walkRoomRequest.getFromPropertyId().equals(propertyId)) {
                throw new BadRequestException(WalkRoomErrorI18nConstant.ONLY_SENDER_CAN_OPERATE,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Only the sender can perform this operation");
            }
        }

        /**
         * 校验是否可以修改接收方
         *
         * @param oriWalkRoomRequest       修改前的walk room数据
         * @param propertyIdAndType2Levels 发送方和接收方的审批层级
         * @return void
         * @author lichen
         * @date 2023/7/18
         */
        private void checkIsCanUpdateReceiver(WalkRoomRequest oriWalkRoomRequest, Map<String, List<WalkRoomApproveLevel>> propertyIdAndType2Levels) {
            Integer fromPropertyId = oriWalkRoomRequest.getFromPropertyId();
            Integer toPropertyId = oriWalkRoomRequest.getToPropertyId();

            //获取发送方的审批层级信息
            String sentKey = WalkRoomApproveLevel.generateKey(fromPropertyId, WalkRoomApproveTypeEnum.SENT.getCode());
            if (propertyIdAndType2Levels.containsKey(sentKey)) {
                //发送方配置了审批层级时，校验：任意入住记录有审批通过的日志则不能修改
                walkRoomApproveLogService.checkIsWithOutApprovedLog(oriWalkRoomRequest.getId(), propertyIdAndType2Levels.get(sentKey),
                        fromPropertyId, WalkRoomApproveTypeEnum.SENT.getCode());
            }

            //获取接收方的审批层级信息
            String receiveKey = WalkRoomApproveLevel.generateKey(toPropertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode());
            if (propertyIdAndType2Levels.containsKey(receiveKey)) {
                //接收方配置了审批层级时，校验：任意入住记录有审批通过的日志则不能修改
                walkRoomApproveLogService.checkIsWithOutApprovedLog(oriWalkRoomRequest.getId(), propertyIdAndType2Levels.get(receiveKey),
                        toPropertyId, WalkRoomApproveTypeEnum.RECEIVE.getCode());
            }

            //校验接收方在入住期间是否 未确认过 入住记录
            walkRoomDateinOtherService.checkReceiverIsUnConfirmed(oriWalkRoomRequest.getId());
        }

        /**
         * 校验当前资产是否接收方
         *
         * @param walkRoomRequest walk room数据
         * @param propertyId      当前资产id
         */
        private void checkCurrentPropertyIsReceive(WalkRoomRequest walkRoomRequest, Integer propertyId) {
            if (!walkRoomRequest.getToPropertyId().equals(propertyId)) {
                throw new BadRequestException(WalkRoomErrorI18nConstant.ONLY_RECEIVER_CAN_OPERATE,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Only the receiver can perform this operation");
            }
        }

    }