diff --git a/checkstyle.xml b/checkstyle.xml
index 230e67eb..74f37d8b 100644
--- a/checkstyle.xml
+++ b/checkstyle.xml
@@ -250,4 +250,8 @@
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 870ae852..ed574e85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,16 @@
org.springframework.boot
spring-boot-starter-validation
+
+ org.aspectj
+ aspectjweaver
+ 1.9.20
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
diff --git a/src/main/java/ru/practicum/shareit/ShareItApp.java b/src/main/java/ru/practicum/shareit/ShareItApp.java
index a00ad567..fe48b8ff 100644
--- a/src/main/java/ru/practicum/shareit/ShareItApp.java
+++ b/src/main/java/ru/practicum/shareit/ShareItApp.java
@@ -6,8 +6,7 @@
@SpringBootApplication
public class ShareItApp {
- public static void main(String[] args) {
- SpringApplication.run(ShareItApp.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(ShareItApp.class, args);
+ }
}
diff --git a/src/main/java/ru/practicum/shareit/aspects/LoggingAspect.java b/src/main/java/ru/practicum/shareit/aspects/LoggingAspect.java
new file mode 100644
index 00000000..a056794c
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/aspects/LoggingAspect.java
@@ -0,0 +1,114 @@
+package ru.practicum.shareit.aspects;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+import ru.practicum.shareit.constants.MyConstants;
+import ru.practicum.shareit.item.dto.ItemDto;
+import ru.practicum.shareit.user.dto.UserDto;
+
+import java.util.List;
+
+@Component
+@Aspect
+@Slf4j
+public class LoggingAspect {
+
+ @AfterReturning(pointcut = MyConstants.ADD_USER_POINTCUT, returning = "userDto")
+ public void afterReturningAddUserAdvices(UserDto userDto) {
+ log.info("Пользователь " + userDto + "добавлен.");
+ }
+
+ @AfterThrowing(pointcut = MyConstants.ADD_USER_POINTCUT, throwing = "exception")
+ public void afterThrowingAddUserAdvices(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.REMOVE_USER_POINTCUT, returning = "response")
+ public void afterReturningRemoveUserByIdAdvices(String response) {
+ log.info(response);
+ }
+
+ @AfterThrowing(pointcut = MyConstants.REMOVE_USER_POINTCUT, throwing = "exception")
+ public void afterThrowingRemoveUserByIdAdvices(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.GET_ALL_USERS_POINTCUT)
+ public void afterReturningGetAllUserAdvice() {
+ log.info("Список всех пользователей получен.");
+ }
+
+ @AfterReturning(pointcut = MyConstants.UPDATE_USER_POINTCUT, returning = "userDto")
+ public void afterReturningUpdateUserAdvice(UserDto userDto) {
+ log.info("Пользователь с id:" + userDto.getId() + " обновлён.");
+ }
+
+ @AfterThrowing(pointcut = MyConstants.UPDATE_USER_POINTCUT, throwing = "exception")
+ public void afterThrowingUpdateUserAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.ADD_ITEM_POINTCUT, returning = "itemDto")
+ public void afterReturningAddItemAdvice(ItemDto itemDto) {
+ log.info("Item: " + itemDto.getName() + " с id:" + itemDto.getId() + " добавлен.");
+ }
+
+ @AfterThrowing(pointcut = MyConstants.ADD_ITEM_POINTCUT, throwing = "exception")
+ public void afterThrowingAddItemAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.UPDATE_ITEM_POINTCUT, returning = "itemDto")
+ public void afterReturningUpdateItemAdvice(ItemDto itemDto) {
+ log.info("Item с id:" + itemDto.getId() + " обновлён.");
+ }
+
+ @AfterThrowing(pointcut = MyConstants.UPDATE_ITEM_POINTCUT, throwing = "exception")
+ public void afterThrowingUpdateItemAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.GET_ITEM_BY_ID_POINTCUT, returning = "itemDto")
+ public void afterReturningGetItemByIdAdvice(ItemDto itemDto) {
+ log.info("Получен Item: " + itemDto);
+ }
+
+ @AfterThrowing(pointcut = MyConstants.GET_ITEM_BY_ID_POINTCUT, throwing = "exception")
+ public void afterThrowingGetItemByIdAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.GET_ALL_ITEM_POINTCUT)
+ public void afterReturningGetAllItemForOwnerAdvice() {
+ log.info("Список всех Item получен.");
+ }
+
+ @AfterThrowing(pointcut = MyConstants.GET_ALL_ITEM_POINTCUT, throwing = "exception")
+ public void afterThrowingGetAllItemForOwnerAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+
+ @AfterReturning(pointcut = MyConstants.SEARCH_ITEM_POINTCUT, returning = "itemDtoList")
+ public void afterReturningSearchItemAdvice(List itemDtoList) {
+ log.info("Список Item по запросу получен: " + itemDtoList);
+ }
+
+ @AfterThrowing(pointcut = MyConstants.SEARCH_ITEM_POINTCUT, throwing = "exception")
+ public void afterThrowingSearchItemAdvice(JoinPoint joinPoint, Throwable exception) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ log.info("В методе " + methodSignature.getMethod() + " выброшено исключение: " + exception.getMessage());
+ }
+}
+
diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/src/main/java/ru/practicum/shareit/booking/Booking.java
index 2d9c6668..8d8aa113 100644
--- a/src/main/java/ru/practicum/shareit/booking/Booking.java
+++ b/src/main/java/ru/practicum/shareit/booking/Booking.java
@@ -1,7 +1,22 @@
package ru.practicum.shareit.booking;
-/**
- * TODO Sprint add-bookings.
- */
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import ru.practicum.shareit.item.model.Item;
+import ru.practicum.shareit.user.User;
+
+import java.time.LocalDateTime;
+
+@Data
+@EqualsAndHashCode
+@ToString
public class Booking {
+
+ private int id;
+ private LocalDateTime start;
+ private LocalDateTime end;
+ private Item item;
+ private User booker;
+ private BookingStatus status;
}
diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/src/main/java/ru/practicum/shareit/booking/BookingStatus.java
new file mode 100644
index 00000000..bdd840a0
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/booking/BookingStatus.java
@@ -0,0 +1,8 @@
+package ru.practicum.shareit.booking;
+
+public enum BookingStatus {
+ WAITING,
+ APPROVED,
+ REJECTED,
+ CANCELED;
+}
diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java
index 861de9e0..b7fa7d9c 100644
--- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java
+++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java
@@ -1,7 +1,23 @@
package ru.practicum.shareit.booking.dto;
-/**
- * TODO Sprint add-bookings.
- */
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import ru.practicum.shareit.booking.BookingStatus;
+import ru.practicum.shareit.item.model.Item;
+import ru.practicum.shareit.user.User;
+
+import java.time.LocalDateTime;
+
+@Data
+@EqualsAndHashCode
+@ToString
public class BookingDto {
+
+ private int id;
+ private LocalDateTime start;
+ private LocalDateTime end;
+ private Item item;
+ private User booker;
+ private BookingStatus status;
}
diff --git a/src/main/java/ru/practicum/shareit/constants/MyConstants.java b/src/main/java/ru/practicum/shareit/constants/MyConstants.java
new file mode 100644
index 00000000..3ca2b2b7
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/constants/MyConstants.java
@@ -0,0 +1,29 @@
+package ru.practicum.shareit.constants;
+
+public class MyConstants {
+ public static final String ADD_USER_POINTCUT = "execution(public ru.practicum.shareit.user.dto.UserDto ru.practicum.shareit.user.dao.UserDaoImpl.addUser" +
+ "(ru.practicum.shareit.user.User))";
+ public static final String REMOVE_USER_POINTCUT = "execution(public String ru.practicum.shareit.user.dao.UserDaoImpl.removeUserById" +
+ "(*))";
+
+ public static final String GET_ALL_USERS_POINTCUT = "execution(public java.util.List " +
+ "ru.practicum.shareit.user.dao.UserDaoImpl.getAllUsers())";
+
+ public static final String UPDATE_USER_POINTCUT = "execution(public ru.practicum.shareit.user.dto.UserDto " +
+ "ru.practicum.shareit.user.dao.UserDaoImpl.UpdateUser(..))";
+
+ public static final String ADD_ITEM_POINTCUT = "execution(public ru.practicum.shareit.item.dto.ItemDto " +
+ "ru.practicum.shareit.item.dao.ItemDaoImpl.addItem(..))";
+
+ public static final String UPDATE_ITEM_POINTCUT = "execution(public ru.practicum.shareit.item.dto.ItemDto " +
+ "ru.practicum.shareit.item.dao.ItemDaoImpl.updateItem(..))";
+
+ public static final String GET_ITEM_BY_ID_POINTCUT = "execution(public ru.practicum.shareit.item.dto.ItemDto " +
+ "ru.practicum.shareit.item.dao.ItemDaoImpl.getItemById(..))";
+
+ public static final String GET_ALL_ITEM_POINTCUT = "execution(public java.util.List " +
+ "ru.practicum.shareit.item.dao.ItemDaoImpl.getAllItemForOwner(..))";
+
+ public static final String SEARCH_ITEM_POINTCUT = "execution(public java.util.List " +
+ "ru.practicum.shareit.item.dao.ItemDaoImpl.searchItem(..))";
+}
diff --git a/src/main/java/ru/practicum/shareit/exception/EmailDuplicateException.java b/src/main/java/ru/practicum/shareit/exception/EmailDuplicateException.java
new file mode 100644
index 00000000..3c1e0e3d
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/exception/EmailDuplicateException.java
@@ -0,0 +1,8 @@
+package ru.practicum.shareit.exception;
+
+public class EmailDuplicateException extends RuntimeException {
+
+ public EmailDuplicateException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java b/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java
new file mode 100644
index 00000000..051c25fb
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/exception/ErrorHandler.java
@@ -0,0 +1,23 @@
+package ru.practicum.shareit.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class ErrorHandler {
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse noDataFound(NoDataFoundException e) {
+ return new ErrorResponse(e.getMessage(), "Данные не найдены.");
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.CONFLICT)
+ public ErrorResponse emailDuplicate(EmailDuplicateException e) {
+ return new ErrorResponse(e.getMessage(), "Данный email уже существует.");
+ }
+
+}
diff --git a/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java b/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java
new file mode 100644
index 00000000..e98af6f2
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/exception/ErrorResponse.java
@@ -0,0 +1,22 @@
+package ru.practicum.shareit.exception;
+
+import lombok.Data;
+
+@Data
+public class ErrorResponse {
+ private String error;
+ private String description;
+
+ public ErrorResponse(String error, String description) {
+ this.error = error;
+ this.description = description;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java b/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java
new file mode 100644
index 00000000..dbef4b4b
--- /dev/null
+++ b/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java
@@ -0,0 +1,7 @@
+package ru.practicum.shareit.exception;
+
+public class NoDataFoundException extends RuntimeException {
+ public NoDataFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java
index bb17668b..97d79911 100644
--- a/src/main/java/ru/practicum/shareit/item/ItemController.java
+++ b/src/main/java/ru/practicum/shareit/item/ItemController.java
@@ -1,12 +1,46 @@
package ru.practicum.shareit.item;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import ru.practicum.shareit.item.dto.ItemDto;
+import ru.practicum.shareit.item.model.Item;
+import ru.practicum.shareit.item.service.ItemService;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
-/**
- * TODO Sprint add-controllers.
- */
@RestController
@RequestMapping("/items")
public class ItemController {
+ @Autowired
+ ItemService itemService;
+
+ @PostMapping
+ public ItemDto addItem(@RequestHeader("X-Sharer-User-Id") int userId,
+ @Valid @RequestBody Item item) {
+ return itemService.addItem(userId, item);
+ }
+
+ @GetMapping("/{id}")
+ public ItemDto getItemById(@PathVariable(name = "id") int itemId) {
+ return itemService.getItemDtoById(itemId);
+ }
+
+ @GetMapping
+ public List getAllItemForOwner(@RequestHeader("X-Sharer-User-Id") int userId) {
+ return itemService.getAllItemForOwner(userId);
+ }
+
+ @PatchMapping("/{id}")
+ public ItemDto updateItem(@RequestHeader("X-Sharer-User-Id") int userId,
+ @PathVariable(name = "id") int itemId,
+ @RequestBody Map