package com.goi.erp.service; import com.goi.erp.client.SamsaraStatOdometerClient; import com.goi.erp.dto.ExtSamsaraOdometerFetchCommand; import com.goi.erp.dto.ScheduleWorkerRequestDto; import com.goi.erp.dto.ScheduleWorkerResponseDto; import com.goi.erp.entity.VehicleDispatch; import com.goi.erp.repository.VehicleDispatchRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.time.LocalDate; import java.util.List; import java.util.Map; import java.util.Objects; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor @Slf4j public class SchedulerOdometerRawOrchestrator { private final SamsaraStatOdometerClient statOdometerClient; private final ExtSamsaraOdometerIngestService ingestService; private final VehicleDispatchRepository vehicleDispatchRepository; private final VehicleExternalMapService vehicleExternalMapService; public ScheduleWorkerResponseDto run(ScheduleWorkerRequestDto request) { try { LocalDate dispatchDate = request.getFrom().toLocalDate(); // 1. 대상 dispatch 조회 (NOT CLOSED) List targets = vehicleDispatchRepository.findAllNotClosed(dispatchDate); if (targets.isEmpty()) { log.info("[ODOMETER_RAW] no dispatch to process"); return ScheduleWorkerResponseDto.successEmpty(); } // 2. internal vehicleId 수집 List vehicleIds = targets.stream() .map(VehicleDispatch::getVedVehId) .filter(Objects::nonNull) .distinct() .toList(); if (vehicleIds.isEmpty()) { log.info("[ODOMETER_RAW] no vehicles to process"); return ScheduleWorkerResponseDto.successEmpty(); } // 3. internal → external (Samsara) 매핑 Map vehicleIdToExternalId = vehicleExternalMapService.findExternalIdsByVehicleIds( "SAMSARA", vehicleIds ); List externalIds = vehicleIdToExternalId.values().stream() .filter(Objects::nonNull) .distinct() .toList(); if (externalIds.isEmpty()) { log.info("[ODOMETER_RAW] no external vehicle ids"); return ScheduleWorkerResponseDto.successEmpty(); } // 4. ★ request 에 externalIds 세팅 (중요) request.setVehicleExternalIds(externalIds); // 5. integration-service fetch ExtSamsaraOdometerFetchCommand fetchResult = statOdometerClient.fetchOdometer(request); if (fetchResult == null || fetchResult.getRecords() == null) { return ScheduleWorkerResponseDto.successEmpty(); } // 6. raw ingest int inserted = ingestService.ingest(fetchResult); log.info( "[ODOMETER_RAW][DONE] fetched={} inserted={}", fetchResult.getRecords().size(), inserted ); return ScheduleWorkerResponseDto.builder() .success(true) .processedCount(fetchResult.getRecords().size()) .successCount(inserted) .failCount(fetchResult.getRecords().size() - inserted) .build(); } catch (Exception e) { log.error("[ODOMETER_RAW][RUN_FAIL]", e); return ScheduleWorkerResponseDto.builder() .success(false) .errorCode("ODOMETER_RAW_INGEST_ERROR") .errorMessage(e.getMessage()) .build(); } } }