Отказ от остаточной UTC-семантики: naive LocalDateTime трактуется как
локальное время единой зоны всех сервисов.
Backend (границы внешних систем):
- VisibilityPayloadParser, SyncSpacecraftFromNsiUseCase: ZoneOffset.UTC →
ZoneId.systemDefault() для проекции внешних Instant/ISO-с-Z в naive.
- тесты границ перевёрнуты на systemDefault (под Europe/Moscow ждут +3).
- чистка UTC-формулировок в DTO-комментариях, мёртвых ссылок на
docs/standards/DATETIME_UTC.md.
Frontend (pcp-tgu-ops-ui):
- utils/utcTime.ts → utils/localTime.ts: parseLocal/formatLocal*/toLocalIso/
toLocalInputValue с локальной семантикой (без дописывания Z и timeZone:UTC).
- замена getUTC*/Date.UTC/toISOString-сериализации на локальные аналоги.
- убраны пользовательские подписи «UTC» в редакторе/таймлайне.
- удалён utcTime.guard.test.ts (форсил обратный UTC-инвариант); тест-фикстуры
сделаны зоно-независимыми. tsc + vitest зелёные под TZ=UTC и TZ=Europe/Moscow.
Включает также прочие незакоммиченные правки рабочего дерева.
Бэкенд (pcp-tgu-service):
- REJECTED трактуется как «план неправильный»: авто-перевыдача больше НЕ
взводится, цепочка встаёт на паузу (новый флаг
SpacecraftPlanningStateEntity.pausedAfterReject, миграция V13). Технические
негативы («не заложен»/«не принят») по-прежнему дают срочную перевыдачу.
- Пауза централизована в PlanProjectionService.project(): для отклонённой
цепочки проекция пустая, воркер выдачи ничего не материализует. Флаг
снимается при ручной выдаче/промоуте черновика/приёмке (оператор вмешался).
- Режим «Черновики»: GET /plans/drafts (опц. ?spacecraftId) -> только DRAFT.
- Гард дублей черновиков: (КА + начало + конец) уникальны среди DRAFT,
повторное создание окна -> 409.
- ZrvWindowMatcher: сравнение по истинной abs-длительности Duration (<=1с),
устойчиво к усечению ISO на фронте до целых секунд.
Фронт (pcp-tgu-ops-ui): вкладка «Планы» — таймлайн цепочек, детали плана,
панель ЗРВ (TguZrvPanel), диалог создания цепочки, режим черновиков.
Удалён устаревший docs/tasks/TASK_tgu-plan-versioning-manual-reissue.md.
Селектор «Целевая ЗРВ» в EditorToolbar: текущий слот (replace, по умолчанию)
либо будущая ЗРВ из проекции pcp-tgu-service (fetchSpacecraftPlans →
GET /api/plans/{spacecraftId}, фильтр futureZrvWindows: PLANNED строго в
будущем, кроме базы — та же проекция, что валидирует бэк). Выбор окна
переводит обзор редактора и заставляет ensureDraft слать mode=fork-forward
(naive-UTC окно + kpp); селектор блокируется после создания DRAFT.
mission-planing: POST /api/missions/{id}/clone — полный клон (replace)
или по перекрытию с окном (fork-forward, [start,stop) открытый правый конец);
пустые drop-mode (все съёмки вне окна) не клонируются
tgu-service: PlannedPlanStatus.DRAFT; POST /api/plans/{planId}/draft
(CreateDraftUseCase: guard replace/fork-forward, clone mission → planId=newMissionId,
компенсация при сбое); DRAFT отфильтрован из PlanQueryService read-пути;
MissionPlaningClient + MissionPlaningProperties + mission-planing.base-url в yaml
тесты: MissionCloneTest (6 граничных кейсов предиката перекрытия),
PlanQueryServiceTest (DRAFT не видна в ответе)
- ручная выдача вынесена из TestTguController в PlanController
- assertReissuableInSlot: 422 при LAID_IN и заморозке (now >= start - layinFreezeMinutes),
409 при активной выдаче другого плана КА; перевыдача того же плана поверх своей
in-flight attempt разрешена (новая attemptNo++ замещает летящую)
- REISSUABLE_STATUSES удалён — гард по времени/статусу его заместил
- layinFreezeMinutes (деф. 10) в PlanningProperties + config-repo/application yaml
- граничные тесты в IssueDuePlanWorkerOnDemandTest, переписан PlanIssueAndDecisionFlowTest
- дизайн-док версионирования (фаза 1 отмечена сделанной)
Время бэка (naive LocalDateTime и OffsetDateTime) разбиралось через
new Date(string)/Date.parse, из-за чего naive-строки трактовались как
локальное время браузера: вкладки расходились по времени, а путь создания
заявки сдвигал введённое время на офсет. Ввёл единую точку utils/utcTime
(parseUtc/formatUtc*/toUtcInputValue/toUtcIso) и перевёл на неё вкладки
«Планы», «Заявки», «Карта 2D» — чтение, пикеры диапазона, создание заявки.
Плюс на вкладке «Планы» график по умолчанию открывается на интервал
сейчас−30 мин … сейчас+3 дня.
docs/tasks/TASK_datetime-utc-consistency.md — ТЗ на сверку всей группы
сервисов pcp на единообразие времени.
Раньше вся будущая цепочка планов материализовалась в planned_plan как
PLANNED-строки, а отдельный воркер пересчёта (RebuildPlanScheduleUseCase +
PlanRecalculationJob) держал её в актуальном состоянии и гасил выпавшие планы
в SUPERSEDED/EXPIRED. Это плодило вложенные планы, гонки пересчёта и мусор в БД.
Новая модель: в БД живёт только выданное (история навсегда), будущее — проекция,
вычисляемая по запросу из ЗРВ. Перекрывать (supersede) и протухать (expire)
больше нечего.
Бэкенд:
- Удалены TrackedPlan (entity/source/status + repo) и PlanRecalculationJob
(entity/repo/service/worker) — материализация и воркер пересчёта больше не нужны.
- Удалён RebuildPlanScheduleUseCase; будущее строит новый PlanProjectionService
поверх PlanCalculationService.
- PlanQueryService отдаёт проекцию (выданное из БД + будущее на лету).
- Новый флоу реакции на смену параметров станции: StationParamsChangedConsumer +
HandleStationParamsChangedUseCase (срочный перевыпуск через planning_state).
- Новые консьюмеры обратной связи исполнения: LayinFailedConsumer,
PlanNotAcceptedConsumer (+ DTO PlanExecutionFeedbackMessage,
StationParamsChangedMessage).
- PlannedPlanStatus: убраны мёртвые SUPERSEDED/EXPIRED; статусы выровнены под
жизненный цикл выдачи/закладки.
Миграции (ddl-auto: validate):
- V7 drop tracked_plan
- V8 drop plan_recalculation_job
- V9 planning_state: поля срочного перевыпуска
- V10 снять unique-ограничение бизнес-ключа planned_plan
- V11 удалить легаси PLANNED-строки (материализованное будущее)
- V12 удалить легаси SUPERSEDED/EXPIRED и столбец superseded_by_plan_id
Тесты: удалены JobRerunFlowTest и RebuildPlanScheduleUseCaseTest; добавлены
PlanProjectionServiceTest, PlanQueryServiceTest, IssueDuePlanWorkerOnDemandTest,
HandleStationParamsChangedUseCaseTest, VisibilityPayloadParserTest. Скорректированы
PlanIssueAndDecisionFlowTest, PlanCalculationServiceTest, VisibilityFlowTest и др.
V11/V12 необратимы — перед миграцией на проде снять дамп planned_plan.
Port the TGU editor prototype into pcp-tgu-ops-ui as a new editor tab, add draft/conflict/pass logic with tests, extend the 2D map picking API, and include editor styles/theme aliases and task/prototype docs.
Validation: npm run test; npm run build in services/pcp-tgu-ops-ui.