Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
81d9e03
Добавляем запрос вещи
AleksOBM Apr 5, 2026
170b162
Выделяем валидацию в отдельный сервис
AleksOBM Apr 7, 2026
97dd6d1
Тесты Postman пройдены
AleksOBM Apr 10, 2026
6b87c73
Исправлена логика поиска прошлых и будущих дат бронирования
AleksOBM Apr 12, 2026
b5200d5
Исправлена логика поиска вещи по названию и описанию
AleksOBM Apr 13, 2026
b5f889d
Исправлен баг поиска бронирований пользователя
AleksOBM Apr 13, 2026
06ed277
Небольшая корректировка поиска бронирований пользователя
AleksOBM Apr 13, 2026
b4a4588
QueryDsl перенесен в отдельный репозиторий
AleksOBM Apr 13, 2026
3120077
Исправлен баг отсутствия сохранения при подтверждении брони
AleksOBM Apr 14, 2026
4003fd8
Небольшое упрощение StateOfBooking больше не возвращает null
AleksOBM Apr 15, 2026
e2a38c1
Все мапперы теперь компоненты
AleksOBM Apr 15, 2026
00814e2
Очистка ErrorHandler от лишнего
AleksOBM Apr 15, 2026
38731da
Удаление checkstyle.xml из индкеса
AleksOBM Apr 15, 2026
9de2643
Замена checkstyle.xml
AleksOBM Apr 15, 2026
0b8778f
Удаление лишних файлов checkstyle.xml
AleksOBM Apr 15, 2026
d7b1dbd
Удаление еще файлов
AleksOBM Apr 15, 2026
d29946e
Попытка добавить файлы обратно
AleksOBM Apr 16, 2026
565f163
Добавление еще файлов
AleksOBM Apr 16, 2026
f27c159
Еще одна попытка
AleksOBM Apr 16, 2026
df4b682
Убрал чекстайл из корня и разложил по проектам
AleksOBM Apr 16, 2026
748f6be
Rerun CI
AleksOBM Apr 16, 2026
db6c5b5
Очередная перегруппировка чекстайла
AleksOBM Apr 16, 2026
12a5377
Добавить тесты и вернуть чекстайл из первого коммита
AleksOBM Apr 16, 2026
a746892
Попытка исправления ошибки Caused by: java.net.ConnectException: Conn…
AleksOBM Apr 16, 2026
855ad80
Добавить @Transactional в DataJpa тесты
AleksOBM Apr 16, 2026
c556881
Переделать equals и hashcode
AleksOBM Apr 17, 2026
88fc513
Корректировка тестов
AleksOBM Apr 17, 2026
9d55a46
С-16 Р-2
AleksOBM Apr 17, 2026
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
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
14 changes: 14 additions & 0 deletions .run/ShareItGateway.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ShareItGateway" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="ru.practicum.shareit.ShareItGateway" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="ru.practicum.shareit.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
14 changes: 14 additions & 0 deletions .run/ShareItServer.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ShareItServer" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="ru.practicum.shareit.ShareItServer" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="ru.practicum.shareit.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
# java-shareit

### Database map
![SchemaDatabase.png](SchemaDatabase.png)
Binary file removed SchemaDatabase.png
Binary file not shown.
16 changes: 0 additions & 16 deletions compose.yaml

This file was deleted.

47 changes: 47 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
services:
gateway:
build:
context: ./gateway
dockerfile: Dockerfile
image: shareit-gateway
container_name: shareit-gateway
ports:
- "8080:8080"
depends_on:
- server
environment:
# - TZ=Europe/Moscow
- SHAREIT_SERVER_URL=http://server:9090

server:
build:
context: ./server
dockerfile: Dockerfile
image: shareit-server
container_name: shareit-server
ports:
- "9090:9090"
depends_on:
- db
environment:
# - TZ=Europe/Moscow
- 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:
# - TZ=Europe/Moscow
- POSTGRES_DB=shareit
- POSTGRES_USER=shareit
- POSTGRES_PASSWORD=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"]
65 changes: 65 additions & 0 deletions gateway/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?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 http://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>

<name>ShareIt Gateway</name>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>
</dependencies>

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

</project>
11 changes: 11 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,11 @@
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,66 @@
package ru.practicum.shareit.booking;

import jakarta.validation.ValidationException;
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.booking.dto.BookingState;
import ru.practicum.shareit.booking.dto.GBookingDto;
import ru.practicum.shareit.client.BaseClient;

import java.time.LocalDateTime;
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> getBookings(long userId, BookingState state, Integer from, Integer size) {
Map<String, Object> parameters = Map.of(
"state", state.name(),
"from", from,
"size", size
);
return get("?state={state}&from={from}&size={size}", userId, parameters);
}

public ResponseEntity<Object> bookItem(long userId, GBookingDto requestDto) {
LocalDateTime start = requestDto.getStart();
LocalDateTime end = requestDto.getEnd();
if (start.isAfter(end) || start.isEqual(end)) {
throw new ValidationException("Дата начала бронирования должна быть раньше даты окончания");
}
return post("", userId, requestDto);
}

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

public ResponseEntity<Object> getBookingsByOwner(long userId, BookingState state, Integer from, Integer size) {
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> approveBooking(long userId, long bookingId, boolean approved) {
return patch("/" + bookingId + "?approved=" + approved, userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ru.practicum.shareit.booking;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.PositiveOrZero;
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.*;
import ru.practicum.shareit.booking.dto.BookingState;
import ru.practicum.shareit.booking.dto.GBookingDto;
import ru.practicum.shareit.util.Marker;

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

@GetMapping
public ResponseEntity<Object> getBookingsByBooker(
@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);
}

@GetMapping("/owner")
public ResponseEntity<Object> getAllBookingsByOwner(
@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 by Owner with state {}, userId={}, from={}, size={}", stateParam, userId, from, size);
return bookingClient.getBookingsByOwner(userId, state, from, size);
}

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

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

@PatchMapping("/{bookingId}")
public ResponseEntity<Object> approveBooking(@RequestHeader("X-Sharer-User-Id") long userId,
@PathVariable long bookingId,
@RequestParam boolean approved) {
log.info("Approve booking {}, userId={}", bookingId, userId);
return bookingClient.approveBooking(userId, bookingId, approved);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ru.practicum.shareit.booking.dto;

import java.util.Optional;

public enum BookingState {
// Все
ALL,
// Текущие
CURRENT,
// Будущие
FUTURE,
// Завершенные
PAST,
// Отклоненные
REJECTED,
// Ожидающие подтверждения
WAITING;

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