diff --git a/.gitignore b/.gitignore index 549e00a..605918c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ +/target/ + ### STS ### .apt_generated @@ -18,6 +20,7 @@ target/ *.iws *.iml *.ipr +*.class ### NetBeans ### /nbproject/private/ diff --git a/.run/ShareItGateway.run.xml b/.run/ShareItGateway.run.xml new file mode 100644 index 0000000..32c8129 --- /dev/null +++ b/.run/ShareItGateway.run.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/.run/ShareItServer.run.xml b/.run/ShareItServer.run.xml new file mode 100644 index 0000000..a8ed9e5 --- /dev/null +++ b/.run/ShareItServer.run.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..abe6570 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +services: + gateway: + build: gateway + image: shareit-gateway + container_name: shareit-gateway + ports: + - "8080:8080" + depends_on: + - server + environment: + - SHAREIT_SERVER_URL=http://server:9090 + + server: + build: server + image: shareit-server + container_name: shareit-server + ports: + - "9090:9090" + depends_on: + - db + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shareit + - SPRING_DATASOURCE_USERNAME=shareit + - SPRING_DATASOURCE_PASSWORD=shareit + + db: + image: postgres:16.1 + container_name: postgres + ports: + - "6541:5432" + environment: + - POSTGRES_PASSWORD=shareit + - POSTGRES_USER=shareit + - POSTGRES_DB=shareit + healthcheck: + test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER + timeout: 5s + interval: 5s + retries: 10 \ No newline at end of file diff --git a/gateway/Dockerfile b/gateway/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/gateway/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/gateway/pom.xml b/gateway/pom.xml new file mode 100644 index 0000000..f3394c1 --- /dev/null +++ b/gateway/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + ru.practicum + shareit + 0.0.1-SNAPSHOT + + + shareit-gateway + 0.0.1-SNAPSHOT + + ShareIt Gateway + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.hibernate.validator + hibernate-validator + + + + org.apache.httpcomponents.client5 + httpclient5 + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/ShareItGateway.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/ShareItGateway.java new file mode 100644 index 0000000..0276c51 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/ShareItGateway.java @@ -0,0 +1,12 @@ +package ru.practicum.shareit.practicum.shareit; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ShareItGateway { + public static void main(String[] args) { + SpringApplication.run(ShareItGateway.class, args); + } + +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClient.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClient.java new file mode 100644 index 0000000..52419a8 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClient.java @@ -0,0 +1,65 @@ +package ru.practicum.shareit.practicum.shareit.booking; + + +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import ru.practicum.shareit.practicum.shareit.booking.dto.BookItemRequestDto; +import ru.practicum.shareit.practicum.shareit.booking.dto.BookingState; +import ru.practicum.shareit.practicum.shareit.booking.dto.NewBookingDto; +import ru.practicum.shareit.practicum.shareit.client.BaseClient; + +import java.util.Map; + + +public class BookingClient extends BaseClient { + + public BookingClient(RestTemplate restTemplate) { + super(restTemplate); + } + + public ResponseEntity getBookings(long userId, BookingState state, Integer from, Integer size) { + Map parameters = Map.of( + "state", state.name(), + "from", from, + "size", size + ); + return get("?state={state}&from={from}&size={size}", userId, parameters); + } + + + public ResponseEntity bookItem(long userId, BookItemRequestDto requestDto) { + return post("", userId, requestDto); + } + + public ResponseEntity getBooking(long userId, Long bookingId) { + return get("/" + bookingId, userId); + } + + public ResponseEntity create(NewBookingDto newBookingDto, long userId) { + return post("", userId, newBookingDto); + } + + + public ResponseEntity approveBooking(long userId, long bookingId, boolean approved) { + Map uriVariables = Map.of("bookingId", bookingId, "approved", approved); + return patch("/" + bookingId + "?approved=" + approved, userId, approved); + } + + public ResponseEntity findById(long userId, long bookingId) { + return get("/" + bookingId, userId); + } + + public ResponseEntity findByBooker(long userId, BookingState state) { + Map parameters = Map.of( + "state", state.name() + ); + return get("?state={state}", userId, parameters); + } + + public ResponseEntity findByOwner(long userId, BookingState state) { + Map parameters = Map.of( + "state", state.name() + ); + return get("/owner", userId, parameters); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClientConfig.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClientConfig.java new file mode 100644 index 0000000..6850032 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingClientConfig.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.practicum.shareit.booking; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +@Configuration +public class BookingClientConfig { + @Value("${shareit-server.url}") + private String serverUrl; + + @Bean + public RestTemplate bookingRestTemplate(RestTemplateBuilder builder) { + return builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + "/bookings")) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build(); + } + + @Bean + public BookingClient bookingClient(RestTemplate bookingRestTemplate) { + return new BookingClient(bookingRestTemplate); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingController.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingController.java new file mode 100644 index 0000000..db1dd91 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingController.java @@ -0,0 +1,55 @@ +package ru.practicum.shareit.practicum.shareit.booking; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.practicum.shareit.booking.dto.BookingState; +import ru.practicum.shareit.practicum.shareit.booking.dto.NewBookingDto; + + +/** + * TODO Sprint add-bookings. + */ +@RestController +@RequestMapping(path = "/bookings") +@RequiredArgsConstructor +@Validated +public class BookingController { + private final BookingClient bookingClient; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public ResponseEntity create(@RequestBody @Valid NewBookingDto newBookingDto, @RequestHeader("X-Sharer-User-Id") @NotNull long userId) { + return bookingClient.create(newBookingDto, userId); + } + + @PatchMapping("/{bookingId}") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity approveBooking(@RequestHeader("X-Sharer-User-Id") long userId, @PathVariable Long bookingId, @RequestParam Boolean approved) { + return bookingClient.approveBooking(userId, bookingId, approved); + } + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public ResponseEntity findByBooker(@RequestHeader("X-Sharer-User-Id") @NotNull long userId, + @RequestParam(defaultValue = "ALL") BookingState state) { + return bookingClient.findByBooker(userId, state); + } + + @GetMapping("/owner") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity findByOwner(@RequestHeader("X-Sharer-User-Id") @NotNull long userId, + @RequestParam(defaultValue = "ALL") BookingState state) { + return bookingClient.findByOwner(userId, state); + } + + @GetMapping("/{bookingId}") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity findById(@RequestHeader("X-Sharer-User-Id") @NotNull long userId, @PathVariable @NotNull long bookingId) { + return bookingClient.findById(userId, bookingId); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingStatus.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingStatus.java new file mode 100644 index 0000000..7a87396 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/BookingStatus.java @@ -0,0 +1,5 @@ +package ru.practicum.shareit.practicum.shareit.booking; + +public enum BookingStatus { + WAITING, APPROVED, REJECTED, CANCELED +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookItemRequestDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookItemRequestDto.java new file mode 100644 index 0000000..cf5f384 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookItemRequestDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.practicum.shareit.booking.dto; + +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.FutureOrPresent; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class BookItemRequestDto { + private long itemId; + @FutureOrPresent + private LocalDateTime start; + @Future + private LocalDateTime end; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingDto.java new file mode 100644 index 0000000..07f556a --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingDto.java @@ -0,0 +1,23 @@ +package ru.practicum.shareit.practicum.shareit.booking.dto; + +import lombok.Builder; +import lombok.Data; +import ru.practicum.shareit.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.practicum.shareit.user.dto.UserDto; + +import java.time.LocalDateTime; + +/** + * TODO Sprint add-bookings. + */ +@Data +@Builder +public class BookingDto { + private Long id; + private LocalDateTime start; + private LocalDateTime end; + private ItemDto item; + private UserDto booker; + private BookingStatus status; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingState.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingState.java new file mode 100644 index 0000000..1ebf974 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/BookingState.java @@ -0,0 +1,27 @@ +package ru.practicum.shareit.practicum.shareit.booking.dto; + +import java.util.Optional; + +public enum BookingState { + // Все + ALL, + // Текущие + CURRENT, + // Будущие + FUTURE, + // Завершенные + PAST, + // Отклоненные + REJECTED, + // Ожидающие подтверждения + WAITING; + + public static Optional from(String stringState) { + for (BookingState state : values()) { + if (state.name().equalsIgnoreCase(stringState)) { + return Optional.of(state); + } + } + return Optional.empty(); + } +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/NewBookingDto.java similarity index 66% rename from src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/NewBookingDto.java index be4d6e6..47a2cd4 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/booking/dto/NewBookingDto.java @@ -1,6 +1,5 @@ -package ru.practicum.shareit.booking.dto; +package ru.practicum.shareit.practicum.shareit.booking.dto; -import jakarta.validation.constraints.FutureOrPresent; import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; @@ -10,10 +9,10 @@ @Data @Builder public class NewBookingDto { - @FutureOrPresent + @NotNull private LocalDateTime start; - @FutureOrPresent + @NotNull private LocalDateTime end; @NotNull diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/client/BaseClient.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/client/BaseClient.java new file mode 100644 index 0000000..e7bf6c0 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/client/BaseClient.java @@ -0,0 +1,117 @@ +package ru.practicum.shareit.practicum.shareit.client; + +import org.springframework.http.*; +import org.springframework.lang.Nullable; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.Map; + +public class BaseClient { + protected final RestTemplate rest; + + public BaseClient(RestTemplate rest) { + this.rest = rest; + } + + protected ResponseEntity get(String path) { + return get(path, null, null); + } + + protected ResponseEntity get(String path, long userId) { + return get(path, userId, null); + } + + protected ResponseEntity get(String path, Long userId, @Nullable Map parameters) { + return makeAndSendRequest(HttpMethod.GET, path, userId, parameters, null); + } + + protected ResponseEntity post(String path, T body) { + return post(path, null, null, body); + } + + protected ResponseEntity post(String path, long userId, T body) { + return post(path, userId, null, body); + } + + protected ResponseEntity post(String path, Long userId, @Nullable Map parameters, T body) { + return makeAndSendRequest(HttpMethod.POST, path, userId, parameters, body); + } + + protected ResponseEntity put(String path, long userId, T body) { + return put(path, userId, null, body); + } + + protected ResponseEntity put(String path, long userId, @Nullable Map parameters, T body) { + return makeAndSendRequest(HttpMethod.PUT, path, userId, parameters, body); + } + + protected ResponseEntity patch(String path, T body) { + return patch(path, null, null, body); + } + + protected ResponseEntity patch(String path, long userId) { + return patch(path, userId, null, null); + } + + protected ResponseEntity patch(String path, long userId, T body) { + return patch(path, userId, null, body); + } + + protected ResponseEntity patch(String path, Long userId, @Nullable Map parameters, T body) { + return makeAndSendRequest(HttpMethod.PATCH, path, userId, parameters, body); + } + + protected ResponseEntity delete(String path) { + return delete(path, null, null); + } + + protected ResponseEntity delete(String path, long userId) { + return delete(path, userId, null); + } + + protected ResponseEntity delete(String path, Long userId, @Nullable Map parameters) { + return makeAndSendRequest(HttpMethod.DELETE, path, userId, parameters, null); + } + + private ResponseEntity makeAndSendRequest(HttpMethod method, String path, Long userId, @Nullable Map parameters, @Nullable T body) { + HttpEntity requestEntity = new HttpEntity<>(body, defaultHeaders(userId)); + + ResponseEntity shareitServerResponse; + try { + if (parameters != null) { + shareitServerResponse = rest.exchange(path, method, requestEntity, Object.class, parameters); + } else { + shareitServerResponse = rest.exchange(path, method, requestEntity, Object.class); + } + } catch (HttpStatusCodeException e) { + return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsByteArray()); + } + return prepareGatewayResponse(shareitServerResponse); + } + + private HttpHeaders defaultHeaders(Long userId) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + if (userId != null) { + headers.set("X-Sharer-User-Id", String.valueOf(userId)); + } + return headers; + } + + private static ResponseEntity prepareGatewayResponse(ResponseEntity response) { + if (response.getStatusCode().is2xxSuccessful()) { + return response; + } + + ResponseEntity.BodyBuilder responseBuilder = ResponseEntity.status(response.getStatusCode()); + + if (response.hasBody()) { + return responseBuilder.body(response.getBody()); + } + + return responseBuilder.build(); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/CommentDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/CommentDto.java new file mode 100644 index 0000000..2af0cb4 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/CommentDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.practicum.shareit.dto; + +import lombok.Builder; +import lombok.Data; +import ru.practicum.shareit.practicum.shareit.item.Item; + +import java.time.Instant; + +@Data +@Builder +public class CommentDto { + private Long id; + private String text; + private Item item; + private String authorName; + private Instant created; +} diff --git a/src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/NewCommentDto.java similarity index 73% rename from src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/NewCommentDto.java index 56968a0..4eaab28 100644 --- a/src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/dto/NewCommentDto.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.comment.dto; +package ru.practicum.shareit.practicum.shareit.dto; import jakarta.validation.constraints.NotBlank; import lombok.Data; diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/Item.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/Item.java new file mode 100644 index 0000000..7ee7d97 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/Item.java @@ -0,0 +1,25 @@ +package ru.practicum.shareit.practicum.shareit.item; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.practicum.shareit.user.User; + +/** + * TODO Sprint add-controllers. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Item { + private Long id; + private String name; + private String description; + private boolean available; + private User owner; + private ItemRequest request; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClient.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClient.java new file mode 100644 index 0000000..d0c3b10 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClient.java @@ -0,0 +1,43 @@ +package ru.practicum.shareit.practicum.shareit.item; + + +import org.springframework.http.ResponseEntity; + +import org.springframework.web.client.RestTemplate; +import ru.practicum.shareit.practicum.shareit.client.BaseClient; +import ru.practicum.shareit.practicum.shareit.dto.NewCommentDto; +import ru.practicum.shareit.practicum.shareit.item.dto.NewItemDto; +import ru.practicum.shareit.practicum.shareit.item.dto.UpdateItemDto; + + +public class ItemClient extends BaseClient { + + + public ItemClient(RestTemplate restTemplate) { + super(restTemplate); + } + + public ResponseEntity create(NewItemDto itemDto, Long userId) { + return post("", userId, itemDto); + } + + public ResponseEntity update(Long itemId, UpdateItemDto itemDto, Long userId) { + return patch("/" + itemId, userId, itemDto); + } + + public ResponseEntity getById(Long itemId) { + return get("/" + itemId); + } + + public ResponseEntity getAllItemsByOwner(Long userId) { + return get("", userId); + } + + public ResponseEntity search(String searchText) { + return get("/search?text" + searchText); + } + + public ResponseEntity createComment(NewCommentDto newCommentDto, long itemId, long userId) { + return post("/" + itemId + "/comment", userId, newCommentDto); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClientConfig.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClientConfig.java new file mode 100644 index 0000000..97cc1dc --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemClientConfig.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.practicum.shareit.item; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +@Configuration +public class ItemClientConfig { + @Value("${shareit-server.url}") + private String serverUrl; + + @Bean + public RestTemplate itemRestTemplate(RestTemplateBuilder builder) { + return builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + "/items")) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build(); + } + + @Bean + public ItemClient itemClient(RestTemplate itemRestTemplate) { + return new ItemClient(itemRestTemplate); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemController.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemController.java new file mode 100644 index 0000000..95e3acd --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/ItemController.java @@ -0,0 +1,64 @@ +package ru.practicum.shareit.practicum.shareit.item; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.practicum.shareit.dto.NewCommentDto; +import ru.practicum.shareit.practicum.shareit.item.dto.NewItemDto; +import ru.practicum.shareit.practicum.shareit.item.dto.UpdateItemDto; + + +/** + * TODO Sprint add-controllers. + */ +@RestController +@RequestMapping("/items") +@RequiredArgsConstructor +@Validated +public class ItemController { + private final ItemClient itemClient; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public ResponseEntity create(@Valid @RequestBody NewItemDto itemDto, @RequestHeader("X-Sharer-User-Id") Long userId) { + + return itemClient.create(itemDto, userId); + } + + @PatchMapping("/{itemId}") + public ResponseEntity update(@PathVariable("itemId") Long itemId, + @RequestBody UpdateItemDto itemDto, + @RequestHeader(value = "X-Sharer-User-Id") Long userId) { + + return itemClient.update(itemId, itemDto, userId); + } + + @GetMapping("/{itemId}") + public ResponseEntity getItemById(@PathVariable("itemId") Long itemId) { + + return itemClient.getById(itemId); + } + + @GetMapping + public ResponseEntity getUserItems(@RequestHeader("X-Sharer-User-Id") Long userId) { + + return itemClient.getAllItemsByOwner(userId); + } + + @GetMapping("/search") + public ResponseEntity search(@RequestParam("text") String searchText) { + + return itemClient.search(searchText); + } + + @PostMapping("/{itemId}/comment") + @ResponseStatus(HttpStatus.CREATED) + public ResponseEntity createComment(@RequestHeader("X-Sharer-User-Id") long userId, + @PathVariable("itemId") long itemId, + @RequestBody @Valid NewCommentDto newCommentDto) { + return itemClient.createComment(newCommentDto, itemId, userId); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemDto.java new file mode 100644 index 0000000..21844c6 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemDto.java @@ -0,0 +1,21 @@ +package ru.practicum.shareit.practicum.shareit.item.dto; + +import lombok.Builder; +import lombok.Data; +import ru.practicum.shareit.practicum.shareit.user.dto.UserDto; + + +/** + * TODO Sprint add-controllers. + */ +@Data +@Builder +public class ItemDto { + private Long id; + private String name; + private String description; + private Boolean available; + private UserDto owner; + private Long requestId; + +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemResponseToRequestDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemResponseToRequestDto.java new file mode 100644 index 0000000..f331c35 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemResponseToRequestDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.practicum.shareit.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ItemResponseToRequestDto { + private long id; + private long ownerId; + private String name; + +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemWithCommentsDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemWithCommentsDto.java new file mode 100644 index 0000000..349e543 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/ItemWithCommentsDto.java @@ -0,0 +1,24 @@ +package ru.practicum.shareit.practicum.shareit.item.dto; + +import lombok.Builder; +import lombok.Data; +import ru.practicum.shareit.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.practicum.shareit.dto.CommentDto; +import ru.practicum.shareit.practicum.shareit.user.dto.UserDto; + +import java.util.List; + +@Data +@Builder +public class ItemWithCommentsDto { + private long id; + + private String name; + private String description; + private Boolean available; + private UserDto owner; + private BookingDto lastBooking; + private BookingDto nextBooking; + private List comments; + private Long requestId; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/NewItemDto.java similarity index 77% rename from src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/NewItemDto.java index 3c02052..ff3fccb 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/NewItemDto.java @@ -1,22 +1,20 @@ -package ru.practicum.shareit.item.dto; +package ru.practicum.shareit.practicum.shareit.item.dto; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; -import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.practicum.shareit.user.User; @Data @Builder public class NewItemDto { @NotBlank(message = "название предмета не может быть пустым") private String name; - @NotBlank(message = "описание не должно быть пустым") private String description; - @NotNull(message = "не установлен статус доступности бронирования") private Boolean available; - - private ItemRequest request; + private User owner; + private Long requestId; } diff --git a/src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/UpdateItemDto.java similarity index 88% rename from src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/UpdateItemDto.java index ead598d..3ecd8b7 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/item/dto/UpdateItemDto.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.item.dto; +package ru.practicum.shareit.practicum.shareit.item.dto; import lombok.Data; diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequest.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequest.java new file mode 100644 index 0000000..0e24d1e --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequest.java @@ -0,0 +1,34 @@ +package ru.practicum.shareit.practicum.shareit.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.practicum.shareit.item.Item; +import ru.practicum.shareit.practicum.shareit.user.User; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + + +/** + * TODO Sprint add-item-requests. + */ + + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemRequest { + + private long id; + private String description; + private User requestor; + private LocalDateTime created; + @Builder.Default + private List responsesList = new ArrayList<>(); + + +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClient.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClient.java new file mode 100644 index 0000000..85f3bca --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClient.java @@ -0,0 +1,27 @@ +package ru.practicum.shareit.practicum.shareit.request; + + +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import ru.practicum.shareit.practicum.shareit.client.BaseClient; +import ru.practicum.shareit.practicum.shareit.request.dto.NewItemRequestDto; + + +public class ItemRequestClient extends BaseClient { + + public ItemRequestClient(RestTemplate restTemplate) { + super(restTemplate); + } + + public ResponseEntity create(NewItemRequestDto newItemRequestDto, Long userId) { + return post("", userId, newItemRequestDto); + } + + public ResponseEntity getByUser(Long userId) { + return get("", userId); + } + + public ResponseEntity getById(Long requestId) { + return get("/" + requestId); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClientConfig.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClientConfig.java new file mode 100644 index 0000000..e38ba73 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestClientConfig.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.practicum.shareit.request; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +@Configuration +public class ItemRequestClientConfig { + @Value("${shareit-server.url}") + private String serverUrl; + + @Bean + public RestTemplate itemRequestRestTemplate(RestTemplateBuilder builder) { + return builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + "/requests")) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build(); + } + + @Bean + public ItemRequestClient itemRequestClient(RestTemplate itemRequestRestTemplate) { + return new ItemRequestClient(itemRequestRestTemplate); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestController.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestController.java new file mode 100644 index 0000000..d1ef0f3 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/ItemRequestController.java @@ -0,0 +1,33 @@ +package ru.practicum.shareit.practicum.shareit.request; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.practicum.shareit.request.dto.NewItemRequestDto; + +/** + * TODO Sprint add-item-requests. + */ +@RestController +@RequestMapping(path = "/requests") +@RequiredArgsConstructor +public class ItemRequestController { + private final ItemRequestClient requestClient; + + @PostMapping + public ResponseEntity create(@RequestBody NewItemRequestDto newItemRequestDto, + @RequestHeader("X-Sharer-User-Id") Long userId) { + return requestClient.create(newItemRequestDto, userId); + } + + @GetMapping + public ResponseEntity getRequestsByUser(@RequestHeader("X-Sharer-User-Id") Long userId) { + return requestClient.getByUser(userId); + } + + @GetMapping("/{requestId}") + public ResponseEntity getRequestById(@PathVariable Long requestId) { + return requestClient.getById(requestId); + } + +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/ItemRequestDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/ItemRequestDto.java new file mode 100644 index 0000000..dcc0645 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/ItemRequestDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.practicum.shareit.request.dto; + +import lombok.Builder; +import lombok.Data; +import ru.practicum.shareit.practicum.shareit.item.dto.ItemResponseToRequestDto; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * TODO Sprint add-item-requests. + */ +@Data +@Builder +public class ItemRequestDto { + private long id; + private String description; + private LocalDateTime created; + private List items; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/NewItemRequestDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/NewItemRequestDto.java new file mode 100644 index 0000000..3822829 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/request/dto/NewItemRequestDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.practicum.shareit.request.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class NewItemRequestDto { + private String description; + private LocalDateTime created; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/User.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/User.java new file mode 100644 index 0000000..a8dd7e1 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/User.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.practicum.shareit.user; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * TODO Sprint add-controllers. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class User { + private Long id; + private String name; + private String email; +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClient.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClient.java new file mode 100644 index 0000000..4e9605c --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClient.java @@ -0,0 +1,32 @@ +package ru.practicum.shareit.practicum.shareit.user; + + +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; +import ru.practicum.shareit.practicum.shareit.client.BaseClient; +import ru.practicum.shareit.practicum.shareit.user.dto.NewUserDto; +import ru.practicum.shareit.practicum.shareit.user.dto.UpdateUserDto; + + +public class UserClient extends BaseClient { + + public UserClient(RestTemplate restTemplate) { + super(restTemplate); + } + + public ResponseEntity create(NewUserDto userDto) { + return post("", userDto); + } + + public ResponseEntity getById(Long userId) { + return get("/" + userId); + } + + public ResponseEntity update(Long userId, UpdateUserDto userDto) { + return patch("/" + userId, userId, userDto); + } + + public ResponseEntity deleteUser(Long userId) { + return delete("/" + userId, userId); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClientConfig.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClientConfig.java new file mode 100644 index 0000000..6e3f152 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserClientConfig.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.practicum.shareit.user; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +@Configuration +public class UserClientConfig { + @Value("${shareit-server.url}") + private String serverUrl; + + @Bean + public RestTemplate userRestTemplate(RestTemplateBuilder builder) { + return builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + "/users")) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build(); + } + + @Bean + public UserClient userClient(RestTemplate userRestTemplate) { + return new UserClient(userRestTemplate); + } +} diff --git a/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserController.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserController.java new file mode 100644 index 0000000..49bd021 --- /dev/null +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/UserController.java @@ -0,0 +1,51 @@ +package ru.practicum.shareit.practicum.shareit.user; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.practicum.shareit.user.dto.NewUserDto; +import ru.practicum.shareit.practicum.shareit.user.dto.UpdateUserDto; + +/** + * TODO Sprint add-controllers. + */ + +@RestController +@AllArgsConstructor +@RequestMapping(path = "/users") +@Validated +public class UserController { + private final UserClient userClient; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public ResponseEntity createUser(@Valid @RequestBody @NotNull NewUserDto userDto) { + return userClient.create(userDto); + } + + @GetMapping("/{userId}") + public ResponseEntity getUserById(@PathVariable("userId") @NotNull @Positive Long userId) { + + return userClient.getById(userId); + } + + @PatchMapping("/{userId}") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity updateUser(@PathVariable("userId") @NotNull @Positive Long userId, @Validated @RequestBody(required = false) @NotNull UpdateUserDto userDto) { + + return userClient.update(userId, userDto); + } + + @DeleteMapping("/{userId}") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity deleteUser(@PathVariable("userId") @NotNull @Positive Long userId) { + return userClient.deleteUser(userId); + + } +} + diff --git a/src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/NewUserDto.java similarity index 88% rename from src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/NewUserDto.java index f95ecb8..d3eaa2b 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/NewUserDto.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.user.dto; +package ru.practicum.shareit.practicum.shareit.user.dto; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UpdateUserDto.java similarity index 87% rename from src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UpdateUserDto.java index bd9e396..1a5d595 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UpdateUserDto.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.user.dto; +package ru.practicum.shareit.practicum.shareit.user.dto; import jakarta.validation.constraints.Email; import lombok.Data; diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UserDto.java similarity index 65% rename from src/main/java/ru/practicum/shareit/user/dto/UserDto.java rename to gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UserDto.java index eef5ae4..eb1c70c 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java +++ b/gateway/src/main/java/ru.practicum.shareit/practicum/shareit/user/dto/UserDto.java @@ -1,7 +1,10 @@ -package ru.practicum.shareit.user.dto; +package ru.practicum.shareit.practicum.shareit.user.dto; import jakarta.validation.constraints.Email; -import lombok.*; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; @Getter diff --git a/gateway/src/main/resources/application.properties b/gateway/src/main/resources/application.properties new file mode 100644 index 0000000..773f8fa --- /dev/null +++ b/gateway/src/main/resources/application.properties @@ -0,0 +1,8 @@ +logging.level.org.springframework.web.client.RestTemplate=DEBUG +#logging.level.org.apache.http=DEBUG +#logging.level.httpclient.wire=DEBUG + +server.port=8080 + +shareit-server.url=http://localhost:9090 +spring.aot.enabled=false \ No newline at end of file diff --git a/pom.xml b/pom.xml index e1f3a93..e59910a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ ru.practicum shareit + pom 0.0.1-SNAPSHOT ShareIt @@ -19,76 +20,29 @@ 21 - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - org.postgresql - postgresql - runtime - - - - org.projectlombok - lombok - true - - - - com.h2database - h2 - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-validation - - + + gateway + server + - - - src/main/resources - true - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - + + org.springframework.boot + spring-boot-maven-plugin + + + true + + + + org.projectlombok + lombok + + + + org.apache.maven.plugins maven-surefire-plugin @@ -172,7 +126,7 @@ LINE COVEREDRATIO - 0.9 + 0.8 BRANCH @@ -235,17 +189,5 @@ - - coverage - - - - org.jacoco - jacoco-maven-plugin - - - - - - + \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/server/pom.xml b/server/pom.xml new file mode 100644 index 0000000..7f3f7b1 --- /dev/null +++ b/server/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + ru.practicum + shareit + 0.0.1-SNAPSHOT + + + shareit-server + 0.0.1-SNAPSHOT + + ShareIt Server + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.postgresql + postgresql + runtime + + + + com.h2database + h2 + runtime + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.3.2 + + + process-test-aot + none + + + + + + + + + + coverage + + + + org.jacoco + jacoco-maven-plugin + + + + + + + diff --git a/src/main/java/ru/practicum/shareit/ShareItApp.java b/server/src/main/java/ru/practicum/shareit/ShareItServer.java similarity index 73% rename from src/main/java/ru/practicum/shareit/ShareItApp.java rename to server/src/main/java/ru/practicum/shareit/ShareItServer.java index a00ad56..303541d 100644 --- a/src/main/java/ru/practicum/shareit/ShareItApp.java +++ b/server/src/main/java/ru/practicum/shareit/ShareItServer.java @@ -4,10 +4,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class ShareItApp { +public class ShareItServer { public static void main(String[] args) { - SpringApplication.run(ShareItApp.class, args); + SpringApplication.run(ShareItServer.class, args); } } diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/server/src/main/java/ru/practicum/shareit/booking/Booking.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/Booking.java rename to server/src/main/java/ru/practicum/shareit/booking/Booking.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java similarity index 66% rename from src/main/java/ru/practicum/shareit/booking/BookingController.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingController.java index 889b7c1..0a4d11e 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -1,10 +1,6 @@ package ru.practicum.shareit.booking; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.booking.dto.BookingDto; @@ -24,7 +20,7 @@ public class BookingController { @PostMapping @ResponseStatus(HttpStatus.CREATED) - public BookingDto create(@RequestBody @Valid NewBookingDto newBookingDto, @RequestHeader("X-Sharer-User-Id") long userId) { + public BookingDto create(@RequestBody NewBookingDto newBookingDto, @RequestHeader("X-Sharer-User-Id") long userId) { return bookingService.create(newBookingDto, userId); } @@ -37,17 +33,15 @@ public BookingDto approveBooking(@RequestHeader("X-Sharer-User-Id") long userId, @GetMapping @ResponseStatus(HttpStatus.OK) public List findByBooker(@RequestHeader("X-Sharer-User-Id") long userId, - @RequestParam(defaultValue = "ALL") BookingState state, - @PageableDefault(size = 20, sort = "start", direction = Sort.Direction.DESC) Pageable pageable) { - return bookingService.findByBooker(userId, state, pageable).getContent(); + @RequestParam(defaultValue = "ALL") BookingState state) { + return bookingService.findByBooker(userId, state); } @GetMapping("/owner") @ResponseStatus(HttpStatus.OK) public List findByOwner(@RequestHeader("X-Sharer-User-Id") long userId, - @RequestParam(defaultValue = "ALL") BookingState state, - @PageableDefault(size = 20, sort = "start", direction = Sort.Direction.DESC) Pageable pageable) { - return bookingService.findByOwner(userId, state, pageable).getContent(); + @RequestParam(defaultValue = "ALL") BookingState state) { + return bookingService.findByOwner(userId, state); } @GetMapping("/{bookingId}") diff --git a/src/main/java/ru/practicum/shareit/booking/BookingMapper.java b/server/src/main/java/ru/practicum/shareit/booking/BookingMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingMapper.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingMapper.java diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingRepository.java b/server/src/main/java/ru/practicum/shareit/booking/BookingRepository.java new file mode 100644 index 0000000..94f1295 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingRepository.java @@ -0,0 +1,45 @@ +package ru.practicum.shareit.booking; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +public interface BookingRepository extends JpaRepository { + List findByBooker_Id(long bookerId); + + List findByItemOwner_Id(long ownerId); + + @Query("SELECT b FROM Booking b " + + " WHERE b.booker.id = :bookerId " + + " AND b.start <= :now " + + " AND b.end >= :now " + + " AND b.status = ru.practicum.shareit.booking.BookingStatus.APPROVED") + List findCurrentByBooker(@Param("bookerId") long bookerId, @Param("now") LocalDateTime now); + + @Query("SELECT b FROM Booking b " + + " WHERE b.item.owner.id = :ownerId " + + " AND b.start <= :now " + + " AND b.end >= :now " + + " AND b.status = ru.practicum.shareit.booking.BookingStatus.APPROVED") + List findCurrentByOwner(@Param("ownerId") long ownerId, @Param("now") LocalDateTime now); + + List findByBooker_IdAndEndBefore(long bookerId, LocalDateTime now); + + List findByItemOwner_IdAndEndBefore(long ownerId, LocalDateTime now); + + List findByBooker_IdAndStartAfter(long bookerId, LocalDateTime now); + + List findByItemOwner_IdAndStartAfter(long ownerId, LocalDateTime now); + + List findByBooker_IdAndStatus(long bookerId, BookingStatus status); + + List findByItemOwner_IdAndStatus(long ownerId, BookingStatus status); + + List findByItem_idAndStatus(long itemId, BookingStatus status); + + Optional findByItem_idAndBooker_id(long itemId, long bookerId); +} diff --git a/src/main/java/ru/practicum/shareit/booking/BookingService.java b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java similarity index 58% rename from src/main/java/ru/practicum/shareit/booking/BookingService.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingService.java index 8d4c2bb..a1f1610 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -1,18 +1,19 @@ package ru.practicum.shareit.booking; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; + import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.dto.NewBookingDto; +import java.util.List; + public interface BookingService { BookingDto create(NewBookingDto newBookingDto, long bookerId); BookingDto approveBooking(long userId, long bookingId, boolean approved); - Page findByBooker(long bookerId, BookingState state, Pageable pageable); + List findByBooker(long bookerId, BookingState state); - Page findByOwner(long ownerId, BookingState state, Pageable pageable); + List findByOwner(long ownerId, BookingState state); BookingDto findById(long userId, long bookingId); } diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/server/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java similarity index 82% rename from src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java index 6067f84..67cdd0d 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java @@ -3,8 +3,6 @@ import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.dto.NewBookingDto; @@ -17,6 +15,7 @@ import ru.practicum.shareit.user.UserRepository; import java.time.LocalDateTime; +import java.util.List; @Service @RequiredArgsConstructor @@ -54,39 +53,39 @@ public BookingDto approveBooking(long userId, long bookingId, boolean approved) } @Override - public Page findByBooker(long bookerId, BookingState state, Pageable pageable) { + public List findByBooker(long bookerId, BookingState state) { if (!userExistById(bookerId)) { throw new NotFoundException("Пользователь не найден"); } LocalDateTime timeNow = LocalDateTime.now(); - Page page = switch (state) { - case CURRENT -> bookingRepository.findCurrentByBooker(bookerId, timeNow, pageable); - case PAST -> bookingRepository.findByBooker_IdAndEndBefore(bookerId, timeNow, pageable); - case FUTURE -> bookingRepository.findByBooker_IdAndStartAfter(bookerId, timeNow, pageable); - case WAITING -> bookingRepository.findByBooker_IdAndStatus(bookerId, BookingStatus.WAITING, pageable); - case REJECTED -> bookingRepository.findByBooker_IdAndStatus(bookerId, BookingStatus.REJECTED, pageable); - case ALL -> bookingRepository.findByBooker_Id(bookerId, pageable); + List bookings = switch (state) { + case CURRENT -> bookingRepository.findCurrentByBooker(bookerId, timeNow); + case PAST -> bookingRepository.findByBooker_IdAndEndBefore(bookerId, timeNow); + case FUTURE -> bookingRepository.findByBooker_IdAndStartAfter(bookerId, timeNow); + case WAITING -> bookingRepository.findByBooker_IdAndStatus(bookerId, BookingStatus.WAITING); + case REJECTED -> bookingRepository.findByBooker_IdAndStatus(bookerId, BookingStatus.REJECTED); + case ALL -> bookingRepository.findByBooker_Id(bookerId); default -> throw new NotFoundException("Некорректный параметр state"); }; - return page.map(BookingMapper::mapToBookingDto); + return bookings.stream().map(BookingMapper::mapToBookingDto).toList(); } @Override - public Page findByOwner(long ownerId, BookingState state, Pageable pageable) { + public List findByOwner(long ownerId, BookingState state) { if (!userExistById(ownerId)) { throw new NotFoundException("Пользователь не найден"); } LocalDateTime timeNow = LocalDateTime.now(); - Page page = switch (state) { - case CURRENT -> bookingRepository.findCurrentByOwner(ownerId, timeNow, pageable); - case PAST -> bookingRepository.findByItemOwner_IdAndEndBefore(ownerId, timeNow, pageable); - case FUTURE -> bookingRepository.findByItemOwner_IdAndStartAfter(ownerId, timeNow, pageable); - case WAITING -> bookingRepository.findByItemOwner_IdAndStatus(ownerId, BookingStatus.WAITING, pageable); - case REJECTED -> bookingRepository.findByItemOwner_IdAndStatus(ownerId, BookingStatus.REJECTED, pageable); - case ALL -> bookingRepository.findByItemOwner_Id(ownerId, pageable); + List bookings = switch (state) { + case CURRENT -> bookingRepository.findCurrentByOwner(ownerId, timeNow); + case PAST -> bookingRepository.findByItemOwner_IdAndEndBefore(ownerId, timeNow); + case FUTURE -> bookingRepository.findByItemOwner_IdAndStartAfter(ownerId, timeNow); + case WAITING -> bookingRepository.findByItemOwner_IdAndStatus(ownerId, BookingStatus.WAITING); + case REJECTED -> bookingRepository.findByItemOwner_IdAndStatus(ownerId, BookingStatus.REJECTED); + case ALL -> bookingRepository.findByItemOwner_Id(ownerId); default -> throw new NotFoundException("Некорректный параметр state"); }; - return page.map(BookingMapper::mapToBookingDto); + return bookings.stream().map(BookingMapper::mapToBookingDto).toList(); } @Override diff --git a/src/main/java/ru/practicum/shareit/booking/BookingState.java b/server/src/main/java/ru/practicum/shareit/booking/BookingState.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingState.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingState.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/server/src/main/java/ru/practicum/shareit/booking/BookingStatus.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingStatus.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingStatus.java diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/server/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java rename to server/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java diff --git a/server/src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java b/server/src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java new file mode 100644 index 0000000..0829910 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/booking/dto/NewBookingDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.booking.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class NewBookingDto { + private LocalDateTime start; + private LocalDateTime end; + private Long itemId; +} diff --git a/src/main/java/ru/practicum/shareit/comment/CommentMapper.java b/server/src/main/java/ru/practicum/shareit/comment/CommentMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/comment/CommentMapper.java rename to server/src/main/java/ru/practicum/shareit/comment/CommentMapper.java diff --git a/src/main/java/ru/practicum/shareit/comment/CommentRepository.java b/server/src/main/java/ru/practicum/shareit/comment/CommentRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/comment/CommentRepository.java rename to server/src/main/java/ru/practicum/shareit/comment/CommentRepository.java diff --git a/src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java b/server/src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java similarity index 75% rename from src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java rename to server/src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java index da53c85..33db81d 100644 --- a/src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java +++ b/server/src/main/java/ru/practicum/shareit/comment/dto/CommentDto.java @@ -1,13 +1,17 @@ package ru.practicum.shareit.comment.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import ru.practicum.shareit.item.model.Item; import java.time.Instant; @Data @Builder +@AllArgsConstructor +@NoArgsConstructor public class CommentDto { private Long id; private String text; diff --git a/server/src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java b/server/src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java new file mode 100644 index 0000000..d2be429 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/comment/dto/NewCommentDto.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.comment.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewCommentDto { + + private String text; +} diff --git a/src/main/java/ru/practicum/shareit/comment/model/Comment.java b/server/src/main/java/ru/practicum/shareit/comment/model/Comment.java similarity index 92% rename from src/main/java/ru/practicum/shareit/comment/model/Comment.java rename to server/src/main/java/ru/practicum/shareit/comment/model/Comment.java index b3cb9f8..cdf3e2d 100644 --- a/src/main/java/ru/practicum/shareit/comment/model/Comment.java +++ b/server/src/main/java/ru/practicum/shareit/comment/model/Comment.java @@ -1,7 +1,6 @@ package ru.practicum.shareit.comment.model; import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -23,7 +22,7 @@ public class Comment { Long id; @Column(name = "text") - @NotBlank + String text; @ManyToOne(cascade = CascadeType.PERSIST) diff --git a/src/main/java/ru/practicum/shareit/eror/ErrorHandler.java b/server/src/main/java/ru/practicum/shareit/eror/ErrorHandler.java similarity index 67% rename from src/main/java/ru/practicum/shareit/eror/ErrorHandler.java rename to server/src/main/java/ru/practicum/shareit/eror/ErrorHandler.java index 4257b59..bd02b6b 100644 --- a/src/main/java/ru/practicum/shareit/eror/ErrorHandler.java +++ b/server/src/main/java/ru/practicum/shareit/eror/ErrorHandler.java @@ -10,15 +10,6 @@ @RestControllerAdvice @Slf4j public class ErrorHandler { - @ExceptionHandler - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ErrorResponse handleValidationError(final ValidationException e) { - log.error("Ошибка валидации {}", e.getMessage()); - return new ErrorResponse( - "Ошибка валидации", - e.getMessage() - ); - } @ExceptionHandler @ResponseStatus(HttpStatus.NOT_FOUND) @@ -30,16 +21,6 @@ public ErrorResponse handleNotFound(final NotFoundException e) { ); } - @ExceptionHandler - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ErrorResponse handleNoDataFound(final NoDataFoundException e) { - log.error("Ошибка заполнения данных {}", e.getMessage()); - return new ErrorResponse( - "Ошибка заполнения данных", - e.getMessage() - ); - } - @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleAvailableError(final NotAvailableItemException e) { diff --git a/src/main/java/ru/practicum/shareit/eror/ErrorResponse.java b/server/src/main/java/ru/practicum/shareit/eror/ErrorResponse.java similarity index 100% rename from src/main/java/ru/practicum/shareit/eror/ErrorResponse.java rename to server/src/main/java/ru/practicum/shareit/eror/ErrorResponse.java diff --git a/src/main/java/ru/practicum/shareit/exception/NoAccessException.java b/server/src/main/java/ru/practicum/shareit/exception/NoAccessException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exception/NoAccessException.java rename to server/src/main/java/ru/practicum/shareit/exception/NoAccessException.java diff --git a/src/main/java/ru/practicum/shareit/exception/NotAvailableItemException.java b/server/src/main/java/ru/practicum/shareit/exception/NotAvailableItemException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exception/NotAvailableItemException.java rename to server/src/main/java/ru/practicum/shareit/exception/NotAvailableItemException.java diff --git a/src/main/java/ru/practicum/shareit/exception/NotFoundException.java b/server/src/main/java/ru/practicum/shareit/exception/NotFoundException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exception/NotFoundException.java rename to server/src/main/java/ru/practicum/shareit/exception/NotFoundException.java diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/server/src/main/java/ru/practicum/shareit/item/ItemController.java similarity index 89% rename from src/main/java/ru/practicum/shareit/item/ItemController.java rename to server/src/main/java/ru/practicum/shareit/item/ItemController.java index 8f1185d..658db31 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -1,6 +1,6 @@ package ru.practicum.shareit.item; -import jakarta.validation.Valid; + import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; @@ -26,7 +26,7 @@ public class ItemController { @PostMapping @ResponseStatus(HttpStatus.CREATED) - public ItemDto create(@Valid @RequestBody NewItemDto itemDto, @RequestHeader("X-Sharer-User-Id") Long userId) { + public ItemDto create(@RequestBody NewItemDto itemDto, @RequestHeader("X-Sharer-User-Id") Long userId) { return itemService.create(itemDto, userId); } @@ -61,7 +61,7 @@ public List search(@RequestParam("text") String searchText) { @ResponseStatus(HttpStatus.CREATED) public CommentDto createComment(@RequestHeader("X-Sharer-User-Id") long userId, @PathVariable("itemId") long itemId, - @RequestBody @Valid NewCommentDto newCommentDto) { + @RequestBody NewCommentDto newCommentDto) { return itemService.createComment(newCommentDto, itemId, userId); } } diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java similarity index 76% rename from src/main/java/ru/practicum/shareit/item/ItemMapper.java rename to server/src/main/java/ru/practicum/shareit/item/ItemMapper.java index 197ac47..5466457 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemMapper.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -5,11 +5,9 @@ import ru.practicum.shareit.booking.BookingMapper; import ru.practicum.shareit.comment.CommentMapper; import ru.practicum.shareit.comment.model.Comment; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemWithCommentsDto; -import ru.practicum.shareit.item.dto.NewItemDto; -import ru.practicum.shareit.item.dto.UpdateItemDto; +import ru.practicum.shareit.item.dto.*; import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; import ru.practicum.shareit.user.User; import ru.practicum.shareit.user.UserMapper; @@ -18,22 +16,26 @@ public class ItemMapper { public static ItemDto mapToItemDto(Item item) { + Long requestId = item.getRequest() == null ? null : item.getRequest().getId(); return ItemDto.builder() .id(item.getId()) .name(item.getName()) .description(item.getDescription()) .available(item.isAvailable()) .owner(UserMapper.mapToUserDto(item.getOwner())) + .requestId(requestId) .build(); } public static Item mapToNewItem(NewItemDto newItemDto, User owner) { + ItemRequest request = newItemDto.getRequestId() == null ? null : ItemRequest.builder().id(newItemDto.getRequestId()).build(); + return Item.builder() .name(newItemDto.getName()) .description(newItemDto.getDescription()) .available(newItemDto.getAvailable()) .owner(owner) - .request(newItemDto.getRequest()) + .request(request) .build(); } @@ -58,6 +60,7 @@ public static ItemWithCommentsDto mapToItemWithCommentsDto(Item item, List comments; + private Long requestId; } diff --git a/server/src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java b/server/src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java new file mode 100644 index 0000000..508058f --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.item.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.user.User; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewItemDto { + private String name; + private String description; + private Boolean available; + private User owner; + private Long requestId; +} diff --git a/server/src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java b/server/src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java new file mode 100644 index 0000000..dd96e3a --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/dto/UpdateItemDto.java @@ -0,0 +1,28 @@ +package ru.practicum.shareit.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class UpdateItemDto { + private String name; + private String description; + private Boolean available; + + public boolean hasName() { + return !(name == null || name.isBlank()); + } + + public boolean hasDescription() { + return !(description == null || description.isBlank()); + } + + public boolean hasAvailable() { + return Boolean.FALSE.equals(available); + } +} diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/server/src/main/java/ru/practicum/shareit/item/model/Item.java similarity index 90% rename from src/main/java/ru/practicum/shareit/item/model/Item.java rename to server/src/main/java/ru/practicum/shareit/item/model/Item.java index a8f7e3b..bb46597 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/server/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -2,7 +2,6 @@ import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -24,17 +23,15 @@ public class Item { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name", nullable = false) - @NotBlank private String name; @Column(name = "description", nullable = false) - @NotBlank private String description; @Column(name = "available") private boolean available; @ManyToOne @JoinColumn(name = "owner_id") private User owner; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "request_id") private ItemRequest request; } diff --git a/server/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/server/src/main/java/ru/practicum/shareit/request/ItemRequest.java new file mode 100644 index 0000000..75f2293 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/ItemRequest.java @@ -0,0 +1,43 @@ +package ru.practicum.shareit.request; + +import jakarta.persistence.*; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.User; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + + +/** + * TODO Sprint add-item-requests. + */ + +@Entity +@Table(name = "requests") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemRequest { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + @Column(name = "description") + private String description; + @OneToOne + @JoinColumn(name = "requestor_id") + private User requestor; + @Column(name = "created") + private LocalDateTime created; + @OneToMany(mappedBy = "request", fetch = FetchType.EAGER) + @Builder.Default + private List responsesList = new ArrayList<>(); + + +} diff --git a/server/src/main/java/ru/practicum/shareit/request/ItemRequestController.java b/server/src/main/java/ru/practicum/shareit/request/ItemRequestController.java new file mode 100644 index 0000000..957ecdd --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/ItemRequestController.java @@ -0,0 +1,35 @@ +package ru.practicum.shareit.request; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + +import java.util.List; + +/** + * TODO Sprint add-item-requests. + */ +@RestController +@RequestMapping(path = "/requests") +@RequiredArgsConstructor +public class ItemRequestController { + private final ItemRequestService requestService; + + @PostMapping + public ItemRequestDto create(@RequestBody NewItemRequestDto newItemRequestDto, + @RequestHeader("X-Sharer-User-Id") Long userId) { + return requestService.create(newItemRequestDto, userId); + } + + @GetMapping + public List getRequestsByUser(@RequestHeader("X-Sharer-User-Id") Long userId) { + return requestService.getByUser(userId); + } + + @GetMapping("/{requestId}") + public ItemRequestDto getRequestById(@PathVariable Long requestId) { + return requestService.getById(requestId); + } + +} diff --git a/server/src/main/java/ru/practicum/shareit/request/ItemRequestRepository.java b/server/src/main/java/ru/practicum/shareit/request/ItemRequestRepository.java new file mode 100644 index 0000000..a7cfbba --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/ItemRequestRepository.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.request; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ItemRequestRepository extends JpaRepository { + + List getAllByRequestorId(long userId); +} diff --git a/server/src/main/java/ru/practicum/shareit/request/ItemRequestService.java b/server/src/main/java/ru/practicum/shareit/request/ItemRequestService.java new file mode 100644 index 0000000..4273003 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/ItemRequestService.java @@ -0,0 +1,14 @@ +package ru.practicum.shareit.request; + +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + +import java.util.List; + +public interface ItemRequestService { + ItemRequestDto create(NewItemRequestDto newItemRequestDto, long userId); + + List getByUser(long id); + + ItemRequestDto getById(long id); +} diff --git a/server/src/main/java/ru/practicum/shareit/request/ItemRequestServiceImpl.java b/server/src/main/java/ru/practicum/shareit/request/ItemRequestServiceImpl.java new file mode 100644 index 0000000..f1b6e5a --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/ItemRequestServiceImpl.java @@ -0,0 +1,53 @@ +package ru.practicum.shareit.request; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; +import ru.practicum.shareit.user.User; +import ru.practicum.shareit.user.UserRepository; + +import java.util.Comparator; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ItemRequestServiceImpl implements ItemRequestService { + private final ItemRequestRepository requestRepository; + private final UserRepository userRepository; + + @Override + public ItemRequestDto create(NewItemRequestDto newItemRequestDto, long userId) { + ItemRequest itemRequest = RequestMapper.toModel(newItemRequestDto); + itemRequest.setRequestor(getUserById(userId)); + return RequestMapper.toDto(requestRepository.save(itemRequest)); + } + + @Override + public List getByUser(long id) { + getUserById(id); + List requests = requestRepository.getAllByRequestorId(id); + return requests.stream() + .map(RequestMapper::toDto) + .sorted(Comparator.comparing(ItemRequestDto::getCreated).reversed()) + .toList(); + } + + @Override + public ItemRequestDto getById(long id) { + return RequestMapper.toDto(getRequestById(id)); + } + + + private User getUserById(long id) { + return userRepository.findById(id) + .orElseThrow(() -> new NotFoundException("Пользователь с id = " + id + " не найден")); + } + + private ItemRequest getRequestById(long id) { + return requestRepository.findById(id) + .orElseThrow(() -> new NotFoundException("Запрос вещи с id = " + id + " не найден")); + + } +} diff --git a/server/src/main/java/ru/practicum/shareit/request/RequestMapper.java b/server/src/main/java/ru/practicum/shareit/request/RequestMapper.java new file mode 100644 index 0000000..ce537f4 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/RequestMapper.java @@ -0,0 +1,25 @@ +package ru.practicum.shareit.request; + +import ru.practicum.shareit.item.ItemMapper; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + +import java.time.LocalDateTime; + +public class RequestMapper { + public static ItemRequest toModel(NewItemRequestDto requestCreateDto) { + return ItemRequest.builder() + .description(requestCreateDto.getDescription()) + .created(LocalDateTime.now()) + .build(); + } + + public static ItemRequestDto toDto(ItemRequest request) { + return ItemRequestDto.builder() + .id(request.getId()) + .description(request.getDescription()) + .created(request.getCreated()) + .items(request.getResponsesList().stream().map(ItemMapper::itemResponseToRequestDto).toList()) + .build(); + } +} diff --git a/server/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java b/server/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java new file mode 100644 index 0000000..e5c455d --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java @@ -0,0 +1,24 @@ +package ru.practicum.shareit.request.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.item.dto.ItemResponseToRequestDto; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * TODO Sprint add-item-requests. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ItemRequestDto { + private long id; + private String description; + private LocalDateTime created; + private List items; +} diff --git a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java b/server/src/main/java/ru/practicum/shareit/request/dto/NewItemRequestDto.java similarity index 54% rename from src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java rename to server/src/main/java/ru/practicum/shareit/request/dto/NewItemRequestDto.java index c6aa1c7..647df5d 100644 --- a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java +++ b/server/src/main/java/ru/practicum/shareit/request/dto/NewItemRequestDto.java @@ -1,19 +1,17 @@ package ru.practicum.shareit.request.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -import ru.practicum.shareit.user.dto.UserDto; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; -/** - * TODO Sprint add-item-requests. - */ @Data @Builder -public class ItemRequestDto { - private Long id; +@NoArgsConstructor +@AllArgsConstructor +public class NewItemRequestDto { private String description; - private UserDto requestor; private LocalDateTime created; } diff --git a/src/main/java/ru/practicum/shareit/user/User.java b/server/src/main/java/ru/practicum/shareit/user/User.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/User.java rename to server/src/main/java/ru/practicum/shareit/user/User.java diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/server/src/main/java/ru/practicum/shareit/user/UserController.java similarity index 92% rename from src/main/java/ru/practicum/shareit/user/UserController.java rename to server/src/main/java/ru/practicum/shareit/user/UserController.java index c849a60..662d8df 100644 --- a/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserController.java @@ -1,6 +1,6 @@ package ru.practicum.shareit.user; -import jakarta.validation.Valid; + import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; @@ -22,7 +22,7 @@ public class UserController { @PostMapping @ResponseStatus(HttpStatus.CREATED) - public UserDto createUser(@Valid @RequestBody NewUserDto userDto) { + public UserDto createUser(@RequestBody NewUserDto userDto) { return userService.create(userDto); } diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/server/src/main/java/ru/practicum/shareit/user/UserMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserMapper.java rename to server/src/main/java/ru/practicum/shareit/user/UserMapper.java diff --git a/src/main/java/ru/practicum/shareit/user/UserRepository.java b/server/src/main/java/ru/practicum/shareit/user/UserRepository.java similarity index 69% rename from src/main/java/ru/practicum/shareit/user/UserRepository.java rename to server/src/main/java/ru/practicum/shareit/user/UserRepository.java index e303ab5..7bce122 100644 --- a/src/main/java/ru/practicum/shareit/user/UserRepository.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserRepository.java @@ -2,5 +2,8 @@ import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); } diff --git a/src/main/java/ru/practicum/shareit/user/UserService.java b/server/src/main/java/ru/practicum/shareit/user/UserService.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserService.java rename to server/src/main/java/ru/practicum/shareit/user/UserService.java diff --git a/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java b/server/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserServiceImpl.java rename to server/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java diff --git a/server/src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java b/server/src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java new file mode 100644 index 0000000..67ee94f --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/user/dto/NewUserDto.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.user.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewUserDto { + + private String name; + + private String email; +} diff --git a/server/src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java b/server/src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java new file mode 100644 index 0000000..1a87b85 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/user/dto/UpdateUserDto.java @@ -0,0 +1,26 @@ +package ru.practicum.shareit.user.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class UpdateUserDto { + private String name; + + + private String email; + + public boolean hasName() { + return !(name == null || name.isBlank()); + } + + public boolean hasEmail() { + return !(email == null || email.isBlank()); + } +} diff --git a/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java new file mode 100644 index 0000000..50da151 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.user.dto; + + +import lombok.*; + + +@Getter +@Setter +@ToString +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class UserDto { + private Long id; + private String name; + private String email; +} diff --git a/server/src/main/resources/application-test.properties b/server/src/main/resources/application-test.properties new file mode 100644 index 0000000..37265c6 --- /dev/null +++ b/server/src/main/resources/application-test.properties @@ -0,0 +1,22 @@ +spring.jpa.hibernate.ddl-auto=none +spring.jpa.properties.hibernate.format_sql=true +spring.sql.init.mode=always +spring.aot.enabled=false + +logging.level.org.springframework.orm.jpa=INFO +logging.level.org.springframework.transaction=INFO +logging.level.org.springframework.transaction.interceptor=TRACE +logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG + +# TODO Append connection to DB +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:shareit +spring.datasource.username=sa +spring.datasource.password=12345 +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console + + +spring.main.banner-mode=OFF +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC \ No newline at end of file diff --git a/src/main/resources/application.properties b/server/src/main/resources/application.properties similarity index 89% rename from src/main/resources/application.properties rename to server/src/main/resources/application.properties index fa544b9..7898400 100644 --- a/src/main/resources/application.properties +++ b/server/src/main/resources/application.properties @@ -1,9 +1,11 @@ -server.port=8080 +server.port=9090 # ???? ???????????? ???????????? spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.format_sql=true spring.sql.init.mode=always +spring.aot.enabled=false + logging.level.org.springframework.orm.jpa=INFO logging.level.org.springframework.transaction=INFO diff --git a/src/main/resources/schema.sql b/server/src/main/resources/schema.sql similarity index 65% rename from src/main/resources/schema.sql rename to server/src/main/resources/schema.sql index 47c804c..0c0e5ed 100644 --- a/src/main/resources/schema.sql +++ b/server/src/main/resources/schema.sql @@ -1,12 +1,23 @@ +drop table IF EXISTS users CASCADE; +drop table IF EXISTS items CASCADE; +drop table IF EXISTS requests CASCADE; +drop table IF EXISTS items CASCADE; +drop table IF EXISTS bookings CASCADE; +drop table IF EXISTS comments CASCADE; + + CREATE TABLE IF NOT EXISTS users ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name varchar, email varchar UNIQUE NOT NULL ); -CREATE TABLE IF NOT EXISTS request ( -id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -description varchar NOT NULL, -requestor_id BIGINT REFERENCES users (id) + +CREATE TABLE IF NOT EXISTS requests +( +id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY NOT NULL, +description VARCHAR(360) NOT NULL, +requestor_id BIGINT REFERENCES users(id), +created TIMESTAMP WITHOUT TIME ZONE NOT NULL ); @@ -16,7 +27,7 @@ name varchar NOT NULL, description varchar NOT NULL, available boolean, owner_id BIGINT REFERENCES users (id), -request_id BIGINT REFERENCES request (id) +request_id BIGINT REFERENCES requests (id) ); CREATE TABLE IF NOT EXISTS bookings ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, diff --git a/src/test/java/ru/practicum/shareit/ShareItTests.java b/server/src/test/java/ru/practicum/shareit/ShareItTests.java similarity index 79% rename from src/test/java/ru/practicum/shareit/ShareItTests.java rename to server/src/test/java/ru/practicum/shareit/ShareItTests.java index 4d79052..1d13d7f 100644 --- a/src/test/java/ru/practicum/shareit/ShareItTests.java +++ b/server/src/test/java/ru/practicum/shareit/ShareItTests.java @@ -6,8 +6,8 @@ @SpringBootTest class ShareItTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } -} +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java new file mode 100644 index 0000000..9fb80fe --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java @@ -0,0 +1,110 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.NewBookingDto; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(BookingController.class) +@AutoConfigureMockMvc +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class BookingControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private BookingService bookingService; + + @Autowired + private ObjectMapper objectMapper; + + private final BookingDto bookingDto = BookingDto.builder() + .id(1L) + .start(LocalDateTime.now().plusDays(1)) + .end(LocalDateTime.now().plusDays(2)) + .status(BookingStatus.APPROVED) + .build(); + + @Test + void addBookingTest() throws Exception { + NewBookingDto newBookingDto = NewBookingDto.builder() + .itemId(1L) + .start(LocalDateTime.now().plusDays(1)) + .end(LocalDateTime.now().plusDays(2)) + .build(); + + when(bookingService.create(any(), anyLong())).thenReturn(bookingDto); + + mockMvc.perform(post("/bookings") + .contentType(MediaType.APPLICATION_JSON) + .header("X-Sharer-User-Id", 1) + .content(objectMapper.writeValueAsString(newBookingDto))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(1L)); + } + + @Test + void bookingConfirmationTest() throws Exception { + when(bookingService.approveBooking(anyLong(), anyLong(), anyBoolean())) + .thenReturn(bookingDto); + + mockMvc.perform(patch("/bookings/1?approved=true") + .contentType(MediaType.APPLICATION_JSON) + .header("X-Sharer-User-Id", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1L)); + } + + @Test + void getBookingByIdTest() throws Exception { + when(bookingService.findById(anyLong(), anyLong())) + .thenReturn(bookingDto); + + mockMvc.perform(get("/bookings/1") + .header("X-Sharer-User-Id", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1L)); + } + + + @Test + void getAllUsersBookingsTest() throws Exception { + Mockito.when(bookingService.findByBooker(anyLong(), any(BookingState.class))) + .thenReturn(List.of(bookingDto)); + + mockMvc.perform(get("/bookings") + .param("state", "ALL") + .header("X-Sharer-User-Id", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1L)); + } + + @Test + void getAllBookingsForAllUsersItemsTest() throws Exception { + Mockito.when(bookingService.findByOwner(anyLong(), any(BookingState.class))) + .thenReturn(List.of(bookingDto)); + + mockMvc.perform(get("/bookings/owner") + .param("state", "ALL") + .header("X-Sharer-User-Id", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1L)); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingDtoTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingDtoTest.java new file mode 100644 index 0000000..9017c04 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingDtoTest.java @@ -0,0 +1,96 @@ +package ru.practicum.shareit.booking; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.user.dto.UserDto; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.assertThat; + +@JsonTest +class BookingDtoTest { + + @Autowired + private JacksonTester json; + + @Test + void testSerializeBookingDto() throws Exception { + UserDto user = new UserDto(); + user.setId(200L); + user.setName("Pol"); + user.setEmail("pol@example.com"); + + UserDto booker = new UserDto(); + booker.setId(201L); + booker.setName("Tom"); + booker.setEmail("tom@example.com"); + + ItemDto item = new ItemDto(); + item.setId(100L); + item.setName("new_item"); + item.setDescription("item_description"); + item.setAvailable(true); + item.setOwner(user); + + BookingDto dto = BookingDto.builder() + .id(1L) + .start(LocalDateTime.of(2025, 5, 4, 10, 0)) + .end(LocalDateTime.of(2025, 5, 4, 12, 0)) + .item(item) + .booker(booker) + .status(BookingStatus.APPROVED) + .build(); + + var result = json.write(dto); + + assertThat(result).hasJsonPathNumberValue("$.id"); + assertThat(result).extractingJsonPathNumberValue("$.id").isEqualTo(1); + assertThat(result).extractingJsonPathStringValue("$.start").isEqualTo("2025-05-04T10:00:00"); + assertThat(result).extractingJsonPathStringValue("$.end").isEqualTo("2025-05-04T12:00:00"); + assertThat(result).extractingJsonPathStringValue("$.status").isEqualTo("APPROVED"); + assertThat(result).extractingJsonPathMapValue("$.item").containsEntry("id", 100); + assertThat(result).extractingJsonPathMapValue("$.booker").containsEntry("id", 201); + } + + @Test + void testDeserializeBookingDto() throws Exception { + String jsonContent = "{" + + "\"id\": 1," + + "\"start\": \"2025-05-04T10:00:00\"," + + "\"end\": \"2025-05-04T12:00:00\"," + + "\"status\": \"APPROVED\"," + + "\"item\": {" + + " \"id\": 100," + + " \"name\": \"new_item\"," + + " \"description\": \"item_description\"," + + " \"available\": true," + + " \"owner\": {" + + " \"id\": 200," + + " \"name\": \"Tom\"," + + " \"email\": \"tom@example.com\"" + + " }" + + "}," + + "\"booker\": {" + + " \"id\": 201," + + " \"name\": \"Pol\"," + + " \"email\": \"pol@example.com\"" + + "}," + + "\"status\": \"APPROVED\"" + + "}"; + + + BookingDto dto = json.parseObject(jsonContent); + + assertThat(dto.getId()).isEqualTo(1L); + assertThat(dto.getStart()).isEqualTo(LocalDateTime.of(2025, 5, 4, 10, 0)); + assertThat(dto.getEnd()).isEqualTo(LocalDateTime.of(2025, 5, 4, 12, 0)); + assertThat(dto.getStatus()).isEqualTo(BookingStatus.APPROVED); + assertThat(dto.getItem().getId()).isEqualTo(100L); + assertThat(dto.getBooker().getId()).isEqualTo(201L); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingMapperTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingMapperTest.java new file mode 100644 index 0000000..730d98a --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingMapperTest.java @@ -0,0 +1,52 @@ +package ru.practicum.shareit.booking; + +import org.junit.jupiter.api.Test; +import ru.practicum.shareit.booking.dto.NewBookingDto; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.User; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class BookingMapperTest { + + @Test + void mapToBookingDtoTest() { + User user = new User(1L, "Tom", "tom@mail.ru"); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime2 = LocalDateTime.now(); + Item item = new Item(1L, "test-item", "test-description", true, user, null); + + Booking booking = new Booking(1, localDateTime, localDateTime2, item, user, BookingStatus.WAITING); + BookingMapper mapper = new BookingMapper(); + + assertEquals(mapper.mapToBookingDto(booking).getStart(), localDateTime); + assertEquals(mapper.mapToBookingDto(booking).getEnd(), localDateTime2); + assertEquals(mapper.mapToBookingDto(booking).getStatus(), BookingStatus.WAITING); + assertEquals(mapper.mapToBookingDto(booking).getId(), 1); + assertEquals(mapper.mapToBookingDto(booking).getBooker().getId(), user.getId()); + assertEquals(mapper.mapToBookingDto(booking).getItem().getId(), item.getId()); + } + + @Test + void mapToNewBookingDto() { + User user = new User(1L, "Tom", "tom@mail.ru"); + Item item = new Item(1L, "test-item", "test-description", true, user, null); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime2 = LocalDateTime.now(); + NewBookingDto newBookingDto = NewBookingDto.builder() + .start(localDateTime) + .end(localDateTime2) + .itemId(1L) + .build(); + BookingMapper mapper = new BookingMapper(); + assertEquals(mapper.mapToNewBookingDto(newBookingDto, user, item).getStart(), localDateTime); + assertEquals(mapper.mapToNewBookingDto(newBookingDto, user, item).getEnd(), localDateTime2); + assertEquals(mapper.mapToNewBookingDto(newBookingDto, user, item).getStatus(), BookingStatus.WAITING); + assertEquals(mapper.mapToNewBookingDto(newBookingDto, user, item).getBooker().getId(), user.getId()); + assertEquals(mapper.mapToNewBookingDto(newBookingDto, user, item).getItem().getId(), item.getId()); + + + } +} diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingRepositoryTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingRepositoryTest.java new file mode 100644 index 0000000..6a0dd9c --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingRepositoryTest.java @@ -0,0 +1,120 @@ +package ru.practicum.shareit.booking; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import ru.practicum.shareit.item.ItemRepository; + + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + + +@DataJpaTest +public class BookingRepositoryTest { + @Autowired + private BookingRepository bookingRepository; + @Autowired + private ItemRepository itemRepository; + + private List bookingDataList; + + + @Test + void findAllByBookerIdTest() { + bookingDataList = bookingRepository.findByBooker_Id(2); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(3, bookingDataList.size()); + } + + @Test + void findAllByBookerIdAndEndingBeforeTest() { + bookingDataList = bookingRepository.findByBooker_IdAndEndBefore(2, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(2, bookingDataList.size()); + } + + @Test + void findAllByOwnerIdAndEndingBeforeTest() { + bookingDataList = bookingRepository.findByItemOwner_IdAndEndBefore(1, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.size()); + } + + @Test + void findAllByBookerIdAndStartAfterTest() { + bookingDataList = bookingRepository.findByBooker_IdAndStartAfter(2, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(0, bookingDataList.size()); + } + + @Test + void findAllByOwnerIdAndStartAfterTest() { + bookingDataList = bookingRepository.findByItemOwner_IdAndStartAfter(2, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(0, bookingDataList.size()); + } + + @Test + void findCurrentByOwnerTest() { + bookingDataList = bookingRepository.findCurrentByOwner(1, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + + } + + @Test + void findCurrentByBookerTest() { + bookingDataList = bookingRepository.findCurrentByBooker(1, LocalDateTime.now()); + + Assertions.assertNotNull(bookingDataList); + + } + + @Test + void findAllByBookerIdAndStatusTest() { + bookingDataList = bookingRepository.findByBooker_IdAndStatus(1, BookingStatus.WAITING); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.size()); + } + + @Test + void findAllByOwnerIdAndStatusTest() { + bookingDataList = bookingRepository.findByItemOwner_IdAndStatus(3, BookingStatus.WAITING); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.size()); + } + + @Test + void findAllByItemIdAndStatusTest() { + bookingDataList = bookingRepository.findByItem_idAndStatus(3, BookingStatus.WAITING); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.size()); + } + + @Test + void findAllByOwnerIdTest() { + bookingDataList = bookingRepository.findByItemOwner_Id(2); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.size()); + } + + @Test + void findAllByItemIdAndBookerId() { + Optional bookingDataList = bookingRepository.findByItem_idAndBooker_id(3, 2); + + Assertions.assertNotNull(bookingDataList); + Assertions.assertEquals(1, bookingDataList.stream().toList().size()); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java new file mode 100644 index 0000000..28c8a08 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -0,0 +1,204 @@ +package ru.practicum.shareit.booking; + +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.NewBookingDto; +import ru.practicum.shareit.exception.NoAccessException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.item.ItemRepository; +import ru.practicum.shareit.user.UserRepository; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@Transactional +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class BookingServiceTest { + private final BookingServiceImpl bookingService; + private final UserRepository userRepository; + private final ItemRepository itemRepository; + + private NewBookingDto newBookingDto; + + @Test + void createBookingTest() { + newBookingDto = new NewBookingDto(LocalDateTime.of(2026, 4, 5, 0, 0, 0), + LocalDateTime.of(2026, 4, 7, 0, 0, 0), 1L); + + BookingDto bookingDto = bookingService.create(newBookingDto, 2); + + Assertions.assertNotNull(bookingDto); + Assertions.assertEquals(5, bookingDto.getId()); + Assertions.assertEquals(1, bookingDto.getItem().getId()); + Assertions.assertEquals(2, bookingDto.getBooker().getId()); + Assertions.assertEquals(BookingStatus.WAITING, bookingDto.getStatus()); + } + + @Test + void createBookingWithWrongBookerIdTest() { + newBookingDto = new NewBookingDto(LocalDateTime.of(2026, 4, 5, 0, 0, 0), + LocalDateTime.of(2026, 4, 7, 0, 0, 0), 1L); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> bookingService.create(newBookingDto, 1000L) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь не найден"); + } + + @Test + void createBookingWithWrongItemIdTest() { + newBookingDto = new NewBookingDto(LocalDateTime.of(2026, 4, 5, 0, 0, 0), + LocalDateTime.of(2026, 4, 7, 0, 0, 0), 1000L); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> bookingService.create(newBookingDto, 1L) + ); + + Assertions.assertEquals(e.getMessage(), "Вещь не найдена"); + } + + + @Test + void createBookingWithNotAvailableItemTest() { + newBookingDto = new NewBookingDto(LocalDateTime.of(2026, 4, 5, 0, 0, 0), + LocalDateTime.of(2026, 4, 7, 0, 0, 0), 4L); + + RuntimeException e = assertThrows(RuntimeException.class, + () -> bookingService.create(newBookingDto, 2) + ); + + Assertions.assertEquals(e.getMessage(), "Вещь недоступна для бронирования"); + + } + + @Test + void bookingApproveTest() { + BookingDto bookingDto = bookingService.approveBooking(3, 3, true); + + Assertions.assertNotNull(bookingDto); + Assertions.assertEquals(BookingStatus.APPROVED, bookingDto.getStatus()); + } + + + @Test + void bookingApproveWhereUserIsNotUserTest() { + RuntimeException e = assertThrows(RuntimeException.class, + () -> bookingService.approveBooking(1, 3, true) + ); + + Assertions.assertEquals(e.getMessage(), "Только владелец вещи имеет доступ к изменению статуса бронирования"); + + } + + @Test + void getBookingByIdTest() { + BookingDto bookingDto1 = bookingService.findById(3, 3); + + Assertions.assertNotNull(bookingDto1); + Assertions.assertEquals(BookingStatus.APPROVED, bookingDto1.getStatus()); + } + + @Test + void getBookingByWrongIdTest() { + NoAccessException e = assertThrows(NoAccessException.class, + () -> bookingService.findById(1000, 2) + ); + + Assertions.assertEquals(e.getMessage(), "No access to booking"); + } + + + @Test + void getAllUsersBookingsTest() { + List bookingDtoList = bookingService.findByBooker(2, BookingState.ALL); + + Assertions.assertNotNull(bookingDtoList); + Assertions.assertEquals(3, bookingDtoList.size()); + + List bookingDtoList1 = bookingService.findByBooker(2, BookingState.PAST); + + Assertions.assertNotNull(bookingDtoList1); + Assertions.assertEquals(2, bookingDtoList1.size()); + + List bookingDtoList2 = bookingService.findByBooker(2, BookingState.FUTURE); + + Assertions.assertNotNull(bookingDtoList2); + Assertions.assertEquals(0, bookingDtoList2.size()); + + List bookingDtoList3 = bookingService.findByBooker(2, BookingState.CURRENT); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(0, bookingDtoList3.size()); + + List bookingDtoList4 = bookingService.findByBooker(2, BookingState.WAITING); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(0, bookingDtoList4.size()); + + List bookingDtoList5 = bookingService.findByBooker(2, BookingState.REJECTED); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(1, bookingDtoList5.size()); + } + + @Test + void getAllUsersBookingsWithWrongStateTest() { + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, + () -> bookingService.findByBooker(2, BookingState.valueOf("asd")) + ); + + Assertions.assertEquals(e.getMessage(), "No enum constant ru.practicum.shareit.booking.BookingState.asd"); + } + + @Test + void getAllBookingsForAllUsersItemsTest() { + List bookingDtoList = bookingService.findByOwner(3, BookingState.ALL); + + Assertions.assertNotNull(bookingDtoList); + Assertions.assertEquals(2, bookingDtoList.size()); + + List bookingDtoList1 = bookingService.findByOwner(3, BookingState.PAST); + + Assertions.assertNotNull(bookingDtoList1); + Assertions.assertEquals(1, bookingDtoList1.size()); + + List bookingDtoList2 = bookingService.findByOwner(3, BookingState.FUTURE); + + Assertions.assertNotNull(bookingDtoList2); + Assertions.assertEquals(1, bookingDtoList2.size()); + + List bookingDtoList3 = bookingService.findByOwner(3, BookingState.CURRENT); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(0, bookingDtoList3.size()); + + List bookingDtoList4 = bookingService.findByOwner(3, BookingState.WAITING); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(1, bookingDtoList4.size()); + + List bookingDtoList5 = bookingService.findByOwner(3, BookingState.REJECTED); + + Assertions.assertNotNull(bookingDtoList3); + Assertions.assertEquals(0, bookingDtoList5.size()); + } + + @Test + void getAllBookingsForAllUsersItemsWithWrongStatusTest() { + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, + () -> bookingService.findByOwner(3, BookingState.valueOf("asd")) + ); + + Assertions.assertEquals(e.getMessage(), "No enum constant ru.practicum.shareit.booking.BookingState.asd"); + } + +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/CommentDtoTest.java b/server/src/test/java/ru/practicum/shareit/item/CommentDtoTest.java new file mode 100644 index 0000000..7fcb62b --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/CommentDtoTest.java @@ -0,0 +1,75 @@ +package ru.practicum.shareit.item; + + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; + +import ru.practicum.shareit.comment.dto.CommentDto; +import ru.practicum.shareit.item.model.Item; + +import java.time.Instant; + +import static org.assertj.core.api.Assertions.assertThat; + +@JsonTest +class CommentDtoTest { + + @Autowired + private JacksonTester json; + + @Test + void testSerialize() throws Exception { + Item item = Item.builder() + .id(1L) + .name("item") + .description("description") + .available(true) + .build(); + String instant = "2024-07-01T12:30:00Z"; + Instant created = Instant.parse(instant); + + CommentDto dto = CommentDto.builder() + .id(10L) + .text("text_test") + .item(item) + .authorName("Alice") + .created(created) + .build(); + + assertThat(json.write(dto)) + .extractingJsonPathNumberValue("$.id").isEqualTo(10); + assertThat(json.write(dto)) + .extractingJsonPathStringValue("$.text").isEqualTo("text_test"); + assertThat(json.write(dto)) + .extractingJsonPathStringValue("$.authorName").isEqualTo("Alice"); + assertThat(json.write(dto)) + .extractingJsonPathStringValue("$.created").isEqualTo("2024-07-01T12:30:00Z"); + } + + @Test + void testDeserialize() throws Exception { + + String content = "{" + + "\"id\": 10," + + "\"text\": \"text_test\"," + + "\"item\": {" + + " \"id\": 1," + + " \"name\": \"item\"," + + " \"description\": \"description\"," + + " \"available\": true" + + "}," + + "\"authorName\": \"Bob\"," + + "\"created\": \"2024-07-01T12:30:00Z\"" + + "}"; + + CommentDto dto = json.parseObject(content); + + assertThat(dto.getId()).isEqualTo(10); + assertThat(dto.getText()).isEqualTo("text_test"); + assertThat(dto.getItem().getId()).isEqualTo(1); + assertThat(dto.getAuthorName()).isEqualTo("Bob"); + assertThat(dto.getCreated()).isEqualTo("2024-07-01T12:30:00Z"); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/CommentRepositoryTest.java b/server/src/test/java/ru/practicum/shareit/item/CommentRepositoryTest.java new file mode 100644 index 0000000..dbc2659 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/CommentRepositoryTest.java @@ -0,0 +1,67 @@ +package ru.practicum.shareit.item; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import ru.practicum.shareit.comment.CommentRepository; +import ru.practicum.shareit.comment.model.Comment; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.User; + +import java.util.ArrayList; +import java.util.List; + + +@DataJpaTest +public class CommentRepositoryTest { + @Autowired + private CommentRepository commentRepository; + + private List itemList; + private List commentList; + + @BeforeEach + void beforeEachTest() { + User user = new User(); + User booker = new User(); + Item item = new Item(); + Comment comment = new Comment(); + + user.setId(1L); + user.setName("new_user"); + user.setEmail("new_user@example.com"); + + booker.setId(2L); + booker.setName("booker"); + booker.setEmail("booker@example.com"); + + item.setId(1L); + item.setOwner(user); + item.setName("new_item"); + item.setDescription("description_new_item"); + + comment.setId(1L); + comment.setText("comment text"); + comment.setAuthor(booker); + comment.setItem(item); + + itemList = new ArrayList<>(); + itemList.add(item); + + commentList = new ArrayList<>(); + commentList.add(comment); + } + + @Test + void findAllByItemIdTest() { + List commentDataList = commentRepository.findByItem_id(1); + + Assertions.assertNotNull(commentDataList); + Assertions.assertEquals(1, commentDataList.size()); + Assertions.assertEquals(commentList.get(0).getId(), commentDataList.get(0).getId()); + } + + +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java new file mode 100644 index 0000000..78bb9db --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -0,0 +1,150 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import ru.practicum.shareit.comment.dto.CommentDto; +import ru.practicum.shareit.comment.dto.NewCommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemWithCommentsDto; +import ru.practicum.shareit.item.dto.NewItemDto; +import ru.practicum.shareit.item.dto.UpdateItemDto; + + +import java.util.List; + +import static org.mockito.ArgumentMatchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(ItemController.class) +@AutoConfigureMockMvc +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class ItemControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemService itemService; + + @Autowired + private ObjectMapper objectMapper; + + private final Long userId = 1L; + private final Long itemId = 1L; + + @Test + void getAllItemsFromUserList() throws Exception { + ItemDto item = new ItemDto(); + item.setId(itemId); + item.setName("Drill"); + + Mockito.when(itemService.getAllItemsByOwner(userId)).thenReturn(List.of(item)); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(itemId)) + .andExpect(jsonPath("$[0].name").value("Drill")); + } + + @Test + void getItemInfo() throws Exception { + ItemWithCommentsDto item = new ItemWithCommentsDto(); + item.setId(itemId); + item.setName("Drill"); + + Mockito.when(itemService.get(itemId)).thenReturn(item); + + mockMvc.perform(get("/items/{itemId}", itemId) + .header("X-Sharer-User-Id", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(itemId)) + .andExpect(jsonPath("$.name").value("Drill")); + } + + @Test + void addNewItem() throws Exception { + NewItemDto createDto = new NewItemDto(); + createDto.setName("Drill"); + + ItemDto responseDto = new ItemDto(); + responseDto.setId(itemId); + responseDto.setName("Drill"); + + Mockito.when(itemService.create(any(), eq(userId))).thenReturn(responseDto); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createDto))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(itemId)) + .andExpect(jsonPath("$.name").value("Drill")); + } + + @Test + void updateItem() throws Exception { + UpdateItemDto updateDto = new UpdateItemDto(); + updateDto.setName("Updated Drill"); + + ItemDto responseDto = new ItemDto(); + responseDto.setId(itemId); + responseDto.setName("Updated Drill"); + + Mockito.when(itemService.update(eq(itemId), any(), eq(userId))).thenReturn(responseDto); + + mockMvc.perform(patch("/items/{itemId}", itemId) + .header("X-Sharer-User-Id", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(itemId)) + .andExpect(jsonPath("$.name").value("Updated Drill")); + } + + @Test + void searchItems() throws Exception { + ItemDto item = new ItemDto(); + item.setId(itemId); + item.setName("Drill"); + + Mockito.when(itemService.search("drill")).thenReturn(List.of(item)); + + mockMvc.perform(get("/items/search") + .param("text", "drill") + .header("X-Sharer-User-Id", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(itemId)) + .andExpect(jsonPath("$[0].name").value("Drill")); + } + + @Test + void addComment() throws Exception { + NewCommentDto createDto = new NewCommentDto(); + createDto.setText("Nice item!"); + + CommentDto commentDto = new CommentDto(); + commentDto.setId(1L); + commentDto.setText("Nice item!"); + + Mockito.when(itemService.createComment(any(), eq(itemId), eq(userId))) + .thenReturn(commentDto); + + mockMvc.perform(post("/items/{itemId}/comment", itemId) + .header("X-Sharer-User-Id", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createDto))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(1L)) + .andExpect(jsonPath("$.text").value("Nice item!")); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemDtoTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemDtoTest.java new file mode 100644 index 0000000..6ae65a5 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemDtoTest.java @@ -0,0 +1,75 @@ +package ru.practicum.shareit.item; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; + +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.user.dto.UserDto; + + +import static org.assertj.core.api.Assertions.assertThat; + +@JsonTest +class ItemDtoTest { + + @Autowired + private JacksonTester json; + + @Test + void testSerialize() throws Exception { + UserDto ownerDto = UserDto.builder() + .id(1L) + .name("John") + .email("john@example.com") + .build(); + + ItemDto itemDto = ItemDto.builder() + .id(1L) + .name("new_item") + .description("new_description") + .available(true) + .owner(ownerDto) + .requestId(null) + .build(); + + assertThat(json.write(itemDto)).hasJsonPathNumberValue("$.id"); + assertThat(json.write(itemDto)).hasJsonPathStringValue("$.name"); + assertThat(json.write(itemDto)).hasJsonPathStringValue("$.description"); + assertThat(json.write(itemDto)).hasJsonPathBooleanValue("$.available"); + assertThat(json.write(itemDto)).hasJsonPathMapValue("$.owner"); + + + } + + @Test + void testDeserialize() throws Exception { + String content = "{" + + "\"id\": 1," + + "\"name\": \"new_item\"," + + "\"description\": \"new_description\"," + + "\"available\": true," + + "\"owner\": {" + + " \"id\": 1," + + " \"name\": \"John\"," + + " \"email\": \"john@example.com\"" + + "}," + + "\"requestId\": \"null\"" + + "}"; + + + ItemDto itemDto = json.parseObject(content); + + assertThat(itemDto.getId()).isEqualTo(1L); + assertThat(itemDto.getName()).isEqualTo("new_item"); + assertThat(itemDto.getDescription()).isEqualTo("new_description"); + assertThat(itemDto.getAvailable()).isTrue(); + assertThat(itemDto.getOwner().getId()).isEqualTo(1L); + assertThat(itemDto.getOwner().getName()).isEqualTo("John"); + assertThat(itemDto.getOwner().getEmail()).isEqualTo("john@example.com"); + + + } + +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemMapperTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemMapperTest.java new file mode 100644 index 0000000..d04d0c7 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemMapperTest.java @@ -0,0 +1,56 @@ +package ru.practicum.shareit.item; + +import org.junit.jupiter.api.Test; +import ru.practicum.shareit.item.dto.NewItemDto; +import ru.practicum.shareit.item.dto.UpdateItemDto; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.User; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ItemMapperTest { + + @Test + void mapToDtoTest() { + User user = new User(1L, "test-name", "test@mail.ru"); + Item item = new Item(1L, "Drill", "test-description", true, user, null); + ItemMapper mapper = new ItemMapper(); + assertEquals(mapper.mapToItemDto(item).getName(), "Drill"); + assertEquals(mapper.mapToItemDto(item).getDescription(), "test-description"); + assertEquals(mapper.mapToItemDto(item).getAvailable(), true); + assertEquals(mapper.mapToItemDto(item).getOwner().getId(), user.getId()); + } + + @Test + void mapToNewItemTest() { + User user = new User(1L, "test-name", "test@mail.ru"); + NewItemDto itemDto = NewItemDto.builder() + .name("Drill") + .description("test-description") + .available(true) + .owner(user) + .build(); + ItemMapper mapper = new ItemMapper(); + assertEquals(mapper.mapToNewItem(itemDto, user).getName(), "Drill"); + assertEquals(mapper.mapToNewItem(itemDto, user).getDescription(), "test-description"); + assertEquals(mapper.mapToNewItem(itemDto, user).isAvailable(), true); + assertEquals(mapper.mapToNewItem(itemDto, user).getOwner().getId(), user.getId()); + + } + + @Test + void mapToUpdateIdemDtoTest() { + User user = new User(1L, "test-name", "test@mail.ru"); + Item item = new Item(1L, "Drill", "test-description", true, user, null); + UpdateItemDto itemDto = UpdateItemDto.builder() + .name("update-name") + .description("update-description") + .build(); + ItemMapper mapper = new ItemMapper(); + assertEquals(mapper.mapToUpdateItemDto(item, itemDto).getName(), "update-name"); + assertEquals(mapper.mapToUpdateItemDto(item, itemDto).getDescription(), "update-description"); + assertEquals(mapper.mapToUpdateItemDto(item, itemDto).isAvailable(), true); + assertEquals(mapper.mapToUpdateItemDto(item, itemDto).getOwner().getId(), user.getId()); + + } +} diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemRepositoryTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemRepositoryTest.java new file mode 100644 index 0000000..237416c --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemRepositoryTest.java @@ -0,0 +1,56 @@ +package ru.practicum.shareit.item; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.User; +import ru.practicum.shareit.user.UserRepository; + +import java.util.ArrayList; +import java.util.List; + + +@DataJpaTest +public class ItemRepositoryTest { + + @Autowired + private ItemRepository itemRepository; + + @Autowired + private UserRepository userRepository; + + + @BeforeEach + void beforeEachTest() { + Item item = new Item(); + User user = new User(); + List itemList = new ArrayList<>(); + user.setId(1L); + user.setName("new_user"); + user.setEmail("new_user@example.com"); + item.setOwner(user); + item.setName("new_item"); + item.setDescription("description_new_item"); + itemList.add(item); + } + + @Test + void findAllByOwnerIdTest() { + List itemDataList = itemRepository.findByOwner(userRepository.getById(1L)); + + Assertions.assertNotNull(itemDataList); + Assertions.assertEquals(1, itemDataList.size()); + } + + @Test + void findAllByOwnerIdAndTextTest() { + List itemDataList = itemRepository.searchItem("description_new_item"); + + Assertions.assertNotNull(itemDataList); + Assertions.assertEquals(1, itemDataList.size()); + + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemServiceImplTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemServiceImplTest.java new file mode 100644 index 0000000..c9053fd --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemServiceImplTest.java @@ -0,0 +1,168 @@ +package ru.practicum.shareit.item; + +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.comment.dto.CommentDto; +import ru.practicum.shareit.comment.dto.NewCommentDto; +import ru.practicum.shareit.exception.NoAccessException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.item.dto.*; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@Transactional +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class ItemServiceImplTest { + private final ItemServiceImpl itemService; + + @Test + void addNewItemTest() { + NewItemDto newItemDto = NewItemDto.builder() + .name("new_item_5") + .description("new_item_5_description") + .available(true) + .build(); + + ItemDto itemDto = itemService.create(newItemDto, 1); + + Assertions.assertNotNull(itemDto); + assertEquals(5, itemDto.getId()); + assertEquals("new_item_5", itemDto.getName()); + assertEquals("new_item_5_description", itemDto.getDescription()); + assertEquals(1, itemDto.getOwner().getId()); + + } + + @Test + void addNewItemWithWrongOwnerTest() { + NewItemDto newItemDto = NewItemDto.builder() + .name("new_item_5") + .description("new_item_5_description") + .available(true) + .build(); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> itemService.create(newItemDto, 1000) + ); + + assertEquals(e.getMessage(), "Пользователь с id = 1000 не найден"); + } + + @Test + void updateItemTest() { + UpdateItemDto updateItemDto = UpdateItemDto.builder() + .name("new_item_test") + .build(); + + ItemDto itemDto = itemService.update(1, updateItemDto, 1); + + Assertions.assertNotNull(itemDto); + assertEquals("new_item_test", itemDto.getName()); + } + + @Test + void updateItemWithWrongIdTest() { + UpdateItemDto updateItemDto = UpdateItemDto.builder() + .name("new_item_test") + .build(); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> itemService.update(1000, updateItemDto, 2) + ); + + assertEquals(e.getMessage(), "Предмет не найден"); + } + + @Test + void updateItemWithUserIsNotOwnerTest() { + UpdateItemDto updateItemDto = UpdateItemDto.builder() + .name("new_item_test") + .build(); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> itemService.update(1, updateItemDto, 3) + ); + + assertEquals(e.getMessage(), "У вас недостаточно прав для обновления вещи"); + } + + @Test + void getItemByIdTest() { + ItemWithCommentsDto itemDto = itemService.get(1L); + + Assertions.assertNotNull(itemDto); + assertEquals("new_item", itemDto.getName()); + assertEquals("description_new_item", itemDto.getDescription()); + } + + @Test + void getItemByWrongIdTest() { + NotFoundException e = assertThrows(NotFoundException.class, + () -> itemService.get(1000) + ); + assertEquals(e.getMessage(), "Предмет не найден"); + } + + @Test + void getItemsByOwner() { + List itemDtoList = itemService.getAllItemsByOwner(3L); + + Assertions.assertNotNull(itemDtoList); + assertEquals(3, itemDtoList.size()); + } + + @Test + void searchItemsTest() { + List itemDtoList = itemService.search("item"); + + Assertions.assertNotNull(itemDtoList); + assertEquals(3, itemDtoList.size()); + } + + @Test + void addNewCommentTest() { + NewCommentDto newCommentDto = NewCommentDto.builder() + .text("comment_test_text").build(); + + CommentDto commentDto = itemService.createComment(newCommentDto, 3, 2); + + Assertions.assertNotNull(commentDto); + assertEquals(2, commentDto.getId()); + assertEquals("comment_test_text", commentDto.getText()); + assertEquals("booker", commentDto.getAuthorName()); + } + + @Test + void addNewCommentWithWrongBookerIdTest() { + NewCommentDto newCommentDto = NewCommentDto.builder() + .text("comment_test_text").build(); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> itemService.createComment(newCommentDto, 3, 3) + ); + + assertEquals(e.getMessage(), "Бронирование для предмета не найдено, невозможно добавить комментарий"); + + } + + @Test + void addNewCommentWithWrongTimeTest() { + NewCommentDto newCommentDto = NewCommentDto.builder() + .text("comment_test_text").build(); + + NoAccessException e = assertThrows(NoAccessException.class, + () -> itemService.createComment(newCommentDto, 3, 1) + ); + + assertEquals(e.getMessage(), "Срок бронирования предмета еще не закончился"); + + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java new file mode 100644 index 0000000..952e113 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -0,0 +1,92 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + + +import java.util.List; + +import static org.mockito.ArgumentMatchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(ItemRequestController.class) +@AutoConfigureMockMvc +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class RequestControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemRequestService requestService; + + @Autowired + private ObjectMapper objectMapper; + + private final Long userId = 1L; + private final Long requestId = 2L; + + @Test + void postRequest() throws Exception { + NewItemRequestDto newItemRequestDto = new NewItemRequestDto(); + newItemRequestDto.setDescription("Need a drill"); + + ItemRequestDto shortDto = new ItemRequestDto(); + shortDto.setId(requestId); + shortDto.setDescription("Need a drill"); + + Mockito.when(requestService.create(any(), eq(userId))) + .thenReturn(shortDto); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(newItemRequestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(requestId)) + .andExpect(jsonPath("$.description").value("Need a drill")); + } + + @Test + void getRequests() throws Exception { + ItemRequestDto dto = new ItemRequestDto(); + dto.setId(requestId); + dto.setDescription("Need a hammer"); + + Mockito.when(requestService.getByUser(userId)) + .thenReturn(List.of(dto)); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(requestId)) + .andExpect(jsonPath("$[0].description").value("Need a hammer")); + } + + + @Test + void getRequestById() throws Exception { + ItemRequestDto dto = new ItemRequestDto(); + dto.setId(requestId); + dto.setDescription("Need a chainsaw"); + + Mockito.when(requestService.getById(requestId)) + .thenReturn(dto); + + mockMvc.perform(get("/requests/{requestId}", requestId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(requestId)) + .andExpect(jsonPath("$.description").value("Need a chainsaw")); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestDtoTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestDtoTest.java new file mode 100644 index 0000000..231bfba --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestDtoTest.java @@ -0,0 +1,88 @@ +package ru.practicum.shareit.request; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; +import ru.practicum.shareit.item.dto.ItemResponseToRequestDto; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.user.User; + + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@JsonTest +class RequestDtoTest { + + @Autowired + private JacksonTester json; + + @Test + void testSerializeRequest() throws Exception { + User requestor = new User(); + requestor.setId(1L); + requestor.setName("Ilona"); + requestor.setEmail("ilona@example.com"); + + LocalDateTime created = LocalDateTime.of(2025, 5, 4, 10, 30); + + ItemRequestDto requestDto = ItemRequestDto.builder() + .id(100L) + .description("description") + .created(created) + .build(); + + User user = new User(); + user.setId(1L); + user.setName("Ilona"); + user.setEmail("ilona@example.com"); + + ItemResponseToRequestDto itemForRequestDto = new ItemResponseToRequestDto(); + itemForRequestDto.setId(10L); + itemForRequestDto.setName("item"); + + requestDto.setItems(List.of(itemForRequestDto)); + + var result = json.write(requestDto); + + assertThat(result).hasJsonPathNumberValue("$.id"); + assertThat(result).extractingJsonPathNumberValue("$.id").isEqualTo(100); + assertThat(result).extractingJsonPathStringValue("$.description").isEqualTo("description"); + assertThat(result).extractingJsonPathStringValue("$.created").isEqualTo("2025-05-04T10:30:00"); + assertThat(result).extractingJsonPathArrayValue("$.items").hasSize(1); + } + + @Test + void testDeserializeRequest() throws Exception { + String jsonContent = + "{\n" + + " \"id\": 100,\n" + + " \"description\": \"description\",\n" + + " \"created\": \"2025-05-04T10:30:00\",\n" + + " \"items\": [\n" + + " {\n" + + " \"id\": 10,\n" + + " \"name\": \"item\",\n" + + " \"ownerId\": 1\n" + + " }\n" + + " ]\n" + + "}"; + + + ItemRequestDto requestDto = json.parseObject(jsonContent); + + assertThat(requestDto.getId()).isEqualTo(100L); + assertThat(requestDto.getDescription()).isEqualTo("description"); + assertThat(requestDto.getCreated()).isEqualTo(LocalDateTime.of(2025, 5, 4, 10, 30)); + + assertThat(requestDto.getItems()).hasSize(1); + ItemResponseToRequestDto item = requestDto.getItems().get(0); + assertThat(item.getId()).isEqualTo(10L); + assertThat(item.getName()).isEqualTo("item"); + assertThat(item.getOwnerId()).isEqualTo(1L); + } + +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestMapperTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestMapperTest.java new file mode 100644 index 0000000..eb57ab8 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestMapperTest.java @@ -0,0 +1,32 @@ +package ru.practicum.shareit.request; + +import org.junit.jupiter.api.Test; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RequestMapperTest { + + @Test + void newRequestDtoMapperTest() { + + NewItemRequestDto newItemRequestDto = new NewItemRequestDto("test-description", LocalDateTime.now()); + RequestMapper requestMapper = new RequestMapper(); + assertEquals(requestMapper.toModel(newItemRequestDto).getDescription(), "test-description"); + + + } + + @Test + void toDtoMapperTest() { + + ItemRequest itemRequestDto = new ItemRequest(); + itemRequestDto.setDescription("test-description"); + RequestMapper requestMapper = new RequestMapper(); + assertEquals(requestMapper.toDto(itemRequestDto).getDescription(), "test-description"); + + + } +} diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestRepositoryTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestRepositoryTest.java new file mode 100644 index 0000000..4ebb53a --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestRepositoryTest.java @@ -0,0 +1,48 @@ +package ru.practicum.shareit.request; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import ru.practicum.shareit.user.User; + + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + + +@DataJpaTest +public class RequestRepositoryTest { + @Autowired + private ItemRequestRepository requestRepository; + + @BeforeEach + void beforeEachTest() { + + User user = new User(); + ItemRequest request = new ItemRequest(); + List requestList = new ArrayList<>(); + + user.setId(1L); + user.setName("new_user"); + user.setEmail("new_user@example.com"); + + request.setId(1); + request.setRequestor(user); + request.setDescription("request_description"); + request.setCreated(LocalDateTime.of(2025, 2, 7, 0, 0, 0)); + + requestList.add(request); + + } + + @Test + void getAllByRequestorIdTest() { + List requesDatatList = requestRepository.getAllByRequestorId(1); + + Assertions.assertNotNull(requesDatatList); + Assertions.assertEquals(1, requesDatatList.size()); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java new file mode 100644 index 0000000..b0d24c4 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java @@ -0,0 +1,65 @@ +package ru.practicum.shareit.request; + +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.request.dto.ItemRequestDto; +import ru.practicum.shareit.request.dto.NewItemRequestDto; + + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +@Transactional +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class RequestServiceTest { + private final ItemRequestServiceImpl requestService; + + @Test + void postRequestTest() { + NewItemRequestDto newItemRequestDto = NewItemRequestDto.builder() + .description("request_test_description") + .build(); + + ItemRequestDto itemRequestDto = requestService.create(newItemRequestDto, 1); + + Assertions.assertNotNull(itemRequestDto); + Assertions.assertEquals(2, itemRequestDto.getId()); + Assertions.assertEquals("request_test_description", itemRequestDto.getDescription()); + } + + @Test + void postRequestWithWrongUserIdTest() { + NewItemRequestDto newItemRequestDto = NewItemRequestDto.builder() + .description("request_test_description") + .build(); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> requestService.create(newItemRequestDto, 100) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь с id = 100 не найден"); + } + + @Test + void getRequestByIdTest() { + ItemRequestDto requestDto = requestService.getById(1); + + Assertions.assertNotNull(requestDto); + Assertions.assertEquals("request_description", requestDto.getDescription()); + } + + @Test + void getRequestByWrongIdTest() { + NotFoundException e = assertThrows(NotFoundException.class, + () -> requestService.getById(100) + ); + + Assertions.assertEquals(e.getMessage(), "Запрос вещи с id = 100 не найден"); + } + +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java new file mode 100644 index 0000000..4184014 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -0,0 +1,107 @@ +package ru.practicum.shareit.user; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import ru.practicum.shareit.user.dto.NewUserDto; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UpdateUserDto; + +import static org.mockito.ArgumentMatchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(UserController.class) +@AutoConfigureMockMvc +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class UserControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private UserService userService; + + @Autowired + private ObjectMapper objectMapper; + + private final Long userId = 1L; + + + + @Test + void getUserById() throws Exception { + UserDto user = new UserDto(); + user.setId(userId); + user.setName("Jane"); + user.setEmail("jane@example.com"); + + Mockito.when(userService.getById(userId)).thenReturn(user); + + mockMvc.perform(get("/users/{userId}", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(userId)) + .andExpect(jsonPath("$.name").value("Jane")) + .andExpect(jsonPath("$.email").value("jane@example.com")); + } + + @Test + void createUser() throws Exception { + NewUserDto createDto = new NewUserDto(); + createDto.setName("Alice"); + createDto.setEmail("alice@example.com"); + + UserDto responseDto = new UserDto(); + responseDto.setId(userId); + responseDto.setName("Alice"); + responseDto.setEmail("alice@example.com"); + + Mockito.when(userService.create(any())).thenReturn(responseDto); + + mockMvc.perform(post("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createDto))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(userId)) + .andExpect(jsonPath("$.name").value("Alice")) + .andExpect(jsonPath("$.email").value("alice@example.com")); + } + + @Test + void updateUser() throws Exception { + UpdateUserDto updateDto = new UpdateUserDto(); + updateDto.setName("Updated Name"); + updateDto.setEmail("updated@example.com"); + + UserDto updatedUser = new UserDto(); + updatedUser.setId(userId); + updatedUser.setName("Updated Name"); + updatedUser.setEmail("updated@example.com"); + + Mockito.when(userService.update(eq(userId), any())).thenReturn(updatedUser); + + mockMvc.perform(patch("/users/{userId}", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(userId)) + .andExpect(jsonPath("$.name").value("Updated Name")) + .andExpect(jsonPath("$.email").value("updated@example.com")); + } + + @Test + void deleteUserById() throws Exception { + Mockito.doNothing().when(userService).deleteUser(userId); + + mockMvc.perform(delete("/users/{userId}", userId)) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/user/UserDtoTest.java b/server/src/test/java/ru/practicum/shareit/user/UserDtoTest.java new file mode 100644 index 0000000..8bec5b0 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserDtoTest.java @@ -0,0 +1,45 @@ +package ru.practicum.shareit.user; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; +import ru.practicum.shareit.user.dto.UserDto; + +import static org.assertj.core.api.Assertions.assertThat; + +@JsonTest +class UserDtoTest { + + @Autowired + private JacksonTester json; + + @Test + void testSerializeUser() throws Exception { + UserDto userDto = UserDto.builder() + .id(1L) + .name("Ilona") + .email("ilona@example.com") + .build(); + + assertThat(json.write(userDto)).hasJsonPathNumberValue("$.id"); + assertThat(json.write(userDto)).extractingJsonPathNumberValue("$.id").isEqualTo(1); + assertThat(json.write(userDto)).extractingJsonPathStringValue("$.name").isEqualTo("Ilona"); + assertThat(json.write(userDto)).extractingJsonPathStringValue("$.email").isEqualTo("ilona@example.com"); + } + + @Test + void testDeserializeUser() throws Exception { + String jsonContent = "{" + + "\"id\": 1," + + "\"name\": \"Ilona\"," + + "\"email\": \"ilona@example.com\"" + + "}"; + + UserDto userDto = json.parseObject(jsonContent); + + assertThat(userDto.getId()).isEqualTo(1L); + assertThat(userDto.getName()).isEqualTo("Ilona"); + assertThat(userDto.getEmail()).isEqualTo("ilona@example.com"); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/user/UserMapperTest.java b/server/src/test/java/ru/practicum/shareit/user/UserMapperTest.java new file mode 100644 index 0000000..fa85a70 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserMapperTest.java @@ -0,0 +1,53 @@ +package ru.practicum.shareit.user; + +import org.junit.jupiter.api.Test; +import ru.practicum.shareit.user.dto.NewUserDto; +import ru.practicum.shareit.user.dto.UpdateUserDto; +import ru.practicum.shareit.user.dto.UserDto; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class UserMapperTest { + @Test + void userMapToDtoTest() { + User user = new User(); + user.setId(1L); + user.setName("Tom"); + user.setEmail("tom@mail.ru"); + UserMapper mapper = new UserMapper(); + assertEquals(mapper.mapToUserDto(user).getId(), 1); + assertEquals(mapper.mapToUserDto(user).getName(), "Tom"); + assertEquals(mapper.mapToUserDto(user).getEmail(), "tom@mail.ru"); + } + + @Test + void newUserMapTest() { + NewUserDto user = new NewUserDto("Tom", "tom@mail.ru"); + UserMapper mapper = new UserMapper(); + assertEquals(mapper.mapToNewUser(user).getName(), "Tom"); + assertEquals(mapper.mapToNewUser(user).getEmail(), "tom@mail.ru"); + } + + @Test + void updateUserMapTest() { + UpdateUserDto updateUserDto = new UpdateUserDto("Tom", "tom@mail.ru"); + User user = new User(); + user.setId(1L); + user.setName("Sam"); + user.setEmail("sam@mail.ru"); + UserMapper mapper = new UserMapper(); + assertEquals(mapper.mapToUserUpdate(user, updateUserDto).getName(), "Tom"); + assertEquals(mapper.mapToUserUpdate(user, updateUserDto).getEmail(), "tom@mail.ru"); + + } + + @Test + void userMapTest() { + UserDto user = new UserDto(1L, "Tom", "tom@mail.ru"); + UserMapper mapper = new UserMapper(); + assertEquals(mapper.mapToUser(user).getName(), "Tom"); + assertEquals(mapper.mapToUser(user).getEmail(), "tom@mail.ru"); + } + +} + diff --git a/server/src/test/java/ru/practicum/shareit/user/UserRepositoryTest.java b/server/src/test/java/ru/practicum/shareit/user/UserRepositoryTest.java new file mode 100644 index 0000000..2ddb2dc --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserRepositoryTest.java @@ -0,0 +1,25 @@ +package ru.practicum.shareit.user; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import java.util.Optional; + +@DataJpaTest +public class UserRepositoryTest { + @Autowired + private UserRepository userRepository; + + @Test + void findByEmailTest() { + User user = new User(); + user.setName("new_user"); + user.setEmail("new_user@example.com"); + Optional userData = userRepository.findByEmail(user.getEmail()); + + Assertions.assertNotNull(Optional.ofNullable(userData)); + Assertions.assertEquals(userData.get().getName(), "new_user"); + } +} \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/user/UserServiceImplTest.java b/server/src/test/java/ru/practicum/shareit/user/UserServiceImplTest.java new file mode 100644 index 0000000..81bf4b0 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserServiceImplTest.java @@ -0,0 +1,150 @@ +package ru.practicum.shareit.user; + +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.user.dto.NewUserDto; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UpdateUserDto; + + +import static org.junit.jupiter.api.Assertions.assertThrows; + + +@SpringBootTest +@Transactional +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class UserServiceImplTest { + private final UserServiceImpl userService; + + private NewUserDto newUserDto; + private NewUserDto newUserDto2; + private UpdateUserDto updateUserDto; + + @Test + void addUserTest() { + newUserDto = new NewUserDto("Don", "don@example.com"); + UserDto userDto = userService.create(newUserDto); + + Assertions.assertNotNull(userDto); + Assertions.assertEquals(4, userDto.getId()); + Assertions.assertEquals("Don", userDto.getName()); + Assertions.assertEquals("don@example.com", userDto.getEmail()); + } + + @Test + void addUserWithoutEmailTest() { + newUserDto = new NewUserDto("Don", "don@example.com"); + newUserDto.setEmail(null); + + DataIntegrityViolationException e = assertThrows(DataIntegrityViolationException.class, + () -> userService.create(newUserDto) + ); + + } + + @Test + void addUserWithSameEmailTest() { + newUserDto = new NewUserDto("Don", "don@example.com"); + newUserDto2 = new NewUserDto("Don2", "don@example.com"); + userService.create(newUserDto); + + + DataIntegrityViolationException e = assertThrows(DataIntegrityViolationException.class, + () -> userService.create(newUserDto2) + ); + + } + + + @Test + void updateUserTest() { + updateUserDto = new UpdateUserDto("Tom", "tom@example.com"); + UserDto userDto = userService.update(3L, updateUserDto); + + Assertions.assertNotNull(userDto); + Assertions.assertEquals(3, userDto.getId()); + Assertions.assertEquals("Tom", userDto.getName()); + Assertions.assertEquals("tom@example.com", userDto.getEmail()); + } + + @Test + void updateUserNameTest() { + UserDto userDto = userService.update(1L, UpdateUserDto.builder().name("new_user_name").build()); + + Assertions.assertNotNull(userDto); + Assertions.assertEquals(1, userDto.getId()); + Assertions.assertEquals("new_user_name", userDto.getName()); + Assertions.assertEquals("new_user@example.com", userDto.getEmail()); + } + + @Test + void updateUserEmailTest() { + UserDto userDto = userService.update(1L, UpdateUserDto.builder().email("new_user_email@example.com").build()); + + Assertions.assertNotNull(userDto); + Assertions.assertEquals(1, userDto.getId()); + Assertions.assertEquals("new_user", userDto.getName()); + Assertions.assertEquals("new_user_email@example.com", userDto.getEmail()); + } + + @Test + void updateUserWithWrongUserIdTest() { + updateUserDto = new UpdateUserDto("Tom", "tom@example.com"); + NotFoundException e = assertThrows(NotFoundException.class, + () -> userService.update(1000L, updateUserDto) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь с id = 1000 не найден"); + + } + + + @Test + void getUserByIdTest() { + UserDto userDto = userService.getById(1); + + Assertions.assertNotNull(userDto); + Assertions.assertEquals("new_user", userDto.getName()); + Assertions.assertEquals("new_user@example.com", userDto.getEmail()); + + } + + @Test + void getUserByWrongId() { + NotFoundException e = assertThrows(NotFoundException.class, + () -> userService.getById(1000L) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь с id = 1000 не найден"); + } + + + @Test + void deleteTest() { + userService.deleteUser(1); + + NotFoundException e = assertThrows(NotFoundException.class, + () -> userService.getById(1) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь с id = 1 не найден"); + + } + + @Test + void deleteWrongIdTest() { + + NotFoundException e = assertThrows(NotFoundException.class, + () -> userService.deleteUser(1000) + ); + + Assertions.assertEquals(e.getMessage(), "Пользователь с id = 1000 не найден"); + + } +} \ No newline at end of file diff --git a/server/src/test/resources/data.sql b/server/src/test/resources/data.sql new file mode 100644 index 0000000..8bfb151 --- /dev/null +++ b/server/src/test/resources/data.sql @@ -0,0 +1,42 @@ +INSERT INTO users (name, email) +VALUES ('new_user', 'new_user@example.com'); + +INSERT INTO users (name, email) +VALUES ('booker', 'booker@example.com'); + +INSERT INTO users (name, email) +VALUES ('user_3', 'user_3@example.com'); + +INSERT INTO items (name, description, available, owner_id) +VALUES ('new_item', 'description_new_item', true, 1); + +INSERT INTO items (name, description, available, owner_id) +VALUES ('item_2', 'description_item_2', true, 3); + +INSERT INTO items (name, description, available, owner_id) +VALUES ('item_3', 'description_item_3', true, 3); + +INSERT INTO items (name, description, available, owner_id) +VALUES ('item_4', 'description_item_4', false, 3); + +INSERT INTO bookings (start_time, end_time, item_id, booker_id, status) +VALUES ('2024-06-03 00:00:00', '2024-07-07 00:00:00', 1, 2, 'APPROVED'); + +INSERT INTO bookings (start_time, end_time, item_id, booker_id, status) +VALUES ('2025-02-03 00:00:00', '2025-07-07 00:00:00', 2, 2, 'REJECTED'); + +INSERT INTO bookings (start_time, end_time, item_id, booker_id, status) +VALUES ('2022-05-01 00:00:00', '2022-07-07 00:00:00', 3, 2, 'APPROVED'); + +INSERT INTO bookings (start_time, end_time, item_id, booker_id, status) +VALUES ('2025-07-07 00:00:00', '2025-07-08 00:00:00', 3, 1, 'WAITING'); + +--INSERT INTO bookings (start_time, end_time, item_id, booker_id, status) +--VALUES ('2022-05-01 00:00:00', '2022-06-07 00:00:00', 3, 2, 'APPROVED'); + + +INSERT INTO comments(item_id, author_id, text,created) +VALUES (1, 2, 'comment text','2025-02-07 00:00:00'); + +INSERT INTO requests(description, requestor_id, created) +VALUES ('request_description', 1, '2025-02-07 00:00:00'); \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/booking/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/BookingRepository.java deleted file mode 100644 index 2bf7bd5..0000000 --- a/src/main/java/ru/practicum/shareit/booking/BookingRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.practicum.shareit.booking; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -public interface BookingRepository extends JpaRepository { - Page findByBooker_Id(long bookerId, Pageable pageable); - - Page findByItemOwner_Id(long ownerId, Pageable pageable); - - @Query("SELECT b FROM Booking b " + - " WHERE b.booker.id = :bookerId " + - " AND b.start <= :now " + - " AND b.end >= :now " + - " AND b.status = ru.practicum.shareit.booking.BookingStatus.APPROVED") - Page findCurrentByBooker(@Param("bookerId") long bookerId, @Param("now") LocalDateTime now, Pageable pageable); - - @Query("SELECT b FROM Booking b " + - " WHERE b.item.owner.id = :ownerId " + - " AND b.start <= :now " + - " AND b.end >= :now " + - " AND b.status = ru.practicum.shareit.booking.BookingStatus.APPROVED") - Page findCurrentByOwner(@Param("ownerId") long ownerId, @Param("now") LocalDateTime now, Pageable pageable); - - Page findByBooker_IdAndEndBefore(long bookerId, LocalDateTime now, Pageable pageable); - - Page findByItemOwner_IdAndEndBefore(long ownerId, LocalDateTime now, Pageable pageable); - - Page findByBooker_IdAndStartAfter(long bookerId, LocalDateTime now, Pageable pageable); - - Page findByItemOwner_IdAndStartAfter(long ownerId, LocalDateTime now, Pageable pageable); - - Page findByBooker_IdAndStatus(long bookerId, BookingStatus status, Pageable pageable); - - Page findByItemOwner_IdAndStatus(long ownerId, BookingStatus status, Pageable pageable); - - List findByItem_idAndStatus(long itemId, BookingStatus status); - - Optional findByItem_idAndBooker_id(long itemId, long bookerId); -} diff --git a/src/main/java/ru/practicum/shareit/exception/ConflictException.java b/src/main/java/ru/practicum/shareit/exception/ConflictException.java deleted file mode 100644 index 7885123..0000000 --- a/src/main/java/ru/practicum/shareit/exception/ConflictException.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.exception; - -public class ConflictException extends RuntimeException { - public ConflictException(String message) { - super(message); - } -} diff --git a/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java b/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java deleted file mode 100644 index dbef4b4..0000000 --- a/src/main/java/ru/practicum/shareit/exception/NoDataFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -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/exception/ValidationException.java b/src/main/java/ru/practicum/shareit/exception/ValidationException.java deleted file mode 100644 index 59043da..0000000 --- a/src/main/java/ru/practicum/shareit/exception/ValidationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.exception; - -public class ValidationException extends RuntimeException { - public ValidationException(String message) { - super(message); - } -} diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/ItemRequest.java deleted file mode 100644 index f90c328..0000000 --- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -package ru.practicum.shareit.request; - -import jakarta.persistence.*; -import jakarta.validation.constraints.NotBlank; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import ru.practicum.shareit.user.User; - - -/** - * TODO Sprint add-item-requests. - */ - -@Entity -@Table(name = "request") -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ItemRequest { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - long id; - @Column(name = "description", nullable = false) - @NotBlank - String description; - @ManyToOne - @JoinColumn(name = "requestor_id") - User requestor; - - -} diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequestController.java b/src/main/java/ru/practicum/shareit/request/ItemRequestController.java deleted file mode 100644 index 064e2e9..0000000 --- a/src/main/java/ru/practicum/shareit/request/ItemRequestController.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.practicum.shareit.request; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * TODO Sprint add-item-requests. - */ -@RestController -@RequestMapping(path = "/requests") -public class ItemRequestController { -}