# CustomerSatisfactionServiceImpl.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.S3Utils;
    import cloud.wconnect.commonlib.util.TransactionUtils;
    import cloud.wconnect.workperformance.cons.S3BucketFunctionCons;
    import cloud.wconnect.workperformance.cons.monthlyreport.AreaEnum;
    import cloud.wconnect.workperformance.entity.monthlyreport.*;
    import cloud.wconnect.workperformance.mapper.monthlyreport.CustomerSatisfactionMapper;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.AttachmentDTO;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.customersatisfaction.CustomerSatisfactionDetailDTO;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.customersatisfaction.CustomerScoreDTO;
    import cloud.wconnect.workperformance.service.monthlyreport.ICustomerSatisfactionService;
    import cloud.wconnect.workperformance.service.monthlyreport.ICustomerScoreService;
    import cloud.wconnect.workperformance.service.monthlyreport.IHandlePropertySettingChange;
    import cloud.wconnect.workperformance.service.monthlyreport.IReportAttachmentService;
    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.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.concurrent.Executor;

    /**
     * <p>
     * 月报Customer Satisfaction（客户满意度）区域 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-09-01
     */
    @Service
    @DS("monthly_report")
    public class CustomerSatisfactionServiceImpl extends ServiceImpl<CustomerSatisfactionMapper, CustomerSatisfaction> implements ICustomerSatisfactionService, IHandlePropertySettingChange {

        @Autowired
        private ICustomerScoreService customerScoreService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IReportAttachmentService reportAttachmentService;
        @Value("${aws-s3.region}")
        private String region;
        @Value("#{${aws-s3.function-bucket}}")
        private Map<String, Map<String, Object>> bucketMap;
        @Autowired
        private Executor executor;

        /**
         * 查询客户满意度详情
         *
         * @param monthlyReport 月报
         * @param propertyId    资产id
         * @return cloud.wconnect.workperformance.pojo.dto.monthlyreport.CustomerSatisfactionDTO
         * @author lichen
         * @date 2023/9/4
         */
        @Override
        public CustomerSatisfactionDetailDTO getCustomerSatisfaction(MonthlyReport monthlyReport, Integer propertyId) {
            //查询客户满意度
            CustomerSatisfaction customerSatisfaction = getOne(new LambdaQueryWrapper<CustomerSatisfaction>()
                    .eq(CustomerSatisfaction::getReportId, monthlyReport.getId())
                    .eq(CustomerSatisfaction::getPropertyId, propertyId));
            //查询客户评分
            List<CustomerScoreDTO> customerScoreDTOS = customerScoreService.listByReportId(propertyId, monthlyReport.getId())
                    .stream().map(item -> beanMapper.map(item, CustomerScoreDTO.class)).toList();
            //查询附件
            List<AttachmentDTO> attachmentDTOS = reportAttachmentService.listByReportIdAndAreaId(propertyId, monthlyReport.getId(), AreaEnum.CUSTOMER_SATISFACTION.getAreaId())
                    .stream().map(item -> beanMapper.map(item, AttachmentDTO.class)).toList();
            if (Objects.isNull(customerSatisfaction)) {
                CustomerSatisfactionDetailDTO customerSatisfactionDetailDTO = new CustomerSatisfactionDetailDTO();
                //客户评分
                customerSatisfactionDetailDTO.setCustomerScores(customerScoreDTOS);
                //附件
                customerSatisfactionDetailDTO.setAttachments(attachmentDTOS);
                return customerSatisfactionDetailDTO;
            }
            return beanMapper.map(customerSatisfaction, CustomerSatisfactionDetailDTO.class, dto -> {
                dto.setCustomerScores(customerScoreDTOS);
                dto.setAttachments(attachmentDTOS);
            });
        }

        /**
         * 保存客户满意度数据
         *
         * @param monthlyReport                 月报
         * @param propertyDTO                   资产DTO
         * @param customerSatisfactionDetailDTO 客户满意度数据
         * @param loginUserId                   登录用户id
         * @return void
         * @author lichen
         * @date 2023/9/4
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void save(MonthlyReport monthlyReport, PropertyDTO propertyDTO, CustomerSatisfactionDetailDTO customerSatisfactionDetailDTO, int loginUserId) {
            Integer propertyId = propertyDTO.getId();
            Integer tenantId = propertyDTO.getTenantId();
            //保存前的s3key集合
            List<String> saveBeforeS3Keys = reportAttachmentService.listByReportIdAndAreaId(propertyId, monthlyReport.getId(), AreaEnum.CUSTOMER_SATISFACTION.getAreaId())
                    .stream().map(ReportAttachment::getFileKey).toList();

            remove(new LambdaQueryWrapper<CustomerSatisfaction>()
                    .eq(CustomerSatisfaction::getReportId, monthlyReport.getId())
                    .eq(CustomerSatisfaction::getPropertyId, propertyId));
            reportAttachmentService.removeByReportIdAndAreaId(propertyId, monthlyReport.getId(), AreaEnum.CUSTOMER_SATISFACTION.getAreaId());
            customerScoreService.remove(new LambdaQueryWrapper<CustomerScore>()
                    .eq(CustomerScore::getReportId, monthlyReport.getId())
                    .eq(CustomerScore::getPropertyId, propertyId));

            //新增客户满意度信息
            CustomerSatisfaction customerSatisfaction = beanMapper.map(customerSatisfactionDetailDTO, CustomerSatisfaction.class, entity -> {
                entity.setTenantId(tenantId);
                entity.setPropertyId(propertyId);
                entity.setReportId(monthlyReport.getId());
                entity.setUpdateId(loginUserId);
                entity.setUpdateTime(DateTimeUtils.nowTimestamp());
            });
            save(customerSatisfaction);

            //新增附件
            List<AttachmentDTO> attachments = customerSatisfactionDetailDTO.getAttachments();
            List<String> saveAfterS3Keys = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(attachments)) {
                List<ReportAttachment> reportAttachments = Lists.newArrayListWithCapacity(attachments.size());
                for (AttachmentDTO attachment : attachments) {
                    reportAttachments.add(ReportAttachment.builder()
                            .tenantId(tenantId)
                            .propertyId(propertyId)
                            .reportId(monthlyReport.getId())
                            .areaId(AreaEnum.CUSTOMER_SATISFACTION.getAreaId())
                            .fileName(attachment.getFileName())
                            .fileKey(attachment.getFileKey())
                            .build());
                    saveAfterS3Keys.add(attachment.getFileKey());
                }
                reportAttachmentService.saveBatch(reportAttachments);
            }

            //新增客户评分
            List<CustomerScoreDTO> customerScoreDTOS = customerSatisfactionDetailDTO.getCustomerScores();
            if (CollectionUtils.isNotEmpty(customerScoreDTOS)) {
                List<CustomerScore> customerScores = customerScoreDTOS.stream().map(item -> CustomerScore.builder()
                        .tenantId(tenantId)
                        .propertyId(propertyId)
                        .reportId(monthlyReport.getId())
                        .score(item.getScore())
                        .reason(item.getReason())
                        .updateId(loginUserId)
                        .updateTime(DateTimeUtils.nowTimestamp())
                        .build()).toList();
                customerScoreService.saveBatch(customerScores);
            }
            /**
             * 事务提交后删除s3附件
             */
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                List<String> delS3Keys = Lists.newArrayList(saveBeforeS3Keys);
                delS3Keys.removeAll(saveAfterS3Keys);
                S3Utils.batchDeleteFile(region, bucketMap.get(S3BucketFunctionCons.MONTHLY_REPORT), delS3Keys);
            });
        }

        /**
         * 删除区域数据
         *
         * @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<CustomerSatisfaction>()
                    .in(CustomerSatisfaction::getReportId, reportIds)
                    .eq(CustomerSatisfaction::getPropertyId, propertyDTO.getId()));
        }
    }