pcp: миграция времени плана ТГУ на явный Z (OffsetDateTime)
PlanResponse (pcp-tgu-service) и зависящий от него TguPlanResponse (pcp-ui-service) переведены с naive LocalDateTime на OffsetDateTime в UTC → на проводе явная зона Z. Домен/БД (PlannedPlanEntity/CalculatedPlan) остаются naive LocalDateTime (= UTC); конвертация только на границе API (atOffset(ZoneOffset.UTC)). Потребитель один (ui-service.TguPlanningService), обновлён синхронно; фронт parseUtc совместим с Z. - контрактные тесты обновлены на Z (PlanResponseContractTest, TguPlanningDtoContractTest); - тестовые фикстуры/ассерты приведены к OffsetDateTime/Z (PlanQueryServiceTest, CatalogControllerTest, TguPlanningServiceTest); - docs/standards/DATETIME_UTC.md: отражена миграция и обновлена таблица сервисов.
This commit is contained in:
@@ -43,8 +43,8 @@
|
|||||||
| Сервис | Преобладает на границе API | Naive? | Вердикт |
|
| Сервис | Преобладает на границе API | Naive? | Вердикт |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| pcp-request-service | `OffsetDateTime` (`Z`) | нет | **эталон**: явная зона на проводе |
|
| pcp-request-service | `OffsetDateTime` (`Z`) | нет | **эталон**: явная зона на проводе |
|
||||||
| pcp-tgu-service | `LocalDateTime` (planId/plan times) | да | задокументирован «=UTC» (`PlanResponse`); баги конвертаций исправлены |
|
| pcp-tgu-service | REST `PlanResponse` — `OffsetDateTime` (`Z`); Kafka/прочие DTO — `LocalDateTime` | частично | `PlanResponse` **мигрирован на `Z`**; баги конвертаций исправлены; Kafka-DTO остаются naive (=UTC) |
|
||||||
| pcp-ui-service | `LocalDateTime` (агрегатор/CZML, summaries) | да | задокументировать «=UTC»; кандидат на `Z` |
|
| pcp-ui-service | `LocalDateTime` (агрегатор/CZML, summaries); план ТГУ — `OffsetDateTime` (`Z`) | частично | `TguPlanResponse` **мигрирован на `Z`** вслед за tgu; прочие naive DTO — задокументировать |
|
||||||
| pcp-complex-mission-service | `LocalDateTime` (+ часть `Instant`) | смешано | проверить смешение; задокументировать |
|
| pcp-complex-mission-service | `LocalDateTime` (+ часть `Instant`) | смешано | проверить смешение; задокументировать |
|
||||||
| pcp-dynamic-plan-service | `LocalDateTime` (+ offset на входе клиента) | да | задокументировать «=UTC» |
|
| pcp-dynamic-plan-service | `LocalDateTime` (+ offset на входе клиента) | да | задокументировать «=UTC» |
|
||||||
| pcp-ballistics-service | `LocalDateTime` | да | задокументировать «=UTC» |
|
| pcp-ballistics-service | `LocalDateTime` | да | задокументировать «=UTC» |
|
||||||
@@ -77,13 +77,24 @@
|
|||||||
Оба формата на проводе закреплены сериализационными тестами (mapper зеркалит конфиг Spring Boot —
|
Оба формата на проводе закреплены сериализационными тестами (mapper зеркалит конфиг Spring Boot —
|
||||||
JavaTimeModule + `disable(WRITE_DATES_AS_TIMESTAMPS)`):
|
JavaTimeModule + `disable(WRITE_DATES_AS_TIMESTAMPS)`):
|
||||||
|
|
||||||
- `PlanResponseContractTest` (pcp-tgu-service) — naive `LocalDateTime` без зоны.
|
- `PlanResponseContractTest` (pcp-tgu-service) — `OffsetDateTime` с `Z` (после миграции, см. ниже).
|
||||||
- `RequestResponseDtoContractTest` (pcp-request-service) — `OffsetDateTime` с `Z` (эталон).
|
- `RequestResponseDtoContractTest` (pcp-request-service) — `OffsetDateTime` с `Z` (эталон).
|
||||||
- `TguPlanningDtoContractTest` (pcp-ui-service) — оба формата: naive `LocalDateTime` + `Instant` с `Z`.
|
- `TguPlanningDtoContractTest` (pcp-ui-service) — план ТГУ `OffsetDateTime` с `Z` + `Instant` с `Z`.
|
||||||
|
|
||||||
Прочие сервисы с naive-временем (ballistics, complex-mission, dynamic-plan, slots, coverage-scheme,
|
Прочие сервисы с naive-временем (ballistics, complex-mission, dynamic-plan, slots, coverage-scheme,
|
||||||
mission-planing) используют тот же дефолтный Jackson-конфиг → тот же naive-формат; при желании
|
mission-planing) используют тот же дефолтный Jackson-конфиг → тот же naive-формат; при желании
|
||||||
пер-сервисный страж копируется по образцу `PlanResponseContractTest`.
|
пер-сервисный страж копируется по образцу `RequestResponseDtoContractTest`.
|
||||||
|
|
||||||
|
### Миграция к `Z` — выполнено
|
||||||
|
|
||||||
|
- **План ТГУ (tgu → ui-service → фронт).** `PlanResponse` (pcp-tgu-service) и зависящий от него
|
||||||
|
`TguPlanResponse` (pcp-ui-service) переведены с naive `LocalDateTime` на `OffsetDateTime` в UTC →
|
||||||
|
на проводе `Z`. Домен/БД (`PlannedPlanEntity`/`CalculatedPlan`) остались naive `LocalDateTime` (=UTC);
|
||||||
|
конвертация только на границе (`atOffset(ZoneOffset.UTC)`). Потребитель один (ui-service), обновлён
|
||||||
|
синхронно; фронт `parseUtc` совместим. Контракт закреплён тестами выше.
|
||||||
|
|
||||||
|
Следующие кандидаты на миграцию (по согласованию, по сервису): остальные naive-DTO ui-service,
|
||||||
|
ballistics, complex-mission, dynamic-plan, slots, coverage-scheme.
|
||||||
|
|
||||||
## 5. Правило для нового кода
|
## 5. Правило для нового кода
|
||||||
|
|
||||||
|
|||||||
+16
-13
@@ -4,16 +4,17 @@ import space.nstart.pcp_tgu_service.domain.CalculatedPlan
|
|||||||
import space.nstart.pcp_tgu_service.entity.PlannedPlanEntity
|
import space.nstart.pcp_tgu_service.entity.PlannedPlanEntity
|
||||||
import space.nstart.pcp_tgu_service.entity.PlannedPlanStatus
|
import space.nstart.pcp_tgu_service.entity.PlannedPlanStatus
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.time.LocalDateTime
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO ответа REST API для плана.
|
* DTO ответа REST API для плана.
|
||||||
*
|
*
|
||||||
* Времена ([startTime]/[endTime]) — `LocalDateTime` и сериализуются как ISO-строка без зоны
|
* Времена ([startTime]/[endTime]) — `OffsetDateTime` в UTC и сериализуются как ISO-строка с явной
|
||||||
* (напр. `"2026-05-29T01:00:00"`). По соглашению системы это **UTC** (см. `docs/standards/DATETIME_UTC.md`):
|
* зоной `Z` (напр. `"2026-05-29T01:00:00Z"`), см. `docs/standards/DATETIME_UTC.md`. Внутреннее
|
||||||
* потребители обязаны парсить эти строки как UTC (фронт — через `utils/utcTime.parseUtc`), а не как
|
* хранение и домен (`PlannedPlanEntity`/`CalculatedPlan`) остаются naive `LocalDateTime` (= UTC);
|
||||||
* локальное время. Кандидат на миграцию к явному `Z` (`OffsetDateTime`/`Instant`) на границе API.
|
* конвертация в `Z` происходит только на границе API.
|
||||||
*/
|
*/
|
||||||
data class PlanResponse(
|
data class PlanResponse(
|
||||||
|
|
||||||
@@ -23,11 +24,11 @@ data class PlanResponse(
|
|||||||
/** Идентификатор космического аппарата */
|
/** Идентификатор космического аппарата */
|
||||||
val spacecraftId: String,
|
val spacecraftId: String,
|
||||||
|
|
||||||
/** Время начала плана (UTC, naive ISO без зоны). */
|
/** Время начала плана (UTC, ISO с `Z`). */
|
||||||
val startTime: LocalDateTime,
|
val startTime: OffsetDateTime,
|
||||||
|
|
||||||
/** Время окончания плана (UTC, naive ISO без зоны). */
|
/** Время окончания плана (UTC, ISO с `Z`). */
|
||||||
val endTime: LocalDateTime,
|
val endTime: OffsetDateTime,
|
||||||
|
|
||||||
/** Идентификатор пункта закладки */
|
/** Идентификатор пункта закладки */
|
||||||
val kppId: String,
|
val kppId: String,
|
||||||
@@ -45,8 +46,9 @@ data class PlanResponse(
|
|||||||
PlanResponse(
|
PlanResponse(
|
||||||
planId = plan.planId,
|
planId = plan.planId,
|
||||||
spacecraftId = plan.spacecraftId,
|
spacecraftId = plan.spacecraftId,
|
||||||
startTime = plan.startTime,
|
// naive LocalDateTime в БД = UTC → отдаём с явной зоной Z.
|
||||||
endTime = plan.endTime,
|
startTime = plan.startTime.atOffset(ZoneOffset.UTC),
|
||||||
|
endTime = plan.endTime.atOffset(ZoneOffset.UTC),
|
||||||
kppId = plan.kppId,
|
kppId = plan.kppId,
|
||||||
status = plan.status
|
status = plan.status
|
||||||
)
|
)
|
||||||
@@ -61,8 +63,9 @@ data class PlanResponse(
|
|||||||
PlanResponse(
|
PlanResponse(
|
||||||
planId = deterministicPlanId(plan),
|
planId = deterministicPlanId(plan),
|
||||||
spacecraftId = plan.spacecraftId,
|
spacecraftId = plan.spacecraftId,
|
||||||
startTime = plan.startTime,
|
// naive LocalDateTime расчёта = UTC → отдаём с явной зоной Z.
|
||||||
endTime = plan.endTime,
|
startTime = plan.startTime.atOffset(ZoneOffset.UTC),
|
||||||
|
endTime = plan.endTime.atOffset(ZoneOffset.UTC),
|
||||||
kppId = plan.kppId,
|
kppId = plan.kppId,
|
||||||
status = PlannedPlanStatus.PLANNED
|
status = PlannedPlanStatus.PLANNED
|
||||||
)
|
)
|
||||||
|
|||||||
+11
-14
@@ -6,13 +6,14 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
|||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import space.nstart.pcp_tgu_service.entity.PlannedPlanStatus
|
import space.nstart.pcp_tgu_service.entity.PlannedPlanStatus
|
||||||
import java.time.LocalDateTime
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контракт формата времени на проводе для [PlanResponse]: naive ISO без зоны (= UTC,
|
* Контракт формата времени на проводе для [PlanResponse]: `OffsetDateTime` в UTC → ISO с явной зоной `Z`
|
||||||
* см. docs/standards/DATETIME_UTC.md). Тест ловит молчаливый дрейф контракта — смену типа поля
|
* (см. docs/standards/DATETIME_UTC.md). Тест ловит молчаливый дрейф контракта — смену типа поля
|
||||||
* (на `OffsetDateTime`/`Instant`) или Jackson-конфига, которые поломали бы потребителей.
|
* (назад на naive `LocalDateTime`) или Jackson-конфига, которые поломали бы потребителей.
|
||||||
*
|
*
|
||||||
* Mapper зеркалит конфиг Spring Boot: JavaTimeModule + disable(WRITE_DATES_AS_TIMESTAMPS).
|
* Mapper зеркалит конфиг Spring Boot: JavaTimeModule + disable(WRITE_DATES_AS_TIMESTAMPS).
|
||||||
*/
|
*/
|
||||||
@@ -22,24 +23,20 @@ class PlanResponseContractTest {
|
|||||||
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `serializes plan times as naive ISO without zone`() {
|
fun `serializes plan times as ISO with explicit Z zone`() {
|
||||||
val response = PlanResponse(
|
val response = PlanResponse(
|
||||||
planId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
|
planId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
|
||||||
spacecraftId = "25544",
|
spacecraftId = "25544",
|
||||||
startTime = LocalDateTime.of(2026, 5, 29, 1, 0, 0),
|
startTime = OffsetDateTime.of(2026, 5, 29, 1, 0, 0, 0, ZoneOffset.UTC),
|
||||||
endTime = LocalDateTime.of(2026, 5, 29, 2, 0, 0),
|
endTime = OffsetDateTime.of(2026, 5, 29, 2, 0, 0, 0, ZoneOffset.UTC),
|
||||||
kppId = "KPP-1",
|
kppId = "KPP-1",
|
||||||
status = PlannedPlanStatus.PLANNED
|
status = PlannedPlanStatus.PLANNED
|
||||||
)
|
)
|
||||||
|
|
||||||
val node = mapper.readTree(mapper.writeValueAsString(response))
|
val node = mapper.readTree(mapper.writeValueAsString(response))
|
||||||
|
|
||||||
assertEquals("2026-05-29T01:00:00", node.get("startTime").asText())
|
assertEquals("2026-05-29T01:00:00Z", node.get("startTime").asText())
|
||||||
assertEquals("2026-05-29T02:00:00", node.get("endTime").asText())
|
assertEquals("2026-05-29T02:00:00Z", node.get("endTime").asText())
|
||||||
// Нет суффикса зоны (Z/±офсет) — иначе потребитель, читающий naive как UTC, ошибётся.
|
assertTrue(node.get("startTime").asText().endsWith("Z"), "ожидалась явная зона Z")
|
||||||
assertTrue(
|
|
||||||
node.get("startTime").asText().matches(Regex("""\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}""")),
|
|
||||||
"ожидался naive ISO без зоны"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -39,9 +39,10 @@ class PlanQueryServiceTest {
|
|||||||
val result = service.getAllPlans(historyDays = 7)
|
val result = service.getAllPlans(historyDays = 7)
|
||||||
|
|
||||||
assertEquals(2, result.size)
|
assertEquals(2, result.size)
|
||||||
val persistedResponse = result.first { it.startTime == persisted.startTime }
|
// PlanResponse.startTime — OffsetDateTime(UTC); доменные времена naive LocalDateTime (= UTC).
|
||||||
|
val persistedResponse = result.first { it.startTime == persisted.startTime.atOffset(ZoneOffset.UTC) }
|
||||||
assertEquals(PlannedPlanStatus.AWAITING_LAYIN, persistedResponse.status)
|
assertEquals(PlannedPlanStatus.AWAITING_LAYIN, persistedResponse.status)
|
||||||
val projectedResponse = result.first { it.startTime == freshProjected.startTime }
|
val projectedResponse = result.first { it.startTime == freshProjected.startTime.atOffset(ZoneOffset.UTC) }
|
||||||
assertEquals(PlannedPlanStatus.PLANNED, projectedResponse.status)
|
assertEquals(PlannedPlanStatus.PLANNED, projectedResponse.status)
|
||||||
// Отсортировано по startTime.
|
// Отсортировано по startTime.
|
||||||
assertTrue(result[0].startTime <= result[1].startTime)
|
assertTrue(result[0].startTime <= result[1].startTime)
|
||||||
|
|||||||
+6
-4
@@ -2,11 +2,13 @@ package space.nstart.pcp.slots_service.dto.tgu
|
|||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import java.time.OffsetDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Времена в этом файле — UTC (см. docs/standards/DATETIME_UTC.md): `LocalDateTime` сериализуется как
|
* Времена в этом файле — UTC (см. docs/standards/DATETIME_UTC.md). Времена плана ([TguPlanResponse]) —
|
||||||
* naive ISO без зоны (= UTC), `Instant` — с `Z`. Потребители (фронт через utils/utcTime) парсят как UTC.
|
* `OffsetDateTime` с явной зоной `Z` (как отдаёт pcp-tgu-service); `Instant` — тоже с `Z`. `LocalDateTime`
|
||||||
|
* (напр. [TguPlanDecisionMessage.decisionTime]) — naive ISO без зоны (= UTC). Фронт парсит через utils/utcTime.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
data class TguPlatformResponse(
|
data class TguPlatformResponse(
|
||||||
@@ -23,8 +25,8 @@ data class TguPlatformResponse(
|
|||||||
data class TguPlanResponse(
|
data class TguPlanResponse(
|
||||||
val planId: UUID,
|
val planId: UUID,
|
||||||
val spacecraftId: String,
|
val spacecraftId: String,
|
||||||
val startTime: LocalDateTime,
|
val startTime: OffsetDateTime,
|
||||||
val endTime: LocalDateTime,
|
val endTime: OffsetDateTime,
|
||||||
val kppId: String,
|
val kppId: String,
|
||||||
val status: String
|
val status: String
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-2
@@ -45,6 +45,8 @@ import space.nstart.pcp.slots_service.service.SlotService
|
|||||||
import space.nstart.pcp.slots_service.service.StationService
|
import space.nstart.pcp.slots_service.service.StationService
|
||||||
import space.nstart.pcp.slots_service.service.TguPlanningService
|
import space.nstart.pcp.slots_service.service.TguPlanningService
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
@@ -210,8 +212,8 @@ class CatalogControllerTest {
|
|||||||
TguPlanResponse(
|
TguPlanResponse(
|
||||||
planId = planId,
|
planId = planId,
|
||||||
spacecraftId = "56756",
|
spacecraftId = "56756",
|
||||||
startTime = LocalDateTime.of(2026, 5, 29, 10, 0),
|
startTime = OffsetDateTime.of(2026, 5, 29, 10, 0, 0, 0, ZoneOffset.UTC),
|
||||||
endTime = LocalDateTime.of(2026, 5, 29, 10, 15),
|
endTime = OffsetDateTime.of(2026, 5, 29, 10, 15, 0, 0, ZoneOffset.UTC),
|
||||||
kppId = "KPP-1",
|
kppId = "KPP-1",
|
||||||
status = "WAITING_DECISION"
|
status = "WAITING_DECISION"
|
||||||
)
|
)
|
||||||
|
|||||||
+11
-11
@@ -6,13 +6,15 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
|||||||
import org.junit.jupiter.api.Assertions.assertTrue
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контракт формата времени на проводе для DTO вкладки ТГУ в pcp-ui-service:
|
* Контракт формата времени на проводе для DTO вкладки ТГУ в pcp-ui-service:
|
||||||
* naive `LocalDateTime` → ISO без зоны (= UTC), `Instant` → ISO с `Z`
|
* времена плана ([TguPlanResponse]) — `OffsetDateTime` с `Z` (как отдаёт pcp-tgu-service),
|
||||||
* (см. docs/standards/DATETIME_UTC.md). Тест ловит молчаливый дрейф контракта.
|
* `Instant` ([TguPlatformResponse.validFrom]) — тоже с `Z` (см. docs/standards/DATETIME_UTC.md).
|
||||||
|
* Тест ловит молчаливый дрейф контракта.
|
||||||
*
|
*
|
||||||
* Mapper зеркалит конфиг Spring Boot: JavaTimeModule + disable(WRITE_DATES_AS_TIMESTAMPS).
|
* Mapper зеркалит конфиг Spring Boot: JavaTimeModule + disable(WRITE_DATES_AS_TIMESTAMPS).
|
||||||
*/
|
*/
|
||||||
@@ -22,23 +24,21 @@ class TguPlanningDtoContractTest {
|
|||||||
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `serializes plan times as naive ISO without zone`() {
|
fun `serializes plan times as ISO with explicit Z zone`() {
|
||||||
val plan = TguPlanResponse(
|
val plan = TguPlanResponse(
|
||||||
planId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
|
planId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
|
||||||
spacecraftId = "25544",
|
spacecraftId = "25544",
|
||||||
startTime = LocalDateTime.of(2026, 5, 29, 1, 0, 0),
|
startTime = OffsetDateTime.of(2026, 5, 29, 1, 0, 0, 0, ZoneOffset.UTC),
|
||||||
endTime = LocalDateTime.of(2026, 5, 29, 2, 0, 0),
|
endTime = OffsetDateTime.of(2026, 5, 29, 2, 0, 0, 0, ZoneOffset.UTC),
|
||||||
kppId = "KPP-1",
|
kppId = "KPP-1",
|
||||||
status = "PLANNED"
|
status = "PLANNED"
|
||||||
)
|
)
|
||||||
|
|
||||||
val node = mapper.readTree(mapper.writeValueAsString(plan))
|
val node = mapper.readTree(mapper.writeValueAsString(plan))
|
||||||
|
|
||||||
assertEquals("2026-05-29T01:00:00", node.get("startTime").asText())
|
assertEquals("2026-05-29T01:00:00Z", node.get("startTime").asText())
|
||||||
assertTrue(
|
assertEquals("2026-05-29T02:00:00Z", node.get("endTime").asText())
|
||||||
node.get("startTime").asText().matches(Regex("""\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}""")),
|
assertTrue(node.get("startTime").asText().endsWith("Z"), "ожидалась явная зона Z")
|
||||||
"ожидался naive ISO без зоны"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ class TguPlanningServiceTest {
|
|||||||
exchange.requestURI.path == "/api/plans" || exchange.requestURI.path == "/api/plans/56756" -> respond(
|
exchange.requestURI.path == "/api/plans" || exchange.requestURI.path == "/api/plans/56756" -> respond(
|
||||||
exchange,
|
exchange,
|
||||||
200,
|
200,
|
||||||
"""[{"planId":"6d0941e4-61d6-4f96-8fa8-90ba11db121e","spacecraftId":"56756","startTime":"2026-05-29T10:00:00","endTime":"2026-05-29T10:15:00","kppId":"KPP-1","status":"WAITING_DECISION"}]"""
|
"""[{"planId":"6d0941e4-61d6-4f96-8fa8-90ba11db121e","spacecraftId":"56756","startTime":"2026-05-29T10:00:00Z","endTime":"2026-05-29T10:15:00Z","kppId":"KPP-1","status":"WAITING_DECISION"}]"""
|
||||||
)
|
)
|
||||||
exchange.requestURI.path.startsWith("/test/tgu/plans/") -> respond(
|
exchange.requestURI.path.startsWith("/test/tgu/plans/") -> respond(
|
||||||
exchange,
|
exchange,
|
||||||
|
|||||||
Reference in New Issue
Block a user