# ActionPlanServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.monthlyreport.AreaEnum;
    import cloud.wconnect.workperformance.entity.monthlyreport.ActionPlan;
    import cloud.wconnect.workperformance.entity.monthlyreport.AreaTypeConfig;
    import cloud.wconnect.workperformance.entity.monthlyreport.MonthlyReport;
    import cloud.wconnect.workperformance.mapper.monthlyreport.ActionPlanMapper;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.actionplans.ActionPlanDTO;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.actionplans.CategoryId2ActionPlanDTO;
    import cloud.wconnect.workperformance.service.monthlyreport.*;
    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.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 月报的Action Plans区域表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-09-01
     */
    @Service
    @DS("monthly_report")
    public class ActionPlanServiceImpl extends ServiceImpl<ActionPlanMapper, ActionPlan> implements IActionPlanService, IHandlePropertySettingChange, IHandleAreaTypeConfigChange {

        @Autowired
        private BeanMapper beanMapper;
        @Lazy
        @Autowired
        private IMonthlyReportService monthlyReportService;
        @Autowired
        private IAreaTypeConfigService areaTypeConfigService;
        @Autowired
        private ObjectMapper objectMapper;

        /**
         * 获取Action Plans区域详情
         *
         * @param monthlyReport 月报
         * @param propertyDTO   资产DTO
         * @return java.util.List<cloud.wconnect.workperformance.pojo.dto.monthlyreport.actionplans.CategoryId2ActionPlanDTO>
         * @author lichen
         * @date 2023/9/5
         */
        @Override
        public List<CategoryId2ActionPlanDTO> getActionPlan(MonthlyReport monthlyReport, PropertyDTO propertyDTO) {
            List<ActionPlanDTO> actionPlanDTOS = list(new LambdaQueryWrapper<ActionPlan>()
                    .eq(ActionPlan::getReportId, monthlyReport.getId())
                    .eq(ActionPlan::getPropertyId, propertyDTO.getId())
                    .orderByAsc(ActionPlan::getId))
                    .stream().map(item -> beanMapper.map(item, ActionPlanDTO.class)).toList();

            //校验是否历史月报
            Boolean isHistoryMonthlyReport = monthlyReportService.checkIsHistoryMonthlyReport(monthlyReport, propertyDTO);

            //获取行动计划集合中的分类集合
            Map<Integer, String> categoryId2Name = actionPlanDTOS.stream().collect(Collectors.toMap(ActionPlanDTO::getCategoryId, ActionPlanDTO::getCategoryName, (v1, v2) -> v1));

            /**
             * 历史月报：按照区域表存储的数据，组装返回对象
             * 当前正在使用或未来的数据：按照最新的区域类型配置 组装返回对象
             */
            if (!isHistoryMonthlyReport) {
                //查询区域配置的类型
                categoryId2Name = areaTypeConfigService.listByAreaId(propertyDTO.getId(), Lists.newArrayList(AreaEnum.ACTION_PLANS.getAreaId()))
                        .stream().collect(Collectors.toMap(AreaTypeConfig::getId, AreaTypeConfig::getName));
            }

            //按照分类id对行动计划集合分组
            Map<Integer, List<ActionPlanDTO>> categoryId2ActionPlansMap = actionPlanDTOS.stream().collect(Collectors.groupingBy(ActionPlanDTO::getCategoryId));

            List<CategoryId2ActionPlanDTO> resultList = Lists.newArrayListWithCapacity(categoryId2Name.size());
            categoryId2Name.forEach((key, value) -> {
                resultList.add(CategoryId2ActionPlanDTO.builder()
                        .categoryId(key)
                        .categoryName(value)
                        .actionPlans(categoryId2ActionPlansMap.getOrDefault(key, Collections.emptyList()))
                        .build());
            });
            return resultList.stream().sorted(Comparator.comparing(CategoryId2ActionPlanDTO::getCategoryId)).toList();
        }

        /**
         * 保存Action Plans区域数据
         *
         * @param monthlyReport     月报
         * @param propertyDTO       资产DTO
         * @param actionPlanDTOList 区域数据集合
         * @param loginUserId       登录用户id
         * @return void
         * @author lichen
         * @date 2023/9/5
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void save(MonthlyReport monthlyReport, PropertyDTO propertyDTO, List<ActionPlanDTO> actionPlanDTOList, int loginUserId) {
            remove(new LambdaQueryWrapper<ActionPlan>()
                    .eq(ActionPlan::getReportId, monthlyReport.getId())
                    .eq(ActionPlan::getPropertyId, propertyDTO.getId()));

            if (CollectionUtils.isNotEmpty(actionPlanDTOList)) {
                List<ActionPlan> actionPlans = beanMapper.mapList(actionPlanDTOList, ActionPlan.class, (dto, entity) -> {
                    entity.setTenantId(propertyDTO.getTenantId());
                    entity.setPropertyId(propertyDTO.getId());
                    entity.setReportId(monthlyReport.getId());
                    entity.setUpdateId(loginUserId);
                    entity.setUpdateTime(DateTimeUtils.nowTimestamp());
                });
                saveBatch(actionPlans);
            }
        }

        /**
         * 删除区域数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @return void
         * @author lichen
         * @date 2023/9/5
         */
        @Override
        public void delete(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports) {
            List<Long> reportIds = monthlyReports.stream().map(MonthlyReport::getId).toList();
            if (CollectionUtils.isEmpty(reportIds)) return;
            remove(new LambdaQueryWrapper<ActionPlan>()
                    .in(ActionPlan::getReportId, reportIds)
                    .eq(ActionPlan::getPropertyId, propertyDTO.getId()));
        }

        /**
         * 更新分类
         *
         * @param propertyDTO       资产DTO
         * @param monthlyReports    月报集合
         * @param areaTypeConfig    分类
         * @param oriAreaTypeConfig 修改前的 分类
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void updateCategory(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, AreaTypeConfig areaTypeConfig, AreaTypeConfig oriAreaTypeConfig) {
            List<Long> monthlyReportIds = monthlyReports.stream().map(MonthlyReport::getId).collect(Collectors.toList());

            //查询需要更新分类名称的数据
            List<ActionPlan> actionPlans = list(new LambdaQueryWrapper<ActionPlan>()
                    .in(ActionPlan::getReportId, monthlyReportIds)
                    .eq(ActionPlan::getPropertyId, propertyDTO.getId())
                    .eq(ActionPlan::getCategoryId, areaTypeConfig.getId()));
            if (CollectionUtils.isEmpty(actionPlans)) return;

            //设置新的分类名称
            actionPlans.forEach(item -> item.setCategoryName(areaTypeConfig.getName()));
            //更新名称
            updateBatchById(actionPlans);
        }

        /**
         * 删除区域分类id对应的数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @param categoryId     分类id
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void deleteAreaDataByCategoryId(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, Integer categoryId) {
            List<Long> monthlyReportIds = monthlyReports.stream().map(MonthlyReport::getId).collect(Collectors.toList());

            //删除区域分类id对应的数据
            remove(new LambdaQueryWrapper<ActionPlan>()
                    .in(ActionPlan::getReportId, monthlyReportIds)
                    .eq(ActionPlan::getPropertyId, propertyDTO.getId())
                    .eq(ActionPlan::getCategoryId, categoryId));
        }

        /**
         * 根据分类，新增区域数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @param areaTypeConfig 区域分类
         * @return void
         * @author lichen
         * @date 2023/9/8
         */
        @Override
        public void insertAreaDataByCategory(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, AreaTypeConfig areaTypeConfig) {
            List<ActionPlan> actionPlans = monthlyReports.stream()
                    .map(monthlyReport -> ActionPlan.builder()
                            .tenantId(propertyDTO.getTenantId())
                            .propertyId(propertyDTO.getId())
                            .reportId(monthlyReport.getId())
                            .categoryId(areaTypeConfig.getId())
                            .categoryName(areaTypeConfig.getName())
                            .concern("")
                            .actionPlan("")
                            .progress("")
                            .updateId(0)
                            .updateTime(DateTimeUtils.nowTimestamp())
                            .build())
                    .toList();
            saveBatch(actionPlans);
        }

        /**
         * 初始化区域数据
         *
         * @param propertyDTO            资产DTO
         * @param monthlyReports         月报集合
         * @param areaId2AreaTypeConfigs 区域分类集合
         * @return void
         * @author lichen
         * @date 2023/9/8
         */
        @Override
        public void init(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports,
                         Map<Integer, List<AreaTypeConfig>> areaId2AreaTypeConfigs) {
            //过滤出开通对应区域的月报
            List<MonthlyReport> openAreaMonthlyReports = monthlyReports.stream().filter(monthlyReport -> {
                List<Integer> openAreaIds = JsonUtils.convertStringToList(objectMapper, monthlyReport.getAreaIds(), Integer.class);
                return openAreaIds.contains(AreaEnum.ACTION_PLANS.getAreaId());
            }).toList();

            if (CollectionUtils.isEmpty(openAreaMonthlyReports)) return;

            //获取分类集合
            List<AreaTypeConfig> areaTypeConfigs = areaId2AreaTypeConfigs.get(AreaEnum.ACTION_PLANS.getAreaId());
            if (CollectionUtils.isEmpty(areaTypeConfigs)) return;

            List<ActionPlan> actionPlans = Lists.newArrayListWithCapacity(areaTypeConfigs.size() * openAreaMonthlyReports.size());

            for (MonthlyReport openAreaMonthlyReport : openAreaMonthlyReports) {
                for (AreaTypeConfig areaTypeConfig : areaTypeConfigs) {
                    actionPlans.add(ActionPlan.builder()
                            .tenantId(propertyDTO.getTenantId())
                            .propertyId(propertyDTO.getId())
                            .reportId(openAreaMonthlyReport.getId())
                            .categoryId(areaTypeConfig.getId())
                            .categoryName(areaTypeConfig.getName())
                            .concern("")
                            .actionPlan("")
                            .progress("")
                            .updateId(0)
                            .updateTime(DateTimeUtils.nowTimestamp())
                            .build());
                }
            }
            saveBatch(actionPlans);
        }

        ;
    }