# HkInventoryCategoryConfigController.java

    package cloud.wconnect.workperformance.controller.hkinventory;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.hkinventory.HkInventoryErrorI18nConstant;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryCategoryConfig;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryRoomTypeConfig;
    import cloud.wconnect.workperformance.pojo.dto.hkinventory.HkInventoryCategoryConfigDTO;
    import cloud.wconnect.workperformance.pojo.query.hkinventory.HkInventoryCategoryConfigQuery;
    import cloud.wconnect.workperformance.pojo.vo.hkinventory.HkInventoryCategoryConfigVO;
    import cloud.wconnect.workperformance.pojo.vo.hkinventory.HkInventoryRoomTypeConfigVO;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryCategoryConfigService;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryRoomTypeConfigService;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Sets;
    import jakarta.validation.Valid;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;

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

    /**
     * 客房库存管理-分类配置控制层
     *
     * @author lichen
     * @date 2025/4/22
     */
    @RestController
    @RequestMapping("/hk-inventory/category-config")
    public class HkInventoryCategoryConfigController {

        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private IHkInventoryCategoryConfigService categoryConfigService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private IHkInventoryRoomTypeConfigService roomTypeConfigService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询指定资产的分类配置
         *
         * @param property                       资产
         * @param hkInventoryCategoryConfigQuery 查询对象
         * @return java.util.List<cloud.wconnect.workperformance.pojo.vo.hkinventory.HkInventoryCategoryConfigVO>
         * @author lichen
         * @date 2025/4/22
         */
        @ApiId(1422)
        @GetMapping
        public List<HkInventoryCategoryConfigVO> list(String property, HkInventoryCategoryConfigQuery hkInventoryCategoryConfigQuery) {
            int propertyId = sessionContext.getPropertyId(property);
            List<HkInventoryCategoryConfig> categoryConfigList = categoryConfigService.listByName(propertyId,
                    hkInventoryCategoryConfigQuery.getCategoryName());
            if (CollectionUtils.isEmpty(categoryConfigList)) return Collections.emptyList();

            List<Integer> roomTypeIdList = categoryConfigList.stream()
                    .map(categoryConfig -> JsonUtils.convertStringToList(objectMapper, categoryConfig.getRoomTypeIds(), Integer.class))
                    .flatMap(Collection::stream).distinct().toList();

            Map<Integer, HkInventoryRoomTypeConfig> id2RoomType = Collections.emptyMap();
            if(CollectionUtils.isNotEmpty(roomTypeIdList)){
                id2RoomType = roomTypeConfigService.listByIds(roomTypeIdList).stream()
                        .collect(Collectors.toMap(HkInventoryRoomTypeConfig::getId, Function.identity()));
            }
            final Map<Integer, HkInventoryRoomTypeConfig> finalId2RoomType = id2RoomType;

            return beanMapper.mapList(categoryConfigList, HkInventoryCategoryConfigVO.class, (entity, vo) -> {
                List<HkInventoryRoomTypeConfig> roomTypeList = JsonUtils.convertStringToList(objectMapper, entity.getRoomTypeIds(), Integer.class)
                        .stream().map(finalId2RoomType::get).toList();
                vo.setRoomTypes(beanMapper.mapList(roomTypeList, HkInventoryRoomTypeConfigVO.class));
            });
        }

        /**
         * 保存分类配置
         *
         * @param property          资产标识
         * @param categoryId        分类id
         * @param categoryConfigDTO 分类配置DTO
         * @return java.util.Map<java.lang.String, java.lang.Integer>
         * @author lichen
         * @date 2025/4/22
         */
        @ApiId(1423)
        @PostMapping("/{categoryId:\\d+}")
        public Map<String, Integer> save(String property, @PathVariable Integer categoryId, @RequestBody @Valid HkInventoryCategoryConfigDTO categoryConfigDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            int loginUserId = sessionContext.getLoginUserId();

            if (categoryId > 0) {
                //校验分类配置是否存在
                HkInventoryCategoryConfig categoryConfig = categoryConfigService.checkExist(categoryId);
                //校验归属
                categoryConfigService.checkBelong(categoryConfig, propertyId);
                //校验新增、删除的房型id
                checkRoomTypeIds(propertyId, categoryConfigDTO, categoryConfig);
                //校验名称是否重复
                categoryConfigService.checkNameRepeat(propertyId, categoryConfigDTO.getCategoryName(), categoryId);
                //修改
                categoryConfigService.update(propertyId, categoryConfig, categoryConfigDTO, loginUserId);
                return ImmutableMap.of("id", categoryId);
            } else {
                //校验名称是否重复
                categoryConfigService.checkNameRepeat(propertyId, categoryConfigDTO.getCategoryName(), categoryId);
                //校验新增、删除的房型id
                checkRoomTypeIds(propertyId, categoryConfigDTO, null);
                return ImmutableMap.of("id", categoryConfigService.insert(propertyId, categoryConfigDTO, loginUserId));
            }
        }

        /**
         * 删除分类配置
         *
         * @param property   资产标识
         * @param categoryId 分类id
         * @return java.util.Map<java.lang.String, java.lang.String>
         * @author lichen
         * @date 2025/4/22
         */
        @ApiId(1424)
        @DeleteMapping("/{categoryId:\\d+}")
        public Map<String, String> delete(String property, @PathVariable Integer categoryId) {
            int propertyId = sessionContext.getPropertyId(property);
            //校验分类配置是否存在
            HkInventoryCategoryConfig categoryConfig = categoryConfigService.checkExist(categoryId);
            //校验归属
            categoryConfigService.checkBelong(categoryConfig, propertyId);
            //删除分类配置
            categoryConfigService.delete(propertyId, categoryConfig);
            return Collections.emptyMap();
        }

        /**
         * 校验新增、删除的房型id
         *
         * @param propertyId        资产id
         * @param categoryConfigDTO 分类配置DTO
         * @param categoryConfig    修改前的分类配置
         * @return void
         * @author lichen
         * @date 2025/4/22
         */
        private void checkRoomTypeIds(int propertyId, HkInventoryCategoryConfigDTO categoryConfigDTO, HkInventoryCategoryConfig categoryConfig) {
            List<Integer> addRoomTypeIds = categoryConfigDTO.getAddRoomTypeIds();
            List<Integer> deleteRoomTypeIds = categoryConfigDTO.getDeleteRoomTypeIds();

            ArrayList<Integer> allRoomTypeIds = new ArrayList<>();
            allRoomTypeIds.addAll(addRoomTypeIds);
            allRoomTypeIds.addAll(deleteRoomTypeIds);

            if (CollectionUtils.isEmpty(allRoomTypeIds)) return;

            //校验roomTypeId是否重复
            if (allRoomTypeIds.size() != Sets.newHashSet(allRoomTypeIds).size()) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("roomTypeId"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "roomTypeId cannot repeat");
            }
            //校验是否存在
            List<HkInventoryRoomTypeConfig> roomTypeConfigList = roomTypeConfigService.checkExistByIds(allRoomTypeIds);
            categoryConfigDTO.setRoomTypeConfigList(roomTypeConfigList);
            //校验归属
            roomTypeConfigService.checkBelongProperty(roomTypeConfigList, propertyId);

            if (Objects.nonNull(categoryConfig)) {
                //修改前分类下的房型id集合
                List<Integer> oriRoomTypeIds = JsonUtils.convertStringToList(objectMapper, categoryConfig.getRoomTypeIds(), Integer.class);
                if (CollectionUtils.isNotEmpty(oriRoomTypeIds)) {
                    //校验【addRoomTypeIds】是否已经属于当前分类
                    if (CollectionUtils.isNotEmpty(addRoomTypeIds) && addRoomTypeIds.stream().anyMatch(oriRoomTypeIds::contains)) {
                        throw new BadRequestException(HkInventoryErrorI18nConstant.ROOM_TYPE_ALREADY_BELONGS_TO_CATEGORY,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "addRoomTypeIds already belong category");
                    }
                    //校验【deleteRoomTypeIds】是否属于当前分类
                    if (CollectionUtils.isNotEmpty(deleteRoomTypeIds) && !new HashSet<>(oriRoomTypeIds).containsAll(deleteRoomTypeIds)) {
                        throw new BadRequestException(HkInventoryErrorI18nConstant.ROOM_TYPE_NOT_BELONGS_TO_CATEGORY,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "deleteRoomTypeIds not belong category");
                    }
                } else {
                    if (CollectionUtils.isNotEmpty(deleteRoomTypeIds)) {
                        throw new BadRequestException(CommonErrorI18nConstant.MUST_EMPTY,
                                i18nMessageUtils.getErrorParamMapNotNeedTranslate("deleteRoomTypeIds"),
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "oriRoomTypeIds is empty,deleteRoomTypeIds must be empty");
                    }
                }
            } else {
                if (CollectionUtils.isNotEmpty(deleteRoomTypeIds)) {
                    throw new BadRequestException(CommonErrorI18nConstant.MUST_EMPTY,
                            i18nMessageUtils.getErrorParamMapNotNeedTranslate("deleteRoomTypeIds"),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "insert categoryConfig,deleteRoomTypeIds must be empty");
                }
            }
        }

    }