# SalesReportController.java

    package cloud.wconnect.workperformance.controller.mor.salessources;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.ReportImportResultCons;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.group.Edition;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.mor.SalesImportLog;
    import cloud.wconnect.workperformance.pojo.dto.mor.sales.SalesImportLogDTO;
    import cloud.wconnect.workperformance.pojo.dto.mor.sales.SalesImportReportDTO;
    import cloud.wconnect.workperformance.pojo.query.mor.sales.SalesImportLogQuery;
    import cloud.wconnect.workperformance.service.mor.ISalesImportLogService;
    import cloud.wconnect.workperformance.service.mor.operatingstatistics.ISalesOperatingStatisticsParseService;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Sets;
    import jakarta.annotation.Resource;
    import jakarta.validation.Valid;
    import org.springframework.context.ApplicationContext;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;

    import java.text.MessageFormat;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * 控制器类：销售额信息 - 报告导入
     *
     * @author zc
     * @date 2024/06/01
     */
    @RestController
    @RequestMapping("/mor/sales-sources/report")
    public class SalesReportController {
        @Resource
        private ISalesImportLogService importLogService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private SessionContext sessionContext;
        @Resource
        private ApplicationContext applicationContext;

        /**
         * 获取报告导入记录
         *
         * @param property 资产标识
         * @param query    查询条件
         * @return SalesImportLogDTO 集合
         * @author zc
         * @date 2024/6/1
         */
        @ApiId(1182)
        @GetMapping("/import-log")
        public ListPagedDTO<SalesImportLogDTO> listImportLog(@RequestParam String property, @Valid SalesImportLogQuery query) {
            int tenantId = sessionContext.getTenantSymbolBO().getId();
            int propertyId = sessionContext.getPropertyId(property);
            return importLogService.list(tenantId, propertyId, query);
        }

        /**
         * 解决导入异常记录
         *
         * @param property        资产标识
         * @param id              异常记录 id
         * @param importReportDTO Import Report DTO
         * @return empty map
         * @author zc
         * @date 2024/6/1
         */
        @ApiId(1183)
        @PutMapping("/import-log/{id:\\d+}/resolve")
        public Map<Object, Object> resolve(@RequestParam String property, @PathVariable long id,
                                           @Validated(Edition.class) SalesImportReportDTO importReportDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            // 校验是否存在
            SalesImportLog importLog = importLogService.checkExist(id);
            // 校验归属
            importLogService.checkBelong(propertyId, importLog);
            // 校验是否是失败、缺失记录
            checkImportResult(importLog.getImportResult());

            // 解决异常
            if (Objects.nonNull(importReportDTO.getFile()) && Objects.nonNull(importReportDTO.getSource())) {
                List<PropertyDTO> propertyDTOList = propertyI18nRedisService.list(Lists.newArrayList(propertyId));

                // 转换来源标识
                String source = SalesImportReportDTO.SOURCE_M3 == importReportDTO.getSource() ?
                        SystemPlatformEnum.M3.getDesc() : SystemPlatformEnum.OTHER.getDesc();

                ISalesOperatingStatisticsParseService parser = getOperatingStatisticsReportParser(source);

                // 校验文件是否满足需求
                parser.checkFile(propertyDTOList, importReportDTO.getFile());

                // 组装资产数据范围
                Map<Integer, List<Long>> propertyId2DateRange = propertyDTOList.stream()
                        .collect(Collectors.toMap(PropertyDTO::getId, propertyDTO ->
                                Lists.newArrayList(importLog.getStartDate(), importLog.getEndDate())));

                // 更新日志为修复中
                importLogService.updateById(new SalesImportLog().setId(id)
                        .setImportResult(ReportImportResultCons.IMPORT_RESULT_REPAIRING));

                // 处理数据
                parser.handleData(propertyDTOList, importReportDTO.getFile(), propertyId2DateRange, Lists.newArrayList(id),
                        sessionContext.getLoginUserId());
            } else {
                // 更新记录为忽略
                importLogService.updateById(new SalesImportLog().setId(id)
                        .setImportResult(ReportImportResultCons.IMPORT_RESULT_IGNORE)
                        .setResolvedBy(sessionContext.getLoginUserId())
                        .setResolvedTime(DateTimeUtils.nowTimestamp()));
            }
            return Collections.emptyMap();
        }

        /**
         * 导入报告
         *
         * @param importReportDTO 导入报告 DTO
         * @return empty map
         * @author zc
         * @date 2024/6/3
         */
        @ApiId(1184)
        @PostMapping
        public Map<Objects, Objects> importReport(@Validated(Edition.class) SalesImportReportDTO importReportDTO) {
            // 校验日期范围
            dateParamCheck(importReportDTO.getStartDate(), importReportDTO.getEndDate());
            // 校验是否有权限处理资产数据
            List<Integer> propertyIds = importReportDTO.getPropertyIds();
            if (!Sets.newHashSet(sessionContext.getPropertyIds()).containsAll(propertyIds)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        "Cannot be operated others property data; propertyIds: " + propertyIds);
            }
            List<PropertyDTO> propertyDTOList = propertyI18nRedisService.list(propertyIds);

            // 转换来源标识
            String source = SalesImportReportDTO.SOURCE_M3 == importReportDTO.getSource() ?
                    SystemPlatformEnum.M3.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            ISalesOperatingStatisticsParseService parser = getOperatingStatisticsReportParser(source);

            // 校验文件是否满足需求
            parser.checkFile(propertyDTOList, importReportDTO.getFile());

            // 组装资产数据范围
            Map<Integer, List<Long>> propertyId2DateRange = propertyDTOList.stream()
                    .collect(Collectors.toMap(PropertyDTO::getId, propertyDTO ->
                            Lists.newArrayList(importReportDTO.getStartDate(), importReportDTO.getEndDate())));

            // 插入进行中导入记录
            List<Long> importLogIds = importLogService.addBatch(propertyDTOList, propertyId2DateRange,
                    SalesImportReportDTO.REPORT_TYPE_OPERATING, ReportImportResultCons.IMPORT_IN_PROGRESS,
                    sessionContext.getLoginUserId(), null, new HashMap<>());

            // 处理数据
            parser.handleData(propertyDTOList, importReportDTO.getFile(), propertyId2DateRange,
                    importLogIds, sessionContext.getLoginUserId());

            return Collections.emptyMap();
        }

        /**
         * 校验日期查询条件
         *
         * @param startDate 开始时间
         * @param endDate   结束时间
         * @author zc
         * @date 2024/6/3
         */
        private void dateParamCheck(long startDate, long endDate) {
            if (startDate > endDate) {
                throw new BadRequestException(CommonErrorI18nConstant.START_DATE_CANNOT_GREATER_THAN_END_DATE,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The startDate cannot be greater than endDate; startDate:{0}, endDate:{1}",
                                startDate, endDate));
            }
        }

        /**
         * 校验是否是失败、缺失记录
         *
         * @param importResult 导入记录状态
         * @author zc
         * @date 2024/6/13
         */
        private void checkImportResult(int importResult) {
            if (importResult != ReportImportResultCons.IMPORT_RESULT_FAIL
                    && importResult != ReportImportResultCons.IMPORT_RESULT_MISSED) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_INTEGRATION_ONLY_HANDLE_EXCEPTION,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "Cannot operate status is not importResultFail or importResultMissed log");
            }
        }

        /**
         * 获取加班报告解析服务
         *
         * @param source 来源标识
         * @return 报告解析服务
         * @author zc
         * @date 2024/8/19
         */
        private ISalesOperatingStatisticsParseService getOperatingStatisticsReportParser(String source) {
            Collection<ISalesOperatingStatisticsParseService> parserList =
                    applicationContext.getBeansOfType(ISalesOperatingStatisticsParseService.class).values();
            ISalesOperatingStatisticsParseService parser = null;
            for (ISalesOperatingStatisticsParseService parseService : parserList) {
                if (parseService.supports(source)) {
                    parser = parseService;
                    break;
                }
            }
            if (Objects.isNull(parser)) {
                throw new BadRequestException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(),
                        "Can not find Mor Sales Source Operating Statistics report parser");
            }
            return parser;
        }
    }