package com.goi.integration.samsara.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.goi.integration.common.dto.ExtIngestResult; import com.goi.integration.common.util.DateTimeUtil; import com.goi.integration.common.util.ExtPayloadHashUtil; import com.goi.integration.samsara.client.OprIngestClient; import com.goi.integration.samsara.dto.ExtInspectionIngestCommand; import com.goi.integration.samsara.dto.ExtInspectionRecordDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Slf4j @Service @RequiredArgsConstructor public class InspectionIngestService { private final ObjectMapper objectMapper; private final OprIngestClient oprIngestClient; /** * Samsara DVIR raw JSON 응답을 받아 * 1) record 단위로 분해 * 2) hash 생성 * 3) opr-rest-api ingest endpoint 호출 */ public ExtIngestResult ingestFromRawJson(String rawJson) { try { // 전체 JSON 파싱 JsonNode root = objectMapper.readTree(rawJson); JsonNode data = root.path("data"); // data[] 없음 if (!data.isArray()) { log.warn("Samsara DVIR response has no data[] array"); return ExtIngestResult.empty("SAMSARA"); } // List records = new ArrayList<>(); log.info("inspection data size={}", data.size()); // data[] 각 node 가 하나의 inspection (preTrip / postTrip) for (JsonNode node : data) { // parsing String externalId = node.path("id").asText(null); String vehicleExtId = node.path("vehicle").path("id").asText(null); String driverExtId = node.path("authorSignature") .path("signatoryUser") .path("id") .asText(null); String inspectionType = node.path("type").asText(null); LocalDateTime startTime = DateTimeUtil.parseToToronto(node.path("startTime").asText(null)); LocalDateTime endTime = DateTimeUtil.parseToToronto(node.path("endTime").asText(null)); LocalDateTime signedAt = DateTimeUtil.parseToToronto( node.path("authorSignature").path("signedAtTime").asText(null) ); // record 단위 hash 생성 (opr-rest-api 에서 idempotent ingest 판단용) String hash = ExtPayloadHashUtil.sha256FromJsonNode(node); // record DTO records.add( ExtInspectionRecordDto.builder() .externalId(externalId) .vehicleExternalId(vehicleExtId) .driverExternalId(driverExtId) .inspectionType(inspectionType) .startTime(startTime) .endTime(endTime) .signedAt(signedAt) .payloadJson(node) // 원본 payload (JSON 그대로 저장) .payloadHash(hash) .build() ); } // ingest command 생성 ExtInspectionIngestCommand command = ExtInspectionIngestCommand.builder() .source("SAMSARA") .fetchedAt(LocalDateTime.now()) .records(records) .build(); // opr-rest-api ingest endpoint 호출 return oprIngestClient.ingestInspection(command); } catch (Exception e) { log.error("Failed to ingest samsara DVIR payload", e); throw new RuntimeException(e); } } }