# RoomTypeServiceImpl.java

    package cloud.wconnect.rateshop.service.rateshop.impl;

    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.util.UpdateLogUtil;
    import cloud.wconnect.rateshop.cons.rateshop.RateShopCons;
    import cloud.wconnect.rateshop.cons.rateshop.RateShopErrorI18nConstant;
    import cloud.wconnect.rateshop.entity.rateshop.RoomType;
    import cloud.wconnect.rateshop.entity.rateshop.RoomTypeInfoRel;
    import cloud.wconnect.rateshop.mapper.rateshop.RoomTypeMapper;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.roomtype.RoomTypeDTO;
    import cloud.wconnect.rateshop.service.rateshop.IRoomTypeInfoRelService;
    import cloud.wconnect.rateshop.service.rateshop.IRoomTypeService;
    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.ImmutableMap;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.text.MessageFormat;
    import java.util.*;

    /**
     * <p>
     * 类型 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-06-09
     */
    @DS("rate_shop")
    @Service
    public class RoomTypeServiceImpl extends ServiceImpl<RoomTypeMapper, RoomType> implements IRoomTypeService {

        @Autowired
        private RoomTypeMapper roomTypeMapper;
        @Autowired
        private UpdateLogUtil updateLogUtil;
        @Autowired
        private IRoomTypeInfoRelService roomTypeInfoRelService;

        /**
         * 校验类型是否存在
         *
         * @param typeId 类型id
         * @return cloud.wconnect.rateshop.entity.rateshop.RoomType
         * @author lichen
         * @date 2023/6/9
         */
        @Override
        public RoomType checkExist(Integer typeId) {
            RoomType roomType = getById(typeId);
            if (Objects.isNull(roomType)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The room type is not found; typeId: " + typeId);
            }
            return roomType;
        }

        /**
         * 根据平台信息和销售地区查询某资产配置的类型信息
         *
         * @param propertyId     资产id
         * @param platformIdList 平台id集合
         * @param pos            销售地区 us：美国 tw：台湾
         * @return java.util.List<cloud.wconnect.rateshop.entity.rateshop.RoomType>
         * @author lichen
         * @date 2023/6/17
         */
        @Override
        public List<RoomType> listByPlatformIdsAndPos(Integer propertyId, Collection<Integer> platformIdList, String pos) {
            return list(new LambdaQueryWrapper<RoomType>()
                    .eq(RoomType::getPropertyId, propertyId)
                    .in(RoomType::getPlatformId, platformIdList)
                    .eq(RoomType::getPos, pos)
                    .orderByAsc(RoomType::getSeq));
        }

        /**
         * 校验类型名称是否唯一
         *
         * @param propertyId  资产id
         * @param roomTypeDTO 类型DTO
         * @param ignoreId    忽略的数据id
         * @return void
         * @author lichen
         * @date 2023/6/20
         */
        @Override
        public void checkTitleSole(Integer propertyId, RoomTypeDTO roomTypeDTO, Integer ignoreId) {
            long count = count(new LambdaQueryWrapper<RoomType>()
                    .ne(Objects.nonNull(ignoreId), RoomType::getId, ignoreId)
                    .eq(RoomType::getPropertyId, propertyId)
                    .eq(RoomType::getPlatformId, roomTypeDTO.getPlatformId())
                    .eq(RoomType::getPos, roomTypeDTO.getPos())
                    .eq(RoomType::getTitle, roomTypeDTO.getTitle()));
            if (count > 0) {
                throw new BadRequestException(RateShopErrorI18nConstant.ROOM_TYPE_TITLE_ALREADY_EXIST,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The room type title already exist; title: " + roomTypeDTO.getTitle());
            }
        }

        /**
         * 新增类型
         *
         * @param propertyId  资产id
         * @param roomTypeDTO 类型DTO
         * @param userId      用户ID
         * @return java.util.Map
         * @author lichen
         * @date 2023/6/20
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Map save(Integer propertyId, RoomTypeDTO roomTypeDTO, int userId) {
            Integer maxSeq = roomTypeMapper.selectMaxOrderForUpdate(propertyId, roomTypeDTO.getPlatformId(), roomTypeDTO.getPos());
            if (Objects.isNull(maxSeq)) {
                maxSeq = 0;
            }

            //构建roomType对象
            RoomType roomType = new RoomType();
            roomType.setSeq(++maxSeq);
            roomType.setPlatformId(roomTypeDTO.getPlatformId());
            roomType.setPos(roomTypeDTO.getPos());
            roomType.setPropertyId(propertyId);
            roomType.setTitle(roomTypeDTO.getTitle());
            roomType.setUpdateLog(updateLogUtil.get(userId));
            //新增
            save(roomType);
            return ImmutableMap.of("id", roomType.getId());
        }

        /**
         * 排序类型
         *
         * @param oriRoomType 类型对象
         * @param type        排序类型 1：上移 2：下移
         * @return void
         * @author lichen
         * @date 2023/6/21
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void order(RoomType oriRoomType, Integer type) {
            Integer oriSeq = oriRoomType.getSeq();
            //查询条件
            LambdaQueryWrapper<RoomType> queryWrapper = new LambdaQueryWrapper<RoomType>()
                    .eq(RoomType::getPropertyId, oriRoomType.getPropertyId())
                    .eq(RoomType::getPlatformId, oriRoomType.getPlatformId())
                    .eq(RoomType::getPos, oriRoomType.getPos());
            //上移
            if (RoomType.UP == type) {
                queryWrapper.lt(RoomType::getSeq, oriSeq);
                queryWrapper.orderByDesc(RoomType::getSeq);
            } else {
                //下移
                queryWrapper.gt(RoomType::getSeq, oriSeq);
                queryWrapper.orderByAsc(RoomType::getSeq);
            }
            queryWrapper.last("limit 1");

            //查询相邻的roomType
            RoomType roomType = getOne(queryWrapper);
            if (Objects.isNull(roomType)) return;
            Integer seq = roomType.getSeq();

            //互换order
            roomType.setSeq(oriSeq);
            oriRoomType.setSeq(seq);

            //批量更新
            saveOrUpdateBatch(Arrays.asList(oriRoomType, roomType));
        }

        /**
         * 删除类型
         *
         * @param roomType 类型
         * @return void
         * @author lichen
         * @date 2023/6/23
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void delete(RoomType roomType) {
            //删除类型
            removeById(roomType.getId());
            //删除类型和实际房型的关联关系
            roomTypeInfoRelService.remove(new LambdaQueryWrapper<RoomTypeInfoRel>()
                    .eq(RoomTypeInfoRel::getPropertyId, roomType.getPropertyId())
                    .eq(RoomTypeInfoRel::getRoomTypeId, roomType.getId()));
        }

        /**
         * 校验类型是否归属于指定资产、指定平台、指定销售地区
         *
         * @param roomType   类型
         * @param propertyId 资产ID
         * @param platformId 平台ID
         * @param pos        销售地区
         * @return void
         * @author lichen
         * @date 2024/7/10
         */
        @Override
        public void checkBelong(RoomType roomType, Integer propertyId, Integer platformId, String pos) {
            if (!roomType.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The room type cannot belong property, roomTypeId:{0},roomTypeBelongPropertyId:{1},currentPropertyId:{2}",
                                roomType.getId(), roomType.getPropertyId(), propertyId));
            }
            if (!roomType.getPlatformId().equals(platformId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The room type cannot belong platform, roomTypeId:{0},roomTypeBelongPlatformId:{1},currentPlatformId:{2}",
                                roomType.getId(), roomType.getPlatformId(), platformId));
            }
            if (!roomType.getPos().equals(pos)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The room type cannot belong pos, roomTypeId:{0},roomTypeBelongPos:{1},currentPos:{2}",
                                roomType.getId(), roomType.getPos(), pos));
            }
        }
    }