@@ -289,7 +289,7 @@ class WorkoutService(
289289 return response
290290 }
291291
292- fun copyWorkoutsNormally (
292+ private fun copyWorkoutsNormally (
293293 request : CopyFromCalendarToCalendarRequest
294294 ): CopyWorkoutsResponse {
295295
@@ -428,177 +428,7 @@ class WorkoutService(
428428 val workoutRepository = workoutRepositoryMap[request.platform]!!
429429 workoutRepository.deleteWorkoutsFromCalendar(request.startDate, request.endDate)
430430 }
431-
432- fun reconcileScheduledTrainerRoadToTrainingPeaks (
433- request : CopyFromCalendarToCalendarRequest
434- ): CopyWorkoutsResponse {
435-
436- require(request.sourcePlatform == Platform .TRAINER_ROAD ) {
437- " Scheduled reconciliation requires TrainerRoad as source"
438- }
439-
440- require(request.targetPlatform == Platform .TRAINING_PEAKS ) {
441- " Scheduled reconciliation requires TrainingPeaks as target"
442- }
443-
444- log.info(
445- " Starting scheduled TrainerRoad to TrainingPeaks reconciliation: {}" ,
446- request
447- )
448-
449- val sourceRepository =
450- workoutRepositoryMap[request.sourcePlatform]!!
451-
452- val targetRepository =
453- workoutRepositoryMap[request.targetPlatform]!!
454-
455- val allSourceWorkouts =
456- sourceRepository.getWorkoutsFromCalendar(
457- request.startDate,
458- request.endDate
459- )
460-
461- val sourceWorkouts = allSourceWorkouts.filter {
462- request.types.contains(it.details.type)
463- }
464-
465- val skippedByType =
466- allSourceWorkouts.size - sourceWorkouts.size
467-
468- /*
469- * Important safeguard:
470- * an empty response from TrainerRoad must never cause existing
471- * TrainingPeaks workouts to be deleted.
472- */
473- if (sourceWorkouts.isEmpty()) {
474- log.info(
475- " TrainerRoad returned no matching workouts. " +
476- " No TrainingPeaks workouts will be removed."
477- )
478-
479- return CopyWorkoutsResponse (
480- copied = 0 ,
481- filteredOut = skippedByType,
482- skippedByType = skippedByType,
483- skippedAlreadySynced = 0 ,
484- startDate = request.startDate,
485- endDate = request.endDate,
486- externalData = ExternalData .empty()
487- )
488- }
489-
490- val sourceWithoutTrainerRoadId = sourceWorkouts.filter {
491- it.details.externalData.trainerRoadId.isNullOrBlank()
492- }
493-
494- val validSourceWorkouts = sourceWorkouts.filter {
495- ! it.details.externalData.trainerRoadId.isNullOrBlank()
496- }
497-
498- val invalidSourceFailures =
499- sourceWithoutTrainerRoadId.map { workout ->
500- WorkoutSyncFailure (
501- workoutName = workout.details.name,
502- workoutDate = workout.date,
503- message = " TrainerRoad workout ID is missing"
504- )
505- }
506-
507- val targetWorkouts =
508- targetRepository.getWorkoutsFromCalendar(
509- request.startDate,
510- request.endDate
511- )
512-
513- val managedTargetWorkouts = targetWorkouts.filter {
514- isApplicationManagedTrainerRoadWorkout(it)
515- }
516-
517- val sourceTrainerRoadIds = validSourceWorkouts
518- .mapNotNull {
519- it.details.externalData.trainerRoadId
520- }
521- .toSet()
522-
523- val targetTrainerRoadIds = managedTargetWorkouts
524- .mapNotNull {
525- it.details.externalData.trainerRoadId
526- }
527- .toSet()
528-
529- val workoutsToCreate = validSourceWorkouts.filter {
530- it.details.externalData.trainerRoadId !in targetTrainerRoadIds
531- }
532-
533- val alreadySynced =
534- validSourceWorkouts.size - workoutsToCreate.size
535-
536- val workoutsToRemove = managedTargetWorkouts.filter {
537- it.details.externalData.trainerRoadId !in sourceTrainerRoadIds
538- }
539-
540- /*
541- * Create the replacement first.
542- */
543- val saveResult = saveWorkoutsIndividually(
544- repository = targetRepository,
545- workouts = workoutsToCreate
546- )
547-
548- val copyFailures =
549- invalidSourceFailures + saveResult.failures
550-
551- /*
552- * Do not remove the previous workout if any new workout failed
553- * to be created.
554- */
555- val deleteResult = if (copyFailures.isEmpty()) {
556- deleteWorkoutsIndividually(
557- repository = targetRepository,
558- workouts = workoutsToRemove
559- )
560- } else {
561- log.warn(
562- " Skipping removal of {} replaced workouts because " +
563- " {} source workouts failed to sync" ,
564- workoutsToRemove.size,
565- copyFailures.size
566- )
567-
568- DeleteWorkoutsResult (
569- removed = 0 ,
570- failures = emptyList()
571- )
572- }
573-
574- val response = CopyWorkoutsResponse (
575- copied = saveResult.copied,
576- filteredOut = skippedByType + alreadySynced,
577- skippedByType = skippedByType,
578- skippedAlreadySynced = alreadySynced,
579- startDate = request.startDate,
580- endDate = request.endDate,
581- externalData = ExternalData .empty(),
582- failed = copyFailures.size,
583- failedWorkouts = copyFailures,
584- removed = deleteResult.removed,
585- failedToRemove = deleteResult.failures.size,
586- failedRemovals = deleteResult.failures
587- )
588-
589- log.info(
590- " Scheduled reconciliation completed. copied={}, " +
591- " alreadySynced={}, removed={}, failed={}, failedToRemove={}" ,
592- response.copied,
593- response.skippedAlreadySynced,
594- response.removed,
595- response.failed,
596- response.failedToRemove
597- )
598-
599- return response
600- }
601-
431+
602432 private fun isApplicationManagedTrainerRoadWorkout (
603433 workout : Workout
604434 ): Boolean {
0 commit comments