Files
dc-observatio/docs/бэклог-pcp-tgu-ops-ui.md
T
Дмитрий Соловьев c74327011a docs(бэклог): #39 — авторасчёт выдаёт маршруты с креном >45° (slots/каталог)
Зафиксирована диагностика: корень — оптические полосы Emissio в каталоге
(satellite_slot_angle) уходят до 50.42°, slots-service берёт центр полосы
без зажима по 45°. Версия «логика локации» проверена и отклонена.
2026-06-08 13:55:01 +03:00

21 KiB
Raw Blame History

Бэклог pcp-tgu-ops-ui

Список задач по сервису pcp-tgu-ops-ui (и связанным бэкендам). Ведётся вручную и с помощью Claude: по просьбе — отмечаем выполненное и добавляем новые задачи.

Обозначения статуса:

  • [ ] — не начато
  • [~] — в работе
  • [x] — выполнено (переносится в раздел «Выполнено» с пометкой)

У каждой задачи есть стабильный номер #N — он не меняется при правках списка, на него удобно ссылаться. Новые задачи получают следующий свободный номер.

Задачи #12–#25 заведены по результатам аудита. Подробности, обоснование и рекомендации по каждой — в аудит-проекта-2026-06-06.md (ссылки на коды находок B/F/R/C).

Обновлено: 2026-06-08


Активные задачи

Карта и отображение

  • #1 — Отображать трассы полос исходя из возможности съёмки КА. Для оптики показывать только участки, попадающие в допустимый угол Солнца.
  • #2 — При клике в область, где пересекается несколько полос обзора, выводить список этих объектов на правой панели; при выборе элемента — выделять соответствующий объект на карте.
  • #3 — Показ забронированных слотов на вкладках «Карта» и «Редактор». Включает подгрузку данных по забронированным слотам с бэкенда (фетч), а не только отрисовку уже имеющихся. На вкладке «Редактор» они должны быть другого цвета и выделяться.

Группировка

  • #36 — Заполнение бортового накопителя на вкладке «Группировка». Сейчас (MVP) считается на фронте из объёмов маршрутов плана (volumeMb): старт 0 на начало интервала плана, +vol на конце съёмки, vol на конце сброса, ёмкость борта — модельные 500 ГБ (ONBOARD_CAPACITY_MB в features/constellation/realData.ts). Довести до реального источника: брать ёмкость борта из НСИ платформы (не хардкод), а заполнение — из телеметрии/бортового учёта, когда такой канал появится; уточнить модель «съёмка копит / сброс опустошает» (частичные сбросы, очерёдность).

Редактор

  • #4 — Показывать на вкладке «Редактор» только те заявки, которые может удовлетворить аппарат (например, для оптики не показывать заявку, для которой доступна только локация).
  • #5 — Дать возможность превратить план в статусе PLANNED (построенный цепочкой от последнего LAID_IN) в черновик и вручную наполнить его включениями — до того, как он будет автоматически выдан по таймеру.
  • #38 — Правка SLOTS-маршрута «телепортирует» его (исчезает с карты). При «Редактировать» редактор пересобирает контур через survey-route/build, передавая сохранённый timeStart. Для маршрутов source=MANUAL это корректно (их timeStart = время построения, контур воспроизводится). Для source=SLOTS timeStart/виток/контур посчитаны другим конвейером и не согласованы: напр. режим 174 хранит timeStart=2026-06-07T01:51:38, виток 152, контур над Чёрным морем (центр 45.42, 39.40), но в 01:51:38 спутник по flight-line над Индией (12–16° с.ш., виток 150) — пересборка даёт контур над Индией (10.73, 77.06), исходный прячется → маршрут «пропадает» из вида. Корень — та же баллистическая рассинхронизация, что и [#37]. Решение (2026-06-08): чиним только на бэкенде — согласовать timeStart/виток/контур у SLOTS-режимов, чтобы survey-route/build воспроизводил их. UI-страховку (не прятать исходный контур / блокировать правку SLOTS) сознательно НЕ делаем — симптом остаётся до бэкенд-фикса.

Комплексный план

  • #6 — Пересчитывать комплексный план при бронировании новых слотов или при поступлении новой заявки.

Бэкенд / инфраструктура

  • #7 — Перевести сервис станций на ordinis (по примеру получения аппаратов в сервисе tgu).
  • #37 — Рассинхрон номеров витков между баллистическими источниками. Для одного и того же КА/времени flight-line (трасса, /api/tgu-planning/spacecraft/{norad}/flight-line) и survey-route/build (контур, pcp-mission-planing) отдают разный номер витка: на Emissio 1 (norad 2) 2026-06-06 12:5012:55 трасса помечена витком 142, а контур/сохранённые режимы — витком 144 (по широте ~74° с.ш. согласованы, расходится только нумерация). В редакторе карта фильтрует трассу/полосу обзора по видимому витку (buildEditorMapScenevisibleRevolutions), поэтому при сужении селектора до «виток N» точки трассы с другим номером выпадают и пропадает орбитальный контекст. Свести нумерацию витков к единому источнику (или маппинг на границе), чтобы трасса и маршрут согласовывались по витку.

Проверка сервисов

  • #27 — Проверить сервис получения паспорта маршрута по отдельности.
  • #28 — Проверить связь сервиса заданий и сервиса получения паспорта маршрута между собой.

Баги

  • #8 — Ошибка при попытке принять план на вкладке «Планы».
  • #39 — Авторасчёт плана выдаёт нереализуемые маршруты съёмки с креном > 45° (напр. survey-211, Emissio 1, крен 46.8°). Такой маршрут нельзя построить вручную: фронт зажимает MAX_ROUTE_ROLL_DEG = 45 (TguEditorTab.tsx), а баллистика/геометрия маршрута и фильтр видимости (МПЛ, abs(kren) <= 45°) определены только до 45°. Диагностика (2026-06-08): корень — данные каталога, не логика. slots-service строит крен слота как центр угловой полосы из каталога (SlotService.kt:903-905, gamma=(begin+end)/2) и предел 45° не учитывает; полосы берутся напрямую из satellite_slot_angle. В сиде каталога (pcp-satellite-catalog-service/.../V1__initial.sql) у оптических Emissio (id 1-6, 22) собственный профиль полос уходит до 50.42°, и полоса №17 [46.08°, 47.51°] даёт центр ровно 46.8°. Версия «посчитали по логике локации» проверена и НЕ подтвердилась: в slots-service нет ветвления по типу КА (оптика/локация) — все КА строятся одним TestSatelliteImpl, солвер выбирается стратегией запроса (GREEDY/CONTINUOUS), type_code не используется. Reflexio (локация) наоборот имеет узкие полосы ~17-25°. Решение (вернуться позже): либо обрезать/убрать в каталоге оптические полосы за 45° (поз. №16-20 у Emissio), либо добавить в slots-service зажим/отсев слотов по рабочему пределу крена КА. Истинный предел Emissio подтвердить у владельца каталога/баллистиков перед правкой.

Аудит — надёжность и бэкенд

Источник и рекомендации: аудит-проекта-2026-06-06.md.

  • #12 — (B1, высокий) Camunda job-воркеры в FlowService молча глотают исключения (catch { logger.warn(ex.message) }) при autoComplete=false: задача не завершается и не падает, BPMN-процесс зависает без инцидента. Завершать через newFailCommand/проброс наверх, логировать error(msg, ex).
  • #13 — (B2, средний) Снять симуляционную заглушку Thread.sleep(5000) («имитация подтверждения плана») в FlowService.sendPlan при появлении реального канала подтверждений.
  • #14 — (B3, средний) Привести в порядок несогласованные пакеты-копипасты (ballistics→pcp_request_service, complex-mission→pcp_satellites_service, ui-service и slots-service делят slots_service, request→org.nstart.dep265, tgu→без .pcp.). Отдельной задачей из-за широкого охвата.
  • #15 — (B4, низкий) Опечатка «srpring» в pcp-srpring-boot-admin-server растиражирована по каталогу, пакету, CI, docker-compose, gradle. Чинить вместе с #14.
  • #16 — (B5, низкий) ~9 мест logger.warn/error(ex.message) теряют stack trace — заменить на logger.error("...", ex).

Аудит — фронтенд

Источник и рекомендации: аудит-проекта-2026-06-06.md.

  • #17 — (F1, средний) Вынести общий src/api/http.ts (fetchJson + extractErrorText + маппинг ошибок): extractErrorText продублирован в 5 клиентах, fetch-обвязка повторяется ~22 раза. Заодно устранить расхождение приоритета полей ошибки (F5).
  • #18 — (F2, низкий) Перевести нетипизированный островок features/constellation/* (.jsx/.js, allowJs) на TS или добавить декларации типов на границе.
  • #19 — (F3, низкий) Удалить мёртвый barrel features/constellation/index.js (нигде не импортируется).
  • #20 — (F4, низкий) Декомпозировать God-компонент TguEditorTab.tsx (1727 строк): вынести хуки (useDraftHistory, useRouteBuilder), разнести панели.

Аудит — гигиена репозитория и конфиги

Источник и рекомендации: аудит-проекта-2026-06-06.md.

  • #21 — (R1, средний) Убрать из git крупные дампы в корне (pcp_requests_converted_create_requests.json ~228 КБ, response_заданияКубернетс.json ~157 КБ, response_заданияЕмельянов.json ~66 КБ) — перенести в src/test/resources/docs или удалить с добавлением в .gitignore.
  • #22 — (R2, низкий) Удалить посторонние артефакты в корне: node_modules/ + пустой package-lock.json, obj_terra.zip; при желании добавить /package-lock.json в .gitignore.
  • #23 — (R3, низкий) Прогнать ./gradlew clean / удалить 26 устаревших каталогов bin/ (задваивают исходники, шумят при grep).
  • #24 — (C1, средний) Унифицировать креды БД в config-repo: привести все сервисы к переопределяемому password: ${DB_PASSWORD:...} (как в tgu-service), убрать зашитые password: password.
  • #25 — (C2, низкий) Сузить CORS для прода в pcp-ui-service (allowedOriginPatterns("*") + allowCredentials) до конкретных origin; держать в курсе отсутствие CORS у напрямую вызываемых сервисов (работает только через прокси/nginx).

Аудит — сервис заданий (pcp-request-service)

Источник и рекомендации: аудит-сервис-заданий.md (коды находок RS1–RS7).

  • #30 — (RS2, высокий) Матчинг засчитывает покрытие по любому геометрическому пересечению, игнорируя совместимость аппарата (survey_type, крен, разрешение, угол Солнца). Добавить фильтр совместимости маршрут↔заявка перед зачётом покрытия; тип сенсора в паспорте маршрута согласовать в рамках #28. Отложено до #28 (решение, 2026-06-06): RoutePassportDto не несёт явный surveyType — контракт фиксируется в рамках аудита связи сервисов #28, тогда же делаем фильтр.
  • #33 — (RS5, низкий) Площади считаются планарно в градусах (JTS area на EPSG:4326) — искажение для крупных/высокоширотных заявок. Перейти на геодезию (ST_Area(geography) или равновеликая проекция), когда вырастут требования к точности. Отложено по решению аудита: покрытие считается отношением площадей (планар ≈ геодезия для обычных AOI), а переключение area() затрагивает matching и точечные ассерты тестов — вводим при росте требований к точности.

Выполнено

  • #34 — (RS6) Проброс требуемого процента покрытия из API + разведение терминов. Готово: в CreateRequestDto добавлено опциональное поле coverageRequiredPercent (0 < x ≤ 100, по умолчанию 100), оно пробрасывается в сущность и используется как порог COMPLETED; захардкоженная константа убрана. В KDoc/коде разведены «прогресс покрытия» (coverageRequiredPercent) и «важность заявки» (importance, карта приоритетов ячеек). Тесты: RequestServiceTest, RequestApiDtoContractTest.
  • #31 — (RS3) DLQ и error-handler для Kafka-листенера маршрутов. Готово: KafkaConsumerConfigDefaultErrorHandler + DeadLetterPublishingRecoverer в топик pcp.route.georeference-dlq.v1, экспоненциальный bounded retry, контрактные ошибки (JsonProcessingException/ConstraintViolationException) → DLQ без ретраев, диагностические заголовки. Настройки app.kafka.consumer.route.*, активируется при заданном spring.kafka.bootstrap-servers. Тест KafkaConsumerConfigTest.
  • #35 — (RS7) Уведомление geoportal о финале заявки. Готово: единый топик pcp.request.status.v1 (заменил orphan pcp.request.completed.v1) с терминальным статусом в payload (COMPLETED/EXPIRED). Эмиссия из двух мест через тот же transactional outbox: RouteMatchingService (по покрытию) и RequestExpiryService (по сроку, #29). Сервис RequestCompletedOutboxServiceRequestStatusOutboxService, eventType REQUEST_TERMINAL_STATUS. Outbox получил backoff: колонки attempts/next_attempt_at, удвоение initial→max, предел max-attempts (терминальный FAILED). Конфиг pcp.outbox.*. Тесты: OutboxPublisherServiceTest, OutboxEventRepositoryJpaTest, RequestStatusOutboxServiceTest, RequestExpiryServiceTest, RouteMatchingServiceTest. Док: интеракции обновлены. Известный мелкий зазор: заявка, созданная уже просроченной, события не шлёт (вырожденный кейс).
  • #29 — (RS1) Планировщик истечения заявок. Готово: RequestExpiryService (@Scheduled, FOR UPDATE SKIP LOCKED, батчи с верхним лимитом) переводит просроченные ACCEPTED/ACTIVE в EXPIRED; несколько инстансов безопасны. refreshStatus теперь вызывается и при создании заявки — статус приёма отражает окно (ACCEPTED/ACTIVE/EXPIRED), а не всегда ACCEPTED. Конфиг pcp.request.expiry.* в config-repo. Тесты: RequestExpiryServiceTest (юнит) + RequestRepositoryJpaTest (H2). Разблокирует EXPIRED-эмиссию в #35.
  • #32 — (RS4) Удалить мёртвый конфиг сервиса заданий. Готово: из config-repo/pcp-request-service.yaml убраны app.request.cleanup-cron/cleanup-retention-days и неиспользуемый топик app.kafka.topics.request (pcp.request.in.v1); кода под ними не было, @Value-привязок нет.
  • #26 — Проверить сервис заданий (pcp-request-service) по отдельности. Готово: аудит в аудит-сервис-заданий.md — карта взаимодействий, учёт покрытия, жизненный цикл, мультиинстанс; находки RS1–RS7 (RS1/RS2 — высокий приоритет).
  • #9 — Расширить вправо левую панель информации на вкладке «Редактор» (цифры у границы смотрелись плохо). Готово: commit 69dfd80, рейл 15.5rem → 17rem.
  • #10 — Проставлять статусы слотов только после того, как план заложен на КА. Готово: commit 69dfd80, слоты занимаются по LAID_IN, а не по ACCEPT.
  • #11 — Запретить нажимать «Подтвердить закладку», пока начало закладки в будущем. Готово: commit 69dfd80.

Добавил вручную:

  • убрать кнопки + - квадрат с вкладки редактор и карта с карты ибо ничего не делают