refactor(komoot): move import mapping to separate table
Signed-off-by: Marcus Fihlon <marcus@fihlon.swiss>
This commit is contained in:
parent
ea47cccdb1
commit
3135a36679
8 changed files with 136 additions and 70 deletions
|
|
@ -117,13 +117,6 @@ public class Activity {
|
||||||
@Column(name = "source_file_format", nullable = false, length = 10)
|
@Column(name = "source_file_format", nullable = false, length = 10)
|
||||||
private String sourceFileFormat;
|
private String sourceFileFormat;
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional internal reference to the originating Komoot activity.
|
|
||||||
* Used for import matching and deduplication only.
|
|
||||||
*/
|
|
||||||
@Column(name = "komoot_activity_id")
|
|
||||||
private Long komootActivityId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if this is an indoor activity (e.g., virtual rides, indoor trainer sessions).
|
* Indicates if this is an indoor activity (e.g., virtual rides, indoor trainer sessions).
|
||||||
* Indoor activities are displayed in timeline but excluded from heatmap generation.
|
* Indoor activities are displayed in timeline but excluded from heatmap generation.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package net.javahippie.fitpub.model.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal link between a FitPub activity and its originating Komoot activity.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "komoot_imports",
|
||||||
|
uniqueConstraints = {
|
||||||
|
@UniqueConstraint(name = "uk_komoot_imports_activity_id", columnNames = "activity_id"),
|
||||||
|
@UniqueConstraint(name = "uk_komoot_imports_user_komoot_activity_id", columnNames = {"user_id", "komoot_activity_id"})
|
||||||
|
},
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_komoot_imports_user_id", columnList = "user_id"),
|
||||||
|
@Index(name = "idx_komoot_imports_komoot_activity_id", columnList = "komoot_activity_id")
|
||||||
|
})
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class KomootImport {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "user_id", nullable = false)
|
||||||
|
private UUID userId;
|
||||||
|
|
||||||
|
@Column(name = "activity_id", nullable = false)
|
||||||
|
private UUID activityId;
|
||||||
|
|
||||||
|
@Column(name = "komoot_activity_id", nullable = false)
|
||||||
|
private Long komootActivityId;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "created_at", nullable = false, updatable = false)
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
}
|
||||||
|
|
@ -20,37 +20,9 @@ import java.util.UUID;
|
||||||
@Repository
|
@Repository
|
||||||
public interface ActivityRepository extends JpaRepository<Activity, UUID> {
|
public interface ActivityRepository extends JpaRepository<Activity, UUID> {
|
||||||
|
|
||||||
interface KomootImportLinkProjection {
|
|
||||||
UUID getId();
|
|
||||||
Long getKomootActivityId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Query("SELECT a.id FROM Activity a")
|
@Query("SELECT a.id FROM Activity a")
|
||||||
List<UUID> findAllIds();
|
List<UUID> findAllIds();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all imported Komoot activity IDs for the given local user.
|
|
||||||
*/
|
|
||||||
@Query("SELECT a.komootActivityId FROM Activity a " +
|
|
||||||
"WHERE a.userId = :userId AND a.komootActivityId IS NOT NULL")
|
|
||||||
List<Long> findImportedKomootActivityIdsByUserId(@Param("userId") UUID userId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a previously imported Komoot activity for the given user.
|
|
||||||
*/
|
|
||||||
Optional<Activity> findByUserIdAndKomootActivityId(UUID userId, Long komootActivityId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds imported Komoot activities for the given user and Komoot IDs.
|
|
||||||
*/
|
|
||||||
@Query("SELECT a.id AS id, a.komootActivityId AS komootActivityId " +
|
|
||||||
"FROM Activity a " +
|
|
||||||
"WHERE a.userId = :userId AND a.komootActivityId IN :komootActivityIds")
|
|
||||||
List<KomootImportLinkProjection> findKomootImportLinksByUserIdAndKomootActivityIdIn(
|
|
||||||
@Param("userId") UUID userId,
|
|
||||||
@Param("komootActivityIds") List<Long> komootActivityIds
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all activities for a specific user.
|
* Find all activities for a specific user.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.javahippie.fitpub.repository;
|
||||||
|
|
||||||
|
import net.javahippie.fitpub.model.entity.KomootImport;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface KomootImportRepository extends JpaRepository<KomootImport, UUID> {
|
||||||
|
|
||||||
|
interface KomootImportLinkProjection {
|
||||||
|
UUID getActivityId();
|
||||||
|
Long getKomootActivityId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query("SELECT k.komootActivityId FROM KomootImport k WHERE k.userId = :userId")
|
||||||
|
List<Long> findImportedKomootActivityIdsByUserId(@Param("userId") UUID userId);
|
||||||
|
|
||||||
|
Optional<KomootImport> findByUserIdAndKomootActivityId(UUID userId, Long komootActivityId);
|
||||||
|
|
||||||
|
@Query("SELECT k.activityId AS activityId, k.komootActivityId AS komootActivityId " +
|
||||||
|
"FROM KomootImport k " +
|
||||||
|
"WHERE k.userId = :userId AND k.komootActivityId IN :komootActivityIds")
|
||||||
|
List<KomootImportLinkProjection> findKomootImportLinksByUserIdAndKomootActivityIdIn(
|
||||||
|
@Param("userId") UUID userId,
|
||||||
|
@Param("komootActivityIds") List<Long> komootActivityIds
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,9 @@ import net.javahippie.fitpub.model.dto.KomootActivitySummaryDTO;
|
||||||
import net.javahippie.fitpub.model.dto.KomootImportExecutionResponse;
|
import net.javahippie.fitpub.model.dto.KomootImportExecutionResponse;
|
||||||
import net.javahippie.fitpub.model.dto.KomootImportRequest;
|
import net.javahippie.fitpub.model.dto.KomootImportRequest;
|
||||||
import net.javahippie.fitpub.model.entity.Activity;
|
import net.javahippie.fitpub.model.entity.Activity;
|
||||||
|
import net.javahippie.fitpub.model.entity.KomootImport;
|
||||||
import net.javahippie.fitpub.repository.ActivityRepository;
|
import net.javahippie.fitpub.repository.ActivityRepository;
|
||||||
|
import net.javahippie.fitpub.repository.KomootImportRepository;
|
||||||
import net.javahippie.fitpub.util.ByteArrayMultipartFile;
|
import net.javahippie.fitpub.util.ByteArrayMultipartFile;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
|
|
@ -57,6 +59,7 @@ public class KomootImportService {
|
||||||
private static final DateTimeFormatter KOMOOT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
private static final DateTimeFormatter KOMOOT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||||
private final RestTemplate restTemplate;
|
private final RestTemplate restTemplate;
|
||||||
private final ActivityRepository activityRepository;
|
private final ActivityRepository activityRepository;
|
||||||
|
private final KomootImportRepository komootImportRepository;
|
||||||
private final ActivityFileService activityFileService;
|
private final ActivityFileService activityFileService;
|
||||||
private final ActivityPostProcessingService activityPostProcessingService;
|
private final ActivityPostProcessingService activityPostProcessingService;
|
||||||
|
|
||||||
|
|
@ -75,14 +78,14 @@ public class KomootImportService {
|
||||||
public KomootActivitiesResponse fetchCompletedActivities(KomootImportRequest request, UUID fitPubUserId) {
|
public KomootActivitiesResponse fetchCompletedActivities(KomootImportRequest request, UUID fitPubUserId) {
|
||||||
List<KomootActivitySummaryDTO> activities = new ArrayList<>();
|
List<KomootActivitySummaryDTO> activities = new ArrayList<>();
|
||||||
Set<Long> importedKomootActivityIds = new HashSet<>(
|
Set<Long> importedKomootActivityIds = new HashSet<>(
|
||||||
activityRepository.findImportedKomootActivityIdsByUserId(fitPubUserId));
|
komootImportRepository.findImportedKomootActivityIdsByUserId(fitPubUserId));
|
||||||
Map<Long, UUID> fitPubActivityIdsByKomootId = new HashMap<>();
|
Map<Long, UUID> fitPubActivityIdsByKomootId = new HashMap<>();
|
||||||
if (!importedKomootActivityIds.isEmpty()) {
|
if (!importedKomootActivityIds.isEmpty()) {
|
||||||
activityRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(
|
komootImportRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(
|
||||||
fitPubUserId,
|
fitPubUserId,
|
||||||
new ArrayList<>(importedKomootActivityIds)
|
new ArrayList<>(importedKomootActivityIds)
|
||||||
)
|
)
|
||||||
.forEach(link -> fitPubActivityIdsByKomootId.put(link.getKomootActivityId(), link.getId()));
|
.forEach(link -> fitPubActivityIdsByKomootId.put(link.getKomootActivityId(), link.getActivityId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
URI nextUri = buildInitialUri(request);
|
URI nextUri = buildInitialUri(request);
|
||||||
|
|
@ -122,10 +125,10 @@ public class KomootImportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public KomootImportExecutionResponse importActivity(KomootActivityImportRequest request, UUID fitPubUserId) {
|
public KomootImportExecutionResponse importActivity(KomootActivityImportRequest request, UUID fitPubUserId) {
|
||||||
Activity existingActivity = activityRepository.findByUserIdAndKomootActivityId(fitPubUserId, request.getActivityId()).orElse(null);
|
KomootImport existingImport = komootImportRepository.findByUserIdAndKomootActivityId(fitPubUserId, request.getActivityId()).orElse(null);
|
||||||
if (existingActivity != null) {
|
if (existingImport != null) {
|
||||||
return new KomootImportExecutionResponse(
|
return new KomootImportExecutionResponse(
|
||||||
existingActivity.getId(),
|
existingImport.getActivityId(),
|
||||||
request.getActivityId(),
|
request.getActivityId(),
|
||||||
"SKIPPED_ALREADY_IMPORTED",
|
"SKIPPED_ALREADY_IMPORTED",
|
||||||
"Komoot activity " + request.getActivityId() + " was already imported."
|
"Komoot activity " + request.getActivityId() + " was already imported."
|
||||||
|
|
@ -156,13 +159,17 @@ public class KomootImportService {
|
||||||
mappedVisibility
|
mappedVisibility
|
||||||
);
|
);
|
||||||
|
|
||||||
importedActivity.setKomootActivityId(request.getActivityId());
|
|
||||||
importedActivity.setTitle(mappedTitle);
|
importedActivity.setTitle(mappedTitle);
|
||||||
importedActivity.setDescription(mappedDescription);
|
importedActivity.setDescription(mappedDescription);
|
||||||
importedActivity.setVisibility(mappedVisibility);
|
importedActivity.setVisibility(mappedVisibility);
|
||||||
importedActivity.setActivityType(mappedActivityType);
|
importedActivity.setActivityType(mappedActivityType);
|
||||||
|
|
||||||
importedActivity = activityRepository.save(importedActivity);
|
importedActivity = activityRepository.save(importedActivity);
|
||||||
|
komootImportRepository.save(KomootImport.builder()
|
||||||
|
.userId(fitPubUserId)
|
||||||
|
.activityId(importedActivity.getId())
|
||||||
|
.komootActivityId(request.getActivityId())
|
||||||
|
.build());
|
||||||
activityPostProcessingService.processActivityAsync(importedActivity.getId(), fitPubUserId);
|
activityPostProcessingService.processActivityAsync(importedActivity.getId(), fitPubUserId);
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
-- Add optional internal reference to the originating Komoot activity.
|
|
||||||
--
|
|
||||||
-- This field is only used for import matching and deduplication. It is not
|
|
||||||
-- intended for public display or API exposure.
|
|
||||||
|
|
||||||
ALTER TABLE activities
|
|
||||||
ADD COLUMN komoot_activity_id BIGINT;
|
|
||||||
|
|
||||||
-- A Komoot activity may only be imported once per local user.
|
|
||||||
CREATE UNIQUE INDEX idx_activities_user_komoot_activity_id
|
|
||||||
ON activities(user_id, komoot_activity_id)
|
|
||||||
WHERE komoot_activity_id IS NOT NULL;
|
|
||||||
|
|
||||||
COMMENT ON COLUMN activities.komoot_activity_id IS
|
|
||||||
'Optional internal Komoot activity ID used for import matching and deduplication';
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
-- Track imported Komoot activities separately from the core activities table.
|
||||||
|
--
|
||||||
|
-- This keeps the import-specific state isolated and allows all import-related
|
||||||
|
-- columns to be strictly non-nullable.
|
||||||
|
|
||||||
|
CREATE TABLE komoot_imports (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
activity_id UUID NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
|
||||||
|
komoot_activity_id BIGINT NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT uk_komoot_imports_activity_id UNIQUE (activity_id),
|
||||||
|
CONSTRAINT uk_komoot_imports_user_komoot_activity_id UNIQUE (user_id, komoot_activity_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_komoot_imports_user_id
|
||||||
|
ON komoot_imports(user_id);
|
||||||
|
|
||||||
|
CREATE INDEX idx_komoot_imports_komoot_activity_id
|
||||||
|
ON komoot_imports(komoot_activity_id);
|
||||||
|
|
||||||
|
COMMENT ON TABLE komoot_imports IS
|
||||||
|
'Internal mapping between FitPub activities and their originating Komoot activities';
|
||||||
|
|
@ -5,7 +5,9 @@ import net.javahippie.fitpub.model.dto.KomootActivitiesResponse;
|
||||||
import net.javahippie.fitpub.model.dto.KomootImportExecutionResponse;
|
import net.javahippie.fitpub.model.dto.KomootImportExecutionResponse;
|
||||||
import net.javahippie.fitpub.model.dto.KomootImportRequest;
|
import net.javahippie.fitpub.model.dto.KomootImportRequest;
|
||||||
import net.javahippie.fitpub.model.entity.Activity;
|
import net.javahippie.fitpub.model.entity.Activity;
|
||||||
|
import net.javahippie.fitpub.model.entity.KomootImport;
|
||||||
import net.javahippie.fitpub.repository.ActivityRepository;
|
import net.javahippie.fitpub.repository.ActivityRepository;
|
||||||
|
import net.javahippie.fitpub.repository.KomootImportRepository;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
@ -41,10 +43,10 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
|
||||||
|
|
||||||
class KomootImportServiceTest {
|
class KomootImportServiceTest {
|
||||||
|
|
||||||
private static ActivityRepository.KomootImportLinkProjection importLink(UUID activityId, Long komootActivityId) {
|
private static KomootImportRepository.KomootImportLinkProjection importLink(UUID activityId, Long komootActivityId) {
|
||||||
return new ActivityRepository.KomootImportLinkProjection() {
|
return new KomootImportRepository.KomootImportLinkProjection() {
|
||||||
@Override
|
@Override
|
||||||
public UUID getId() {
|
public UUID getActivityId() {
|
||||||
return activityId;
|
return activityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,6 +60,7 @@ class KomootImportServiceTest {
|
||||||
private MockRestServiceServer server;
|
private MockRestServiceServer server;
|
||||||
private KomootImportService service;
|
private KomootImportService service;
|
||||||
private ActivityRepository activityRepository;
|
private ActivityRepository activityRepository;
|
||||||
|
private KomootImportRepository komootImportRepository;
|
||||||
private ActivityFileService activityFileService;
|
private ActivityFileService activityFileService;
|
||||||
private ActivityPostProcessingService activityPostProcessingService;
|
private ActivityPostProcessingService activityPostProcessingService;
|
||||||
private TimeZone originalTimeZone;
|
private TimeZone originalTimeZone;
|
||||||
|
|
@ -69,9 +72,10 @@ class KomootImportServiceTest {
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
server = MockRestServiceServer.bindTo(restTemplate).build();
|
server = MockRestServiceServer.bindTo(restTemplate).build();
|
||||||
activityRepository = mock(ActivityRepository.class);
|
activityRepository = mock(ActivityRepository.class);
|
||||||
|
komootImportRepository = mock(KomootImportRepository.class);
|
||||||
activityFileService = mock(ActivityFileService.class);
|
activityFileService = mock(ActivityFileService.class);
|
||||||
activityPostProcessingService = mock(ActivityPostProcessingService.class);
|
activityPostProcessingService = mock(ActivityPostProcessingService.class);
|
||||||
service = new KomootImportService(restTemplate, activityRepository, activityFileService, activityPostProcessingService);
|
service = new KomootImportService(restTemplate, activityRepository, komootImportRepository, activityFileService, activityPostProcessingService);
|
||||||
ReflectionTestUtils.setField(service, "komootBaseUrl", "https://www.komoot.com");
|
ReflectionTestUtils.setField(service, "komootBaseUrl", "https://www.komoot.com");
|
||||||
ReflectionTestUtils.setField(service, "paginatedRequestDelayMillis", 0L);
|
ReflectionTestUtils.setField(service, "paginatedRequestDelayMillis", 0L);
|
||||||
ReflectionTestUtils.setField(service, "detailToGpxDelayMillis", 0L);
|
ReflectionTestUtils.setField(service, "detailToGpxDelayMillis", 0L);
|
||||||
|
|
@ -92,8 +96,8 @@ class KomootImportServiceTest {
|
||||||
doNothing().when(throttledService).pauseBeforeNextPageRequest();
|
doNothing().when(throttledService).pauseBeforeNextPageRequest();
|
||||||
UUID existingActivityId = UUID.fromString("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee");
|
UUID existingActivityId = UUID.fromString("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee");
|
||||||
|
|
||||||
when(activityRepository.findImportedKomootActivityIdsByUserId(userId)).thenReturn(List.of(1002L));
|
when(komootImportRepository.findImportedKomootActivityIdsByUserId(userId)).thenReturn(List.of(1002L));
|
||||||
when(activityRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(userId, List.of(1002L)))
|
when(komootImportRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(userId, List.of(1002L)))
|
||||||
.thenReturn(List.of(importLink(existingActivityId, 1002L)));
|
.thenReturn(List.of(importLink(existingActivityId, 1002L)));
|
||||||
|
|
||||||
server.expect(once(), requestTo("https://www.komoot.com/api/v007/users/123456/tours/?type=tour_recorded&sort_field=date&sort_direction=desc&limit=100&status=private&name=&hl=en&page=0"))
|
server.expect(once(), requestTo("https://www.komoot.com/api/v007/users/123456/tours/?type=tour_recorded&sort_field=date&sort_direction=desc&limit=100&status=private&name=&hl=en&page=0"))
|
||||||
|
|
@ -176,8 +180,8 @@ class KomootImportServiceTest {
|
||||||
UUID userId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
UUID userId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
UUID existingActivityId = UUID.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff");
|
UUID existingActivityId = UUID.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff");
|
||||||
|
|
||||||
when(activityRepository.findImportedKomootActivityIdsByUserId(userId)).thenReturn(List.of(1003L));
|
when(komootImportRepository.findImportedKomootActivityIdsByUserId(userId)).thenReturn(List.of(1003L));
|
||||||
when(activityRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(userId, List.of(1003L)))
|
when(komootImportRepository.findKomootImportLinksByUserIdAndKomootActivityIdIn(userId, List.of(1003L)))
|
||||||
.thenReturn(List.of(importLink(existingActivityId, 1003L)));
|
.thenReturn(List.of(importLink(existingActivityId, 1003L)));
|
||||||
|
|
||||||
server.expect(once(), requestTo("https://www.komoot.com/api/v007/users/123456/tours/?type=tour_recorded&sort_field=date&sort_direction=desc&limit=100&start_date=2026-04-25T22:00:00.000Z&end_date=2026-04-27T21:59:59.999Z"))
|
server.expect(once(), requestTo("https://www.komoot.com/api/v007/users/123456/tours/?type=tour_recorded&sort_field=date&sort_direction=desc&limit=100&start_date=2026-04-25T22:00:00.000Z&end_date=2026-04-27T21:59:59.999Z"))
|
||||||
|
|
@ -252,7 +256,7 @@ class KomootImportServiceTest {
|
||||||
doNothing().when(throttledService).pauseBetweenDetailAndGpxRequest();
|
doNothing().when(throttledService).pauseBetweenDetailAndGpxRequest();
|
||||||
doNothing().when(throttledService).pauseAfterActivityImport();
|
doNothing().when(throttledService).pauseAfterActivityImport();
|
||||||
|
|
||||||
when(activityRepository.findByUserIdAndKomootActivityId(userId, 2880957035L)).thenReturn(Optional.empty());
|
when(komootImportRepository.findByUserIdAndKomootActivityId(userId, 2880957035L)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957035?hl=en"))
|
server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957035?hl=en"))
|
||||||
.andExpect(method(HttpMethod.GET))
|
.andExpect(method(HttpMethod.GET))
|
||||||
|
|
@ -290,6 +294,7 @@ class KomootImportServiceTest {
|
||||||
|
|
||||||
when(activityFileService.processActivityFile(any(), any(), any(), any(), any())).thenReturn(importedActivity);
|
when(activityFileService.processActivityFile(any(), any(), any(), any(), any())).thenReturn(importedActivity);
|
||||||
when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||||
|
when(komootImportRepository.save(any(KomootImport.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||||
|
|
||||||
KomootImportExecutionResponse response = throttledService.importActivity(
|
KomootImportExecutionResponse response = throttledService.importActivity(
|
||||||
new KomootActivityImportRequest("user@example.com", "secret", "123456", 2880957035L),
|
new KomootActivityImportRequest("user@example.com", "secret", "123456", 2880957035L),
|
||||||
|
|
@ -299,11 +304,11 @@ class KomootImportServiceTest {
|
||||||
assertThat(response.getImportedActivityId()).isEqualTo(importedActivityId);
|
assertThat(response.getImportedActivityId()).isEqualTo(importedActivityId);
|
||||||
assertThat(response.getImportedKomootActivityId()).isEqualTo(2880957035L);
|
assertThat(response.getImportedKomootActivityId()).isEqualTo(2880957035L);
|
||||||
assertThat(response.getStatus()).isEqualTo("IMPORTED");
|
assertThat(response.getStatus()).isEqualTo("IMPORTED");
|
||||||
assertThat(importedActivity.getKomootActivityId()).isEqualTo(2880957035L);
|
|
||||||
assertThat(importedActivity.getTitle()).isEqualTo("Latest Ride");
|
assertThat(importedActivity.getTitle()).isEqualTo("Latest Ride");
|
||||||
assertThat(importedActivity.getDescription()).isEqualTo("Imported from Komoot");
|
assertThat(importedActivity.getDescription()).isEqualTo("Imported from Komoot");
|
||||||
assertThat(importedActivity.getVisibility()).isEqualTo(Activity.Visibility.PUBLIC);
|
assertThat(importedActivity.getVisibility()).isEqualTo(Activity.Visibility.PUBLIC);
|
||||||
assertThat(importedActivity.getActivityType()).isEqualTo(Activity.ActivityType.RIDE);
|
assertThat(importedActivity.getActivityType()).isEqualTo(Activity.ActivityType.RIDE);
|
||||||
|
verify(komootImportRepository).save(any(KomootImport.class));
|
||||||
|
|
||||||
verify(throttledService).pauseBetweenDetailAndGpxRequest();
|
verify(throttledService).pauseBetweenDetailAndGpxRequest();
|
||||||
verify(throttledService).pauseAfterActivityImport();
|
verify(throttledService).pauseAfterActivityImport();
|
||||||
|
|
@ -317,8 +322,8 @@ class KomootImportServiceTest {
|
||||||
UUID userId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
UUID userId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||||
UUID existingActivityId = UUID.fromString("dddddddd-dddd-dddd-dddd-dddddddddddd");
|
UUID existingActivityId = UUID.fromString("dddddddd-dddd-dddd-dddd-dddddddddddd");
|
||||||
|
|
||||||
when(activityRepository.findByUserIdAndKomootActivityId(userId, 3002L)).thenReturn(
|
when(komootImportRepository.findByUserIdAndKomootActivityId(userId, 3002L)).thenReturn(
|
||||||
Optional.of(Activity.builder().id(existingActivityId).userId(userId).komootActivityId(3002L).build())
|
Optional.of(KomootImport.builder().activityId(existingActivityId).userId(userId).komootActivityId(3002L).build())
|
||||||
);
|
);
|
||||||
|
|
||||||
KomootImportExecutionResponse response = service.importActivity(
|
KomootImportExecutionResponse response = service.importActivity(
|
||||||
|
|
@ -342,7 +347,7 @@ class KomootImportServiceTest {
|
||||||
doNothing().when(throttledService).pauseBetweenDetailAndGpxRequest();
|
doNothing().when(throttledService).pauseBetweenDetailAndGpxRequest();
|
||||||
doNothing().when(throttledService).pauseAfterActivityImport();
|
doNothing().when(throttledService).pauseAfterActivityImport();
|
||||||
|
|
||||||
when(activityRepository.findByUserIdAndKomootActivityId(userId, 2880957036L)).thenReturn(Optional.empty());
|
when(komootImportRepository.findByUserIdAndKomootActivityId(userId, 2880957036L)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957036?hl=en"))
|
server.expect(once(), requestTo("https://www.komoot.com/api/v007/tours/2880957036?hl=en"))
|
||||||
.andExpect(method(HttpMethod.GET))
|
.andExpect(method(HttpMethod.GET))
|
||||||
|
|
@ -380,6 +385,7 @@ class KomootImportServiceTest {
|
||||||
|
|
||||||
when(activityFileService.processActivityFile(any(), any(), any(), any(), any())).thenReturn(importedActivity);
|
when(activityFileService.processActivityFile(any(), any(), any(), any(), any())).thenReturn(importedActivity);
|
||||||
when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||||
|
when(komootImportRepository.save(any(KomootImport.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||||
|
|
||||||
KomootImportExecutionResponse response = throttledService.importActivity(
|
KomootImportExecutionResponse response = throttledService.importActivity(
|
||||||
new KomootActivityImportRequest("user@example.com", "secret", "123456", 2880957036L),
|
new KomootActivityImportRequest("user@example.com", "secret", "123456", 2880957036L),
|
||||||
|
|
@ -389,6 +395,7 @@ class KomootImportServiceTest {
|
||||||
assertThat(response.getImportedActivityId()).isEqualTo(importedActivityId);
|
assertThat(response.getImportedActivityId()).isEqualTo(importedActivityId);
|
||||||
assertThat(response.getStatus()).isEqualTo("IMPORTED");
|
assertThat(response.getStatus()).isEqualTo("IMPORTED");
|
||||||
assertThat(importedActivity.getActivityType()).isEqualTo(Activity.ActivityType.OTHER);
|
assertThat(importedActivity.getActivityType()).isEqualTo(Activity.ActivityType.OTHER);
|
||||||
|
verify(komootImportRepository).save(any(KomootImport.class));
|
||||||
|
|
||||||
verify(throttledService).pauseBetweenDetailAndGpxRequest();
|
verify(throttledService).pauseBetweenDetailAndGpxRequest();
|
||||||
verify(throttledService).pauseAfterActivityImport();
|
verify(throttledService).pauseAfterActivityImport();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue