backend: правки complex-mission/mission-planing/request + тестовые паспорта

ComplexPlanRunOrchestrationService, MissionController, MissionPlaningService,
KafkaProducerConfig; обновлены тестовые JSON-паспорта route-processing.
This commit is contained in:
Дмитрий Соловьев
2026-06-06 00:04:17 +03:00
parent b454c01c09
commit 1d07588690
6 changed files with 64 additions and 27 deletions
@@ -253,10 +253,12 @@ class MissionController(
}
@Operation(
summary = "Полностью очистить план",
description = "Удаляет ВСЕ включения плана миссии: съёмки (включая построенные вручную, source=MANUAL) " +
"и сбросы, вместе с бронями слотов и связями съёмка↔сброс. В отличие от пересчёта плана, " +
"ручные маршруты тоже удаляются. Используется кнопкой «Очистить план» в редакторе."
summary = "Очистить включения плана",
description = "Удаляет включения плана миссии вместе с бронями слотов и связями съёмка↔сброс. " +
"Сбросы удаляются всегда. Для съёмок поведение выбирает оператор флагом keepManual: " +
"keepManual=true — ручные маршруты съёмки (source=MANUAL) сохраняются, удаляются только " +
"рассчитанные (как при пересчёте плана); keepManual=false (по умолчанию) — удаляются ВСЕ " +
"съёмки, включая ручные. Используется кнопкой «Очистить план» в редакторе."
)
@ApiResponses(
value = [
@@ -267,9 +269,11 @@ class MissionController(
@DeleteMapping("/{mission_id}/modes")
fun clearPlan(
@Parameter(description = "Идентификатор миссии")
@PathVariable("mission_id") id: UUID
@PathVariable("mission_id") id: UUID,
@Parameter(description = "Сохранить ручные маршруты съёмки (source=MANUAL)")
@RequestParam(name = "keepManual", required = false, defaultValue = "false") keepManual: Boolean
): ResponseEntity<Void> {
missionPlaningService.clearPlan(id)
missionPlaningService.clearPlan(id, keepManual)
return ResponseEntity.noContent().build()
}
@@ -937,18 +937,29 @@ class MissionPlaningService(
}
/**
* Полная очистка плана: удаляет ВСЕ включения миссии — съёмки (включая ручные, source=MANUAL)
* и сбросы — вместе с бронями слотов и связями съёмка↔сброс. В отличие от пересчёта плана
* ([loadSlots]/[calculateDrops]), ручные маршруты тоже удаляются. Сбросы удаляются первыми,
* чтобы снять связи до удаления съёмок и не плодить проверку осиротевших сбросов.
* Очистка плана. Всегда удаляет все сбросы и брони слотов; для съёмок поведение выбирает
* оператор флагом [keepManual]:
* - `keepManual=true` — сохраняются ручные маршруты съёмки (source=MANUAL), удаляются только
* рассчитанные (как и при пересчёте плана [loadSlots]/[calculateDrops]);
* - `keepManual=false` — удаляются ВСЕ съёмки, включая ручные (полная очистка).
* Сбросы удаляются первыми, чтобы снять связи до удаления съёмок и не плодить проверку
* осиротевших сбросов.
*/
@Transactional
fun clearPlan(missionId: UUID) {
fun clearPlan(missionId: UUID, keepManual: Boolean) {
missionRepository.findById(missionId).orElseThrow { notFound(missionId) }
val modes = modeRepository.findAllByPlan_Mission_MissionIdOrderByTimeStartAsc(missionId)
modes.filterIsInstance<DropModeEntity>().forEach { deleteDropMode(it) }
modes.filterIsInstance<SurveyModeEntity>().forEach { deleteSurveyMode(it) }
logger.info("План миссии {} полностью очищен: удалено включений={}", missionId, modes.size)
val drops = modes.filterIsInstance<DropModeEntity>()
val surveys = modes.filterIsInstance<SurveyModeEntity>()
val (keptSurveys, deletedSurveys) =
if (keepManual) surveys.partition { it.source == SurveyModeSource.MANUAL }
else emptyList<SurveyModeEntity>() to surveys
drops.forEach { deleteDropMode(it) }
deletedSurveys.forEach { deleteSurveyMode(it) }
logger.info(
"План миссии {} очищен (keepManual={}): удалено сбросов={}, съёмок={}, сохранено ручных съёмок (MANUAL)={}",
missionId, keepManual, drops.size, deletedSurveys.size, keptSurveys.size
)
}
/**