# HkInventoryServiceImpl.java

    package cloud.wconnect.workperformance.service.hkinventory.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    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.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationNumberDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.*;
    import cloud.wconnect.workperformance.cons.PrecisionCons;
    import cloud.wconnect.workperformance.cons.hkinventory.StatusEnum;
    import cloud.wconnect.workperformance.entity.hkinventory.*;
    import cloud.wconnect.workperformance.mapper.hkinventory.HkInventoryMapper;
    import cloud.wconnect.workperformance.pojo.dto.hkinventory.*;
    import cloud.wconnect.workperformance.service.hkinventory.*;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import jakarta.annotation.Nullable;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.math.BigDecimal;
    import java.text.MessageFormat;
    import java.time.LocalDate;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 客房库存管理 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2025-04-19
     */
    @Service
    @DS("work_performance")
    public class HkInventoryServiceImpl extends ServiceImpl<HkInventoryMapper, HkInventory> implements IHkInventoryService {

        @Autowired
        private IHkInventoryCategoryService categoryService;
        @Autowired
        private IHkInventoryRoomTypeService roomTypeService;
        @Autowired
        private IHkInventoryItemService itemService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IHkInventoryPurchaseOrderService purchaseOrderService;
        @Autowired
        private UpdateLogUtil updateLogUtil;
        @Autowired
        private IHkInventoryCategoryConfigService categoryConfigService;
        @Autowired
        private IHkInventoryRoomTypeConfigService roomTypeConfigService;
        @Autowired
        private IHkInventoryItemConfigService itemConfigService;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 条件查询客房库存管理列表
         *
         * @param propertyId 资产ID
         * @param year       年份
         * @param month      月份
         * @param status     状态
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventory>
         * @author lichen
         * @date 2025/4/19
         */
        @Override
        public List<HkInventory> listByCondition(Integer propertyId, @Nullable Integer year, @Nullable Integer month, @Nullable Integer status) {
            return list(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getPropertyId, propertyId)
                    .eq(Objects.nonNull(year), HkInventory::getYear, year)
                    .eq(Objects.nonNull(month), HkInventory::getMonth, month)
                    .eq(Objects.nonNull(status), HkInventory::getStatus, status)
                    .orderByDesc(HkInventory::getId));
        }

        /**
         * 校验客房库存管理是否存在
         *
         * @param hkInventoryId 库存id
         * @return cloud.wconnect.workperformance.entity.hkinventory.HkInventory
         * @author lichen
         * @date 2025/4/19
         */
        @Override
        public HkInventory checkExist(Integer hkInventoryId) {
            HkInventory hkInventory = getById(hkInventoryId);
            if (Objects.isNull(hkInventory)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "Housekeeping Inventory not found,id=" + hkInventoryId);
            }
            return hkInventory;
        }

        /**
         * 校验客房库存管理是否归属资产
         *
         * @param hkInventory 客房库存管理数据
         * @param propertyId  资产id
         * @return void
         * @author lichen
         * @date 2025/4/19
         */
        @Override
        public void checkBelong(HkInventory hkInventory, Integer propertyId) {
            if (!hkInventory.getPropertyId().equals(propertyId)) {
                throw new BadRequestException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(), BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The Housekeeping Inventory not belong currentPropertyId, hkInventoryId:{0}, belongPropertyId:{1}, currentPropertyId:{2}",
                                hkInventory.getId(), hkInventory.getPropertyId(), propertyId));
            }
        }

        /**
         * 客房库存管理详情
         *
         * @param hkInventory 库存
         * @return cloud.wconnect.workperformance.pojo.dto.hkinventory.HkInventoryDetailDTO
         * @author lichen
         * @date 2025/4/19
         */
        @Override
        public HkInventoryDetailDTO detail(HkInventory hkInventory) {
            //查询库存分类
            List<HkInventoryCategory> categoryList = categoryService.listByHkInventoryId(hkInventory.getPropertyId(), hkInventory.getId());
            List<Integer> categoryIds = categoryList.stream().map(HkInventoryCategory::getCategoryId).toList();

            ArrayList<HkInventoryCategoryDetailDTO> hkInventoryCategoryDetailDTOS = Lists.newArrayListWithCapacity(categoryList.size());
            if (CollectionUtils.isNotEmpty(categoryIds)) {
                //分类下的房型集合
                Map<Integer, List<HkInventoryRoomType>> categoryId2RoomTypeList = roomTypeService.listByHkInventoryIdAndCategoryIds(hkInventory.getPropertyId(), hkInventory.getId(), categoryIds)
                        .stream().collect(Collectors.groupingBy(HkInventoryRoomType::getCategoryId));

                //分类下的item集合
                List<HkInventoryItem> hkInventoryItems = itemService.listByHkInventoryIdAndCategoryIds(hkInventory.getPropertyId(), hkInventory.getId(), categoryIds);
                Map<Integer, Map<Integer, List<HkInventoryItem>>> category2RoomType2ItemList = hkInventoryItems.stream()
                        .collect(Collectors.groupingBy(HkInventoryItem::getCategoryId, Collectors.groupingBy(HkInventoryItem::getRoomTypeId)));

                //采购单集合
                List<Integer> purchaseOrderIdList = hkInventoryItems.stream().map(HkInventoryItem::getPurchaseOrderId).filter(purchaseOrderId -> purchaseOrderId > 0).toList();
                Map<Integer, HkInventoryPurchaseOrder> purchaseOrderMap = Collections.emptyMap();
                if (CollectionUtils.isNotEmpty(purchaseOrderIdList)) {
                    purchaseOrderMap = purchaseOrderService.listByIds(purchaseOrderIdList).stream()
                            .collect(Collectors.toMap(HkInventoryPurchaseOrder::getId, Function.identity()));
                }
                final Map<Integer, HkInventoryPurchaseOrder> finalPurchaseOrderMap = purchaseOrderMap;

                for (HkInventoryCategory hkInventoryCategory : categoryList) {
                    HkInventoryCategoryDetailDTO hkInventoryCategoryDetailDTO = beanMapper.map(hkInventoryCategory, HkInventoryCategoryDetailDTO.class);

                    //指定分类下的房型集合
                    List<HkInventoryRoomType> hkInventoryRoomTypes = categoryId2RoomTypeList.getOrDefault(hkInventoryCategory.getCategoryId(), Collections.emptyList());
                    List<HkInventoryRoomTypeDetailDTO> hkInventoryRoomTypeDetailDTOS = beanMapper.mapList(hkInventoryRoomTypes, HkInventoryRoomTypeDetailDTO.class, (entity, dto) -> {
                        //指定分类指定房型下的item集合
                        List<HkInventoryItem> itemList = category2RoomType2ItemList.getOrDefault(hkInventoryCategory.getCategoryId(), Collections.emptyMap())
                                .getOrDefault(entity.getRoomTypeId(), Collections.emptyList());
                        dto.setItems(beanMapper.mapList(itemList, HkInventoryItemDetailDTO.class, (itemEntity, itemDTO) -> {
                            //设置订单信息
                            HkInventoryPurchaseOrder purchaseOrder = finalPurchaseOrderMap.get(itemEntity.getPurchaseOrderId());
                            if (Objects.nonNull(purchaseOrder)) {
                                itemDTO.setPurchaseOrder(beanMapper.map(purchaseOrder, ItemLatestPurchaseOrderDTO.class));
                            }
                        }));
                    });
                    hkInventoryCategoryDetailDTO.setRoomTypes(hkInventoryRoomTypeDetailDTOS);

                    hkInventoryCategoryDetailDTOS.add(hkInventoryCategoryDetailDTO);
                }
            }

            //上个月的数据
            Integer preStatus = null;
            HkInventory previousInventory = getPreviousInventory(hkInventory);
            if (Objects.nonNull(previousInventory)) {
                preStatus = previousInventory.getStatus();
            }

            //发布人姓名
            String publishedByName = null;
            if (Objects.nonNull(hkInventory.getPublishedBy()) && hkInventory.getPublishedBy() > 0) {
                UserDTO userDTO = userInternalService.getOne(hkInventory.getTenantId(), hkInventory.getPublishedBy());
                publishedByName = Objects.nonNull(userDTO) ? userDTO.getName() : null;
            }

            HkInventoryDetailDTO hkInventoryDetailDTO = beanMapper.map(hkInventory, HkInventoryDetailDTO.class);
            hkInventoryDetailDTO.setYearMonth(DateTimeUtils.localDateToStr(
                    LocalDate.of(hkInventory.getYear(), hkInventory.getMonth(), 1),
                    BaseConstant.DATE_FORMAT_YYYY_MM));
            hkInventoryDetailDTO.setPreStatus(preStatus);
            hkInventoryDetailDTO.setPublishedByName(publishedByName);
            hkInventoryDetailDTO.setCategoryList(hkInventoryCategoryDetailDTOS);
            return hkInventoryDetailDTO;
        }

        /**
         * 校验状态必须为xx
         *
         * @param status       待校验的状态
         * @param mustBeStatus 必须是的状态
         * @return void
         * @author lichen
         * @date 2025/4/21
         */
        @Override
        public void checkStatusMustBe(int status, int mustBeStatus) {
            if (status != mustBeStatus) {
                Map<Integer, String> status2I18nCode = Arrays.stream(StatusEnum.values()).collect(Collectors.toMap(StatusEnum::getStatus, StatusEnum::getI18nCode));
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.STATUS, status2I18nCode.get(mustBeStatus)),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("Housekeeping Inventory status must be {0}, current status is {1}", mustBeStatus, status));
            }
        }

        /**
         * 获取上一期客房库存管理
         *
         * @param hkInventory 当前期客房库存管理
         * @return cloud.wconnect.workperformance.entity.hkinventory.HkInventory
         * @author lichen
         * @date 2025/4/21
         */
        @Override
        public HkInventory getPreviousInventory(HkInventory hkInventory) {
            if (hkInventory.getMonth() == 1) {
                //上一期年份为当前年份减一
                Integer previousYear = hkInventory.getYear() - 1;
                //上一期月份为12
                Integer previousMonth = 12;
                //上一期客房库存管理
                return getOne(new LambdaQueryWrapper<HkInventory>()
                        .eq(HkInventory::getPropertyId, hkInventory.getPropertyId())
                        .eq(HkInventory::getYear, previousYear)
                        .eq(HkInventory::getMonth, previousMonth));
            } else {
                //上一期客房库存管理
                return getOne(new LambdaQueryWrapper<HkInventory>()
                        .eq(HkInventory::getPropertyId, hkInventory.getPropertyId())
                        .eq(HkInventory::getYear, hkInventory.getYear())
                        .eq(HkInventory::getMonth, hkInventory.getMonth() - 1)
                );
            }
        }

        /**
         * 汇总客房库存管理数据
         *
         * @param hkInventoryId 指定客房库存管理id
         * @param itemList      item集合
         * @return void
         * @author lichen
         * @date 2025/4/21
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void summary(Integer hkInventoryId, List<HkInventoryItem> itemList) {
            if (CollectionUtils.isEmpty(itemList)) return;

            //库存总金额
            BigDecimal totalBalance = itemList.stream().map(HkInventoryItem::getTotalBalance).filter(Objects::nonNull)
                    .reduce(BigDecimal::add).orElse(null);
            //需求采购金额
            BigDecimal requiredPurchaseAmount = itemList.stream().map(HkInventoryItem::getRequiredPurchaseAmount).filter(Objects::nonNull)
                    .reduce(BigDecimal::add).orElse(null);

            HkInventory hkInventory = new HkInventory();
            hkInventory.setId(hkInventoryId);
            hkInventory.setTotalBalance(totalBalance);
            hkInventory.setRequiredPurchaseAmount(requiredPurchaseAmount);
            updateById(hkInventory);
        }

        /**
         * 根据状态查询客房库存管理
         *
         * @param propertyId 资产id
         * @param status     状态
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventoryRoomTypeConfig>
         * @author lichen
         * @date 2025/4/21
         */
        @Override
        public List<HkInventory> listByStatus(Integer propertyId, int status) {
            return list(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getPropertyId, propertyId)
                    .eq(HkInventory::getStatus, status));
        }

        /**
         * 发布客房库存管理
         *
         * @param hkInventory 客房库存管理
         * @param loginUserId 用户ID
         * @return void
         * @author lichen
         * @date 2025/4/21
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void published(HkInventory hkInventory, int loginUserId) {
            hkInventory.setStatus(StatusEnum.PUBLISHED.getStatus());
            hkInventory.setPublishedBy(loginUserId);
            hkInventory.setPublishedTime(DateTimeUtils.nowTimestamp());
            updateById(hkInventory);

            //计算指标
            itemService.calculateIndicators(hkInventory);
        }

        /**
         * 获取最近发布客房库存管理
         *
         * @param propertyId 资产id
         * @return cloud.wconnect.workperformance.entity.hkinventory.HkInventory
         * @author lichen
         * @date 2025/4/24
         */
        @Override
        public HkInventory listRecentPublished(Integer propertyId) {
            return getOne(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getPropertyId, propertyId)
                    .eq(HkInventory::getStatus, StatusEnum.PUBLISHED.getStatus())
                    .orderByDesc(HkInventory::getId)
                    .last("limit 1"));
        }

        /**
         * 创建Housekeeping Inventory
         *
         * @param propertyDTOList 资产集合
         * @param year            年份
         * @param month           月份
         * @return void
         * @author lichen
         * @date 2025/4/25
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void createHkInventory(List<PropertyDTO> propertyDTOList, int year, int month) {
            // 创建Housekeeping Inventory数据
            List<HkInventory> hkInventoryList = propertyDTOList.stream().map(propertyDTO -> {
                HkInventory hkInventory = new HkInventory();
                hkInventory.setTenantId(propertyDTO.getTenantId());
                hkInventory.setPropertyId(propertyDTO.getId());
                hkInventory.setYear(year);
                hkInventory.setMonth(month);
                hkInventory.setStatus(StatusEnum.PENDING.getStatus());
                hkInventory.setUpdateLog(updateLogUtil.get(0));
                return hkInventory;
            }).toList();
            saveBatch(hkInventoryList);

            List<Integer> propertyIds = propertyDTOList.stream().map(PropertyDTO::getId).toList();

            //资产对应的分类配置
            Map<Integer, List<HkInventoryCategoryConfig>> propertyId2CategoryConfigList = categoryConfigService.listByPropertyIds(propertyIds)
                    .stream().collect(Collectors.groupingBy(HkInventoryCategoryConfig::getPropertyId));
            //资产对应的房型配置
            Map<Integer, List<HkInventoryRoomTypeConfig>> propertyId2RoomTypeConfigList = roomTypeConfigService.listByPropertyIds(propertyIds)
                    .stream().collect(Collectors.groupingBy(HkInventoryRoomTypeConfig::getPropertyId));
            //资产对应的item配置
            Map<Integer, List<HkInventoryItemConfig>> propertyId2ItemConfigList = itemConfigService.listByPropertyIds(propertyIds)
                    .stream().collect(Collectors.groupingBy(HkInventoryItemConfig::getPropertyId));

            ArrayList<HkInventoryCategory> categoryList = Lists.newArrayList();
            ArrayList<HkInventoryRoomType> roomTypeList = Lists.newArrayList();
            ArrayList<HkInventoryItem> itemList = Lists.newArrayList();

            for (HkInventory hkInventory : hkInventoryList) {
                Integer propertyId = hkInventory.getPropertyId();

                //当前Housekeeping Inventory对应的分类配置
                List<HkInventoryCategoryConfig> categoryConfigList = propertyId2CategoryConfigList.get(propertyId);
                if (CollectionUtils.isNotEmpty(categoryConfigList)) {
                    //初始化分类数据
                    List<HkInventoryCategory> initCategoryList = initCategory(categoryConfigList, hkInventory);
                    categoryList.addAll(initCategoryList);

                    //当前Housekeeping Inventory对应的房型配置
                    List<HkInventoryRoomTypeConfig> roomTypeConfigList = propertyId2RoomTypeConfigList.get(propertyId);
                    //初始化分类下的房型数据
                    List<HkInventoryRoomType> initRoomTypeList = initRoomType(categoryConfigList, roomTypeConfigList, hkInventory);
                    roomTypeList.addAll(initRoomTypeList);

                    //当前Housekeeping Inventory对应的item配置
                    List<HkInventoryItemConfig> itemConfigs = propertyId2ItemConfigList.get(propertyId);
                    //初始化item数据
                    List<HkInventoryItem> initItemList = itemConfigConvertInitItem(itemConfigs, hkInventory);
                    itemList.addAll(initItemList);

                }
            }

            categoryService.saveBatch(categoryList);
            roomTypeService.saveBatch(roomTypeList);
            itemService.saveBatch(itemList);
        }

        /**
         * 查询待发布数据
         *
         * @param year       年份
         * @param monthValue 月份
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventory>
         * @author lichen
         * @date 2025/4/25
         */
        @Override
        public List<HkInventory> listPendingByYearMonth(int year, int monthValue) {
            return list(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getYear, year)
                    .eq(HkInventory::getMonth, monthValue)
                    .eq(HkInventory::getStatus, StatusEnum.PENDING.getStatus()));
        }

        /**
         * 获取资产指定月份的Housekeeping Inventory
         *
         * @param propertyId 资产id
         * @param year       年份
         * @param monthValue 月份
         * @return cloud.wconnect.workperformance.entity.hkinventory.HkInventory
         * @author lichen
         * @date 2025/4/26
         */
        @Override
        public HkInventory getByYearMonth(Integer propertyId, int year, int monthValue) {
            return getOne(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getPropertyId, propertyId)
                    .eq(HkInventory::getYear, year).eq(HkInventory::getMonth, monthValue));
        }

        /**
         * 获取资产指定年份和月份的Housekeeping Inventory
         *
         * @param propertyId  资产id
         * @param years       年份集合
         * @param monthValues 月份集合
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventory>
         * @author lichen
         * @date 2025/4/26
         */
        @Override
        public List<HkInventory> listByYearsAndMonths(Integer propertyId, Collection<Integer> years, Collection<Integer> monthValues) {
            return list(new LambdaQueryWrapper<HkInventory>().eq(HkInventory::getPropertyId, propertyId)
                    .in(HkInventory::getYear, years)
                    .in(HkInventory::getMonth, monthValues));
        }

        /**
         * 获取导出数据
         *
         * @param propertyDTO 资产DTO
         * @param hkInventory 待导出的Housekeeping Inventory
         * @return java.util.List<cloud.wconnect.workperformance.pojo.dto.hkinventory.HkInventoryItemExcelDTO>
         * @author lichen
         * @date 2025/7/15
         */
        @Override
        public List<HkInventoryItemExcelDTO> getExportExcelData(PropertyDTO propertyDTO, HkInventory hkInventory) {
            InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
            String currency = number.getCurrency();
            //获取详情
            HkInventoryDetailDTO detailDTO = detail(hkInventory);

            ArrayList<HkInventoryItemExcelDTO> itemExcelDTOS = Lists.newArrayList();

            List<HkInventoryCategoryDetailDTO> categoryList = detailDTO.getCategoryList();
            for (HkInventoryCategoryDetailDTO categoryDetailDTO : categoryList) {
                List<HkInventoryRoomTypeDetailDTO> roomTypes = categoryDetailDTO.getRoomTypes();
                for (HkInventoryRoomTypeDetailDTO roomType : roomTypes) {
                    List<HkInventoryItemDetailDTO> items = roomType.getItems();
                    for (HkInventoryItemDetailDTO item : items) {
                        HkInventoryItemExcelDTO itemExcelDTO = beanMapper.map(item, HkInventoryItemExcelDTO.class);
                        itemExcelDTO.setUnitCostStr(InternationalizationUtils.formatAmountViewValue(item.getUnitCost(), number.getCalculationRule(), currency));
                        itemExcelDTO.setReplenishmentCostStr(InternationalizationUtils.formatAmountViewValue(item.getReplenishmentCost(), number.getCalculationRule(), currency));
                        itemExcelDTO.setTotalBalanceStr(InternationalizationUtils.formatAmountViewValue(item.getTotalBalance(), number.getCalculationRule(), currency));
                        itemExcelDTO.setRequiredPurchaseAmountStr(InternationalizationUtils.formatAmountViewValue(item.getRequiredPurchaseAmount(), number.getCalculationRule(), currency));
                        itemExcelDTO.setExistingParStr(InternationalizationUtils.formatViewValue(item.getExistingPar(), PrecisionCons.HOUSEKEEPING_INVENTORY_PRECISION, number.getCalculationRule(), ""));
                        itemExcelDTO.setDiffParStr(InternationalizationUtils.formatViewValue(item.getDiffPar(), PrecisionCons.HOUSEKEEPING_INVENTORY_PRECISION, number.getCalculationRule(), ""));

                        itemExcelDTO.setCategoryName(categoryDetailDTO.getCategoryName());
                        itemExcelDTO.setRoomTypeName(roomType.getRoomTypeName());
                        itemExcelDTO.setTotalRooms(roomType.getTotalRooms());

                        itemExcelDTOS.add(itemExcelDTO);
                    }
                }
            }
            return itemExcelDTOS;
        }

        /**
         * 查询下一期客房库存管理
         *
         * @param hkInventory 当前期客房库存管理
         * @return cloud.wconnect.workperformance.entity.hkinventory.HkInventory
         * @author lichen
         * @date 2025/9/8
         */
        @Override
        public HkInventory getNextInventory(HkInventory hkInventory) {
            if (hkInventory.getMonth() == 12) {
                //下一期年份为当前年份加1
                Integer nextYear = hkInventory.getYear() + 1;
                //下一期月份为1
                Integer nextMonth = 1;
                //下一期客房库存管理
                return getOne(new LambdaQueryWrapper<HkInventory>()
                        .eq(HkInventory::getPropertyId, hkInventory.getPropertyId())
                        .eq(HkInventory::getYear, nextYear)
                        .eq(HkInventory::getMonth, nextMonth));
            } else {
                //下一期客房库存管理
                return getOne(new LambdaQueryWrapper<HkInventory>()
                        .eq(HkInventory::getPropertyId, hkInventory.getPropertyId())
                        .eq(HkInventory::getYear, hkInventory.getYear())
                        .eq(HkInventory::getMonth, hkInventory.getMonth() + 1)
                );
            }
        }

        /**
         * 撤回
         *
         * @param hkInventory 客房库存管理
         * @param loginUserId 登录用户id
         * @return void
         * @author lichen
         * @date 2025/9/8
         */
        @Override
        public void withdraw(HkInventory hkInventory, int loginUserId) {
            LambdaUpdateWrapper<HkInventory> updateWrapper = new LambdaUpdateWrapper<HkInventory>()
                    .set(HkInventory::getStatus, StatusEnum.PENDING.getStatus())
                    .set(HkInventory::getPublishedBy, null)
                    .set(HkInventory::getPublishedTime, null)
                    .set(HkInventory::getTotalBalance, null)
                    .set(HkInventory::getRequiredPurchaseAmount, null)
                    .set(HkInventory::getUpdateLog, updateLogUtil.append(hkInventory.getUpdateLog(), loginUserId))
                    .eq(HkInventory::getId, hkInventory.getId());
            update(updateWrapper);
        }

        /**
         * 初始化分类
         *
         * @param categoryConfigList 分类配置集合
         * @param hkInventory        客房库存管理
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventoryCategory>
         * @author lichen
         * @date 2025/4/25
         */
        private List<HkInventoryCategory> initCategory(List<HkInventoryCategoryConfig> categoryConfigList, HkInventory hkInventory) {
            return categoryConfigList.stream().map(categoryConfig -> {
                HkInventoryCategory hkInventoryCategory = new HkInventoryCategory();
                hkInventoryCategory.setTenantId(hkInventory.getTenantId());
                hkInventoryCategory.setPropertyId(hkInventory.getPropertyId());
                hkInventoryCategory.setHkInventoryId(hkInventory.getId());
                hkInventoryCategory.setCategoryId(categoryConfig.getId());
                hkInventoryCategory.setCategoryName(categoryConfig.getCategoryName());
                return hkInventoryCategory;
            }).toList();
        }

        /**
         * 初始化分类下的房型数据
         *
         * @param categoryConfigList 分类配置集合
         * @param roomTypeConfigList 房型配置集合
         * @param hkInventory        Housekeeping Inventory数据
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventoryRoomType>
         * @author lichen
         * @date 2025/5/9
         */
        private List<HkInventoryRoomType> initRoomType(List<HkInventoryCategoryConfig> categoryConfigList,
                                                       List<HkInventoryRoomTypeConfig> roomTypeConfigList,
                                                       HkInventory hkInventory) {
            if (CollectionUtils.isEmpty(categoryConfigList) || CollectionUtils.isEmpty(roomTypeConfigList))
                return Collections.emptyList();

            Map<Integer, HkInventoryRoomTypeConfig> roomTypeId2RoomType = roomTypeConfigList.stream()
                    .collect(Collectors.toMap(HkInventoryRoomTypeConfig::getId, Function.identity()));

            List<HkInventoryRoomType> roomTypeList = new ArrayList<>();

            for (HkInventoryCategoryConfig hkInventoryCategoryConfig : categoryConfigList) {
                List<Integer> roomTypeIds = JsonUtils.convertStringToList(objectMapper, hkInventoryCategoryConfig.getRoomTypeIds(), Integer.class);
                if (CollectionUtils.isNotEmpty(roomTypeIds)) {
                    List<HkInventoryRoomType> roomTypes = roomTypeIds.stream().map(roomTypeId -> {
                        //房型配置
                        HkInventoryRoomTypeConfig hkInventoryRoomTypeConfig = roomTypeId2RoomType.get(roomTypeId);

                        HkInventoryRoomType hkInventoryRoomType = new HkInventoryRoomType();
                        hkInventoryRoomType.setTenantId(hkInventory.getTenantId());
                        hkInventoryRoomType.setPropertyId(hkInventory.getPropertyId());
                        hkInventoryRoomType.setHkInventoryId(hkInventory.getId());
                        hkInventoryRoomType.setCategoryId(hkInventoryCategoryConfig.getId());
                        hkInventoryRoomType.setRoomTypeId(roomTypeId);
                        hkInventoryRoomType.setRoomTypeName(hkInventoryRoomTypeConfig.getRoomTypeName());
                        hkInventoryRoomType.setTotalRooms(hkInventoryRoomTypeConfig.getTotalRooms());
                        return hkInventoryRoomType;
                    }).toList();
                    roomTypeList.addAll(roomTypes);
                }
            }
            return roomTypeList;
        }

        /**
         * item配置转化成初始化的item
         *
         * @param itemConfigs item 配置
         * @param hkInventory Housekeeping Inventory
         * @return java.util.List<cloud.wconnect.workperformance.entity.hkinventory.HkInventoryItem>
         * @author lichen
         * @date 2025/4/25
         */
        private List<HkInventoryItem> itemConfigConvertInitItem(List<HkInventoryItemConfig> itemConfigs, HkInventory hkInventory) {
            return beanMapper.mapList(itemConfigs, HkInventoryItem.class, (itemConfig, item) -> {
                item.setHkInventoryId(hkInventory.getId());
                item.setItemId(itemConfig.getId());
                item.setUpdateLog(updateLogUtil.get(0));
                item.setPurchaseOrderId(0);
                item.setId(null);
            });
        }
    }