# ExpenseCategoryServiceImpl.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.AreaTypeConfig;
    import cloud.wconnect.workperformance.entity.monthlyreport.ExpenseCategory;
    import cloud.wconnect.workperformance.entity.monthlyreport.MonthlyReport;
    import cloud.wconnect.workperformance.mapper.monthlyreport.ExpenseCategoryMapper;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.parsereport.ExpenseCategoryByReportDTO;
    import cloud.wconnect.workperformance.service.monthlyreport.IHandlePropertySettingChange;
    import cloud.wconnect.workperformance.service.monthlyreport.IExpenseCategoryService;
    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.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.stereotype.Service;

    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 月报EXPENSES（花费）区域，花费分类表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-09-01
     */
    @Service
    @DS("monthly_report")
    public class ExpenseCategoryServiceImpl extends ServiceImpl<ExpenseCategoryMapper, ExpenseCategory> implements IExpenseCategoryService, IHandlePropertySettingChange, IHandleAreaTypeConfigChange {

        @Autowired
        private ExpenseCategoryMapper expenseCategoryMapper;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;

        /**
         * 查询花销分类数据
         *
         * @param propertyId 资产id
         * @param reportId   报告id
         * @return java.util.List<cloud.wconnect.workperformance.entity.monthlyreport.ExpenseCategory>
         * @author lichen
         * @date 2023/9/4
         */
        @Override
        public List<ExpenseCategory> listByReportId(Integer propertyId, Long reportId) {
            return list(new LambdaQueryWrapper<ExpenseCategory>()
                    .eq(ExpenseCategory::getReportId, reportId)
                    .eq(ExpenseCategory::getPropertyId, propertyId)
                    .orderByAsc(ExpenseCategory::getCategoryId));
        }

        /**
         * 保存导入的数据
         *
         * @param tenantId                       租户id
         * @param propertyId                     资产id
         * @param monthlyReportId                月报id
         * @param userId                         用户id
         * @param expenseCategoryByReportDTOList 区域数据集合
         * @param areaTypeConfigs                区域分类数据集合
         * @return void
         * @author lichen
         * @date 2023/9/7
         */
        @Override
        public void saveImportData(Integer tenantId, Integer propertyId, Long monthlyReportId, int userId,
                                   List<ExpenseCategoryByReportDTO> expenseCategoryByReportDTOList, List<AreaTypeConfig> areaTypeConfigs) {
            Map<String, Integer> name2CategoryId = areaTypeConfigs.stream().collect(Collectors.toMap(AreaTypeConfig::getName, AreaTypeConfig::getId));
            Set<String> categoryNames = name2CategoryId.keySet();

            List<ExpenseCategory> expenseCategorys = expenseCategoryByReportDTOList.stream()
                    .filter(item -> categoryNames.contains(item.getCategoryName()))
                    .map(item -> beanMapper.map(item, ExpenseCategory.class, entity -> {
                        entity.setTenantId(tenantId);
                        entity.setPropertyId(propertyId);
                        entity.setReportId(monthlyReportId);
                        entity.setCategoryId(name2CategoryId.get(item.getCategoryName()));
                        entity.setUpdateId(userId);
                        entity.setUpdateTime(DateTimeUtils.nowTimestamp());
                    })).toList();
            if (CollectionUtils.isEmpty(expenseCategorys)) return;
            expenseCategoryMapper.saveOrUpdateByUnique(expenseCategorys);
        }

        /**
         * 删除区域数据
         *
         * @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<ExpenseCategory>()
                    .in(ExpenseCategory::getReportId, reportIds)
                    .eq(ExpenseCategory::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<ExpenseCategory> expenseCategorys = list(new LambdaQueryWrapper<ExpenseCategory>()
                    .in(ExpenseCategory::getReportId, monthlyReportIds)
                    .eq(ExpenseCategory::getPropertyId, propertyDTO.getId())
                    .eq(ExpenseCategory::getCategoryId, areaTypeConfig.getId()));
            if (CollectionUtils.isEmpty(expenseCategorys)) return;

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

        /**
         * 删除区域分类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<ExpenseCategory>()
                    .in(ExpenseCategory::getReportId, monthlyReportIds)
                    .eq(ExpenseCategory::getPropertyId, propertyDTO.getId())
                    .eq(ExpenseCategory::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<ExpenseCategory> expenseCategorys = monthlyReports.stream()
                    .map(monthlyReport -> ExpenseCategory.builder()
                            .tenantId(propertyDTO.getTenantId())
                            .propertyId(propertyDTO.getId())
                            .reportId(monthlyReport.getId())
                            .categoryId(areaTypeConfig.getId())
                            .categoryName(areaTypeConfig.getName())
                            .updateId(0)
                            .updateTime(DateTimeUtils.nowTimestamp())
                            .build())
                    .toList();
            saveBatch(expenseCategorys);
        }

        /**
         * 初始化区域数据
         *
         * @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.EXPENSES.getAreaId());
            }).toList();

            if (CollectionUtils.isEmpty(openAreaMonthlyReports)) return;

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

            List<ExpenseCategory> expenseCategorys = Lists.newArrayListWithCapacity(areaTypeConfigs.size() * openAreaMonthlyReports.size());

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

        ;
    }