Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/main/java/ru/practicum/shareit/booking/Booking.java

This file was deleted.

12 changes: 0 additions & 12 deletions src/main/java/ru/practicum/shareit/booking/BookingController.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ru.practicum.shareit.booking.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.booking.dto.BookingDto;
import ru.practicum.shareit.booking.service.BookingService;

/**
* TODO Sprint add-bookings.
*/

@RestController
@RequestMapping(path = "/bookings")
@RequiredArgsConstructor
public class BookingController {
private final BookingService bookingService;

@PostMapping
public BookingDto createBooking(@Valid @RequestBody BookingDto bookingDto,
@RequestHeader("X-Sharer-User-Id") Long bookerId) {
return bookingService.createBooking(bookingDto, bookerId);
}

@PatchMapping("/{bookingId}")
public BookingDto updateBooking(@PathVariable Long bookingId,
@RequestBody BookingDto bookingDto) {
return bookingService.updateBooking(bookingId, bookingDto);
}

@GetMapping("/{bookingId}")
public BookingDto getBookingById(@PathVariable Long bookingId) {
return bookingService.getBookingById(bookingId);
}
}
26 changes: 26 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,33 @@
package ru.practicum.shareit.booking.dto;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.FutureOrPresent;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import ru.practicum.shareit.booking.model.BookingStatus;

import java.time.LocalDateTime;

/**
* TODO Sprint add-bookings.
*/

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookingDto {
@NotNull(message = "Дата начала бронирования обязательна")
@FutureOrPresent(message = "Дата начала должна быть в будущем")
private LocalDateTime start;

@NotNull(message = "Дата окончания бронирования обязательна")
@Future(message = "Дата окончания бронирования должна быть в будущем")
private LocalDateTime end;

@NotNull(message = "ID вещи обязателен")
private Long itemId;
private Long bookerId;
private BookingStatus status;
}
27 changes: 27 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/dto/BookingMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ru.practicum.shareit.booking.dto;

import ru.practicum.shareit.booking.model.Booking;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.user.model.User;

public class BookingMapper {
public static BookingDto toBookingDto(Booking booking) {
return new BookingDto(
booking.getStart(),
booking.getEnd(),
booking.getItem() != null ? booking.getItem().getId() : null,
booking.getBooker() != null ? booking.getBooker().getId() : null,
booking.getStatus()
);
}

public static Booking fromBookingDto(BookingDto bookingDto, Item item, User booker) {
Booking booking = new Booking();
booking.setStart(bookingDto.getStart());
booking.setEnd(bookingDto.getEnd());
booking.setItem(item);
booking.setBooker(booker);
booking.setStatus(bookingDto.getStatus());
return booking;
}
}
25 changes: 25 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/model/Booking.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.practicum.shareit.booking.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.user.model.User;

import java.time.LocalDateTime;

/**
* TODO Sprint add-bookings.
*/

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Booking {
private Long id;
private LocalDateTime start;
private LocalDateTime end;
private Item item;
private User booker;
private BookingStatus status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.practicum.shareit.booking.model;

public enum BookingStatus {
WAITING,
APPROVED,
REJECTED,
CANCELED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ru.practicum.shareit.booking.service;

import ru.practicum.shareit.booking.dto.BookingDto;

public interface BookingService {
BookingDto createBooking(BookingDto bookingDto, Long bookerId);

BookingDto updateBooking(Long bookingId, BookingDto bookingDto);

BookingDto getBookingById(Long bookingId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package ru.practicum.shareit.booking.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.practicum.shareit.booking.model.Booking;
import ru.practicum.shareit.booking.model.BookingStatus;
import ru.practicum.shareit.booking.dto.BookingDto;
import ru.practicum.shareit.booking.dto.BookingMapper;
import ru.practicum.shareit.booking.storage.InMemoryBookingStorage;
import ru.practicum.shareit.exception.NotFoundException;
import ru.practicum.shareit.exception.ValidationException;
import ru.practicum.shareit.exception.AccessDeniedException;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.item.storage.InMemoryItemStorage;
import ru.practicum.shareit.user.model.User;
import ru.practicum.shareit.user.storage.InMemoryUserStorage;

@Service
@RequiredArgsConstructor
public class BookingServiceImpl implements BookingService {
private final InMemoryBookingStorage bookingStorage;
private final InMemoryUserStorage userStorage;
private final InMemoryItemStorage itemStorage;

@Override
public BookingDto createBooking(BookingDto bookingDto, Long bookerId) {
User booker = userStorage.findById(bookerId)
.orElseThrow(() -> new NotFoundException("Пользователь с id " + bookerId + " не найден"));

Item item = itemStorage.findById(bookingDto.getItemId())
.orElseThrow(() -> new NotFoundException("Вещь с id " + bookingDto.getItemId() + " не найдена"));

if (!Boolean.TRUE.equals(item.getAvailable())) {
throw new ValidationException("Вещь с id " + bookingDto.getItemId() + " недоступна для бронирования");
}

if (item.getOwner().getId().equals(bookerId)) {
throw new AccessDeniedException("Пользователь не может бронировать свою собственную вещь");
}

Booking booking = BookingMapper.fromBookingDto(bookingDto, item, booker);
booking.setStatus(BookingStatus.WAITING);
Booking createdBooking = bookingStorage.create(booking);
return BookingMapper.toBookingDto(createdBooking);
}

@Override
public BookingDto updateBooking(Long bookingId, BookingDto bookingDto) {
Booking existingBooking = bookingStorage.findById(bookingId)
.orElseThrow(() -> new NotFoundException("Бронирование с id " + bookingId + " не найдено"));

if (bookingDto.getStart() != null) {
existingBooking.setStart(bookingDto.getStart());
}
if (bookingDto.getEnd() != null) {
existingBooking.setEnd(bookingDto.getEnd());
}
if (bookingDto.getStatus() != null) {
existingBooking.setStatus(bookingDto.getStatus());
}

Booking updatedBooking = bookingStorage.update(existingBooking);
return BookingMapper.toBookingDto(updatedBooking);
}

@Override
public BookingDto getBookingById(Long bookingId) {
Booking booking = bookingStorage.findById(bookingId)
.orElseThrow(() -> new NotFoundException("Бронирование с id " + bookingId + " не найдено"));
return BookingMapper.toBookingDto(booking);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.practicum.shareit.booking.storage;

import org.springframework.stereotype.Repository;
import ru.practicum.shareit.booking.model.Booking;
import ru.practicum.shareit.exception.NotFoundException;

import java.util.*;

@Repository
public class InMemoryBookingStorage {
private final Map<Long, Booking> bookings = new HashMap<>();
private long idCounter = 1;

public Booking create(Booking booking) {
long id = idCounter++;
booking.setId(id);
bookings.put(id, booking);
return booking;
}

public Booking update(Booking booking) {
if (!bookings.containsKey(booking.getId())) {
throw new NotFoundException("Бронирование не найдено");
}

bookings.put(booking.getId(), booking);
return booking;
}

public Optional<Booking> findById(Long id) {
return Optional.ofNullable(bookings.get(id));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class AccessDeniedException extends RuntimeException {
public AccessDeniedException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class DuplicateEmailException extends RuntimeException {
public DuplicateEmailException(String message) {
super(message);
}
}
11 changes: 11 additions & 0 deletions src/main/java/ru/practicum/shareit/exception/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ru.practicum.shareit.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ErrorResponse {
private final String error;
private final String description;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ru.practicum.shareit.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(NotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFoundException(NotFoundException e) {
return new ErrorResponse("Объект не найден", e.getMessage());
}

@ExceptionHandler(ValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationException(ValidationException e) {
return new ErrorResponse("Ошибка валидации", e.getMessage());
}

@ExceptionHandler(AccessDeniedException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public ErrorResponse handleAccessDeniedException(AccessDeniedException e) {
return new ErrorResponse("Доступ запрещен", e.getMessage());
}

@ExceptionHandler(DuplicateEmailException.class)
@ResponseStatus(HttpStatus.CONFLICT)
public ErrorResponse handleDuplicateEmailException(DuplicateEmailException e) {
return new ErrorResponse("Конфликт данных", e.getMessage());
}

@ExceptionHandler(InvalidDateTimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleInvalidDateTimeException(InvalidDateTimeException e) {
return new ErrorResponse("Ошибка даты/времени", e.getMessage());
}

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
String errorMessage = e.getBindingResult().getFieldErrors().stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.findFirst()
.orElse("Ошибка валидации");
return new ErrorResponse("Ошибка валидации", errorMessage);
}

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleException(Exception e) {
return new ErrorResponse("Внутренняя ошибка сервера", e.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class InvalidDateTimeException extends RuntimeException {
public InvalidDateTimeException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.practicum.shareit.exception;

public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
12 changes: 0 additions & 12 deletions src/main/java/ru/practicum/shareit/item/ItemController.java

This file was deleted.

Loading
Loading