forked from Olympic/NTO-2025-Backend-TeamTask
171 lines
5.7 KiB
Java
171 lines
5.7 KiB
Java
package com.example.nto.controller;
|
||
|
||
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<Employee> employeeOpt = employeeService.findByCode(code);
|
||
if (employeeOpt.isEmpty()) {
|
||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||
}
|
||
|
||
Employee employee = employeeOpt.get();
|
||
Map<LocalDate, Booking> bookings = bookingService.getBookingsByEmployee(employee);
|
||
|
||
Map<String, BookingShortDto> 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<LocalDate, List<Place>> available = bookingService.getAvailablePlaces();
|
||
|
||
Map<String, List<BookingShortDto>> 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<Employee> 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<Place> 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
|
||
}
|
||
}
|