# AreaTypeConfigServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.monthlyreport.AreaEnum;
    import cloud.wconnect.workperformance.cons.monthlyreport.MonthlyReportErrorI18nConstant;
    import cloud.wconnect.workperformance.entity.monthlyreport.AreaTypeConfig;
    import cloud.wconnect.workperformance.entity.monthlyreport.MonthlyReport;
    import cloud.wconnect.workperformance.mapper.monthlyreport.AreaTypeConfigMapper;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.areatypeconfig.AreaTypeConfigDTO;
    import cloud.wconnect.workperformance.service.monthlyreport.IAreaTypeConfigService;
    import cloud.wconnect.workperformance.service.monthlyreport.IHandleAreaTypeConfigChange;
    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.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.ImmutableMap;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.text.MessageFormat;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;

    /**
     * <p>
     * 月报区域类型配置表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-09-01
     */
    @Service
    @DS("monthly_report")
    public class AreaTypeConfigServiceImpl extends ServiceImpl<AreaTypeConfigMapper, AreaTypeConfig> implements IAreaTypeConfigService {

        @Autowired
        private ApplicationContext applicationContext;
        @Autowired
        private MonthlyReportServiceImpl monthlyReportService;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询区域配置的类型
         *
         * @param propertyId 资产id
         * @param areaIdList 区域id集合
         * @return java.util.List<cloud.wconnect.workperformance.entity.monthlyreport.AreaTypeConfig>
         * @author lichen
         * @date 2023/9/1
         */
        @Override
        public List<AreaTypeConfig> listByAreaId(Integer propertyId, List<Integer> areaIdList) {
            return list(new LambdaQueryWrapper<AreaTypeConfig>()
                    .eq(AreaTypeConfig::getPropertyId, propertyId)
                    .in(CollectionUtils.isNotEmpty(areaIdList), AreaTypeConfig::getAreaId, areaIdList)
                    .orderByAsc(AreaTypeConfig::getId));
        }

        /**
         * 校验分类名称是否重复
         *
         * @param propertyId 资产id
         * @param areaId     区域id
         * @param name       分类名称
         * @param ignoreId   忽略的分类id
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void checkNameRepeat(Integer propertyId, Integer areaId, String name, Integer ignoreId) {
            long count = count(new LambdaQueryWrapper<AreaTypeConfig>()
                    .eq(AreaTypeConfig::getPropertyId, propertyId)
                    .eq(AreaTypeConfig::getAreaId, areaId)
                    .eq(AreaTypeConfig::getName, name)
                    .ne(Objects.nonNull(ignoreId), AreaTypeConfig::getId, ignoreId));
            if (count > 0) {
                throw new BadRequestException(MonthlyReportErrorI18nConstant.AREA_CATEGORY_NAME_EXIST,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The category name already exists., propertyId:{0}, area:{1}, name:{2}",
                                propertyId, AreaEnum.getDesc(areaId), name));
            }
        }

        /**
         * 校验数据是否存在
         *
         * @param id 分类id
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public AreaTypeConfig checkExist(Integer id) {
            AreaTypeConfig areaTypeConfig = getById(id);
            if (Objects.isNull(areaTypeConfig)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND, BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The category not found, categoryId:{0}", id));
            }
            return areaTypeConfig;
        }

        /**
         * 修改分类
         *
         * @param oriAreaTypeConfig 修改前的分类数据
         * @param areaTypeConfigDTO 修改后的分类dto
         * @param propertyDTO       资产DTO
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void update(AreaTypeConfig oriAreaTypeConfig, AreaTypeConfigDTO areaTypeConfigDTO, PropertyDTO propertyDTO) {
            //修改分类
            AreaTypeConfig updateEntity = AreaTypeConfig.builder()
                    .id(areaTypeConfigDTO.getId())
                    .name(areaTypeConfigDTO.getName())
                    .contentType(areaTypeConfigDTO.getContentType())
                    .type(areaTypeConfigDTO.getType())
                    .build();

            LambdaUpdateWrapper<AreaTypeConfig> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(AreaTypeConfig::getName, updateEntity.getName());
            lambdaUpdateWrapper.set(AreaTypeConfig::getContentType, updateEntity.getContentType());
            lambdaUpdateWrapper.set(AreaTypeConfig::getType, updateEntity.getType());
            lambdaUpdateWrapper.eq(AreaTypeConfig::getId, updateEntity.getId());
            update(lambdaUpdateWrapper);

            /**
             * 分类发生变化后，只影响当前使用（上个月）和未来的月报，历史的月报不影响
             */
            List<MonthlyReport> monthlyReports = monthlyReportService.listUsingAndFuture(propertyDTO.getId(), propertyDTO.getTimezone())
                    .stream().filter(monthlyReport -> {
                        List<Integer> openAreaIds = JsonUtils.convertStringToList(objectMapper, monthlyReport.getAreaIds(), Integer.class);
                        return openAreaIds.contains(areaTypeConfigDTO.getAreaId());
                    }).toList();
            if (CollectionUtils.isEmpty(monthlyReports)) return;

            //获取区域变化对应的处理类
            String handleCategoryServiceImpls = AreaEnum.getHandleCategoryServiceImpls(oriAreaTypeConfig.getAreaId());
            if (StringUtils.isBlank(handleCategoryServiceImpls)) return;

            List<String> serviceImplList = Arrays.asList(handleCategoryServiceImpls.split(","));
            serviceImplList.forEach(serviceImpl -> {
                IHandleAreaTypeConfigChange handleAreaTypeConfigChange = (IHandleAreaTypeConfigChange) applicationContext.getBean(serviceImpl);
                //修改分类时，刷新对应区域的分类
                handleAreaTypeConfigChange.updateCategory(propertyDTO, monthlyReports, updateEntity, oriAreaTypeConfig);
            });
        }

        /**
         * 删除分类
         *
         * @param areaTypeConfig 删除的分类数据
         * @param propertyDTO    资产DTO
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void remove(AreaTypeConfig areaTypeConfig, PropertyDTO propertyDTO) {
            removeById(areaTypeConfig.getId());

            /**
             * 分类发生变化后，只影响当前使用（上个月）和未来的月报，历史的月报不影响
             */
            List<MonthlyReport> monthlyReports = monthlyReportService.listUsingAndFuture(propertyDTO.getId(), propertyDTO.getTimezone())
                    .stream().filter(monthlyReport -> {
                        List<Integer> openAreaIds = JsonUtils.convertStringToList(objectMapper, monthlyReport.getAreaIds(), Integer.class);
                        return openAreaIds.contains(areaTypeConfig.getAreaId());
                    }).toList();
            if (CollectionUtils.isEmpty(monthlyReports)) return;

            //获取区域变化对应的处理类
            String handleCategoryServiceImpls = AreaEnum.getHandleCategoryServiceImpls(areaTypeConfig.getAreaId());
            if (StringUtils.isBlank(handleCategoryServiceImpls)) return;

            List<String> serviceImplList = Arrays.asList(handleCategoryServiceImpls.split(","));
            serviceImplList.forEach(serviceImpl -> {
                IHandleAreaTypeConfigChange handleAreaTypeConfigChange = (IHandleAreaTypeConfigChange) applicationContext.getBean(serviceImpl);
                //删除分类时，删除对应区域的分类数据
                handleAreaTypeConfigChange.deleteAreaDataByCategoryId(propertyDTO, monthlyReports, areaTypeConfig.getId());
            });
        }

        /**
         * 新增分类
         *
         * @param areaTypeConfigDTO 分类dto
         * @param propertyDTO       资产DTO
         * @param loginUserId       登录用户id
         * @return java.util.Map<java.lang.String, java.lang.Integer>
         * @author lichen
         * @date 2023/9/14
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Map<String, Integer> save(AreaTypeConfigDTO areaTypeConfigDTO, PropertyDTO propertyDTO, int loginUserId) {
            AreaTypeConfig insertEntity = AreaTypeConfig.builder()
                    .tenantId(propertyDTO.getTenantId())
                    .propertyId(propertyDTO.getId())
                    .areaId(areaTypeConfigDTO.getAreaId())
                    .name(areaTypeConfigDTO.getName())
                    .contentType(areaTypeConfigDTO.getContentType())
                    .type(areaTypeConfigDTO.getType())
                    .build();
            save(insertEntity);

            /**
             * 分类发生变化后，只影响当前使用（上个月）和未来的月报，历史的月报不影响
             */
            List<MonthlyReport> monthlyReports = monthlyReportService.listUsingAndFuture(propertyDTO.getId(), propertyDTO.getTimezone())
                    .stream().filter(monthlyReport -> {
                        List<Integer> openAreaIds = JsonUtils.convertStringToList(objectMapper, monthlyReport.getAreaIds(), Integer.class);
                        return openAreaIds.contains(insertEntity.getAreaId());
                    }).toList();
            if (CollectionUtils.isEmpty(monthlyReports)) return ImmutableMap.of("id", insertEntity.getId());

            //获取区域变化对应的处理类
            String handleCategoryServiceImpls = AreaEnum.getHandleCategoryServiceImpls(insertEntity.getAreaId());
            if (StringUtils.isBlank(handleCategoryServiceImpls)) return ImmutableMap.of("id", insertEntity.getId());

            List<String> serviceImplList = Arrays.asList(handleCategoryServiceImpls.split(","));
            serviceImplList.forEach(serviceImpl -> {
                IHandleAreaTypeConfigChange handleAreaTypeConfigChange = (IHandleAreaTypeConfigChange) applicationContext.getBean(serviceImpl);
                //新增分类时，初始化区域此分类的数据
                handleAreaTypeConfigChange.insertAreaDataByCategory(propertyDTO, monthlyReports, insertEntity);
            });
            return ImmutableMap.of("id", insertEntity.getId());
        }

        /**
         * 校验type是否重复
         *
         * @param propertyId 资产id
         * @param areaId     区域id
         * @param type       分类类型
         * @param ignoreId   忽略的分类id
         * @return void
         * @author lichen
         * @date 2023/9/14
         */
        @Override
        public void checkTypeRepeat(int propertyId, Integer areaId, Integer type, Integer ignoreId) {
            long count = count(new LambdaQueryWrapper<AreaTypeConfig>()
                    .eq(AreaTypeConfig::getPropertyId, propertyId)
                    .eq(AreaTypeConfig::getAreaId, areaId)
                    .eq(AreaTypeConfig::getType, type)
                    .ne(Objects.nonNull(ignoreId), AreaTypeConfig::getId, ignoreId));
            if (count > 0) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_CANNOT_REPEAT,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("type"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The type already exists, propertyId:{0}, area:{1}, type:{2}",
                                propertyId, AreaEnum.getDesc(areaId), type));
            }
        }
    }