# TaReportController.java

    package cloud.wconnect.finance.controller.ta;

    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.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.group.Addition;
    import cloud.wconnect.commonlib.pojo.dto.group.Edition;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.finance.cons.ta.TaReportTypeCons;
    import cloud.wconnect.finance.entity.ta.TaImportLog;
    import cloud.wconnect.finance.pojo.dto.ta.report.TaImportLogDTO;
    import cloud.wconnect.finance.pojo.dto.ta.report.TaImportReportDTO;
    import cloud.wconnect.finance.pojo.query.ta.TaImportLogQuery;
    import cloud.wconnect.finance.service.ta.ITaImportLogService;
    import cloud.wconnect.finance.service.ta.creditcard.ITaCreditCardParseService;
    import cloud.wconnect.finance.service.ta.ota.ITaOtaParseService;
    import cloud.wconnect.finance.service.ta.portal.ITaPortalParseService;
    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.util.Collection;
    import java.util.Collections;
    import java.util.Map;
    import java.util.Objects;

    /**
     * <p>
     * TA Report 前端控制器
     * </p>
     *
     * @author zc
     * @since 2023-07-07
     */
    @RestController
    @RequestMapping("/ta/report")
    public class TaReportController {
        @Resource
        private ITaImportLogService importLogService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private SessionContext sessionContext;
        @Resource
        private ApplicationContext applicationContext;

        /**
         * 导入报告
         *
         * @param property        资产标识
         * @param importReportDTO 导入报告 DTO
         * @return empty map
         * @author zc
         * @date 2023/7/26
         */
        @ApiId(439)
        @PostMapping
        public Map<Object, Object> importReport(@RequestParam String property,
                                                @Validated(Addition.class) TaImportReportDTO importReportDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            if (importReportDTO.getReportType().equals(TaReportTypeCons.CREDIT_CARD)) {
                importCreditCardReport(propertyDTO, importReportDTO);
            } else if (importReportDTO.getReportType().equals(TaReportTypeCons.OTA)) {
                importOtaReport(propertyDTO, importReportDTO);
            } else {
                importPortalReport(propertyDTO, importReportDTO);
            }

            return Collections.emptyMap();
        }

        /**
         * 导入 Credit Card 报告
         *
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void importCreditCardReport(PropertyDTO propertyDTO, TaImportReportDTO importReportDTO) {
            // 转换来源标识
            String source = TaImportReportDTO.TYPE_OPERA == importReportDTO.getType() ?
                    SystemPlatformEnum.OPERA.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            ITaCreditCardParseService parser = getCreditCardParser(source);

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

            // 插入处理中导入记录
            long logId = importLogService.add(propertyDTO, importReportDTO.getTheDate(), TaReportTypeCons.CREDIT_CARD,
                    ReportImportResultCons.IMPORT_IN_PROGRESS, sessionContext.getLoginUserId(), null);

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importReportDTO.getTheDate(),
                    logId, sessionContext.getLoginUserId());
        }

        /**
         * 导入 OTA 报告
         *
         * @param propertyDTO     资产
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void importOtaReport(PropertyDTO propertyDTO, TaImportReportDTO importReportDTO) {
            // 转换来源标识
            String source = TaImportReportDTO.TYPE_OPERA == importReportDTO.getType() ?
                    SystemPlatformEnum.OPERA.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            ITaOtaParseService parser = getOtaParser(source);

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

            // 插入处理中导入记录
            long logId = importLogService.add(propertyDTO, importReportDTO.getTheDate(), TaReportTypeCons.OTA,
                    ReportImportResultCons.IMPORT_IN_PROGRESS, sessionContext.getLoginUserId(), null);

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importReportDTO.getTheDate(),
                    logId, sessionContext.getLoginUserId());
        }

        /**
         * 导入 Portal 报告
         *
         * @param propertyDTO     资产
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void importPortalReport(PropertyDTO propertyDTO, TaImportReportDTO importReportDTO) {
            ITaPortalParseService parser = getPortalParser(SystemPlatformEnum.OTHER.getDesc());

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

            // 插入处理中导入记录
            long logId = importLogService.add(propertyDTO, importReportDTO.getTheDate(), TaReportTypeCons.PORTAL,
                    ReportImportResultCons.IMPORT_IN_PROGRESS, sessionContext.getLoginUserId(), null);

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importReportDTO.getTheDate(),
                    logId, sessionContext.getLoginUserId());
        }

        /**
         * 解决异常导入报告
         *
         * @param property        资产标识
         * @param id              异常记录 id
         * @param importReportDTO 导入报告 DTO
         * @return empty map
         * @author zc
         * @date 2023/7/26
         */
        @ApiId(867)
        @PostMapping("/exception/{id:\\d+}")
        public Map<Object, Object> resolve(@RequestParam String property, @PathVariable long id,
                                           @Validated(Edition.class) TaImportReportDTO importReportDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);

            // 校验记录是否存在
            TaImportLog importLog = importLogService.checkExist(id);
            // 校验记录归属
            importLogService.checkBelong(propertyDTO.getTenantId(), propertyDTO.getId(), importLog);
            // 校验是否是失败、缺失记录
            checkImportResult(importLog.getImportResult());

            if (importLog.getReportType().equals(TaReportTypeCons.CREDIT_CARD)) {
                resolveCreditCard(propertyDTO, importLog, importReportDTO);
            } else if (importLog.getReportType().equals(TaReportTypeCons.OTA)) {
                resolveOta(propertyDTO, importLog, importReportDTO);
            } else {
                resolvePortal(propertyDTO, importLog, importReportDTO);
            }
            return Collections.emptyMap();
        }

        /**
         * 解决 Credit Card 异常记录
         *
         * @param propertyDTO     资产
         * @param importLog       异常记录
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void resolveCreditCard(PropertyDTO propertyDTO, TaImportLog importLog, TaImportReportDTO importReportDTO) {
            // 转换来源标识
            String source = TaImportReportDTO.TYPE_OPERA == importReportDTO.getType() ?
                    SystemPlatformEnum.OPERA.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            ITaCreditCardParseService parser = getCreditCardParser(source);

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

            // 更新日志为修复中
            importLogService.updateById(TaImportLog.builder()
                    .id(importLog.getId()).importResult(ReportImportResultCons.IMPORT_RESULT_REPAIRING).build());

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importLog.getDataDate(),
                    importLog.getId(), sessionContext.getLoginUserId());
        }

        /**
         * 解决 OTA 异常记录
         *
         * @param propertyDTO     资产
         * @param importLog       异常记录
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void resolveOta(PropertyDTO propertyDTO, TaImportLog importLog, TaImportReportDTO importReportDTO) {
            // 转换来源标识
            String source = TaImportReportDTO.TYPE_OPERA == importReportDTO.getType() ?
                    SystemPlatformEnum.OPERA.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            ITaOtaParseService parser = getOtaParser(source);

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

            // 更新日志为修复中
            importLogService.updateById(TaImportLog.builder()
                    .id(importLog.getId()).importResult(ReportImportResultCons.IMPORT_RESULT_REPAIRING).build());

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importLog.getTheDate(),
                    importLog.getId(), sessionContext.getLoginUserId());
        }

        /**
         * 解决 Portal 异常记录
         *
         * @param propertyDTO     资产
         * @param importLog       异常记录
         * @param importReportDTO 导入报告 DTO
         * @author zc
         * @date 2024/8/22
         */
        private void resolvePortal(PropertyDTO propertyDTO, TaImportLog importLog, TaImportReportDTO importReportDTO) {
            ITaPortalParseService parser = getPortalParser(SystemPlatformEnum.OTHER.getDesc());

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

            // 更新日志为修复中
            importLogService.updateById(TaImportLog.builder()
                    .id(importLog.getId()).importResult(ReportImportResultCons.IMPORT_RESULT_REPAIRING).build());

            // 处理数据
            parser.handleData(propertyDTO, importReportDTO.getFile(), importLog.getDataDate(),
                    importLog.getId(), sessionContext.getLoginUserId());
        }

        /**
         * 获取导入记录
         *
         * @param property         资产标识
         * @param taImportLogQuery 查询条件
         * @return TaExceptionsDTO
         * @author zc
         * @date 2023/7/18
         */
        @ApiId(438)
        @GetMapping("/import-log")
        public ListPagedDTO<TaImportLogDTO> listImportLog(String property, @Valid TaImportLogQuery taImportLogQuery) {
            int tenantId = sessionContext.getTenantSymbolBO().getId();
            int propertyId = sessionContext.getPropertyId(property);

            return importLogService.list(tenantId, propertyId, taImportLogQuery);
        }

        /**
         * 忽略报告异常
         *
         * @param id       异常记录 id
         * @param property 资产标识
         * @author zc
         * @date 2023/7/18
         */
        @ApiId(440)
        @PutMapping("/{id:\\d+}/ignore")
        public Map<Object, Object> ignore(@PathVariable long id, String property) {
            int tenantId = sessionContext.getTenantSymbolBO().getId();
            int propertyId = sessionContext.getPropertyId(property);

            // 校验是否存在
            TaImportLog taImportLog = importLogService.checkExist(id);
            // 校验归属
            importLogService.checkBelong(tenantId, propertyId, taImportLog);
            // 校验是否是失败、缺失记录
            checkImportResult(taImportLog.getImportResult());

            taImportLog.setResolvedBy(sessionContext.getLoginUserId());
            taImportLog.setResolvedTime(DateTimeUtils.nowTimestamp());
            taImportLog.setImportResult(ReportImportResultCons.IMPORT_RESULT_IGNORE);
            importLogService.updateById(taImportLog);

            return Collections.emptyMap();
        }

        /**
         * 校验是否是失败、缺失记录
         *
         * @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");
            }
        }

        /**
         * 获取报告解析服务 for Credit Card
         *
         * @param source 来源标识
         * @return 报告解析服务
         * @author zc
         * @date 2024/8/21
         */
        private ITaCreditCardParseService getCreditCardParser(String source) {
            Collection<ITaCreditCardParseService> parserList = applicationContext.getBeansOfType(ITaCreditCardParseService.class).values();
            ITaCreditCardParseService parser = null;
            for (ITaCreditCardParseService 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 TA Credit Card report parser");
            }
            return parser;
        }

        /**
         * 获取报告解析服务 for OTA
         *
         * @param source 来源标识
         * @return 报告解析服务
         * @author zc
         * @date 2024/8/21
         */
        private ITaOtaParseService getOtaParser(String source) {
            Collection<ITaOtaParseService> parserList = applicationContext.getBeansOfType(ITaOtaParseService.class).values();
            ITaOtaParseService parser = null;
            for (ITaOtaParseService 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 TA OTA report parser");
            }
            return parser;
        }

        /**
         * 获取报告解析服务 for Portal
         *
         * @param source 来源标识
         * @return 报告解析服务
         * @author zc
         * @date 2024/8/22
         */
        private ITaPortalParseService getPortalParser(String source) {
            Collection<ITaPortalParseService> parserList = applicationContext.getBeansOfType(ITaPortalParseService.class).values();
            ITaPortalParseService parser = null;
            for (ITaPortalParseService 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 TA Portal report parser");
            }
            return parser;
        }
    }