RentalQueryController.java
package com.github.jenkaby.bikerental.rental.web.query;
import com.github.jenkaby.bikerental.rental.application.usecase.FindRentalsUseCase;
import com.github.jenkaby.bikerental.rental.application.usecase.GetRentalByIdUseCase;
import com.github.jenkaby.bikerental.rental.domain.model.Rental;
import com.github.jenkaby.bikerental.rental.domain.model.RentalStatus;
import com.github.jenkaby.bikerental.rental.web.query.dto.RentalResponse;
import com.github.jenkaby.bikerental.rental.web.query.dto.RentalSummaryResponse;
import com.github.jenkaby.bikerental.rental.web.query.mapper.RentalQueryMapper;
import com.github.jenkaby.bikerental.shared.config.OpenApiConfig;
import com.github.jenkaby.bikerental.shared.domain.model.vo.Page;
import com.github.jenkaby.bikerental.shared.domain.model.vo.PageRequest;
import com.github.jenkaby.bikerental.shared.mapper.PageMapper;
import com.github.jenkaby.bikerental.shared.web.support.Id;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
@Validated
@RestController
@RequestMapping("/api/rentals")
@Slf4j
@Tag(name = OpenApiConfig.Tags.RENTALS)
class RentalQueryController {
private final GetRentalByIdUseCase getRentalByIdUseCase;
private final FindRentalsUseCase findRentalsUseCase;
private final RentalQueryMapper mapper;
private final PageMapper pageMapper;
RentalQueryController(
GetRentalByIdUseCase getRentalByIdUseCase,
FindRentalsUseCase findRentalsUseCase,
RentalQueryMapper mapper,
PageMapper pageMapper) {
this.getRentalByIdUseCase = getRentalByIdUseCase;
this.findRentalsUseCase = findRentalsUseCase;
this.mapper = mapper;
this.pageMapper = pageMapper;
}
@GetMapping("/{id}")
@Operation(summary = "Get rental by ID")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Rental found",
content = @Content(schema = @Schema(implementation = RentalResponse.class))),
@ApiResponse(responseCode = "400", description = "Invalid ID",
content = @Content(schema = @Schema(implementation = ProblemDetail.class))),
@ApiResponse(responseCode = "404", description = "Rental not found",
content = @Content(schema = @Schema(implementation = ProblemDetail.class)))
})
public ResponseEntity<RentalResponse> getRentalById(@Parameter(description = "Rental ID", example = "1") @PathVariable("id") @Id Long id) {
log.info("[GET] Get rental by id: {}", id);
var rental = getRentalByIdUseCase.execute(id);
return ResponseEntity.ok(mapper.toResponse(rental));
}
@GetMapping
@Operation(summary = "Search rentals", description = "Returns a paginated list of rentals filtered by status, customer or equipment UID")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Rental page returned"),
@ApiResponse(responseCode = "400", description = "Invalid filter parameters",
content = @Content(schema = @Schema(implementation = ProblemDetail.class)))
})
public ResponseEntity<Page<RentalSummaryResponse>> getRentals(
@Parameter(description = "Rental status filter", example = "ACTIVE") @RequestParam(name = "status", required = false) RentalStatus status,
@Parameter(description = "Customer UUID filter") @RequestParam(name = "customerId", required = false) UUID customerId,
@Parameter(description = "Equipment UID filter", example = "BIKE-001") @RequestParam(name = "equipmentUid", required = false) String equipmentUid,
@PageableDefault(size = 20, sort = "expectedReturnAt", direction = Sort.Direction.ASC) Pageable pageable) {
log.info("[GET] Get rentals with filters status={}, customerId={}, equipmentUid={}", status, customerId, equipmentUid);
PageRequest pageRequest = pageMapper.toPageRequest(pageable);
var query = new FindRentalsUseCase.FindRentalsQuery(status, customerId, equipmentUid, pageRequest);
Page<Rental> rentals = findRentalsUseCase.execute(query);
Page<RentalSummaryResponse> response = rentals.map(mapper::toRentalSummaryResponse);
return ResponseEntity.ok(response);
}
}