diff --git a/src/main/java/com/example/nto/controller/BookingController.java b/src/main/java/com/example/nto/controller/BookingController.java index 9885f84..7a58138 100644 --- a/src/main/java/com/example/nto/controller/BookingController.java +++ b/src/main/java/com/example/nto/controller/BookingController.java @@ -1,10 +1,170 @@ package com.example.nto.controller; -/** - * TODO: ДОРАБОТАТЬ в рамках задания - * ================================= - * МОЖНО: Добавлять методы, аннотации, зависимости - * НЕЛЬЗЯ: Изменять название класса и пакета - */ +import com.example.nto.dto.BookingRequestDto; +import com.example.nto.dto.BookingShortDto; +import com.example.nto.dto.EmployeeInfoResponseDto; +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import com.example.nto.entity.Place; +import com.example.nto.repository.PlaceRepository; +import com.example.nto.service.BookingService; +import com.example.nto.service.EmployeeService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.*; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor public class BookingController { + + private final EmployeeService employeeService; + private final BookingService bookingService; + private final PlaceRepository placeRepository; + + /** + * GET api/{code}/info + * + * Ответ (пример из README): + * { + * "name": "Иванов Петр Федорович", + * "photoUrl": "https://...", + * "booking": { + * "2025-01-05": {"id":1,"place":"102"}, + * "2025-01-09": {"id":3,"place":"Зона 51. 50"} + * } + * } + * + * 400 – что-то пошло не так + * 401 – кода не существует + * 200 – ОК + */ + @GetMapping("/{code}/info") + public ResponseEntity getInfo(@PathVariable("code") String code) { + if (code == null || code.isBlank()) { + return ResponseEntity.badRequest().build(); + } + + Optional employeeOpt = employeeService.findByCode(code); + if (employeeOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + Employee employee = employeeOpt.get(); + Map bookings = bookingService.getBookingsByEmployee(employee); + + Map bookingMap = new LinkedHashMap<>(); + bookings.forEach((date, booking) -> bookingMap.put( + date.toString(), + new BookingShortDto( + booking.getPlace().getId(), + booking.getPlace().getPlace() + ) + )); + + EmployeeInfoResponseDto response = new EmployeeInfoResponseDto( + employee.getName(), + employee.getPhotoUrl(), + bookingMap + ); + + return ResponseEntity.ok(response); + } + + /** + * GET api/{code}/booking + * + * Ответ (пример из README): + * { + * "2025-01-05": [{"id":1,"place":"102"}, {"id":2,"place":"209.13"}], + * "2025-01-06": [{"id":3,"place":"Зона 51. 50"}], + * ... + * } + * + * 400 – что-то пошло не так + * 401 – кода не существует + * 200 – ОК + */ + @GetMapping("/{code}/booking") + public ResponseEntity getAvailable(@PathVariable("code") String code) { + if (code == null || code.isBlank()) { + return ResponseEntity.badRequest().build(); + } + + if (!employeeService.existsByCode(code)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + Map> available = bookingService.getAvailablePlaces(); + + Map> body = new LinkedHashMap<>(); + available.forEach((date, places) -> body.put( + date.toString(), + places.stream() + .map(place -> new BookingShortDto(place.getId(), place.getPlace())) + .collect(Collectors.toList()) + )); + + return ResponseEntity.ok(body); + } + + /** + * POST api/{code}/book + * + * Тело: + * { + * "date": "2025-01-05", + * "placeId": 1 + * } + * + * 400 – что-то пошло не так (неправильный формат даты, нет placeId и т.п.) + * 401 – кода не существует + * 409 – место уже занято или у сотрудника уже есть бронь на эту дату + * 201 – бронирование успешно создано + */ + @PostMapping("/{code}/book") + public ResponseEntity createBooking(@PathVariable("code") String code, + @RequestBody BookingRequestDto request) { + if (code == null || code.isBlank()) { + return ResponseEntity.badRequest().build(); + } + + Optional employeeOpt = employeeService.findByCode(code); + if (employeeOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + if (request == null || request.date() == null || request.placeId() == null) { + return ResponseEntity.badRequest().build(); + } + + LocalDate date; + try { + date = LocalDate.parse(request.date()); + } catch (DateTimeParseException ex) { + return ResponseEntity.badRequest().build(); + } + + Optional placeOpt = placeRepository.findById(request.placeId()); + if (placeOpt.isEmpty()) { + return ResponseEntity.badRequest().build(); + } + + Employee employee = employeeOpt.get(); + Place place = placeOpt.get(); + + if (bookingService.existsBookingForEmployeeOnDate(employee, date) + || bookingService.isPlaceBookedOnDate(place, date)) { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); // 409 + } + + bookingService.createBooking(employee, date, place); + return ResponseEntity.status(HttpStatus.CREATED).build(); // 201 + } }