feat(slots): снятие брони пачками с прогрессом (симметрично бронированию)

Бэк (slots-service):
- DELETE /booking/batch (cancelReqSlots) — снятие выбранных броней пачкой;
  одиночный DELETE теперь request-aware (нужен requestId), чтобы шаренный
  между заявками слот рвал только связь своей заявки, а не сносил бронь.
- BookedSlotViewDTO (+toViewDTO) с cycle БРОНИ — slotKey совпадает с ответом
  POST booking/request; GET booking/by-request отдаёт View.

Фронт (pcp-tgu-ui-service):
- runChunked + ChunkProgress: бронь и снятие идут пачками по 200 с общим
  прогресс-баром (стиль/позиция как у оверлея «Расчёт слотов…», сверху).
- «Снять выбранные», «Снять всё» и ✕ в строке — единый чанковый движок
  runCancel (а не bulk-запрос), брони слиты в строки таблицы и выбираемы.

Тесты: SlotServiceCancelTest (шаринг/единоличная/cycle-регрессия), runChunked,
slotsApi.cancelBookedSlots/fetchBookedSlotsByRequest.
This commit is contained in:
Дмитрий Соловьев
2026-06-15 14:26:06 +03:00
parent b9adbce207
commit 33b56ba951
13 changed files with 756 additions and 91 deletions
@@ -0,0 +1,28 @@
package space.nstart.pcp.pcp_types_lib.dto.requests.slots
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign
import java.time.LocalDateTime
/**
* Забронированный слот для отображения и снятия брони (GET /api/slots/booking/by-request/{id}).
*
* В отличие от [SlotDTO] несёт [bookedSlotId] — он нужен фронту, чтобы снимать бронь по списку id
* (DELETE /api/slots/booking/batch). В отличие от [BookedSlotDTO] несёт контур и координаты — нужны
* карте. Критично: [cycle] — это цикл БРОНИ (BookedSlotEntity.cycle), а не базовый slot.cycle,
* иначе ключ sat:slotNum:cycle на фронте не совпадёт с ответом POST booking/request.
*/
class BookedSlotViewDTO(
val bookedSlotId : Long = 0,
val cycle : Long = 0,
val satelliteId : Long = 0,
val tn : LocalDateTime,
val tk : LocalDateTime,
val roll : Double,
val contour : String,
val revolution : Long = 0,
val revolutionSign: RevolutionSign = RevolutionSign.ASC,
val slotNumber : Long = 0,
val state : SlotStatus = SlotStatus.BOOKED,
val latitude : Double = 0.0,
val longitude : Double = 0.0,
)