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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .run/ShareItGateway.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<module name="shareit-gateway" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="ru.practicum.shareit.*" />
<option name="PATTERN" value="ru.practicum.shareit.dto.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
Expand Down
2 changes: 1 addition & 1 deletion .run/ShareItServer.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<module name="shareit-server" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="ru.practicum.shareit.*" />
<option name="PATTERN" value="ru.practicum.shareit.dto.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
Expand Down
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# java-shareit
Template repository for Shareit project.
[![Java Version](https://img.shields.io/badge/Java-17-blue.svg)](https://openjdk.org/)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1.5-brightgreen.svg)](https://spring.io/projects/spring-boot)

Сервис для шеринга вещей позволяет пользователям брать предметы в аренду и предлагать свои вещи в аренду другим.

### Базовый URL
`http://localhost:8080`

### Пользователи
| Метод | Путь | Описание |
|-------|------|----------|
| POST | `/users` | Создание нового пользователя |
| GET | `/users/{userId}` | Получение информации о пользователе |
| PATCH | `/users/{userId}` | Обновление данных пользователя |
| GET | `/users` | Получение списка всех пользователей |

### Вещи
| Метод | Путь | Описание | Требуемые заголовки |
|-------|-----------------------------|-----------------------------------|---------------------|
| POST | `/items` | Добавление новой вещи | `X-Sharer-User-Id` |
| POST | `/items/{itemId}/comment` | Создание комменатрия | `X-Sharer-User-Id` |
| PATCH | `/items/{itemId}` | Обновление вещи | `X-Sharer-User-Id` |
| GET | `/items/{itemId}` | Получение информации о вещи | - |
| GET | `/items` | Получение всех вещей пользователя | `X-Sharer-User-Id` |
| GET | `/items/search?text={text}` | Поиск вещей | - |

### Бронь
| Метод | Путь | Описание | Требуемые заголовки |
|-------|---------------------------------|-----------------------------------------------|---------------------|
| POST | `/bookings` | Добавление новой брони | `X-Sharer-User-Id` |
| PATCH | `/bookings/{bookingId}?approved` | Изменение состояние брони | `X-Sharer-User-Id` |
| PATCH | `/bookings/{bookingId}/canceled` | Отмена брони | `X-Sharer-User-Id` |
| GET | `/bookings/{bookingId}` | Получение информации о брони | `X-Sharer-User-Id` |
| GET | `/bookings?state={state}` | Получение списка брони в определенном статусе | `X-Sharer-User-Id` |
| GET | `/bookings/owner?state={state}` | Получение списка броней всех вещей пользователя| `X-Sharer-User-Id` |

![img.png](img.png)
5 changes: 0 additions & 5 deletions gateway/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.DefaultUriBuilderFactory;

import ru.practicum.shareit.booking.dto.BookItemRequestDto;
Expand Down Expand Up @@ -37,6 +38,16 @@ public ResponseEntity<Object> getBookings(long userId, BookingState state, Integ
return get("?state={state}&from={from}&size={size}", userId, parameters);
}

@GetMapping("/owner")
public ResponseEntity<Object> getBookingsByState(BookingState state, Integer from, Integer size, Long userId) {
Map<String, Object> parameters = Map.of(
"state", state.name(),
"from", from,
"size", size
);
return get("/owner?state={state}&from={from}&size={size}", userId, parameters);
}


public ResponseEntity<Object> bookItem(long userId, BookItemRequestDto requestDto) {
return post("", userId, requestDto);
Expand All @@ -45,4 +56,16 @@ public ResponseEntity<Object> bookItem(long userId, BookItemRequestDto requestDt
public ResponseEntity<Object> getBooking(long userId, Long bookingId) {
return get("/" + bookingId, userId);
}

//Patch /bookings/bookingId?approved
public ResponseEntity<Object> approveBooking(Long bookingId, Boolean approved, Long userId) {
Map<String, Object> parameters = Map.of(
"approved", approved
);
return patch("/" + bookingId + "?approved={approved}", userId, parameters, null);
}

public ResponseEntity<Object> canceledBooking(Long bookingId, Long userId) {
return patch("/" + bookingId + "/canceled", userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
Expand All @@ -19,37 +13,68 @@
import ru.practicum.shareit.booking.dto.BookItemRequestDto;
import ru.practicum.shareit.booking.dto.BookingState;

import java.util.List;


@Controller
@RequestMapping(path = "/bookings")
@RequiredArgsConstructor
@Slf4j
@Validated
public class BookingController {
private final BookingClient bookingClient;

@GetMapping
public ResponseEntity<Object> getBookings(@RequestHeader("X-Sharer-User-Id") long userId,
@RequestParam(name = "state", defaultValue = "all") String stateParam,
@PositiveOrZero @RequestParam(name = "from", defaultValue = "0") Integer from,
@Positive @RequestParam(name = "size", defaultValue = "10") Integer size) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() -> new IllegalArgumentException("Unknown state: " + stateParam));
log.info("Get booking with state {}, userId={}, from={}, size={}", stateParam, userId, from, size);
return bookingClient.getBookings(userId, state, from, size);
}

@PostMapping
public ResponseEntity<Object> bookItem(@RequestHeader("X-Sharer-User-Id") long userId,
@RequestBody @Valid BookItemRequestDto requestDto) {
log.info("Creating booking {}, userId={}", requestDto, userId);
return bookingClient.bookItem(userId, requestDto);
}

@GetMapping("/{bookingId}")
public ResponseEntity<Object> getBooking(@RequestHeader("X-Sharer-User-Id") long userId,
@PathVariable Long bookingId) {
log.info("Get booking {}, userId={}", bookingId, userId);
return bookingClient.getBooking(userId, bookingId);
}
private final BookingClient bookingClient;

@GetMapping
public ResponseEntity<Object> getBookings(@RequestHeader("X-Sharer-User-Id") @Positive long userId,
@RequestParam(name = "state", defaultValue = "all") String stateParam,
@PositiveOrZero @RequestParam(name = "from", defaultValue = "0") Integer from,
@Positive @RequestParam(name = "size", defaultValue = "10") Integer size) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() -> new IllegalArgumentException("Unknown state: " + stateParam));
log.info("Get booking with state {}, userId={}, from={}, size={}", stateParam, userId, from, size);
return bookingClient.getBookings(userId, state, from, size);
}

@GetMapping("/owner")
public ResponseEntity<Object> getBookingsByState(@RequestParam(name = "state", defaultValue = "all")
String stateParam,
@PositiveOrZero @RequestParam(name = "from", defaultValue = "0")
Integer from,
@Positive @RequestParam(name = "size", defaultValue = "10")
Integer size,
@RequestHeader("X-Sharer-User-Id") @Positive Long userId) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() -> new IllegalArgumentException("Unknown state: " + stateParam));
log.info("Get booking owner with state {}, userId={}, from={}, size={}", stateParam, userId, from, size);
return bookingClient.getBookingsByState(state, from, size, userId);
}

@GetMapping("/{bookingId}")
public ResponseEntity<Object> getBooking(@RequestHeader("X-Sharer-User-Id") long userId,
@PathVariable Long bookingId) {
log.info("Get booking {}, userId={}", bookingId, userId);
return bookingClient.getBooking(userId, bookingId);
}

@PostMapping
public ResponseEntity<Object> createBooking(@RequestHeader("X-Sharer-User-Id") long userId,
@RequestBody @Valid BookItemRequestDto requestDto) {
log.info("Creating booking {}, userId={}", requestDto, userId);
return bookingClient.bookItem(userId, requestDto);
}

@PatchMapping("/{bookingId}")
public ResponseEntity<Object> approveBooking(@PathVariable("bookingId") Long bookingId,
@RequestParam("approved") Boolean approved,
@RequestHeader("X-Sharer-User-Id") Long userId) {
log.info("Update booking {}, userId={} on approve = {}", bookingId, userId, approved);
return bookingClient.approveBooking(bookingId, approved, userId);
}

@PatchMapping("/{bookingId}/canceled")
public ResponseEntity<Object> canceledBooking(@PathVariable("bookingId") Long bookingId,
@RequestHeader("X-Sharer-User-Id") Long userId) {
log.info("Cancel booking {}, userId={}", bookingId, userId);
return bookingClient.canceledBooking(bookingId, userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
@NoArgsConstructor
@AllArgsConstructor
public class BookItemRequestDto {
private long itemId;
private Long itemId;

@FutureOrPresent
private LocalDateTime start;

@Future
private LocalDateTime end;
}
52 changes: 52 additions & 0 deletions gateway/src/main/java/ru/practicum/shareit/item/ItemClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ru.practicum.shareit.item;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.util.DefaultUriBuilderFactory;
import ru.practicum.shareit.client.BaseClient;
import ru.practicum.shareit.item.dto.ItemDto;
import ru.practicum.shareit.item.dto.RequestCommentDto;

import java.util.Map;

@Service
public class ItemClient extends BaseClient {
private static final String API_PREFIX = "/items";

@Autowired
public ItemClient(@Value("${shareit-server.url}") String serverUrl, RestTemplateBuilder builder) {
super(builder
.uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX))
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory())
.build());
}

public ResponseEntity<Object> createItem(Long userId, ItemDto item) {
return post("", userId, item);
}

public ResponseEntity<Object> getItemById(Long itemId) {
return get("/" + itemId);
}

public ResponseEntity<Object> getUserItems(Long userId) {
return get("", userId);
}

public ResponseEntity<Object> updateItem(Long userId, Long itemId, ItemDto item) {
return put("/" + itemId, userId, item);
}

public ResponseEntity<Object> createdComment(RequestCommentDto comment, long userId, long itemId) {
return post("/" + itemId + "/comment", userId, comment);
}

public ResponseEntity<Object> searchItems(Long userId, String text) {
Map<String, Object> params = Map.of("text", text);
return get("/search?text={text}", userId, params);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ru.practicum.shareit.item;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.item.dto.ItemDto;
import ru.practicum.shareit.item.dto.RequestCommentDto;

@RestController
@RequestMapping("/items")
@RequiredArgsConstructor
@Validated
public class ItemController {
private final ItemClient client;

@PostMapping
public ResponseEntity<Object> createItem(@RequestHeader("X-Sharer-User-Id") @Positive Long userId,
@RequestBody @Valid ItemDto item) {
return client.createItem(userId, item);
}

@GetMapping("/{itemId}")
public ResponseEntity<Object> getItem(@PathVariable(name = "itemId") @Positive Long itemId) {
return client.getItemById(itemId);
}

@PatchMapping("/{itemId}")
public ResponseEntity<Object> updateItem(@RequestHeader("X-Sharer-User-Id") @Positive Long userId,
@PathVariable(name = "itemId") @Positive Long itemId,
@RequestBody ItemDto item) {
return client.updateItem(userId, itemId, item);
}

@GetMapping
public ResponseEntity<Object> getUserItems(@RequestHeader("X-Sharer-User-Id") @Positive Long userId) {
return client.getUserItems(userId);
}

@GetMapping("/search")
public ResponseEntity<Object> searchItems(@RequestHeader("X-Sharer-User-Id") @Positive Long userId,
@RequestParam("text") @NotBlank String text) {
return client.searchItems(userId, text);
}

@PostMapping("/{itemId}/comment")
public ResponseEntity<Object> createdComment(@RequestHeader("X-Sharer-User-Id") @Positive Long userId,
@PathVariable(name = "itemId") @Positive Long itemId,
@RequestBody @Valid RequestCommentDto comment) {
return client.createdComment(comment, userId, itemId);
}
}
21 changes: 21 additions & 0 deletions gateway/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ru.practicum.shareit.item.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class ItemDto {
@NotBlank
private String name;

@NotBlank
private String description;

@NotNull
private Boolean available;

private Long requestId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ru.practicum.shareit.item.dto;

import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RequestCommentDto {

@NotBlank
private String text;
}
Loading
Loading