# SvaEmployeesReportController.java

    package cloud.wconnect.workperformance.controller.sva.employees;

    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.Addition;
    import cloud.wconnect.commonlib.pojo.dto.group.Edition;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.workperformance.entity.sva.employees.AttendanceEmpImportLog;
    import cloud.wconnect.workperformance.pojo.dto.sva.employee.EmployeeImportReportDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.employee.SvaEmployeesImportLogDTO;
    import cloud.wconnect.workperformance.pojo.query.ImportLogQuery;
    import cloud.wconnect.workperformance.service.sva.employees.IAttendanceEmpImportLogService;
    import cloud.wconnect.workperformance.service.sva.employees.employee.ISvaEmployeeParseService;
    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.util.*;

    /**
     * 控制器类: SVA Employees Report
     *
     * @author zc
     * @date 2023/10/19
     */
    @RestController
    @RequestMapping("/sva/employees/report")
    public class SvaEmployeesReportController {
        @Resource
        private IAttendanceEmpImportLogService importLogService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private SessionContext sessionContext;
        @Resource
        private ApplicationContext applicationContext;

        /**
         * 忽略异常记录
         *
         * @param property 资产标识
         * @param id       异常记录 id
         * @return empty map
         * @author zc
         * @date 2023/3/27
         */
        @ApiId(171)
        @PutMapping("/exception/ignore/{id:\\d+}")
        public Map<Object, Object> ignore(@RequestParam String property, @PathVariable int id) {
            int propertyId = sessionContext.getPropertyId(property);
            // 校验是否存在
            AttendanceEmpImportLog importLog = importLogService.checkExist(id);
            // 校验归属
            importLogService.checkBelong(propertyId, importLog);
            // 校验是否是失败、缺失记录
            checkImportResult(importLog.getImportResult());

            importLogService.ignore(id, sessionContext.getLoginUserId());

            return Collections.emptyMap();
        }

        /**
         * 导入员工报告
         *
         * @param importReportDTO 导入报告 DTO
         * @return Empty Map
         * @author zc
         * @date 2023/2/24
         */
        @ApiId(67)
        @PostMapping
        public Map<Object, Object> importReport(@Validated(Addition.class) EmployeeImportReportDTO importReportDTO) {
            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; propertyIdRange: " + propertyIds);
            }
            List<PropertyDTO> propertyDTOList = propertyI18nRedisService.list(propertyIds);

            // 转换来源标识
            String source = EmployeeImportReportDTO.TYPE_ADP == importReportDTO.getType() ?
                    SystemPlatformEnum.ADP.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            // 获取解析器
            ISvaEmployeeParseService parser = getEmployeeReportParser(source);

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

            // 插入处理中导入记录
            List<Long> importLogIds = importLogService.addBatch(propertyDTOList,
                    ReportImportResultCons.IMPORT_IN_PROGRESS, sessionContext.getLoginUserId(), null);

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

            return Collections.emptyMap();
        }

        /**
         * 解决导入异常
         *
         * @param property        资产标识
         * @param id              异常 id
         * @param importReportDTO 导入报告 DTO
         * @return Empty Map
         * @author zc
         * @date 2023/10/19
         */
        @ApiId(862)
        @PostMapping("/exception/{id:\\d+}")
        public Map<Object, Object> resolve(@RequestParam String property, @PathVariable long id,
                                           @Validated(Edition.class) EmployeeImportReportDTO importReportDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            // 校验日志是否存在
            AttendanceEmpImportLog importLog = importLogService.checkExist(id);
            // 校验日志归属
            importLogService.checkBelong(propertyDTO.getId(), importLog);
            // 校验是否是失败、缺失记录
            checkImportResult(importLog.getImportResult());

            // 转换来源标识
            String source = EmployeeImportReportDTO.TYPE_ADP == importReportDTO.getType() ?
                    SystemPlatformEnum.ADP.getDesc() : SystemPlatformEnum.OTHER.getDesc();

            // 获取解析的类集合
            ISvaEmployeeParseService parser = getEmployeeReportParser(source);

            List<PropertyDTO> propertyDTOList = Lists.newArrayList(propertyDTO);
            // 校验文件后缀、内容是否满足需求
            parser.checkFile(propertyDTOList, importReportDTO.getFile());

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

            // 处理数据
            parser.handleData(propertyDTOList, importReportDTO.getFile(), Lists.newArrayList(id), sessionContext.getLoginUserId());

            return Collections.emptyMap();
        }

        /**
         * 查询报告导入记录
         *
         * @param property 资产标识
         * @param query    查询条件
         * @return SvaEmployeesImportLogDTO
         * @author zc
         * @date 2023/10/19
         */
        @ApiId(863)
        @GetMapping("/import-log")
        public ListPagedDTO<SvaEmployeesImportLogDTO> listImportLog(String property, @Valid ImportLogQuery query) {
            int tenantId = sessionContext.getTenantSymbolBO().getId();
            int propertyId = sessionContext.getPropertyId(property);
            return importLogService.list(tenantId, propertyId, query);
        }

        /**
         * 校验是否是失败、缺失记录
         *
         * @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/16
         */
        private ISvaEmployeeParseService getEmployeeReportParser(String source) {
            Collection<ISvaEmployeeParseService> parserList =
                    applicationContext.getBeansOfType(ISvaEmployeeParseService.class).values();
            ISvaEmployeeParseService parser = null;
            for (ISvaEmployeeParseService employeeReportService : parserList) {
                if (employeeReportService.supports(source)) {
                    parser = employeeReportService;
                    break;
                }
            }
            if (Objects.isNull(parser)) {
                throw new BadRequestException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(),
                        "Can not find Sva Employee report parser");
            }
            return parser;
        }
    }