pcp: откат UTC-слоя — сквозной naive LocalDateTime без зоны на проводе
Возврат к модели «настенных часов»: одна ISO-строка без зоны
("2026-05-29T01:00:00") от БД до экрана, никто не привязывает её к
часовому поясу, сдвигаться нечему.
Бэкенд — снять зону с границы API:
- DTO OffsetDateTime/Instant -> LocalDateTime и убрана конвертация
atOffset(ZoneOffset.UTC)/toUtcOffset() в фабриках и мапперах:
tgu PlanResponse/NewChainDTOs/TguPlanningDTO, request RequestApiDtos,
complex ComplexPlanRun*DTO, dynamic ObservationParametersDebugDTO.
- Удалён толерантный Jackson-слой: PcpTimeModule(+autoconfig, ServiceLoader,
imports), PcpTimeModuleV3, LocalDateTimeTimeZoneSerializer; снята их
регистрация в Camunda/Rest/dynamic JacksonConfig. Штатный JSR-310
(JavaTimeModule + WRITE_DATES_AS_TIMESTAMPS=false) оставлен.
- Kafka-конверт KafkaMessage.time сериализуется ISO без офсета.
- mission-planing Mode/SurveyMode/DropMode entity и репозитории/сервис
переведены на LocalDateTime; колонки БД остаются timestamptz (Hibernate
мапит на naive без миграции — прецедент MissionEntity/PlanEntity).
- RequestServiceClient (dynamic) синхронизирован по типу с request-service.
Анти-регрессия: LocalDateTime.now(ZoneOffset.UTC) для серверных штампов
оставлен (выбор настенных часов UTC, не зона на проводе).
Фронт — снять офсет с egress: toUtcIso/фильтры отдают naive без Z
(после удаления толерантного десериализатора штатный парсер падал бы на Z).
Дисплейные хелперы (показ «как пришло», без сдвига) сохранены.
Тесты: контрактные ждут naive ISO; удалены UTC-артефакты (нормализация
офсетов) и тесты прослоек. Удалён docs/standards/DATETIME_UTC.md.
Операционно перед выкатом: сервисы катить согласованно; Kafka-топики с
ранее опубликованным офсетом +00:00 дренировать/проиграть.
This commit is contained in:
+2
-2
@@ -4,7 +4,7 @@ import jakarta.persistence.Column
|
||||
import jakarta.persistence.DiscriminatorValue
|
||||
import jakarta.persistence.Entity
|
||||
import jakarta.persistence.Table
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity
|
||||
@Table(name = "drop_modes")
|
||||
@@ -12,7 +12,7 @@ import java.time.OffsetDateTime
|
||||
class DropModeEntity(
|
||||
id: Long? = null,
|
||||
plan: PlanEntity? = null,
|
||||
timeStart: OffsetDateTime? = null,
|
||||
timeStart: LocalDateTime? = null,
|
||||
revolution: Long = 0,
|
||||
|
||||
@Column(name = "station")
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import jakarta.persistence.InheritanceType
|
||||
import jakarta.persistence.JoinColumn
|
||||
import jakarta.persistence.ManyToOne
|
||||
import jakarta.persistence.Table
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity
|
||||
@Table(name = "modes")
|
||||
@@ -29,7 +29,7 @@ abstract class ModeEntity(
|
||||
open var plan: PlanEntity? = null,
|
||||
|
||||
@Column(name = "time_start")
|
||||
open var timeStart: OffsetDateTime? = null,
|
||||
open var timeStart: LocalDateTime? = null,
|
||||
|
||||
@Column(name = "revolution", nullable = false)
|
||||
open var revolution: Long = 0
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import jakarta.persistence.EnumType
|
||||
import jakarta.persistence.Enumerated
|
||||
import jakarta.persistence.Table
|
||||
import space.nstart.pcp.pcp_types_lib.dto.routes.SurveyModeStatus
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity
|
||||
@Table(name = "survey_modes")
|
||||
@@ -15,7 +15,7 @@ import java.time.OffsetDateTime
|
||||
class SurveyModeEntity(
|
||||
id: Long? = null,
|
||||
plan: PlanEntity? = null,
|
||||
timeStart: OffsetDateTime? = null,
|
||||
timeStart: LocalDateTime? = null,
|
||||
revolution: Long = 0,
|
||||
|
||||
@Column(name = "lat", nullable = false)
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import org.springframework.data.jpa.repository.Modifying
|
||||
import org.springframework.data.jpa.repository.Query
|
||||
import org.springframework.data.repository.query.Param
|
||||
import space.nstart.pcp.pcp_mission_planing_service.entity.ModeEntity
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.LocalDateTime
|
||||
import java.util.UUID
|
||||
|
||||
interface ModeRepository : JpaRepository<ModeEntity, Long> {
|
||||
@@ -14,7 +14,7 @@ interface ModeRepository : JpaRepository<ModeEntity, Long> {
|
||||
fun findAllByPlan_Mission_MissionIdOrderByTimeStartAsc(missionId: UUID): List<ModeEntity>
|
||||
fun findAllByPlan_Mission_SatelliteIdAndTimeStartIsNotNullAndTimeStartLessThanEqualOrderByTimeStartAsc(
|
||||
satelliteId: Long,
|
||||
timeStop: OffsetDateTime
|
||||
timeStop: LocalDateTime
|
||||
): List<ModeEntity>
|
||||
|
||||
fun countByPlan_Mission_SatelliteId(satelliteId: Long): Long
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import org.springframework.data.jpa.repository.Query
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.data.repository.query.Param
|
||||
import space.nstart.pcp.pcp_mission_planing_service.entity.SurveyModeEntity
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.LocalDateTime
|
||||
import java.util.UUID
|
||||
|
||||
interface SurveyModeRepository : JpaRepository<SurveyModeEntity, Long> {
|
||||
@@ -26,7 +26,7 @@ interface SurveyModeRepository : JpaRepository<SurveyModeEntity, Long> {
|
||||
fun findAllBySatelliteNumberAndRevolutionAndTimeStartBetween(
|
||||
@Param("satelliteNumber") satelliteNumber: String,
|
||||
@Param("revolution") revolution: Long,
|
||||
@Param("timeStartFrom") timeStartFrom: OffsetDateTime,
|
||||
@Param("timeStartTo") timeStartTo: OffsetDateTime
|
||||
@Param("timeStartFrom") timeStartFrom: LocalDateTime,
|
||||
@Param("timeStartTo") timeStartTo: LocalDateTime
|
||||
): List<SurveyModeEntity>
|
||||
}
|
||||
|
||||
+13
-24
@@ -62,7 +62,6 @@ import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeResponseDTO
|
||||
import java.time.Duration
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.util.UUID
|
||||
import kotlin.math.PI
|
||||
@@ -305,7 +304,7 @@ class MissionPlaningService(
|
||||
val modes = modeRepository
|
||||
.findAllByPlan_Mission_SatelliteIdAndTimeStartIsNotNullAndTimeStartLessThanEqualOrderByTimeStartAsc(
|
||||
satelliteId,
|
||||
timeStop.atOffset(ZoneOffset.UTC)
|
||||
timeStop
|
||||
)
|
||||
.filter { it.intersects(timeStart, timeStop) }
|
||||
|
||||
@@ -346,27 +345,18 @@ class MissionPlaningService(
|
||||
.mapValues { (_, slotIds) -> slotIds.filter { it > 0 }.distinct() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Нормализует `OffsetDateTime` к UTC и отбрасывает зону. Все naive `LocalDateTime` в сервисе — UTC
|
||||
* (см. docs/standards/DATETIME_UTC.md), поэтому сравнивать их можно только с UTC-стенкой времени мода,
|
||||
* а не с локальной стенкой произвольного офсета. Голый `toLocalDateTime()` был корректен лишь пока
|
||||
* источник слал офсет 0 (`Z`).
|
||||
*/
|
||||
private fun OffsetDateTime.toUtcLocalDateTime(): LocalDateTime =
|
||||
withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime()
|
||||
|
||||
/**
|
||||
* Пересечение интервала включения с окном `[intervalStart, intervalStop)` (правый конец открыт).
|
||||
* Применяется при fork-forward-клоне: включения строго вне окна не клонируются.
|
||||
*/
|
||||
private fun ModeEntity.intersects(intervalStart: LocalDateTime, intervalStop: LocalDateTime): Boolean {
|
||||
val modeStart = timeStart?.toUtcLocalDateTime() ?: return false
|
||||
val modeStart = timeStart ?: return false
|
||||
val modeStop = modeStop() ?: return false
|
||||
return modeStop.isAfter(intervalStart) && modeStart.isBefore(intervalStop)
|
||||
}
|
||||
|
||||
private fun ModeEntity.modeStop(): LocalDateTime? {
|
||||
val modeStart = timeStart?.toUtcLocalDateTime() ?: return null
|
||||
val modeStart = timeStart ?: return null
|
||||
val durationSeconds = when (this) {
|
||||
is SurveyModeEntity -> duration
|
||||
is DropModeEntity -> duration
|
||||
@@ -731,7 +721,7 @@ class MissionPlaningService(
|
||||
val saved = surveyModeRepository.save(
|
||||
SurveyModeEntity(
|
||||
plan = plan,
|
||||
timeStart = built.timeStart.atOffset(ZoneOffset.UTC),
|
||||
timeStart = built.timeStart,
|
||||
revolution = built.revolution,
|
||||
lat = built.lat,
|
||||
long = built.longitude,
|
||||
@@ -805,7 +795,7 @@ class MissionPlaningService(
|
||||
}
|
||||
val start = survey.timeStart
|
||||
?: throw CustomErrorException("У маршрута съёмки ${survey.id} не задано время начала")
|
||||
val surveyEnd = start.toUtcLocalDateTime()
|
||||
val surveyEnd = start
|
||||
.plusNanos((survey.duration.coerceAtLeast(0.0) * 1_000_000_000L).toLong())
|
||||
if (!surveyEnd.isBefore(req.zoneStart)) {
|
||||
throw CustomErrorException(
|
||||
@@ -826,7 +816,7 @@ class MissionPlaningService(
|
||||
val dropMode = dropModeRepository.save(
|
||||
DropModeEntity(
|
||||
plan = plan,
|
||||
timeStart = req.zoneStart.atOffset(ZoneOffset.UTC),
|
||||
timeStart = req.zoneStart,
|
||||
revolution = req.revolution,
|
||||
station = req.station,
|
||||
duration = usedDuration
|
||||
@@ -867,7 +857,7 @@ class MissionPlaningService(
|
||||
}
|
||||
|
||||
val built = buildContour(req)
|
||||
survey.timeStart = built.timeStart.atOffset(ZoneOffset.UTC)
|
||||
survey.timeStart = built.timeStart
|
||||
survey.revolution = built.revolution
|
||||
survey.lat = built.lat
|
||||
survey.long = built.longitude
|
||||
@@ -1164,12 +1154,11 @@ class MissionPlaningService(
|
||||
val iterator = unassigned.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val survey = iterator.next()
|
||||
val surveyStartOffset = survey.timeStart
|
||||
if (surveyStartOffset == null) {
|
||||
val surveyStart = survey.timeStart
|
||||
if (surveyStart == null) {
|
||||
iterator.remove()
|
||||
continue
|
||||
}
|
||||
val surveyStart = surveyStartOffset.toUtcLocalDateTime()
|
||||
|
||||
val surveyEnd = surveyStart.plusNanos((survey.duration.coerceAtLeast(0.0) * 1_000_000_000L).toLong())
|
||||
if (!surveyEnd.isBefore(zoneStart)) {
|
||||
@@ -1193,7 +1182,7 @@ class MissionPlaningService(
|
||||
val dropMode = dropModeRepository.save(
|
||||
DropModeEntity(
|
||||
plan = plan,
|
||||
timeStart = zoneStart.atOffset(ZoneOffset.UTC),
|
||||
timeStart = zoneStart,
|
||||
revolution = zone.revolution,
|
||||
station = zone.stationId.toString(),
|
||||
duration = usedDuration
|
||||
@@ -1294,8 +1283,8 @@ class MissionPlaningService(
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun findMode(routePassport: RoutePassportDto): SurveyModeEntity? {
|
||||
val searchStart = routePassport.intervalBegin.atOffset(ZoneOffset.UTC).minusSeconds(1)
|
||||
val searchEnd = routePassport.intervalBegin.atOffset(ZoneOffset.UTC).plusSeconds(1)
|
||||
val searchStart = routePassport.intervalBegin.minusSeconds(1)
|
||||
val searchEnd = routePassport.intervalBegin.plusSeconds(1)
|
||||
val candidates = surveyModeRepository.findAllBySatelliteNumberAndRevolutionAndTimeStartBetween(
|
||||
satelliteNumber = routePassport.kaShort.trim(),
|
||||
revolution = routePassport.orbitNumber,
|
||||
@@ -1305,7 +1294,7 @@ class MissionPlaningService(
|
||||
|
||||
return candidates.minByOrNull { candidate ->
|
||||
val candidateStart = candidate.timeStart ?: return@minByOrNull Long.MAX_VALUE
|
||||
abs(Duration.between(routePassport.intervalBegin.atOffset(ZoneOffset.UTC), candidateStart).toMillis())
|
||||
abs(Duration.between(routePassport.intervalBegin, candidateStart).toMillis())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@ import space.nstart.pcp.pcp_mission_planing_service.entity.SurveyModeSource
|
||||
import space.nstart.pcp.pcp_types_lib.dto.routes.SurveyModeStatus
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SatelliteModeResponseDTO
|
||||
import java.time.ZoneOffset
|
||||
|
||||
abstract class LegacySatelliteMissionTypeSupport : SatelliteMissionType {
|
||||
override fun prepareSurvey(
|
||||
@@ -15,7 +14,7 @@ abstract class LegacySatelliteMissionTypeSupport : SatelliteMissionType {
|
||||
plan: PlanEntity
|
||||
): SurveyModeEntity = SurveyModeEntity(
|
||||
plan = plan,
|
||||
timeStart = surv.startTime.atOffset(ZoneOffset.UTC),
|
||||
timeStart = surv.startTime,
|
||||
revolution = surv.revolution,
|
||||
lat = surv.lat,
|
||||
long = surv.longitude,
|
||||
|
||||
+5
-10
@@ -27,8 +27,6 @@ import space.nstart.pcp.pcp_mission_planing_service.service.satellite_type.Refli
|
||||
import space.nstart.pcp.pcp_mission_planing_service.service.satellite_type.SatelliteMissionTypeFactory
|
||||
import space.nstart.pcp.pcp_types_lib.dto.routes.SurveyModeStatus
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
|
||||
@@ -263,27 +261,24 @@ class MissionCloneTest {
|
||||
val plan = PlanEntity(id = ++planAutoId, mission = mission, planNumber = 1)
|
||||
planStore[plan.id!!] = plan
|
||||
val duration = java.time.Duration.between(surveyStart, surveyStop).toMillis().toDouble() / 1000.0
|
||||
val s1 = survey(plan, surveyStart.atOffset(ZoneOffset.UTC), duration)
|
||||
val s2 = survey(plan, surveyStart.plusMinutes(1).atOffset(ZoneOffset.UTC), duration)
|
||||
val s1 = survey(plan, surveyStart, duration)
|
||||
val s2 = survey(plan, surveyStart.plusMinutes(1), duration)
|
||||
val d = drop(plan, surveyStart.plusMinutes(5))
|
||||
return SourceFixture(mission.missionId, plan, s1, s2, d)
|
||||
}
|
||||
|
||||
private fun survey(plan: PlanEntity, startOffset: OffsetDateTime, duration: Double = 300.0): SurveyModeEntity {
|
||||
private fun survey(plan: PlanEntity, start: LocalDateTime, duration: Double = 300.0): SurveyModeEntity {
|
||||
val id = ++modeAutoId
|
||||
val s = SurveyModeEntity(id = id, plan = plan, timeStart = startOffset, revolution = id,
|
||||
val s = SurveyModeEntity(id = id, plan = plan, timeStart = start, revolution = id,
|
||||
lat = 55.0, long = 37.0, duration = duration, roll = 0.0, source = SurveyModeSource.MANUAL,
|
||||
status = SurveyModeStatus.PLANNED)
|
||||
surveyStore[id] = s
|
||||
return s
|
||||
}
|
||||
|
||||
private fun survey(plan: PlanEntity, start: LocalDateTime, duration: Double = 300.0) =
|
||||
survey(plan, start.atOffset(ZoneOffset.UTC), duration)
|
||||
|
||||
private fun drop(plan: PlanEntity, start: LocalDateTime): DropModeEntity {
|
||||
val id = ++modeAutoId
|
||||
val d = DropModeEntity(id = id, plan = plan, timeStart = start.atOffset(ZoneOffset.UTC),
|
||||
val d = DropModeEntity(id = id, plan = plan, timeStart = start,
|
||||
revolution = id, station = "102", duration = 60.0)
|
||||
dropStore[id] = d
|
||||
return d
|
||||
|
||||
+2
-3
@@ -32,7 +32,6 @@ import space.nstart.pcp.pcp_types_lib.dto.routes.SurveyModeStatus
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.DropRouteSaveRequestDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.SurveyRouteBuildRequestDTO
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.util.UUID
|
||||
|
||||
class MissionEditModesTest {
|
||||
@@ -262,7 +261,7 @@ class MissionEditModesTest {
|
||||
private fun survey(): SurveyModeEntity {
|
||||
val id = ++autoId
|
||||
val s = SurveyModeEntity(
|
||||
id = id, plan = plan, timeStart = LocalDateTime.of(2026, 6, 10, 12, 0).atOffset(ZoneOffset.UTC),
|
||||
id = id, plan = plan, timeStart = LocalDateTime.of(2026, 6, 10, 12, 0),
|
||||
revolution = id, lat = 55.0, long = 37.0, duration = 60.0, roll = 0.0,
|
||||
status = SurveyModeStatus.PLANNED, source = SurveyModeSource.MANUAL
|
||||
)
|
||||
@@ -273,7 +272,7 @@ class MissionEditModesTest {
|
||||
private fun drop(): DropModeEntity {
|
||||
val id = ++autoId
|
||||
val d = DropModeEntity(
|
||||
id = id, plan = plan, timeStart = LocalDateTime.of(2026, 6, 10, 13, 0).atOffset(ZoneOffset.UTC),
|
||||
id = id, plan = plan, timeStart = LocalDateTime.of(2026, 6, 10, 13, 0),
|
||||
revolution = id, station = "102", duration = 60.0
|
||||
)
|
||||
dropStore[id] = d
|
||||
|
||||
+8
-45
@@ -41,8 +41,6 @@ import space.nstart.pcp.pcp_mission_planing_service.service.satellite_type.Refli
|
||||
import space.nstart.pcp.pcp_mission_planing_service.service.satellite_type.SatelliteMissionTypeFactory
|
||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDTO
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.util.UUID
|
||||
import java.math.BigDecimal
|
||||
|
||||
@@ -93,7 +91,7 @@ class MissionPlaningServiceTest {
|
||||
val overlappingSurvey = SurveyModeEntity(
|
||||
id = 1L,
|
||||
plan = plan,
|
||||
timeStart = intervalStart.minusMinutes(5).atOffset(ZoneOffset.UTC),
|
||||
timeStart = intervalStart.minusMinutes(5),
|
||||
revolution = 10,
|
||||
lat = 55.0,
|
||||
long = 37.0,
|
||||
@@ -105,7 +103,7 @@ class MissionPlaningServiceTest {
|
||||
val inWindowSurvey = SurveyModeEntity(
|
||||
id = 2L,
|
||||
plan = plan,
|
||||
timeStart = intervalStart.plusMinutes(10).atOffset(ZoneOffset.UTC),
|
||||
timeStart = intervalStart.plusMinutes(10),
|
||||
revolution = 11,
|
||||
lat = 56.0,
|
||||
long = 38.0,
|
||||
@@ -117,7 +115,7 @@ class MissionPlaningServiceTest {
|
||||
val inWindowDrop = DropModeEntity(
|
||||
id = 3L,
|
||||
plan = plan,
|
||||
timeStart = intervalStart.plusMinutes(20).atOffset(ZoneOffset.UTC),
|
||||
timeStart = intervalStart.plusMinutes(20),
|
||||
revolution = 12,
|
||||
station = "station-1",
|
||||
duration = 120.0
|
||||
@@ -126,7 +124,7 @@ class MissionPlaningServiceTest {
|
||||
`when`(
|
||||
modeRepository.findAllByPlan_Mission_SatelliteIdAndTimeStartIsNotNullAndTimeStartLessThanEqualOrderByTimeStartAsc(
|
||||
77,
|
||||
intervalStop.atOffset(ZoneOffset.UTC)
|
||||
intervalStop
|
||||
)
|
||||
).thenReturn(listOf(overlappingSurvey, inWindowSurvey, inWindowDrop))
|
||||
`when`(modeBookingRepository.findAllByMode_IdIn(listOf(1L, 2L))).thenReturn(
|
||||
@@ -153,41 +151,6 @@ class MissionPlaningServiceTest {
|
||||
assertEquals(listOf(2L), (result[2] as DropModeResponseDTO).surveys)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `modesBySatelliteAndInterval normalizes non-UTC mode offsets to UTC before matching`() {
|
||||
val mission = MissionEntity(missionId = UUID.randomUUID(), satelliteId = 77)
|
||||
val plan = PlanEntity(id = 101L, mission = mission, planNumber = 1)
|
||||
val intervalStart = LocalDateTime.of(2026, 3, 16, 10, 0, 0)
|
||||
val intervalStop = LocalDateTime.of(2026, 3, 16, 10, 30, 0)
|
||||
|
||||
// То же мгновение, что 10:10 UTC (внутри окна), но выражено со смещением +03:00 → 13:10.
|
||||
// Голый toLocalDateTime() дал бы 13:10 и выкинул мод из окна; нормализация к UTC оставляет его.
|
||||
val offsetSurvey = SurveyModeEntity(
|
||||
id = 1L,
|
||||
plan = plan,
|
||||
timeStart = OffsetDateTime.of(2026, 3, 16, 13, 10, 0, 0, ZoneOffset.ofHours(3)),
|
||||
revolution = 11,
|
||||
lat = 56.0,
|
||||
long = 38.0,
|
||||
duration = 300.0,
|
||||
contourWkt = "POLYGON((0 0,1 0,1 1,0 0))",
|
||||
roll = 1.0,
|
||||
source = SurveyModeSource.SLOT
|
||||
)
|
||||
|
||||
`when`(
|
||||
modeRepository.findAllByPlan_Mission_SatelliteIdAndTimeStartIsNotNullAndTimeStartLessThanEqualOrderByTimeStartAsc(
|
||||
77,
|
||||
intervalStop.atOffset(ZoneOffset.UTC)
|
||||
)
|
||||
).thenReturn(listOf(offsetSurvey))
|
||||
`when`(modeBookingRepository.findAllByMode_IdIn(listOf(1L))).thenReturn(emptyList())
|
||||
|
||||
val result = service.modesBySatelliteAndInterval(77, intervalStart, intervalStop)
|
||||
|
||||
assertEquals(listOf(1L), result.map { it.id })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `modesBySatelliteAndInterval rejects inverted interval`() {
|
||||
val exception = assertThrows(ResponseStatusException::class.java) {
|
||||
@@ -223,12 +186,12 @@ class MissionPlaningServiceTest {
|
||||
)
|
||||
val exactMode = SurveyModeEntity(
|
||||
id = 10L,
|
||||
timeStart = routePassport.intervalBegin.atOffset(ZoneOffset.UTC),
|
||||
timeStart = routePassport.intervalBegin,
|
||||
revolution = 321
|
||||
)
|
||||
val nearMode = SurveyModeEntity(
|
||||
id = 11L,
|
||||
timeStart = routePassport.intervalBegin.plusSeconds(1).atOffset(ZoneOffset.UTC),
|
||||
timeStart = routePassport.intervalBegin.plusSeconds(1),
|
||||
revolution = 321
|
||||
)
|
||||
|
||||
@@ -236,8 +199,8 @@ class MissionPlaningServiceTest {
|
||||
surveyModeRepository.findAllBySatelliteNumberAndRevolutionAndTimeStartBetween(
|
||||
"22",
|
||||
321,
|
||||
OffsetDateTime.of(routePassport.intervalBegin.minusSeconds(1), ZoneOffset.UTC),
|
||||
OffsetDateTime.of(routePassport.intervalBegin.plusSeconds(1), ZoneOffset.UTC)
|
||||
routePassport.intervalBegin.minusSeconds(1),
|
||||
routePassport.intervalBegin.plusSeconds(1)
|
||||
)
|
||||
).thenReturn(listOf(nearMode, exactMode))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user