package com.goi.erp.service; import com.goi.erp.dto.ExtIngestResult; import com.goi.erp.dto.ExtSamsaraInspectionIngestCommand; import com.goi.erp.dto.ExtSamsaraInspectionRecordDto; import com.goi.erp.entity.ExtSamsaraRawInspection; import com.goi.erp.repository.ExtSamsaraRawInspectionRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class ExtSamsaraInspectionIngestService { private final ExtSamsaraRawInspectionRepository repository; /** * Ingest entry point */ @Transactional public ExtIngestResult ingest(ExtSamsaraInspectionIngestCommand command) { int inserted = 0; int updated = 0; int skipped = 0; @SuppressWarnings("unused") int failed = 0; for (ExtSamsaraInspectionRecordDto record : command.getRecords()) { IngestAction action; try { action = ingestSingle(command, record); } catch (Exception e) { failed++; continue; } switch (action) { case INSERTED -> inserted++; case UPDATED -> updated++; case SKIPPED -> skipped++; case FAILED -> failed++; } } return ExtIngestResult.builder() .source(command.getSource()) .recordType(command.getRecordType()) .received(command.getRecords().size()) .inserted(inserted) .updated(updated) .skipped(skipped) // .failed(failed) // 필요하면 추후 추가 .build(); } /** * Single record ingest (idempotent) */ private IngestAction ingestSingle( ExtSamsaraInspectionIngestCommand command, ExtSamsaraInspectionRecordDto record ) { return repository .findByEsriSourceAndEsriExternalId( command.getSource(), record.getExternalId() ) .map(existing -> updateIfChanged(existing, command, record)) .orElseGet(() -> { insertNew(command, record); return IngestAction.INSERTED; }); } /** * Insert new raw inspection */ private void insertNew( ExtSamsaraInspectionIngestCommand command, ExtSamsaraInspectionRecordDto record ) { ExtSamsaraRawInspection entity = ExtSamsaraRawInspection.builder() .esriSource(command.getSource()) .esriRecordType(command.getRecordType()) .esriExternalId(record.getExternalId()) .esriVehicleExtId(record.getVehicleExternalId()) .esriDriverExtId(record.getDriverExternalId()) .esriInspectionType(record.getInspectionType()) .esriStartTime(record.getStartTime()) .esriEndTime(record.getEndTime()) .esriSignedAt(record.getSignedAt()) .esriHash(record.getPayloadHash()) .esriFetchedAt(command.getFetchedAt()) .esriProcessed(false) .esriPayload(record.getPayloadJson()) .build(); repository.save(entity); } /** * Update only if hash changed */ private IngestAction updateIfChanged( ExtSamsaraRawInspection existing, ExtSamsaraInspectionIngestCommand command, ExtSamsaraInspectionRecordDto record ) { if (existing.getEsriHash().equals(record.getPayloadHash())) { return IngestAction.SKIPPED; } existing.setEsriVehicleExtId(record.getVehicleExternalId()); existing.setEsriDriverExtId(record.getDriverExternalId()); existing.setEsriInspectionType(record.getInspectionType()); existing.setEsriStartTime(record.getStartTime()); existing.setEsriEndTime(record.getEndTime()); existing.setEsriSignedAt(record.getSignedAt()); existing.setEsriHash(record.getPayloadHash()); existing.setEsriFetchedAt(command.getFetchedAt()); existing.setEsriPayload(record.getPayloadJson()); existing.setEsriProcessed(false); existing.setEsriProcessedAt(null); repository.save(existing); return IngestAction.UPDATED; } }