refactor(pcp-request-service): rename REST endpoints and DTOs for clarity
- GET /v1/requests/with-geometry → /v1/requests/map
- GET /v1/requests/{id}/with-cells → /v1/requests/{id}/cells
- GET /v1/cells/with-requests → /v1/cells/priority-map
- CreateRequestRequestDto → CreateRequestDto
- ListRequestsQueryDto → RequestListFilter
- RequestWithGeometry* → RequestMap* (RequestMapItemDto, RequestMapPageDto)
- CellsWithRequestsResponseDto → CellPriorityMapResponseDto
- DeleteRequestStatusDto removed; status field removed from DeleteRequestResponseDto
Updated all consumers (pcp-complex-mission-service, pcp-ui-service, slots-service),
tests, and OpenAPI YAML.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-5
@@ -1,7 +1,7 @@
|
||||
package org.nstart.dep265.requestservice.controller
|
||||
|
||||
import org.nstart.dep265.requestservice.dto.CellPriorityMapResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellsListResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellsWithRequestsResponseDto
|
||||
import org.nstart.dep265.requestservice.service.CellsQueryService
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
@@ -32,13 +32,13 @@ class CellsController(
|
||||
)
|
||||
}
|
||||
|
||||
@GetMapping("/with-requests")
|
||||
fun listCellsWithRequests(
|
||||
@GetMapping("/priority-map")
|
||||
fun listCellsPriorityMap(
|
||||
@RequestParam(required = false) minImportance: Double?,
|
||||
@RequestParam(required = false) countLat: Int?,
|
||||
@RequestParam(required = false) countLong: Int?,
|
||||
): CellsWithRequestsResponseDto {
|
||||
return cellsQueryService.listCellsWithRequests(
|
||||
): CellPriorityMapResponseDto {
|
||||
return cellsQueryService.listCellsPriorityMap(
|
||||
minImportance = minImportance,
|
||||
countLat = countLat,
|
||||
countLong = countLong,
|
||||
|
||||
+40
-7
@@ -1,11 +1,12 @@
|
||||
package org.nstart.dep265.requestservice.controller
|
||||
|
||||
import jakarta.validation.Valid
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestRequestDto
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestDto
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.DeleteRequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.ListRequestsQueryDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestListFilter
|
||||
import org.nstart.dep265.requestservice.dto.RequestListResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestMapPageDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestStatusDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestWithCellsResponseDto
|
||||
@@ -30,7 +31,7 @@ class RequestController(
|
||||
private val requestService: RequestService,
|
||||
) {
|
||||
@PostMapping
|
||||
fun createRequest(@Valid @RequestBody request: CreateRequestRequestDto): ResponseEntity<CreateRequestResponseDto> {
|
||||
fun createRequest(@Valid @RequestBody request: CreateRequestDto): ResponseEntity<CreateRequestResponseDto> {
|
||||
return ResponseEntity.status(201).body(requestService.createRequest(request))
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ class RequestController(
|
||||
@RequestParam(defaultValue = "50") size: Int,
|
||||
@RequestParam(defaultValue = "createdAt,desc") sort: String,
|
||||
): RequestListResponseDto {
|
||||
val query = ListRequestsQueryDto(
|
||||
val query = RequestListFilter(
|
||||
status = status,
|
||||
surveyType = surveyType,
|
||||
kpp = kpp,
|
||||
@@ -66,6 +67,38 @@ class RequestController(
|
||||
return requestService.listRequests(query)
|
||||
}
|
||||
|
||||
@GetMapping("/map")
|
||||
fun listRequestsForMap(
|
||||
@RequestParam(required = false) status: RequestStatusDto?,
|
||||
@RequestParam(required = false) surveyType: SurveyTypeDto?,
|
||||
@RequestParam(required = false) kpp: Int?,
|
||||
@RequestParam(required = false) highPriorityTransmit: Boolean?,
|
||||
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) beginFrom: OffsetDateTime?,
|
||||
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) beginTo: OffsetDateTime?,
|
||||
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) endFrom: OffsetDateTime?,
|
||||
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) endTo: OffsetDateTime?,
|
||||
@RequestParam(defaultValue = "false") includeDeleted: Boolean,
|
||||
@RequestParam(defaultValue = "0") page: Int,
|
||||
@RequestParam(defaultValue = "50") size: Int,
|
||||
@RequestParam(defaultValue = "createdAt,desc") sort: String,
|
||||
): RequestMapPageDto {
|
||||
val query = RequestListFilter(
|
||||
status = status,
|
||||
surveyType = surveyType,
|
||||
kpp = kpp,
|
||||
highPriorityTransmit = highPriorityTransmit,
|
||||
beginFrom = beginFrom,
|
||||
beginTo = beginTo,
|
||||
endFrom = endFrom,
|
||||
endTo = endTo,
|
||||
includeDeleted = includeDeleted,
|
||||
page = page,
|
||||
size = size,
|
||||
sort = sort,
|
||||
)
|
||||
return requestService.listRequestsForMap(query)
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
fun getRequestById(@PathVariable id: UUID): ResponseEntity<RequestResponseDto> {
|
||||
return requestService.getRequestById(id)
|
||||
@@ -73,9 +106,9 @@ class RequestController(
|
||||
?: ResponseEntity.notFound().build()
|
||||
}
|
||||
|
||||
@GetMapping("/{requestId}/with-cells")
|
||||
fun getRequestWithCells(@PathVariable requestId: UUID): ResponseEntity<RequestWithCellsResponseDto> {
|
||||
return requestService.getRequestWithCells(requestId)
|
||||
@GetMapping("/{id}/cells")
|
||||
fun getRequestWithCells(@PathVariable id: UUID): ResponseEntity<RequestWithCellsResponseDto> {
|
||||
return requestService.getRequestWithCells(id)
|
||||
?.let { response -> ResponseEntity.ok(response) }
|
||||
?: ResponseEntity.notFound().build()
|
||||
}
|
||||
|
||||
+4
-4
@@ -43,7 +43,7 @@ data class CellsListResponseDto(
|
||||
)
|
||||
|
||||
/**
|
||||
* Фрагмент заявки внутри ячейки сетки для GET /v1/cells/with-requests.
|
||||
* Фрагмент заявки внутри ячейки сетки для GET /v1/cells/priority-map.
|
||||
*/
|
||||
data class CellRequestFragmentResponseDto(
|
||||
/** Идентификатор заявки. */
|
||||
@@ -60,7 +60,7 @@ data class CellRequestFragmentResponseDto(
|
||||
)
|
||||
|
||||
/**
|
||||
* Ячейка сетки с фрагментами заявок для GET /v1/cells/with-requests.
|
||||
* Ячейка сетки с фрагментами заявок для GET /v1/cells/priority-map.
|
||||
*/
|
||||
data class CellWithRequestsResponseDto(
|
||||
/** Номер ячейки сетки. */
|
||||
@@ -83,9 +83,9 @@ data class CellWithRequestsResponseDto(
|
||||
)
|
||||
|
||||
/**
|
||||
* Список ячеек сетки с фрагментами заявок.
|
||||
* Список ячеек сетки с фрагментами заявок для GET /v1/cells/priority-map.
|
||||
*/
|
||||
data class CellsWithRequestsResponseDto(
|
||||
data class CellPriorityMapResponseDto(
|
||||
/** Ячейки сетки с привязанными request_cells fragments. */
|
||||
val items: List<CellWithRequestsResponseDto>,
|
||||
)
|
||||
|
||||
+70
-15
@@ -27,7 +27,7 @@ abstract class StrictRequestApiDto {
|
||||
/**
|
||||
* Тело запроса на создание заявки по OpenAPI.
|
||||
*/
|
||||
data class CreateRequestRequestDto(
|
||||
data class CreateRequestDto(
|
||||
/** Внешний идентификатор заявки. */
|
||||
@field:NotNull
|
||||
val id: UUID,
|
||||
@@ -68,7 +68,6 @@ data class CreateRequestRequestDto(
|
||||
@field:Valid
|
||||
val rsa: RsaParamsDto? = null,
|
||||
) : StrictRequestApiDto() {
|
||||
/** В create-запросе должен быть указан хотя бы один payload-блок съемки. */
|
||||
@get:AssertTrue(message = "Должен быть указан хотя бы один блок съемки: optics или rsa")
|
||||
@get:JsonIgnore
|
||||
val hasSurveyPayload: Boolean
|
||||
@@ -215,6 +214,73 @@ data class RequestListResponseDto(
|
||||
val totalPages: Int,
|
||||
)
|
||||
|
||||
/**
|
||||
* Краткая карточка заявки с геометрией для GET /v1/requests/map.
|
||||
*/
|
||||
data class RequestMapItemDto(
|
||||
/** Идентификатор заявки. */
|
||||
val id: UUID,
|
||||
|
||||
/** Наименование задания. */
|
||||
val name: String,
|
||||
|
||||
/** Текущий статус заявки. */
|
||||
val status: RequestStatusDto,
|
||||
|
||||
/** Вычисленный тип заявки. */
|
||||
val surveyType: SurveyTypeDto,
|
||||
|
||||
/** Полная геометрия заявки в WKT. */
|
||||
val geometry: String,
|
||||
|
||||
/** Важность заявки для расчета важности ячеек сетки. */
|
||||
val importance: Double,
|
||||
|
||||
/** Начало временного окна выполнения заявки. */
|
||||
val beginDateTime: OffsetDateTime,
|
||||
|
||||
/** Окончание временного окна выполнения заявки. */
|
||||
val endDateTime: OffsetDateTime,
|
||||
|
||||
/** Список номеров КПП для сброса. */
|
||||
val kpp: List<Int> = emptyList(),
|
||||
|
||||
/** Признак высокоприоритетной передачи. */
|
||||
val highPriorityTransmit: Boolean,
|
||||
|
||||
/** Текущий процент покрытия заявки. */
|
||||
val coveragePercent: Double,
|
||||
|
||||
/** Время создания заявки. */
|
||||
val createdAt: OffsetDateTime,
|
||||
|
||||
/** Время последнего обновления заявки. */
|
||||
val updatedAt: OffsetDateTime,
|
||||
|
||||
/** Время soft delete, если заявка удалена. */
|
||||
val deletedAt: OffsetDateTime? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Постраничный список заявок с полной геометрией для GET /v1/requests/map.
|
||||
*/
|
||||
data class RequestMapPageDto(
|
||||
/** Элементы текущей страницы. */
|
||||
val items: List<RequestMapItemDto>,
|
||||
|
||||
/** Номер страницы, начиная с 0. */
|
||||
val page: Int,
|
||||
|
||||
/** Размер страницы. */
|
||||
val size: Int,
|
||||
|
||||
/** Общее количество элементов. */
|
||||
val totalItems: Long,
|
||||
|
||||
/** Общее количество страниц. */
|
||||
val totalPages: Int,
|
||||
)
|
||||
|
||||
/**
|
||||
* Ячейка, связанная с заявкой через request_cells projection.
|
||||
*/
|
||||
@@ -250,9 +316,6 @@ data class DeleteRequestResponseDto(
|
||||
/** Идентификатор заявки. */
|
||||
val id: UUID,
|
||||
|
||||
/** Итоговый статус после удаления. */
|
||||
val status: DeleteRequestStatusDto,
|
||||
|
||||
/** Время soft delete. */
|
||||
val deletedAt: OffsetDateTime,
|
||||
)
|
||||
@@ -342,9 +405,9 @@ data class ErrorDetailDto(
|
||||
)
|
||||
|
||||
/**
|
||||
* Query parameters list endpoint.
|
||||
* Query parameters для list endpoint.
|
||||
*/
|
||||
data class ListRequestsQueryDto(
|
||||
data class RequestListFilter(
|
||||
/** Фильтр по статусу заявки. */
|
||||
val status: RequestStatusDto? = null,
|
||||
|
||||
@@ -405,14 +468,6 @@ enum class RequestStatusDto {
|
||||
DELETED,
|
||||
}
|
||||
|
||||
/**
|
||||
* Статус ответа delete endpoint.
|
||||
*/
|
||||
enum class DeleteRequestStatusDto {
|
||||
/** Заявка удалена или уже была удалена ранее. */
|
||||
DELETED,
|
||||
}
|
||||
|
||||
/**
|
||||
* Вычисленный тип заявки по наличию optics/rsa.
|
||||
*/
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ import org.nstart.dep265.requestservice.dto.CellRequestFragmentResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellSummaryResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellWithRequestsResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellsListResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellsWithRequestsResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CellPriorityMapResponseDto
|
||||
import org.nstart.dep265.requestservice.entity.EarthCellEntity
|
||||
import org.nstart.dep265.requestservice.entity.RequestCellEntity
|
||||
import org.nstart.dep265.requestservice.repository.EarthCellRepository
|
||||
@@ -49,11 +49,11 @@ class CellsQueryService(
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun listCellsWithRequests(
|
||||
fun listCellsPriorityMap(
|
||||
minImportance: Double?,
|
||||
countLat: Int?,
|
||||
countLong: Int?,
|
||||
): CellsWithRequestsResponseDto {
|
||||
): CellPriorityMapResponseDto {
|
||||
validateWithRequestsQuery(minImportance, countLat, countLong)
|
||||
|
||||
val items = if (countLat == null && countLong == null) {
|
||||
@@ -68,7 +68,7 @@ class CellsQueryService(
|
||||
.map { earthCell -> earthCell.toWithRequestsResponse() }
|
||||
}
|
||||
|
||||
return CellsWithRequestsResponseDto(items = items)
|
||||
return CellPriorityMapResponseDto(items = items)
|
||||
}
|
||||
|
||||
private fun validateQuery(
|
||||
|
||||
+55
-20
@@ -4,18 +4,19 @@ import jakarta.persistence.EntityExistsException
|
||||
import jakarta.persistence.EntityManager
|
||||
import jakarta.persistence.PersistenceException
|
||||
import org.hibernate.exception.ConstraintViolationException
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestRequestDto
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestDto
|
||||
import org.nstart.dep265.requestservice.dto.CreateRequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.CoverageStateDto
|
||||
import org.nstart.dep265.requestservice.dto.DeleteRequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.DeleteRequestStatusDto
|
||||
import org.nstart.dep265.requestservice.dto.ListRequestsQueryDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestListFilter
|
||||
import org.nstart.dep265.requestservice.dto.OpticsParamsDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestListResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestCellResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestSummaryResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestWithCellsResponseDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestMapPageDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestMapItemDto
|
||||
import org.nstart.dep265.requestservice.dto.RequestStatusDto
|
||||
import org.nstart.dep265.requestservice.dto.RsaParamsDto
|
||||
import org.nstart.dep265.requestservice.dto.SurveyTypeDto
|
||||
@@ -32,6 +33,7 @@ import org.nstart.dep265.requestservice.repository.RequestCellRepository
|
||||
import org.nstart.dep265.requestservice.repository.RequestOpticsParamsRepository
|
||||
import org.nstart.dep265.requestservice.repository.RequestRepository
|
||||
import org.nstart.dep265.requestservice.repository.RequestRsaParamsRepository
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.PageRequest
|
||||
import org.springframework.data.domain.Sort
|
||||
import org.springframework.stereotype.Service
|
||||
@@ -54,7 +56,7 @@ class RequestService(
|
||||
private val entityManager: EntityManager,
|
||||
) {
|
||||
@Transactional
|
||||
fun createRequest(request: CreateRequestRequestDto): CreateRequestResponseDto {
|
||||
fun createRequest(request: CreateRequestDto): CreateRequestResponseDto {
|
||||
val requestId = request.id
|
||||
if (requestRepository.existsById(requestId)) {
|
||||
throw RequestAlreadyExistsException(requestId)
|
||||
@@ -105,20 +107,8 @@ class RequestService(
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun listRequests(query: ListRequestsQueryDto): RequestListResponseDto {
|
||||
val requests = requestRepository.findRequests(
|
||||
includeDeleted = query.includeDeleted,
|
||||
deletedStatus = RequestStatus.DELETED,
|
||||
status = query.status?.toEntity(),
|
||||
surveyType = query.surveyType?.toEntity(),
|
||||
kpp = query.kpp,
|
||||
highPriorityTransmit = query.highPriorityTransmit,
|
||||
beginFrom = query.beginFrom?.toUtcLocalDateTime(),
|
||||
beginTo = query.beginTo?.toUtcLocalDateTime(),
|
||||
endFrom = query.endFrom?.toUtcLocalDateTime(),
|
||||
endTo = query.endTo?.toUtcLocalDateTime(),
|
||||
pageable = PageRequest.of(query.page, query.size, query.sort.toRequestSort()),
|
||||
)
|
||||
fun listRequests(query: RequestListFilter): RequestListResponseDto {
|
||||
val requests = findRequests(query)
|
||||
return RequestListResponseDto(
|
||||
items = requests.content.map { request -> request.toSummaryResponse() },
|
||||
page = query.page,
|
||||
@@ -128,6 +118,18 @@ class RequestService(
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun listRequestsForMap(query: RequestListFilter): RequestMapPageDto {
|
||||
val requests = findRequests(query)
|
||||
return RequestMapPageDto(
|
||||
items = requests.content.map { request -> request.toMapItemResponse() },
|
||||
page = query.page,
|
||||
size = query.size,
|
||||
totalItems = requests.totalElements,
|
||||
totalPages = requests.totalPages,
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getRequestById(id: UUID): RequestResponseDto? {
|
||||
val request = requestRepository.findById(id).orElse(null) ?: return null
|
||||
@@ -160,7 +162,6 @@ class RequestService(
|
||||
requestCellRepository.deleteByRequestId(request.id)
|
||||
return DeleteRequestResponseDto(
|
||||
id = request.id,
|
||||
status = DeleteRequestStatusDto.DELETED,
|
||||
deletedAt = deletedAt.toOffsetDateTime(),
|
||||
)
|
||||
}
|
||||
@@ -197,6 +198,21 @@ class RequestService(
|
||||
}
|
||||
}
|
||||
|
||||
private fun findRequests(query: RequestListFilter): Page<RequestEntity> =
|
||||
requestRepository.findRequests(
|
||||
includeDeleted = query.includeDeleted,
|
||||
deletedStatus = RequestStatus.DELETED,
|
||||
status = query.status?.toEntity(),
|
||||
surveyType = query.surveyType?.toEntity(),
|
||||
kpp = query.kpp,
|
||||
highPriorityTransmit = query.highPriorityTransmit,
|
||||
beginFrom = query.beginFrom?.toUtcLocalDateTime(),
|
||||
beginTo = query.beginTo?.toUtcLocalDateTime(),
|
||||
endFrom = query.endFrom?.toUtcLocalDateTime(),
|
||||
endTo = query.endTo?.toUtcLocalDateTime(),
|
||||
pageable = PageRequest.of(query.page, query.size, query.sort.toRequestSort()),
|
||||
)
|
||||
|
||||
private fun RequestEntity.toResponse(): RequestResponseDto {
|
||||
val optics = requestOpticsParamsRepository.findById(id).orElse(null)?.toDto()
|
||||
val rsa = requestRsaParamsRepository.findById(id).orElse(null)?.toDto()
|
||||
@@ -247,6 +263,25 @@ class RequestService(
|
||||
)
|
||||
}
|
||||
|
||||
private fun RequestEntity.toMapItemResponse(): RequestMapItemDto {
|
||||
return RequestMapItemDto(
|
||||
id = id,
|
||||
name = name,
|
||||
status = status.toDto(),
|
||||
surveyType = surveyType.toDto(),
|
||||
geometry = geometry,
|
||||
importance = importance,
|
||||
beginDateTime = beginDateTime.toOffsetDateTime(),
|
||||
endDateTime = endDateTime.toOffsetDateTime(),
|
||||
kpp = kpp,
|
||||
highPriorityTransmit = highPriorityTransmit,
|
||||
coveragePercent = coverage().currentPercent,
|
||||
createdAt = createdAt.toOffsetDateTime(),
|
||||
updatedAt = updatedAt.toOffsetDateTime(),
|
||||
deletedAt = deletedAt?.toOffsetDateTime(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun RequestEntity.coverage(): CoverageStateDto {
|
||||
return CoverageStateDto(
|
||||
requiredPercent = coverageRequiredPercent,
|
||||
@@ -254,7 +289,7 @@ class RequestService(
|
||||
)
|
||||
}
|
||||
|
||||
private fun CreateRequestRequestDto.surveyType(): RequestSurveyType {
|
||||
private fun CreateRequestDto.surveyType(): RequestSurveyType {
|
||||
return when {
|
||||
optics != null && rsa != null -> RequestSurveyType.COMBINED
|
||||
optics != null -> RequestSurveyType.OPTICS
|
||||
|
||||
Reference in New Issue
Block a user