# SalesKpiWeeklyAttachmentServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.service.UserInternalService;
    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.entity.saleskpi.SalesKpiWeeklyAttachment;
    import cloud.wconnect.workperformance.mapper.saleskpi.SalesKpiWeeklyAttachmentMapper;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.SalesKpiAttachmentDTO;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiWeeklyAttachmentService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import jakarta.annotation.Resource;
    import java.util.Map;
    import java.util.Objects;
    import java.util.concurrent.Executor;

    /**
     * <p>
     * 服务实现类
     * </p>
     *
     * @author zc
     * @since 2023-09-05
     */
    @Service
    @DS("work_performance")
    public class SalesKpiWeeklyAttachmentServiceImpl extends ServiceImpl<SalesKpiWeeklyAttachmentMapper, SalesKpiWeeklyAttachment> implements ISalesKpiWeeklyAttachmentService {
        @Resource
        private UserInternalService userInternalService;
        @Resource
        private Executor executor;

        @Value("${aws-s3.region}")
        private String region;
        @Value("#{${aws-s3.function-bucket}}")
        private Map<String, Map<String, Object>> bucketMap;

        /**
         * 获取 Weekly 附件
         *
         * @param tenantId   租户 id
         * @param propertyId 资产 id
         * @param weekly     周（yyyyMMdd）
         * @return SalesKpiAttachmentDTO
         * @author zc
         * @date 2023/9/11
         */
        @Override
        public SalesKpiAttachmentDTO getAttachment(int tenantId, int propertyId, long weekly) {
            SalesKpiWeeklyAttachment attachment = getOne(new QueryWrapper<SalesKpiWeeklyAttachment>().lambda()
                    .eq(SalesKpiWeeklyAttachment::getPropertyId, propertyId)
                    .eq(SalesKpiWeeklyAttachment::getWeekly, weekly));
            if (Objects.isNull(attachment)) {
                return null;
            }

            // 提取操作人名称
            Map<Integer, String> userId2Name = userInternalService.getNameMapByIds(tenantId,
                    Lists.newArrayList(attachment.getUpdateBy()));

            return SalesKpiAttachmentDTO.builder()
                    .url(attachment.getUrl())
                    .crawlUrl(attachment.getCrawUrl())
                    .updateUid(attachment.getUpdateBy())
                    .updateName(userId2Name.get(attachment.getUpdateBy()))
                    .updateTime(attachment.getUpdateTime())
                    .build();
        }

        /**
         * 保存 Weekly 附件
         *
         * @param weekly     周（yyyyMMdd）
         * @param propertyId 资产 id
         * @param operatorId 操作人 id
         * @param url        附件
         * @author zc
         * @date 2023/9/11
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveAttachment(long weekly, int propertyId, int operatorId, String url) {
            // 获取原数据
            SalesKpiWeeklyAttachment originAttachment = getByWeekly(weekly, propertyId);

            // 组装参数
            SalesKpiWeeklyAttachment attachment = new SalesKpiWeeklyAttachment();
            attachment.setUrl(url);
            attachment.setUpdateBy(operatorId);
            attachment.setUpdateTime(DateTimeUtils.nowTimestamp());
            if (Objects.isNull(originAttachment)) {
                // 新增
                attachment.setWeekly(weekly);
                attachment.setPropertyId(propertyId);
                attachment.setCrawUrl(StringUtils.EMPTY);
            } else {
                // 更新
                attachment.setId(originAttachment.getId());
                //删除原附件
                TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                    S3Utils.deleteFile(region,bucketMap.get(S3BucketFunctionCons.SALES_KPI),originAttachment.getUrl());
                });
            }

            // 保存附件数据
            saveOrUpdate(attachment);
        }

        /**
         * 根据 Weekly 获取附件数据
         *
         * @param weekly     周（yyyyMMdd）
         * @param propertyId 资产 id
         * @return SalesKpiWeeklyAttachment
         * @author zc
         * @date 2023/9/11
         */
        private SalesKpiWeeklyAttachment getByWeekly(long weekly, int propertyId) {
            return getOne(new QueryWrapper<SalesKpiWeeklyAttachment>().lambda()
                    .eq(SalesKpiWeeklyAttachment::getPropertyId, propertyId)
                    .eq(SalesKpiWeeklyAttachment::getWeekly, weekly));
        }

        /**
         * 保存采集附件
         *
         * @param weekly     周（yyyyMMdd）
         * @param propertyId 资产 id
         * @param url        附件
         * @author zc
         * @date 2023/9/11
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveAttachmentByCrawl(long weekly, int propertyId, String url) {
            if (StringUtils.isBlank(url)) {
                return;
            }
            // 获取原数据
            SalesKpiWeeklyAttachment originAttachment = getByWeekly(weekly, propertyId);

            // 组装参数
            SalesKpiWeeklyAttachment attachment = new SalesKpiWeeklyAttachment();
            attachment.setCrawUrl(url);
            attachment.setUpdateTime(DateTimeUtils.nowTimestamp());
            if (Objects.isNull(originAttachment)) {
                // 新增
                attachment.setWeekly(weekly);
                attachment.setPropertyId(propertyId);
                attachment.setUrl(url);
                attachment.setUpdateBy(BaseConstant.ZERO);
            } else {
                // 更新
                attachment.setId(originAttachment.getId());
                if (StringUtils.isBlank(originAttachment.getUrl())) {
                    attachment.setUrl(url);
                }
            }

            // 保存附件数据
            saveOrUpdate(attachment);
        }

        /**
         * 删除附件
         *
         * @param weekly     周（yyyyMMdd）
         * @param propertyId 资产 id
         * @author zc
         * @date 2023/9/11
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void deleteAttachment(long weekly, int propertyId) {
            SalesKpiWeeklyAttachment attachment = getOne(new QueryWrapper<SalesKpiWeeklyAttachment>().lambda()
                    .eq(SalesKpiWeeklyAttachment::getPropertyId, propertyId)
                    .eq(SalesKpiWeeklyAttachment::getWeekly, weekly));
            if (Objects.isNull(attachment)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The attachment is not found; weekly: " + weekly + "; propertyId: " + propertyId);
            }
            removeById(attachment.getId());

            //删除附件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                S3Utils.deleteFile(region,bucketMap.get(S3BucketFunctionCons.SALES_KPI),attachment.getUrl());
            });
        }
    }