Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
38dd679
Выполнение 16 спринта.
SergikF Apr 26, 2025
fe2cbe3
Выполнение 16 спринта.
SergikF Apr 26, 2025
50aeb40
Выполнение 16 спринта.
SergikF Apr 26, 2025
9d8d0ed
Revert "Выполнение 16 спринта."
SergikF Apr 26, 2025
7289d4d
Revert "Выполнение 16 спринта."
SergikF Apr 26, 2025
209dd47
Revert "Выполнение 16 спринта."
SergikF Apr 26, 2025
c223333
Выполнение 16 спринта.
SergikF Apr 26, 2025
4973f4c
Выполнение 16 спринта.
SergikF Apr 26, 2025
e4004bb
Выполнение 16 спринта.
SergikF Apr 26, 2025
b1631e9
Выполнение 16 спринта.
SergikF Apr 26, 2025
4ad323c
Выполнение 16 спринта.
SergikF Apr 26, 2025
62ccf08
Выполнение 16 спринта.
SergikF Apr 26, 2025
d3061bf
Выполнение 16 спринта.
SergikF Apr 26, 2025
b651afc
Выполнение 16 спринта.
SergikF Apr 26, 2025
570a225
Выполнение 16 спринта.
SergikF Apr 26, 2025
6468724
Выполнение 16 спринта.
SergikF Apr 26, 2025
e643020
Выполнение 16 спринта.
SergikF Apr 26, 2025
913a4c5
Выполнение 16 спринта.
SergikF Apr 26, 2025
447c4bf
Выполнение 16 спринта.
SergikF Apr 26, 2025
0c1f1a9
Выполнение 16 спринта.
SergikF Apr 26, 2025
c2f14e8
Выполнение 16 спринта.
SergikF Apr 26, 2025
c7b025b
Выполнение 16 спринта.
SergikF Apr 26, 2025
07654c0
Выполнение 16 спринта.
SergikF Apr 27, 2025
c0524c4
Выполнение 16 спринта.
SergikF Apr 27, 2025
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
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
_java-shareit_
# Шеринг вещей
### Согласно задания спринта № 14 (add-controllers)
### Согласно задания спринта № 16 ( add-item-requests-and-gateway )
## выполнено Филипповских Сергеем
_**Когорта-53**_


_**Для проверки выполнения 14 спринта использовался postman:
[postman_for_shareit_14.json](/postman_for_shareit_14.json)**_
_**Для проверки выполнения 16 спринта использовался postman:
[postman_for_shareit_16.json](/postman_for_shareit_16.json)**_


![](/er_diagram_shareit.png)

39 changes: 39 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions gateway/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
70 changes: 70 additions & 0 deletions gateway/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.practicum</groupId>
<artifactId>shareit</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>shareit-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>

<name>ShareIt Gateway</name>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<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>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
12 changes: 12 additions & 0 deletions gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.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);
}

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

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.exception.ValidationException;

import java.util.Map;

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

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

public ResponseEntity<Object> addBooking(Long userId, BookingDtoInput requestDto) {
if (requestDto.getStart().equals(requestDto.getEnd())) {
throw new ValidationException("Начало и окончание бронирования не может быть одним и тем же моментом.");
}
if (requestDto.getEnd().isBefore(requestDto.getStart())) {
throw new ValidationException("Окончание бронирования не может быть раньше его начала.");
}
return post("", userId, requestDto);
}

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

public ResponseEntity<Object> getWithStatusById(Long bookingId, Long userId) {
return get("/" + bookingId, userId);
}

public ResponseEntity<Object> getByUserId(Long userId, BookingState state) {
return get("?state=" + state, userId);
}

public ResponseEntity<Object> getByOwnerId(Long userId, BookingState state) {
return get("/owner?state=" + state, userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ru.practicum.shareit.booking;

import jakarta.validation.Valid;
import jakarta.validation.ValidationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping(path = "/bookings")
@RequiredArgsConstructor
@Slf4j
@Validated
public class BookingController {

private final BookingClient bookingClient;

/**
* Создает бронирование.
*
* @param bookerId идентификатор пользователя, создающего бронирование
* @param bookingDto данные бронирования
* @return ResponseEntity с объектом, представляющим результат создания бронирования
*/
@PostMapping
public ResponseEntity<Object> addBooking(@RequestHeader("X-Sharer-User-Id") Long bookerId,
@Valid @RequestBody BookingDtoInput bookingDto) {
log.info("Создано бронирование {}, пользователем {}", bookingDto, bookerId);
return bookingClient.addBooking(bookerId, bookingDto);
}

/**
* Обновляет бронирование владельцем.
*
* @param ownerId идентификатор владельца бронирования
* @param bookingId идентификатор бронирования
* @param approved флаг, указывающий, одобрено ли бронирование
* @return ResponseEntity с объектом, представляющим результат обновления бронирования
*/
@PatchMapping("/{bookingId}")
public ResponseEntity<Object> updateByOwner(@RequestHeader("X-Sharer-User-Id") Long ownerId,
@PathVariable Long bookingId,
@RequestParam Boolean approved) {
log.info("Обновление бронирования {}, владельцем {}, в состояние {}", bookingId, ownerId, approved);
return bookingClient.updateByOwner(ownerId, bookingId, approved);
}

/**
* Получает данные о бронировании по его идентификатору.
*
* @param userId идентификатор пользователя, запрашивающего данные о бронировании
* @param bookingId идентификатор бронирования
* @return ResponseEntity с объектом, представляющим результат получения данных о бронировании
*/
@GetMapping("/{bookingId}")
public ResponseEntity<Object> getWithStatusById(@RequestHeader("X-Sharer-User-Id") Long userId,
@PathVariable Long bookingId) {
log.info("Получение данных о бронировании {}, пользователем {}", bookingId, userId);
return bookingClient.getWithStatusById(bookingId, userId);
}

/**
* Получает все бронирования пользователя по его идентификатору и состоянию.
*
* @param userId идентификатор пользователя, запрашивающего данные о бронировании
* @param stateParam состояние бронирования
* @return ResponseEntity с объектом, представляющим результат получения данных о бронировании
*/
@GetMapping
public ResponseEntity<Object> getByUserId(@RequestHeader("X-Sharer-User-Id") Long userId,
@RequestParam(value = "state",
defaultValue = "ALL", required = false) String stateParam) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() ->
new ValidationException("Неизвестное состояние бронирования: " + stateParam));
log.info("Получение всех бронирований пользователя{}, в состоянии {}", userId, state);
return bookingClient.getByUserId(userId, state);
}

/**
* Получает все забронированные вещи пользователя по его идентификатору и состоянию.
*
* @param userId идентификатор пользователя, запрашивающего данные о бронировании
* @param stateParam состояние бронирования
* @return ResponseEntity с объектом, представляющим результат получения данных о бронировании
*/
@GetMapping("/owner")
public ResponseEntity<Object> getByOwnerId(@RequestHeader("X-Sharer-User-Id") Long userId,
@RequestParam(value = "state", defaultValue = "ALL",
required = false) String stateParam) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() ->
new ValidationException("Неизвестное состояние бронирования: " + stateParam));
log.info("Получение всех забронированных вещей пользователя{}, в состоянии {}", userId, state);
return bookingClient.getByOwnerId(userId, state);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.practicum.shareit.booking;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.FutureOrPresent;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BookingDtoInput {

@NotNull(message = "При создании брони должна быть информация о вещи.")
private Long itemId;

@FutureOrPresent(message = "Дата начала бронирования не должна быть в прошлом")
@NotNull(message = "Дата бронирования не должна быть пустой")
private LocalDateTime start;

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

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

import java.util.Optional;

public enum BookingState {
ALL, CURRENT, PAST, FUTURE, WAITING, REJECTED;

public static Optional<ru.practicum.shareit.booking.BookingState> from(String stringState) {
for (ru.practicum.shareit.booking.BookingState state : values()) {
if (state.name().equalsIgnoreCase(stringState)) {
return Optional.of(state);
}
}
return Optional.empty();
}
}
Loading