From e5014ddd457c3d473b20e2304d501c4433ccea77 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sat, 7 Mar 2026 15:26:38 +0300 Subject: [PATCH 01/11] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=91=D0=94=20=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BD=D1=8B=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D0=B4=20=D1=81=D1=83=D1=89=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D0=B4=D0=BB=D1=8F=20ORM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 13 +++++++ .../shareit/booking/model/Booking.java | 25 +++++++++++- .../practicum/shareit/item/model/Comment.java | 36 +++++++++++++++++ .../ru/practicum/shareit/item/model/Item.java | 20 +++++++++- .../ru/practicum/shareit/user/model/User.java | 18 +++++++-- src/main/resources/application.properties | 8 ++-- src/main/resources/schema.sql | 39 +++++++++++++++++++ 7 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 src/main/java/ru/practicum/shareit/item/model/Comment.java create mode 100644 src/main/resources/schema.sql diff --git a/pom.xml b/pom.xml index 2db888c..1b18148 100644 --- a/pom.xml +++ b/pom.xml @@ -51,15 +51,28 @@ h2 test + org.springframework.boot spring-boot-starter-test test + org.springframework.boot spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.postgresql + postgresql + runtime + diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java index 090f6c9..71ccfc1 100644 --- a/src/main/java/ru/practicum/shareit/booking/model/Booking.java +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -1,7 +1,9 @@ package ru.practicum.shareit.booking.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import ru.practicum.shareit.item.model.Item; import ru.practicum.shareit.user.model.User; @@ -10,13 +12,32 @@ /** * TODO Sprint add-bookings. */ -@Data +@Entity @AllArgsConstructor +@Setter +@Getter +@Table(name = "bookings") public class Booking { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "start_date") private LocalDate start; + + @Column(name = "end_date") private LocalDate end; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") private Item item; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "booker_id") private User booker; + + @Column(name = "status") + @Enumerated(EnumType.STRING) private BookingStatus status; } diff --git a/src/main/java/ru/practicum/shareit/item/model/Comment.java b/src/main/java/ru/practicum/shareit/item/model/Comment.java new file mode 100644 index 0000000..24f0800 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/model/Comment.java @@ -0,0 +1,36 @@ +package ru.practicum.shareit.item.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.user.model.User; +import java.time.LocalDateTime; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "comments") +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "item_id") + private Item item; + + @ManyToOne + @JoinColumn(name = "author_id") + private User author; + + @Column(name = "content") + private String text; + + @Column(name = "created_at") + private LocalDateTime created; +} diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index 68193d0..aa00682 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -1,19 +1,35 @@ package ru.practicum.shareit.item.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; /** * TODO Sprint add-controllers. */ -@Data +@Entity @AllArgsConstructor @NoArgsConstructor +@Getter +@Setter +@Table(name = "items") public class Item { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name") private String name; + + @Column(name = "description") private String description; + + @Column(name = "available") private Boolean available; + + @Column(name = "owner_id") private Long ownerId; } diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java index 2db2df6..3844d55 100644 --- a/src/main/java/ru/practicum/shareit/user/model/User.java +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -1,17 +1,27 @@ package ru.practicum.shareit.user.model; -import jakarta.validation.constraints.Email; +import jakarta.persistence.*; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; /** * TODO Sprint add-controllers. */ -@Data +@Entity @AllArgsConstructor +@Getter +@Setter +@Table(name = "users") public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name") private String name; - @Email(message = "Email should be valid") + + @Column(name = "email") private String email; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 51c5180..5e606fb 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,7 +8,7 @@ logging.level.org.springframework.transaction.interceptor=TRACE logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG # TODO Append connection to Postgres DB -#spring.datasource.driverClassName -#spring.datasource.url -#spring.datasource.username -#spring.datasource.password +#spring.datasource.driverClassName=org.postgresql.Driver +#spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit +#spring.datasource.username=ca +#spring.datasource.password=12345678 diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..3d56497 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,39 @@ +CREATE TABLE IF NOT EXISTS users ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name VARCHAR(255) NOT NULL, + email VARCHAR(512) NOT NULL, + CONSTRAINT pk_user PRIMARY KEY (id), + CONSTRAINT UQ_USER_EMAIL UNIQUE (email) +); + +CREATE TABLE IF NOT EXISTS items ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name VARCHAR(255) NOT NULL, + description VARCHAR(255) NOT NULL, + available BOOLEAN NOT NULL, + owner_id BIGINT NOT NULL, + CONSTRAINT pk_item PRIMARY KEY (id), + FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS bookings ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + start_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + end_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + item_id BIGINT NOT NULL, + booker_id BIGINT NOT NULL, + status VARCHAR(255) NOT NULL, + CONSTRAINT pk_booking PRIMARY KEY (id), + FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE, + FOREIGN KEY (booker_id) REFERENCES users(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS comments ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + item_id BIGINT NOT NULL, + author_id BIGINT NOT NULL, + content TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE, + FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE +); \ No newline at end of file From c5639e69bdad077bbb6bbe86d60ea3502c2b57e2 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sat, 7 Mar 2026 19:19:15 +0300 Subject: [PATCH 02/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8=20=D0=B8=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D0=B8=D1=81=D1=8B=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=B8=20=D1=8E=D0=B7?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=B4=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B5=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../booking/dao/BookingRepository.java | 0 .../booking/service/BookingService.java | 0 .../booking/service/BookingServiceImpl.java | 0 .../shareit/item/dao/CommentMapper.java | 0 .../shareit/item/dao/CommentRepository.java | 0 .../shareit/item/dao/InMemoryItemStorage.java | 79 ------------------- .../shareit/item/dao/ItemRepository.java | 0 .../shareit/item/dto/CommentDto.java | 0 .../shareit/user/dao/InMemoryUserStorage.java | 60 -------------- .../shareit/user/dao/UserRepository.java | 0 10 files changed, 139 deletions(-) create mode 100644 src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java create mode 100644 src/main/java/ru/practicum/shareit/booking/service/BookingService.java create mode 100644 src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java create mode 100644 src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java create mode 100644 src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java delete mode 100644 src/main/java/ru/practicum/shareit/item/dao/InMemoryItemStorage.java create mode 100644 src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentDto.java delete mode 100644 src/main/java/ru/practicum/shareit/user/dao/InMemoryUserStorage.java create mode 100644 src/main/java/ru/practicum/shareit/user/dao/UserRepository.java diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/item/dao/InMemoryItemStorage.java b/src/main/java/ru/practicum/shareit/item/dao/InMemoryItemStorage.java deleted file mode 100644 index 4cfb451..0000000 --- a/src/main/java/ru/practicum/shareit/item/dao/InMemoryItemStorage.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.practicum.shareit.item.dao; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; -import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.item.model.Item; - -import java.util.*; - - -@Slf4j -@Repository -@RequiredArgsConstructor -public class InMemoryItemStorage { - private final Map items = new HashMap<>(); - - private Long getNextId() { - long currentMaxId = items.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } - - public Item addItem(Item item) { - item.setId(getNextId()); - items.put(item.getId(), item); - return item; - } - - public Item updateItem(Item newItem) { - Item item = items.get(newItem.getId()); - if (newItem.getName() != null) { - item.setName(newItem.getName()); - } - if (newItem.getDescription() != null) { - item.setDescription(newItem.getDescription()); - } - if (newItem.getAvailable() != null) { - item.setAvailable(newItem.getAvailable()); - } - return item; - } - - public Item getItem(long itemId) { - if (!items.containsKey(itemId)) { - log.warn("Предмет с указанным id " + itemId + " не найден"); - throw new NotFoundException("Предмет с id = " + itemId + " не найден"); - } - return items.get(itemId); - } - - public List getAllOwnerItems(long ownerId) { - List ownerItems = new ArrayList<>(); - for (Item item : items.values()) { - if (item.getOwnerId() == ownerId) { - ownerItems.add(item); - } - } - return ownerItems; - } - - public List getNecessaryItem(String text) { - List necessaryItems = new ArrayList<>(); - if (text == null || text.isBlank()) { - return Collections.emptyList(); - } - text = text.toLowerCase(Locale.ROOT); - for (Item item : items.values()) { - if (item.getAvailable() && item.getName().toLowerCase(Locale.ROOT).contains(text) - || item.getDescription().toLowerCase(Locale.ROOT).contains(text)) { - necessaryItems.add(item); - } - } - return necessaryItems; - } -} diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/ru/practicum/shareit/user/dao/InMemoryUserStorage.java b/src/main/java/ru/practicum/shareit/user/dao/InMemoryUserStorage.java deleted file mode 100644 index 18c3226..0000000 --- a/src/main/java/ru/practicum/shareit/user/dao/InMemoryUserStorage.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.practicum.shareit.user.dao; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; -import ru.practicum.shareit.user.model.User; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Slf4j -@Repository -@RequiredArgsConstructor -public class InMemoryUserStorage { - private final Map users = new HashMap<>(); - - private Long getNextId() { - long currentMaxId = users.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } - - public User addUser(User user) { - user.setId(getNextId()); - users.put(user.getId(), user); - return user; - } - - public User updateUser(User newUser) { - User user = users.get(newUser.getId()); - if (newUser.getName() != null) { - user.setName(newUser.getName()); - } - if (newUser.getEmail() != null) { - user.setEmail(newUser.getEmail()); - } - return user; - } - - public List getAllUsers() { - return new ArrayList<>(users.values()); - } - - public User getUser(Long id) { - return users.get(id); - } - - public void deleteUser(Long id) { - users.remove(id); - } - - public Map getUsers() { - return users; - } -} diff --git a/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java b/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java new file mode 100644 index 0000000..e69de29 From 2a22f1950c92307f9d61de6c38e976c33377bb59 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sat, 7 Mar 2026 19:19:27 +0300 Subject: [PATCH 03/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8=20=D0=B8=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D0=B8=D1=81=D1=8B=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=B8=20=D1=8E=D0=B7?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=B4=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B5=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../booking/controller/BookingController.java | 55 ++++++++++++++++++- .../booking/dao/BookingRepository.java | 10 ++++ .../booking/service/BookingService.java | 19 +++++++ .../booking/service/BookingServiceImpl.java | 35 ++++++++++++ .../shareit/item/dao/CommentMapper.java | 17 ++++++ .../shareit/item/dao/CommentRepository.java | 16 ++++++ .../shareit/item/dao/ItemMapper.java | 14 ++--- .../shareit/item/dao/ItemRepository.java | 24 ++++++++ .../shareit/item/dto/CommentDto.java | 14 +++++ .../practicum/shareit/item/dto/ItemDto.java | 8 +++ .../ru/practicum/shareit/item/model/Item.java | 2 +- .../shareit/item/service/ItemService.java | 3 + .../shareit/item/service/ItemServiceImpl.java | 43 +++++++++++---- .../user/controller/UserController.java | 3 +- .../shareit/user/dao/UserRepository.java | 9 +++ .../practicum/shareit/user/dto/UserDto.java | 10 +++- .../shareit/user/service/UserService.java | 3 +- .../shareit/user/service/UserServiceImpl.java | 23 ++++---- 18 files changed, 273 insertions(+), 35 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java index 427a4b6..8cd08a3 100644 --- a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java @@ -1,12 +1,63 @@ package ru.practicum.shareit.booking.controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.booking.service.BookingService; + +import java.util.Collection; /** * TODO Sprint add-bookings. */ @RestController @RequestMapping(path = "/bookings") +@RequiredArgsConstructor public class BookingController { + + private final BookingService bookingService; + + @PostMapping + public Booking createBooking(@RequestHeader("X-Sharer-User-Id") @Positive Long userId, + @Valid @RequestBody BookingDto bookingDto) { + + return bookingService.createBooking(userId, bookingDto); + } + + @PatchMapping("/{bookingId}") + public Booking updateBookingStatus( + @RequestHeader("X-Sharer-User-Id") @Positive Long userId, + @PathVariable @Positive Long bookingId, + @RequestParam Boolean approved) { + + return bookingService.updateBookingStatus(userId, bookingId, approved); + } + + @GetMapping("/{bookingId}") + public Booking getBooking( + @RequestHeader("X-Sharer-User-Id") @Positive Long userId, + @PathVariable @Positive Long bookingId) { + + return bookingService.getBooking(userId, bookingId); + } + + @GetMapping + public Collection findByBookerAndState( + @RequestHeader("X-Sharer-User-Id") @Positive Long bookerId, + @RequestParam BookingStatus state) { + + return bookingService.findByBookerAndState(bookerId, state); + } + + @GetMapping("/owner") + public Collection findByOwnerAndState( + @RequestHeader("X-Sharer-User-Id") @Positive Long ownerId, + @RequestParam BookingStatus state) { + + return bookingService.findByOwnerAndState(ownerId, state); + } } diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java index e69de29..3bd694e 100644 --- a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java +++ b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.booking.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.booking.model.Booking; + +@Repository +public interface BookingRepository extends JpaRepository { + +} diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java index e69de29..6246188 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.booking.service; + +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; + +import java.util.Collection; + +public interface BookingService { + Booking createBooking(Long bookerId, BookingDto bookingDto); + + Booking updateBookingStatus(Long userId, Long bookingId, Boolean approved); + + Booking getBooking(Long userId, Long bookingId); + + Collection findByBookerAndState(Long bookerId, BookingStatus state); + + Collection findByOwnerAndState(Long ownerId, BookingStatus state); +} diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java index e69de29..a63c1d9 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java @@ -0,0 +1,35 @@ +package ru.practicum.shareit.booking.service; + +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; + +import java.util.Collection; +import java.util.List; + +public class BookingServiceImpl implements BookingService{ + @Override + public Booking createBooking(Long bookerId, BookingDto bookingDto) { + return null; + } + + @Override + public Booking updateBookingStatus(Long userId, Long bookingId, Boolean approved) { + return null; + } + + @Override + public Booking getBooking(Long userId, Long bookingId) { + return null; + } + + @Override + public Collection findByBookerAndState(Long bookerId, BookingStatus state) { + return List.of(); + } + + @Override + public Collection findByOwnerAndState(Long ownerId, BookingStatus state) { + return List.of(); + } +} diff --git a/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java index e69de29..f12ff09 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java +++ b/src/main/java/ru/practicum/shareit/item/dao/CommentMapper.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dao; + +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.model.Comment; + +public class CommentMapper { + public static CommentDto toCommentDto(Comment comment) { + CommentDto commentDto = new CommentDto(); + commentDto.setId(comment.getId()); + commentDto.setItemId(comment.getItem().getId()); + commentDto.setAuthorName(comment.getAuthor().getName()); + commentDto.setText(comment.getText()); + commentDto.setCreated(comment.getCreated()); + + return commentDto; + } +} diff --git a/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java index e69de29..1b61de8 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java +++ b/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.item.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.item.model.Comment; + +import java.util.Collection; + +@Repository +public interface CommentRepository extends JpaRepository { + Collection findByItemId(Long itemId); + + @Query("SELECT c FROM Comment c JOIN FETCH c.item WHERE c.item.ownerId = ?1") + Collection findByItemOwnerId(Long ownerId); +} diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/dao/ItemMapper.java index 689a5aa..5829d97 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/dao/ItemMapper.java @@ -7,12 +7,12 @@ @UtilityClass public class ItemMapper { public static ItemDto toItemDto(Item item) { - return new ItemDto( - item.getId(), - item.getName(), - item.getDescription(), - item.getAvailable() - ); + ItemDto itemDto = new ItemDto(); + itemDto.setId(item.getId()); + itemDto.setName(item.getName()); + itemDto.setDescription(item.getDescription()); + itemDto.setAvailable(item.getIsAvailable()); + return itemDto; } public static Item toItem(ItemDto itemDto) { @@ -20,7 +20,7 @@ public static Item toItem(ItemDto itemDto) { item.setId(itemDto.getId()); item.setName(itemDto.getName()); item.setDescription(itemDto.getDescription()); - item.setAvailable(itemDto.getAvailable()); + item.setIsAvailable(itemDto.getAvailable()); return item; } } \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java index e69de29..8d52ba6 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java +++ b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java @@ -0,0 +1,24 @@ +package ru.practicum.shareit.item.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.model.User; + +import java.util.Collection; + +@Repository +public interface ItemRepository extends JpaRepository { + + @Query(""" + SELECT i + FROM Item i + WHERE i.isAvailable = true + AND (LOWER(i.name) LIKE LOWER(%:text%) + OR LOWER(i.description) LIKE LOWER(%:text%)) + """) + Collection searchByNameOrDescription(String text); + + Collection findByOwnerId(Long userId); +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java index e69de29..1a228f2 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java @@ -0,0 +1,14 @@ +package ru.practicum.shareit.item.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class CommentDto { + private Long id; + private Long itemId; + private String authorName; + private String text; + private LocalDateTime created; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java index 4c141ef..f8e2967 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java @@ -4,13 +4,18 @@ import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import ru.practicum.shareit.validation.OnCreate; +import java.time.LocalDateTime; +import java.util.Collection; + /** * TODO Sprint add-controllers. */ @Data @AllArgsConstructor +@NoArgsConstructor public class ItemDto { private Long id; @NotBlank(groups = OnCreate.class, message = "Название предмета должно быть заполнено") @@ -19,4 +24,7 @@ public class ItemDto { private String description; @NotNull(groups = OnCreate.class, message = "Статус должен быть заполнен") private Boolean available; + private LocalDateTime lastBooking; + private LocalDateTime nextBooking; + private Collection comments; } diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index aa00682..c7af228 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -28,7 +28,7 @@ public class Item { private String description; @Column(name = "available") - private Boolean available; + private Boolean isAvailable; @Column(name = "owner_id") private Long ownerId; diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemService.java b/src/main/java/ru/practicum/shareit/item/service/ItemService.java index 5119e06..c06d151 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemService.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java @@ -1,5 +1,6 @@ package ru.practicum.shareit.item.service; +import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; import java.util.Collection; @@ -16,4 +17,6 @@ public interface ItemService { List getAllOwnerItems(long ownerId); Collection getNecessaryItem(String text); + + CommentDto addComment(Long userId, Long itemId, CommentDto commentText); } diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index 762aaee..36d273f 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -3,13 +3,19 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.booking.dao.BookingRepository; import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.item.dao.InMemoryItemStorage; +import ru.practicum.shareit.item.dao.CommentRepository; +import ru.practicum.shareit.item.dao.ItemRepository; +import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.model.Comment; import ru.practicum.shareit.item.model.Item; -import ru.practicum.shareit.user.dao.InMemoryUserStorage; +import ru.practicum.shareit.user.dao.UserRepository; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import static ru.practicum.shareit.item.dao.ItemMapper.toItem; @@ -19,41 +25,51 @@ @Service @RequiredArgsConstructor public class ItemServiceImpl implements ItemService { - private final InMemoryItemStorage inMemoryItemStorage; - private final InMemoryUserStorage inMemoryUserStorage; + private final ItemRepository itemRepository; + private final UserRepository userRepository; + private final CommentRepository commentRepository; + private final BookingRepository bookingRepository; @Override + @Transactional public ItemDto addItem(ItemDto itemDto, Long ownerId) { - if (!inMemoryUserStorage.getUsers().containsKey(ownerId)) { + if (!userRepository.existsById(ownerId)) { log.warn("Владелец с указанным id " + ownerId + " не найден"); throw new NotFoundException("Владелец с id " + ownerId + " не найден"); } Item item = toItem(itemDto); item.setOwnerId(ownerId); - return toItemDto(inMemoryItemStorage.addItem(item)); + return toItemDto(itemRepository.save(item)); } @Override + @Transactional public ItemDto updateItem(ItemDto itemDto, long userId) { - if (!inMemoryUserStorage.getUsers().containsKey(userId)) { + if (!userRepository.existsById(userId)) { log.warn("Пользователь с указанным id " + userId + " не найден"); throw new NotFoundException("Пользователь с id " + userId + " не найден"); } Item newItem = toItem(itemDto); newItem.setOwnerId(userId); - return toItemDto(inMemoryItemStorage.updateItem(newItem)); + return toItemDto(itemRepository.save(newItem)); } @Override + @Transactional public ItemDto getItem(long itemId) { - return toItemDto(inMemoryItemStorage.getItem(itemId)); + Item item = toItemDto(itemRepository.findById(itemId)); + ItemDto itemDto = toItemDto(item); + Collection comments = commentRepository.findByItemId(itemId); + + return itemDto; } @Override + @Transactional public List getAllOwnerItems(long ownerId) { List itemDtoList = new ArrayList<>(); - for (Item item : inMemoryItemStorage.getAllOwnerItems(ownerId)) { + for (Item item : itemRepository.findByOwnerId(ownerId)) { itemDtoList.add(toItemDto(item)); } return itemDtoList; @@ -62,9 +78,14 @@ public List getAllOwnerItems(long ownerId) { @Override public List getNecessaryItem(String text) { List itemDtoList = new ArrayList<>(); - for (Item item : inMemoryItemStorage.getNecessaryItem(text)) { + for (Item item : itemRepository.searchByNameOrDescription(text)) { itemDtoList.add(toItemDto(item)); } return itemDtoList; } + + @Override + public CommentDto addComment(Long userId, Long itemId, CommentDto commentText) { + return null; + } } diff --git a/src/main/java/ru/practicum/shareit/user/controller/UserController.java b/src/main/java/ru/practicum/shareit/user/controller/UserController.java index 1c1e928..4cc13f5 100644 --- a/src/main/java/ru/practicum/shareit/user/controller/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/controller/UserController.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.user.model.User; import ru.practicum.shareit.user.service.UserServiceImpl; import ru.practicum.shareit.user.dto.UserDto; @@ -41,7 +42,7 @@ public Collection getAllUsers() { } @GetMapping("/{userId}") - public UserDto getUser(@PathVariable("userId") final Long userId) { + public User getUser(@PathVariable("userId") final Long userId) { log.info("Польователь с id " + userId + " выведен"); return userServiceImpl.getUser(userId); } diff --git a/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java b/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java index e69de29..6ee781a 100644 --- a/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java +++ b/src/main/java/ru/practicum/shareit/user/dao/UserRepository.java @@ -0,0 +1,9 @@ +package ru.practicum.shareit.user.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import ru.practicum.shareit.user.model.User; + +@Repository +public interface UserRepository extends JpaRepository { +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java index b4707c7..a7b696c 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java +++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -2,15 +2,23 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; +import ru.practicum.shareit.validation.OnCreate; +import ru.practicum.shareit.validation.OnUpdate; @Data @Valid @AllArgsConstructor public class UserDto { + private Long id; + + @NotBlank(groups = OnCreate.class, message = "Имя пользователя не может быть пустым") private String name; - @Email(message = "Email should be valid") + + @NotBlank(groups = OnCreate.class, message = "Почта не должна быть пустой") + @Email(groups = {OnCreate.class, OnUpdate.class}, message = "Почта должна быть в нужном формате") private String email; } diff --git a/src/main/java/ru/practicum/shareit/user/service/UserService.java b/src/main/java/ru/practicum/shareit/user/service/UserService.java index ccb07e8..30c7f8c 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserService.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserService.java @@ -1,6 +1,7 @@ package ru.practicum.shareit.user.service; import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.model.User; import java.util.List; @@ -13,7 +14,7 @@ public interface UserService { List getAllUsers(); - UserDto getUser(Long id); + User getUser(Long id); void deleteUser(Long id); } diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java index 2a83d52..860e389 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service; import ru.practicum.shareit.exceptions.BadRequestException; import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.user.dao.InMemoryUserStorage; +import ru.practicum.shareit.user.dao.UserRepository; import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.model.User; @@ -20,7 +20,7 @@ @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { - private final InMemoryUserStorage inMemoryUserStorage; + private final UserRepository userRepository; @Override public UserDto addUser(UserDto userDto) { @@ -29,47 +29,48 @@ public UserDto addUser(UserDto userDto) { log.warn("Некорректная почта"); throw new BadRequestException("некорректный тип почты"); } - for (User usr : inMemoryUserStorage.getUsers().values()) { + for (User usr : userRepository.findAll()) { if (usr.getEmail().equals(user.getEmail())) { log.warn("такая почта уже используется"); throw new ValidationException("Нельзя добавить существующую почту"); } } - return toUserDto(inMemoryUserStorage.addUser((user))); + return toUserDto(userRepository.save(user)); } @Override public UserDto updateUser(UserDto userDto) { - for (User usr : inMemoryUserStorage.getUsers().values()) { + for (User usr : userRepository.findAll()) { if (usr.getEmail().equals(userDto.getEmail())) { log.warn("такая почта уже используется"); throw new ValidationException("Нельзя добавить существующую почту"); } } - if (!inMemoryUserStorage.getUsers().containsKey(userDto.getId())) { + if (!userRepository.existsById(userDto.getId())) { log.warn("Пользователь с указанным id не найден"); throw new NotFoundException("Пользователь с id = " + userDto.getId() + " не найден"); } User newUser = toUser(userDto); - return toUserDto(inMemoryUserStorage.updateUser(newUser)); + return toUserDto(userRepository.save(newUser)); } @Override public List getAllUsers() { List dtoList = new ArrayList<>(); - for (User user : inMemoryUserStorage.getAllUsers()) { + for (User user : userRepository.findAll()) { dtoList.add(toUserDto(user)); } return dtoList; } @Override - public UserDto getUser(Long id) { - return toUserDto(inMemoryUserStorage.getUser(id)); + public User getUser(Long id) { + return userRepository.findById(id) + .orElseThrow(()-> new NotFoundException("Пользователь с id = " + id + " не найден")); } @Override public void deleteUser(Long id) { - inMemoryUserStorage.deleteUser(id); + userRepository.deleteById(id); } } From 2a26611a8f68fdeb728882e7be1312eae3dba713 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Tue, 24 Mar 2026 20:05:55 +0300 Subject: [PATCH 04/11] =?UTF-8?q?=D0=94=D0=BE=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20booking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../booking/controller/BookingController.java | 5 +- .../shareit/booking/dao/BookingMapper.java | 13 +-- .../booking/dao/BookingRepository.java | 25 +++++ .../shareit/booking/dto/BookingDto.java | 19 +++- .../shareit/booking/model/Booking.java | 2 + .../shareit/booking/model/BookingState.java | 10 ++ .../booking/service/BookingService.java | 5 +- .../booking/service/BookingServiceImpl.java | 105 ++++++++++++++++-- .../item/controller/ItemController.java | 10 ++ .../shareit/item/dao/ItemRepository.java | 3 +- .../shareit/item/service/ItemService.java | 3 +- .../shareit/item/service/ItemServiceImpl.java | 20 +++- .../resources/application-test.properties | 9 +- src/main/resources/application.properties | 9 +- 14 files changed, 197 insertions(+), 41 deletions(-) create mode 100644 src/main/java/ru/practicum/shareit/booking/model/BookingState.java diff --git a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java index 8cd08a3..18e5855 100644 --- a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java @@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingState; import ru.practicum.shareit.booking.model.BookingStatus; import ru.practicum.shareit.booking.service.BookingService; @@ -48,7 +49,7 @@ public Booking getBooking( @GetMapping public Collection findByBookerAndState( @RequestHeader("X-Sharer-User-Id") @Positive Long bookerId, - @RequestParam BookingStatus state) { + @RequestParam (defaultValue = "ALL") BookingState state) { return bookingService.findByBookerAndState(bookerId, state); } @@ -56,7 +57,7 @@ public Collection findByBookerAndState( @GetMapping("/owner") public Collection findByOwnerAndState( @RequestHeader("X-Sharer-User-Id") @Positive Long ownerId, - @RequestParam BookingStatus state) { + @RequestParam (defaultValue = "ALL") BookingState state) { return bookingService.findByOwnerAndState(ownerId, state); } diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingMapper.java index 80e814a..b328a53 100644 --- a/src/main/java/ru/practicum/shareit/booking/dao/BookingMapper.java +++ b/src/main/java/ru/practicum/shareit/booking/dao/BookingMapper.java @@ -6,13 +6,10 @@ @UtilityClass public class BookingMapper { - public static BookingDto mapToBooking(Booking booking) { - return new BookingDto( - booking.getStart(), - booking.getEnd(), - booking.getItem(), - booking.getBooker(), - booking.getStatus() - ); + public static Booking mapToBooking(BookingDto bookingDto) { + Booking booking = new Booking(); + booking.setStart(bookingDto.getStart()); + booking.setEnd(bookingDto.getEnd()); + return booking; } } diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java index 3bd694e..4648376 100644 --- a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java +++ b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java @@ -3,8 +3,33 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; + +import java.time.LocalDateTime; +import java.util.Collection; @Repository public interface BookingRepository extends JpaRepository { + Collection findByBookerIdOrderByEndDesc(Long bookerId); + + Collection findByItemOwnerIdOrderByEndDesc(Long ownerId); + + Collection findByBookerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDesc(Long bookerId, LocalDateTime now, + LocalDateTime now1); + + Collection findByBookerIdAndStatusIsOrderByEndDesc(Long bookerId, BookingStatus bookingStatus); + + Collection findByBookerIdAndEndIsBeforeOrderByEndDesc(Long bookerId, LocalDateTime now); + + Collection findByBookerIdAndStartIsAfterOrderByEndDesc(Long bookerId, LocalDateTime now); + + Collection findByItemOwnerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDesc(Long ownerId, LocalDateTime now, + LocalDateTime now1); + + Collection findByItemOwnerIdAndStatusIsOrderByEndDesc(Long ownerId, BookingStatus bookingStatus); + + Collection findByItemOwnerIdAndEndIsBeforeOrderByEndDesc(Long ownerId, LocalDateTime now); + + Collection findByItemOwnerIdAndStartIsAfterOrderByEndDesc(Long ownerId, LocalDateTime now); } diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java index 2f99f25..e016de5 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java @@ -1,20 +1,27 @@ package ru.practicum.shareit.booking.dto; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.AllArgsConstructor; -import ru.practicum.shareit.item.model.Item; -import ru.practicum.shareit.booking.model.BookingStatus; -import ru.practicum.shareit.user.model.User; +import lombok.Getter; +import lombok.Setter; import java.time.LocalDate; /** * TODO Sprint add-bookings. */ +@Setter +@Getter @AllArgsConstructor public class BookingDto { + @NotNull + @Positive + private Long itemId; + @FutureOrPresent private LocalDate start; + @FutureOrPresent private LocalDate end; - private Item item; - private User booker; - private BookingStatus status; + } diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java index 71ccfc1..1f5479f 100644 --- a/src/main/java/ru/practicum/shareit/booking/model/Booking.java +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import ru.practicum.shareit.item.model.Item; import ru.practicum.shareit.user.model.User; @@ -14,6 +15,7 @@ */ @Entity @AllArgsConstructor +@NoArgsConstructor @Setter @Getter @Table(name = "bookings") diff --git a/src/main/java/ru/practicum/shareit/booking/model/BookingState.java b/src/main/java/ru/practicum/shareit/booking/model/BookingState.java new file mode 100644 index 0000000..a574273 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/model/BookingState.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.booking.model; + +public enum BookingState { + ALL, + CURRENT, + PAST, + FUTURE, + WAITING, + REJECTED +} diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java index 6246188..f155fec 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java @@ -2,6 +2,7 @@ import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingState; import ru.practicum.shareit.booking.model.BookingStatus; import java.util.Collection; @@ -13,7 +14,7 @@ public interface BookingService { Booking getBooking(Long userId, Long bookingId); - Collection findByBookerAndState(Long bookerId, BookingStatus state); + Collection findByBookerAndState(Long bookerId, BookingState state); - Collection findByOwnerAndState(Long ownerId, BookingStatus state); + Collection findByOwnerAndState(Long ownerId, BookingState state); } diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java index a63c1d9..f07d81d 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java @@ -1,35 +1,126 @@ package ru.practicum.shareit.booking.service; +import jakarta.validation.ValidationException; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.practicum.shareit.booking.dao.BookingRepository; import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingState; import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.exceptions.BadRequestException; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.item.dao.ItemRepository; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.dao.UserRepository; +import ru.practicum.shareit.user.model.User; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import static ru.practicum.shareit.booking.dao.BookingMapper.mapToBooking; + +@Service +@AllArgsConstructor public class BookingServiceImpl implements BookingService{ + + private final BookingRepository bookingRepository; + private final UserRepository userRepository; + private final ItemRepository itemRepository; + @Override + @Transactional public Booking createBooking(Long bookerId, BookingDto bookingDto) { - return null; + if (!bookingDto.getStart().isBefore(bookingDto.getEnd())) { + throw new BadRequestException("Начало не может быть после конца бронирования"); + } + User user = userRepository.findById(bookerId) + .orElseThrow(() -> new NotFoundException("Пользователь с id " + bookerId + " не найден")); + Item item = itemRepository.findById(bookingDto.getItemId()) + .orElseThrow(() -> new NotFoundException("Предмет с id " + bookingDto.getItemId() + " не найден")); + if (!item.getIsAvailable()) { + throw new BadRequestException("Предмет уже занят"); + } + + Booking booking = mapToBooking(bookingDto); + booking.setItem(item); + booking.setBooker(user); + booking.setStatus(BookingStatus.WAITING); + return booking; } @Override + @Transactional public Booking updateBookingStatus(Long userId, Long bookingId, Boolean approved) { - return null; + Booking booking = bookingRepository.findById(bookingId) + .orElseThrow(() -> new NotFoundException("Бронирование не найдено")); + if (!booking.getBooker().getId().equals(userId)) { + throw new BadRequestException("Менять статус может только владелец"); + } + if (approved) { + booking.setStatus(BookingStatus.APPROVED); + } else { + booking.setStatus(BookingStatus.REJECTED); + } + return bookingRepository.save(booking); } @Override public Booking getBooking(Long userId, Long bookingId) { - return null; + Booking booking = bookingRepository.findById(bookingId) + .orElseThrow(() -> new NotFoundException("Бронирование не найдено")); + if (!booking.getBooker().getId().equals(userId) && !booking.getItem().getOwnerId().equals(userId)) { + throw new ValidationException("Только владелец или арендатор могут посмотреть бронирование"); + } + return booking; } @Override - public Collection findByBookerAndState(Long bookerId, BookingStatus state) { - return List.of(); + @Transactional(readOnly = true) + public Collection findByBookerAndState(Long bookerId, BookingState state) { + if (userRepository.findById(bookerId).isEmpty()) { + throw new NotFoundException("Пользователь с id " + bookerId + " не найден"); + } + LocalDateTime now = LocalDateTime.now(); + + switch (state) { + case CURRENT: + return bookingRepository.findByBookerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDesc(bookerId, now, now); + case REJECTED: + return bookingRepository.findByBookerIdAndStatusIsOrderByEndDesc(bookerId, BookingStatus.REJECTED); + case WAITING: + return bookingRepository.findByBookerIdAndStatusIsOrderByEndDesc(bookerId, BookingStatus.WAITING); + case PAST: + return bookingRepository.findByBookerIdAndEndIsBeforeOrderByEndDesc(bookerId, now); + case FUTURE: + return bookingRepository.findByBookerIdAndStartIsAfterOrderByEndDesc(bookerId, now); + } + return bookingRepository.findByBookerIdOrderByEndDesc(bookerId); } @Override - public Collection findByOwnerAndState(Long ownerId, BookingStatus state) { - return List.of(); + @Transactional(readOnly = true) + public Collection findByOwnerAndState(Long ownerId, BookingState state) { + if (userRepository.findById(ownerId).isEmpty()) { + throw new NotFoundException("Пользователь с id " + ownerId + " не найден"); + } + LocalDateTime now = LocalDateTime.now(); + + switch (state) { + case CURRENT: + return bookingRepository.findByItemOwnerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDesc(ownerId, now, + now); + case REJECTED: + return bookingRepository.findByItemOwnerIdAndStatusIsOrderByEndDesc(ownerId, BookingStatus.REJECTED); + case WAITING: + return bookingRepository.findByItemOwnerIdAndStatusIsOrderByEndDesc(ownerId, BookingStatus.WAITING); + case PAST: + return bookingRepository.findByItemOwnerIdAndEndIsBeforeOrderByEndDesc(ownerId, now); + case FUTURE: + return bookingRepository.findByItemOwnerIdAndStartIsAfterOrderByEndDesc(ownerId, now); + } + return bookingRepository.findByItemOwnerIdOrderByEndDesc(ownerId); } } diff --git a/src/main/java/ru/practicum/shareit/item/controller/ItemController.java b/src/main/java/ru/practicum/shareit/item/controller/ItemController.java index b6fdcf2..f9658ca 100644 --- a/src/main/java/ru/practicum/shareit/item/controller/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/controller/ItemController.java @@ -4,6 +4,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.model.Comment; import ru.practicum.shareit.validation.OnCreate; import ru.practicum.shareit.validation.OnUpdate; import ru.practicum.shareit.item.dto.ItemDto; @@ -55,4 +57,12 @@ public Collection getNecessaryItem(@RequestParam String text) { log.info("Список предметов содержащих " + text + " выведен"); return itemService.getNecessaryItem(text); } + + @PostMapping("/{itemId}/comment") + public CommentDto addComment(@PathVariable("itemId") final long itemId, + @RequestHeader("X-Sharer-User-Id") long ownerId, + @RequestBody Comment comment) { + log.info("Комментарий добавлен"); + return itemService.addComment(ownerId, itemId, comment); + } } diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java index 8d52ba6..9d06834 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java +++ b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java @@ -4,12 +4,11 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import ru.practicum.shareit.item.model.Item; -import ru.practicum.shareit.user.model.User; import java.util.Collection; @Repository -public interface ItemRepository extends JpaRepository { +public interface ItemRepository extends JpaRepository { @Query(""" SELECT i diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemService.java b/src/main/java/ru/practicum/shareit/item/service/ItemService.java index c06d151..ec52303 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemService.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java @@ -2,6 +2,7 @@ import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.model.Comment; import java.util.Collection; import java.util.List; @@ -18,5 +19,5 @@ public interface ItemService { Collection getNecessaryItem(String text); - CommentDto addComment(Long userId, Long itemId, CommentDto commentText); + CommentDto addComment(Long userId, Long itemId, Comment comment); } diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index 36d273f..b5e12e0 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -13,11 +13,13 @@ import ru.practicum.shareit.item.model.Comment; import ru.practicum.shareit.item.model.Item; import ru.practicum.shareit.user.dao.UserRepository; +import ru.practicum.shareit.user.model.User; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static ru.practicum.shareit.item.dao.CommentMapper.toCommentDto; import static ru.practicum.shareit.item.dao.ItemMapper.toItem; import static ru.practicum.shareit.item.dao.ItemMapper.toItemDto; @@ -58,7 +60,9 @@ public ItemDto updateItem(ItemDto itemDto, long userId) { @Override @Transactional public ItemDto getItem(long itemId) { - Item item = toItemDto(itemRepository.findById(itemId)); + Item item = itemRepository.findById(itemId) + .orElseThrow(() -> new NotFoundException("Предмет с id " + itemId + " не найден")); + ItemDto itemDto = toItemDto(item); Collection comments = commentRepository.findByItemId(itemId); @@ -85,7 +89,17 @@ public List getNecessaryItem(String text) { } @Override - public CommentDto addComment(Long userId, Long itemId, CommentDto commentText) { - return null; + public CommentDto addComment(Long userId, Long itemId, Comment comment) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new NotFoundException("Пользователь с id " + userId + " не найден")); + + Item item = itemRepository.findById(itemId) + .orElseThrow(() -> new NotFoundException("Предмет с id " + userId + " не найден")); + CommentDto commentDto = null; + if (item.getOwnerId().equals(user.getId())) { + commentDto = toCommentDto(comment); + commentRepository.save(comment); + } + return commentDto; } } diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 9e9bc4b..f4df433 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -6,8 +6,7 @@ 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 H2 DB -#spring.datasource.driverClassName -#spring.datasource.url -#spring.datasource.username -#spring.datasource.password +spring.datasource.driverClassName +spring.datasource.url +spring.datasource.username +spring.datasource.password diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5e606fb..ec60ebc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,8 +7,7 @@ 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 Postgres DB -#spring.datasource.driverClassName=org.postgresql.Driver -#spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit -#spring.datasource.username=ca -#spring.datasource.password=12345678 +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit +spring.datasource.username=ca +spring.datasource.password=12345678 From 83788adeed3d918beb881bd889aeb2d38e7b4713 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Thu, 26 Mar 2026 17:58:49 +0300 Subject: [PATCH 05/11] =?UTF-8?q?=D0=A0=D0=B5=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=BE=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=B8=D0=B5=D0=B2=20=D0=B8=20=D0=B4=D0=B0?= =?UTF-8?q?=D1=82=20=D0=B1=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../booking/dao/BookingRepository.java | 7 ++ .../booking/model/LastAndNextDate.java | 11 +++ .../shareit/item/dao/CommentRepository.java | 3 +- .../shareit/item/dao/ItemRepository.java | 3 +- .../shareit/item/service/ItemServiceImpl.java | 84 +++++++++++++++---- 5 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 src/main/java/ru/practicum/shareit/booking/model/LastAndNextDate.java diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java index 4648376..cd46323 100644 --- a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java +++ b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java @@ -4,9 +4,11 @@ import org.springframework.stereotype.Repository; import ru.practicum.shareit.booking.model.Booking; import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.booking.model.LastAndNextDate; import java.time.LocalDateTime; import java.util.Collection; +import java.util.List; @Repository public interface BookingRepository extends JpaRepository { @@ -32,4 +34,9 @@ Collection findByItemOwnerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDes Collection findByItemOwnerIdAndEndIsBeforeOrderByEndDesc(Long ownerId, LocalDateTime now); Collection findByItemOwnerIdAndStartIsAfterOrderByEndDesc(Long ownerId, LocalDateTime now); + + boolean existsByItemIdAndBookerIdAndStatusIsAndEndBefore(Long itemId, Long userId, BookingStatus bookingStatus, + LocalDateTime now); + + List findLastAndNextDatesByOwnerId(long ownerId); } diff --git a/src/main/java/ru/practicum/shareit/booking/model/LastAndNextDate.java b/src/main/java/ru/practicum/shareit/booking/model/LastAndNextDate.java new file mode 100644 index 0000000..c793bb1 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/model/LastAndNextDate.java @@ -0,0 +1,11 @@ +package ru.practicum.shareit.booking.model; + +import java.time.LocalDateTime; + +public interface LastAndNextDate { + Long getItemId(); + + LocalDateTime getLastBooking(); + + LocalDateTime getNextBooking(); +} diff --git a/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java index 1b61de8..3a6202c 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java +++ b/src/main/java/ru/practicum/shareit/item/dao/CommentRepository.java @@ -6,11 +6,12 @@ import ru.practicum.shareit.item.model.Comment; import java.util.Collection; +import java.util.List; @Repository public interface CommentRepository extends JpaRepository { Collection findByItemId(Long itemId); @Query("SELECT c FROM Comment c JOIN FETCH c.item WHERE c.item.ownerId = ?1") - Collection findByItemOwnerId(Long ownerId); + List findByItemOwnerId(Long ownerId); } diff --git a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java index 9d06834..f2bc1cf 100644 --- a/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java +++ b/src/main/java/ru/practicum/shareit/item/dao/ItemRepository.java @@ -6,6 +6,7 @@ import ru.practicum.shareit.item.model.Item; import java.util.Collection; +import java.util.List; @Repository public interface ItemRepository extends JpaRepository { @@ -19,5 +20,5 @@ OR LOWER(i.description) LIKE LOWER(%:text%)) """) Collection searchByNameOrDescription(String text); - Collection findByOwnerId(Long userId); + List findByOwnerId(Long userId); } diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index b5e12e0..76c579e 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -5,7 +5,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.practicum.shareit.booking.dao.BookingRepository; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.booking.model.LastAndNextDate; +import ru.practicum.shareit.exceptions.BadRequestException; import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.item.dao.CommentMapper; import ru.practicum.shareit.item.dao.CommentRepository; import ru.practicum.shareit.item.dao.ItemRepository; import ru.practicum.shareit.item.dto.CommentDto; @@ -15,9 +19,10 @@ import ru.practicum.shareit.user.dao.UserRepository; import ru.practicum.shareit.user.model.User; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.time.LocalDateTime; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import static ru.practicum.shareit.item.dao.CommentMapper.toCommentDto; import static ru.practicum.shareit.item.dao.ItemMapper.toItem; @@ -58,7 +63,7 @@ public ItemDto updateItem(ItemDto itemDto, long userId) { } @Override - @Transactional + @Transactional(readOnly = true) public ItemDto getItem(long itemId) { Item item = itemRepository.findById(itemId) .orElseThrow(() -> new NotFoundException("Предмет с id " + itemId + " не найден")); @@ -66,21 +71,57 @@ public ItemDto getItem(long itemId) { ItemDto itemDto = toItemDto(item); Collection comments = commentRepository.findByItemId(itemId); - return itemDto; + return addCommentsToItem(itemDto, comments); } @Override - @Transactional + @Transactional(readOnly = true) public List getAllOwnerItems(long ownerId) { - List itemDtoList = new ArrayList<>(); - for (Item item : itemRepository.findByOwnerId(ownerId)) { - itemDtoList.add(toItemDto(item)); + List items = itemRepository.findByOwnerId(ownerId); + + if (items.isEmpty()) { + return Collections.emptyList(); } - return itemDtoList; + + List itemIds = items.stream() + .map(Item::getId) + .toList(); + + List comments = commentRepository.findByItemOwnerId(ownerId); + Map> commentsMap = comments.stream() + .collect(Collectors.groupingBy( + comment -> comment.getItem().getId(), + Collectors.mapping(CommentMapper::toCommentDto, Collectors.toList()) + )); + + List dates = bookingRepository.findLastAndNextDatesByOwnerId(ownerId); + Map datesMap = new HashMap<>(); + for (LastAndNextDate date : dates) { + datesMap.put(date.getItemId(), date); + } + + return items.stream() + .map(item -> { + ItemDto dto = toItemDto(item); + + LastAndNextDate bookingDates = datesMap.get(item.getId()); + if (bookingDates != null) { + dto.setLastBooking(bookingDates.getLastBooking()); + dto.setNextBooking(bookingDates.getNextBooking()); + } + + dto.setComments(commentsMap.getOrDefault(item.getId(), Collections.emptyList())); + + return dto; + }) + .collect(Collectors.toList()); } @Override public List getNecessaryItem(String text) { + if (text == null || text.isBlank()) { + return Collections.emptyList(); + } List itemDtoList = new ArrayList<>(); for (Item item : itemRepository.searchByNameOrDescription(text)) { itemDtoList.add(toItemDto(item)); @@ -94,12 +135,23 @@ public CommentDto addComment(Long userId, Long itemId, Comment comment) { .orElseThrow(() -> new NotFoundException("Пользователь с id " + userId + " не найден")); Item item = itemRepository.findById(itemId) - .orElseThrow(() -> new NotFoundException("Предмет с id " + userId + " не найден")); - CommentDto commentDto = null; - if (item.getOwnerId().equals(user.getId())) { - commentDto = toCommentDto(comment); - commentRepository.save(comment); + .orElseThrow(() -> new NotFoundException("Предмет с id " + itemId + " не найден")); + + if (!bookingRepository.existsByItemIdAndBookerIdAndStatusIsAndEndBefore( + itemId, userId, BookingStatus.APPROVED, LocalDateTime.now())) { + throw new BadRequestException("Пользователь никогда не брал предмет в аренду"); } - return commentDto; + comment.setItem(item); + comment.setAuthor(user); + comment.setCreated(LocalDateTime.now()); + return toCommentDto(commentRepository.save(comment)); + } + + private ItemDto addCommentsToItem(ItemDto itemDto, Collection comments ) { + Collection commentsDto = comments.stream() + .map(CommentMapper::toCommentDto) + .toList(); + itemDto.setComments(commentsDto); + return itemDto; } } From e24a6fe0f1cdf59aa5cefb48b65a3bf57b35fa77 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sun, 29 Mar 2026 17:22:02 +0300 Subject: [PATCH 06/11] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=20Users?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../booking/dao/BookingRepository.java | 10 +++++++ .../booking/service/BookingServiceImpl.java | 4 +-- .../item/controller/ItemController.java | 3 +- .../shareit/item/service/ItemService.java | 2 +- .../shareit/item/service/ItemServiceImpl.java | 11 ++++++- .../user/controller/UserController.java | 8 +++-- .../practicum/shareit/user/dto/UserDto.java | 3 +- .../ru/practicum/shareit/user/model/User.java | 4 ++- .../shareit/user/service/UserServiceImpl.java | 29 ++++++++----------- .../resources/application-test.properties | 8 ++--- src/main/resources/application.properties | 13 ++++++--- 12 files changed, 61 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 1b18148..165fb32 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ com.h2database h2 - test + runtime diff --git a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java index cd46323..1e08da0 100644 --- a/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java +++ b/src/main/java/ru/practicum/shareit/booking/dao/BookingRepository.java @@ -1,6 +1,7 @@ package ru.practicum.shareit.booking.dao; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import ru.practicum.shareit.booking.model.Booking; import ru.practicum.shareit.booking.model.BookingStatus; @@ -38,5 +39,14 @@ Collection findByItemOwnerIdAndStartIsBeforeAndEndIsBeforeOrderByEndDes boolean existsByItemIdAndBookerIdAndStatusIsAndEndBefore(Long itemId, Long userId, BookingStatus bookingStatus, LocalDateTime now); + @Query(""" + SELECT + b.item.id as itemId, + MAX(CASE WHEN b.start < CURRENT_TIMESTAMP THEN b.start ELSE NULL END) as lastBooking, + MIN(CASE WHEN b.start > CURRENT_TIMESTAMP THEN b.start ELSE NULL END) as nextBooking + FROM Booking b + WHERE b.item.ownerId = ?1 + GROUP BY b.item.id + """) List findLastAndNextDatesByOwnerId(long ownerId); } diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java index f07d81d..b29abed 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java @@ -48,7 +48,7 @@ public Booking createBooking(Long bookerId, BookingDto bookingDto) { booking.setItem(item); booking.setBooker(user); booking.setStatus(BookingStatus.WAITING); - return booking; + return bookingRepository.save(booking); } @Override @@ -56,7 +56,7 @@ public Booking createBooking(Long bookerId, BookingDto bookingDto) { public Booking updateBookingStatus(Long userId, Long bookingId, Boolean approved) { Booking booking = bookingRepository.findById(bookingId) .orElseThrow(() -> new NotFoundException("Бронирование не найдено")); - if (!booking.getBooker().getId().equals(userId)) { + if (!booking.getItem().getOwnerId().equals(userId)) { throw new BadRequestException("Менять статус может только владелец"); } if (approved) { diff --git a/src/main/java/ru/practicum/shareit/item/controller/ItemController.java b/src/main/java/ru/practicum/shareit/item/controller/ItemController.java index f9658ca..5ddfb15 100644 --- a/src/main/java/ru/practicum/shareit/item/controller/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/controller/ItemController.java @@ -35,9 +35,8 @@ public ItemDto addItem(@Validated(OnCreate.class) @RequestBody final ItemDto ite public ItemDto updateItem(@PathVariable("itemId") final long itemId, @RequestHeader("X-Sharer-User-Id") long ownerId, @Validated(OnUpdate.class) @RequestBody final ItemDto itemDto) { - itemDto.setId(itemId); log.info("Предмет обновлен"); - return itemService.updateItem(itemDto, ownerId); + return itemService.updateItem(itemDto, itemId, ownerId); } @GetMapping("/{itemId}") diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemService.java b/src/main/java/ru/practicum/shareit/item/service/ItemService.java index ec52303..277a7e9 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemService.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemService.java @@ -11,7 +11,7 @@ public interface ItemService { ItemDto addItem(ItemDto itemDto, Long userId); - ItemDto updateItem(ItemDto itemDto, long userId); + ItemDto updateItem(ItemDto itemDto, Long itemId, long userId); ItemDto getItem(long itemId); diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index 76c579e..296befa 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -51,7 +51,7 @@ public ItemDto addItem(ItemDto itemDto, Long ownerId) { @Override @Transactional - public ItemDto updateItem(ItemDto itemDto, long userId) { + public ItemDto updateItem(ItemDto itemDto,Long itemId, long userId) { if (!userRepository.existsById(userId)) { log.warn("Пользователь с указанным id " + userId + " не найден"); throw new NotFoundException("Пользователь с id " + userId + " не найден"); @@ -59,6 +59,15 @@ public ItemDto updateItem(ItemDto itemDto, long userId) { Item newItem = toItem(itemDto); newItem.setOwnerId(userId); + if (itemDto.getName() != null) { + newItem.setName(itemDto.getName()); + } + if (itemDto.getDescription() != null) { + newItem.setDescription(itemDto.getDescription()); + } + if (itemDto.getAvailable() != null) { + newItem.setIsAvailable(itemDto.getAvailable()); + } return toItemDto(itemRepository.save(newItem)); } diff --git a/src/main/java/ru/practicum/shareit/user/controller/UserController.java b/src/main/java/ru/practicum/shareit/user/controller/UserController.java index 4cc13f5..e95808f 100644 --- a/src/main/java/ru/practicum/shareit/user/controller/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/controller/UserController.java @@ -3,10 +3,13 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.user.model.User; import ru.practicum.shareit.user.service.UserServiceImpl; import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.validation.OnCreate; +import ru.practicum.shareit.validation.OnUpdate; import java.util.Collection; @@ -23,13 +26,14 @@ public class UserController { private final UserServiceImpl userServiceImpl; @PostMapping - public UserDto addUser(@Valid @RequestBody final UserDto user) { + public UserDto addUser(@Validated(OnCreate.class) @RequestBody final UserDto user) { log.info("Пользователь добавлен"); return userServiceImpl.addUser(user); } @PatchMapping("/{userId}") - public UserDto updateUser(@PathVariable("userId") final Long userId, @Valid @RequestBody final UserDto userDto) { + public UserDto updateUser(@PathVariable("userId") final Long userId, + @Validated(OnUpdate.class) @RequestBody final UserDto userDto) { userDto.setId(userId); log.info("Пользователь обновлен"); return userServiceImpl.updateUser(userDto); diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java index a7b696c..54c617a 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java +++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import ru.practicum.shareit.validation.OnCreate; @@ -18,7 +19,7 @@ public class UserDto { @NotBlank(groups = OnCreate.class, message = "Имя пользователя не может быть пустым") private String name; - @NotBlank(groups = OnCreate.class, message = "Почта не должна быть пустой") + @NotNull(groups = OnCreate.class, message = "Почта не должна быть пустой") @Email(groups = {OnCreate.class, OnUpdate.class}, message = "Почта должна быть в нужном формате") private String email; } diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java index 3844d55..9fd14e5 100644 --- a/src/main/java/ru/practicum/shareit/user/model/User.java +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; /** @@ -10,6 +11,7 @@ */ @Entity @AllArgsConstructor +@NoArgsConstructor @Getter @Setter @Table(name = "users") @@ -22,6 +24,6 @@ public class User { @Column(name = "name") private String name; - @Column(name = "email") + @Column(name = "email", unique = true) private String email; } diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java index 860e389..5a9f256 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import ru.practicum.shareit.exceptions.BadRequestException; import ru.practicum.shareit.exceptions.NotFoundException; import ru.practicum.shareit.user.dao.UserRepository; @@ -22,35 +23,29 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; + @Override + @Transactional public UserDto addUser(UserDto userDto) { User user = toUser(userDto); - if (user.getEmail() == null) { - log.warn("Некорректная почта"); - throw new BadRequestException("некорректный тип почты"); - } - for (User usr : userRepository.findAll()) { - if (usr.getEmail().equals(user.getEmail())) { - log.warn("такая почта уже используется"); - throw new ValidationException("Нельзя добавить существующую почту"); - } - } return toUserDto(userRepository.save(user)); } @Override + @Transactional public UserDto updateUser(UserDto userDto) { - for (User usr : userRepository.findAll()) { - if (usr.getEmail().equals(userDto.getEmail())) { - log.warn("такая почта уже используется"); - throw new ValidationException("Нельзя добавить существующую почту"); - } - } if (!userRepository.existsById(userDto.getId())) { log.warn("Пользователь с указанным id не найден"); throw new NotFoundException("Пользователь с id = " + userDto.getId() + " не найден"); } - User newUser = toUser(userDto); + + User newUser = getUser(userDto.getId()); + if (userDto.getName() != null) { + newUser.setName(userDto.getName()); + } + if (userDto.getEmail() != null) { + newUser.setEmail(userDto.getEmail()); + } return toUserDto(userRepository.save(newUser)); } diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index f4df433..713b80d 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -6,7 +6,7 @@ logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG -spring.datasource.driverClassName -spring.datasource.url -spring.datasource.username -spring.datasource.password +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.username=dbuser +spring.datasource.password=12345 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ec60ebc..6fd9fb5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,7 +7,12 @@ logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG -spring.datasource.driverClassName=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit -spring.datasource.username=ca -spring.datasource.password=12345678 +#spring.datasource.driverClassName=org.postgresql.Driver +#spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit +#spring.datasource.username=dbuser +#spring.datasource.password=12345 + +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.username=dbuser +spring.datasource.password=12345 From e50f38670fad2b2786fa2c41d7524d73eabed1d8 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sun, 29 Mar 2026 18:09:12 +0300 Subject: [PATCH 07/11] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=20=D0=91=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=B2=D0=B5=D1=89=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/practicum/shareit/booking/dto/BookingDto.java | 7 +++++-- .../java/ru/practicum/shareit/booking/model/Booking.java | 9 +++++---- .../ru/practicum/shareit/exceptions/ErrorHandler.java | 2 +- .../practicum/shareit/item/service/ItemServiceImpl.java | 5 +++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java index e016de5..4f7ad3a 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java @@ -8,6 +8,7 @@ import lombok.Setter; import java.time.LocalDate; +import java.time.LocalDateTime; /** * TODO Sprint add-bookings. @@ -19,9 +20,11 @@ public class BookingDto { @NotNull @Positive private Long itemId; + @NotNull @FutureOrPresent - private LocalDate start; + private LocalDateTime start; + @NotNull @FutureOrPresent - private LocalDate end; + private LocalDateTime end; } diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java index 1f5479f..8acdf24 100644 --- a/src/main/java/ru/practicum/shareit/booking/model/Booking.java +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -9,6 +9,7 @@ import ru.practicum.shareit.user.model.User; import java.time.LocalDate; +import java.time.LocalDateTime; /** * TODO Sprint add-bookings. @@ -26,16 +27,16 @@ public class Booking { private Long id; @Column(name = "start_date") - private LocalDate start; + private LocalDateTime start; @Column(name = "end_date") - private LocalDate end; + private LocalDateTime end; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne @JoinColumn(name = "item_id") private Item item; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne @JoinColumn(name = "booker_id") private User booker; diff --git a/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java b/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java index ef558d3..970234e 100644 --- a/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java +++ b/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java @@ -26,7 +26,7 @@ public ErrorResponse handleNotFoundException(final NotFoundException e) { } @ExceptionHandler - @ResponseStatus(HttpStatus.NOT_FOUND) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ErrorResponse handleInternalServerException(final InternalServerException e) { log.warn("Ошибка сервера"); return new ErrorResponse(e.getMessage()); diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index 296befa..74e1177 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -21,7 +21,6 @@ import java.time.LocalDateTime; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; import static ru.practicum.shareit.item.dao.CommentMapper.toCommentDto; @@ -57,8 +56,10 @@ public ItemDto updateItem(ItemDto itemDto,Long itemId, long userId) { throw new NotFoundException("Пользователь с id " + userId + " не найден"); } - Item newItem = toItem(itemDto); + Item newItem = itemRepository.findById(itemId) + .orElseThrow(() -> new NotFoundException("Предмет с id " + itemId + " не найден")); newItem.setOwnerId(userId); + if (itemDto.getName() != null) { newItem.setName(itemDto.getName()); } From 463bbfa395cc6c95663ec1dd96b2516528919cd2 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sun, 29 Mar 2026 18:27:36 +0300 Subject: [PATCH 08/11] checkstyle --- src/main/java/ru/practicum/shareit/ShareItApp.java | 2 -- .../shareit/booking/controller/BookingController.java | 1 - .../java/ru/practicum/shareit/booking/dto/BookingDto.java | 1 - .../java/ru/practicum/shareit/booking/model/Booking.java | 1 - .../practicum/shareit/booking/service/BookingService.java | 1 - .../shareit/booking/service/BookingServiceImpl.java | 1 - src/main/java/ru/practicum/shareit/item/model/Comment.java | 1 - src/main/java/ru/practicum/shareit/item/model/Item.java | 1 - .../ru/practicum/shareit/item/service/ItemServiceImpl.java | 2 +- .../practicum/shareit/user/controller/UserController.java | 3 +-- src/main/java/ru/practicum/shareit/user/dto/UserDto.java | 1 - src/main/java/ru/practicum/shareit/user/model/User.java | 1 - .../java/ru/practicum/shareit/user/service/UserService.java | 3 +-- .../ru/practicum/shareit/user/service/UserServiceImpl.java | 6 +----- src/main/resources/application.properties | 4 ++-- 15 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/ShareItApp.java b/src/main/java/ru/practicum/shareit/ShareItApp.java index a00ad56..83b60e0 100644 --- a/src/main/java/ru/practicum/shareit/ShareItApp.java +++ b/src/main/java/ru/practicum/shareit/ShareItApp.java @@ -5,9 +5,7 @@ @SpringBootApplication public class ShareItApp { - public static void main(String[] args) { SpringApplication.run(ShareItApp.class, args); } - } diff --git a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java index 18e5855..3498754 100644 --- a/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/controller/BookingController.java @@ -7,7 +7,6 @@ import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.model.Booking; import ru.practicum.shareit.booking.model.BookingState; -import ru.practicum.shareit.booking.model.BookingStatus; import ru.practicum.shareit.booking.service.BookingService; import java.util.Collection; diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java index 4f7ad3a..040c09d 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java @@ -7,7 +7,6 @@ import lombok.Getter; import lombok.Setter; -import java.time.LocalDate; import java.time.LocalDateTime; /** diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java index 8acdf24..33ea486 100644 --- a/src/main/java/ru/practicum/shareit/booking/model/Booking.java +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -8,7 +8,6 @@ import ru.practicum.shareit.item.model.Item; import ru.practicum.shareit.user.model.User; -import java.time.LocalDate; import java.time.LocalDateTime; /** diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java index f155fec..4e08db2 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingService.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingService.java @@ -3,7 +3,6 @@ import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.model.Booking; import ru.practicum.shareit.booking.model.BookingState; -import ru.practicum.shareit.booking.model.BookingStatus; import java.util.Collection; diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java index b29abed..9a69b5a 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java @@ -18,7 +18,6 @@ import java.time.LocalDateTime; import java.util.Collection; -import java.util.List; import static ru.practicum.shareit.booking.dao.BookingMapper.mapToBooking; diff --git a/src/main/java/ru/practicum/shareit/item/model/Comment.java b/src/main/java/ru/practicum/shareit/item/model/Comment.java index 24f0800..8463d6a 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Comment.java +++ b/src/main/java/ru/practicum/shareit/item/model/Comment.java @@ -15,7 +15,6 @@ @Entity @Table(name = "comments") public class Comment { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index c7af228..3dab078 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -16,7 +16,6 @@ @Setter @Table(name = "items") public class Item { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index 74e1177..cca085b 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -164,4 +164,4 @@ private ItemDto addCommentsToItem(ItemDto itemDto, Collection comments itemDto.setComments(commentsDto); return itemDto; } -} +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/controller/UserController.java b/src/main/java/ru/practicum/shareit/user/controller/UserController.java index e95808f..d198bf1 100644 --- a/src/main/java/ru/practicum/shareit/user/controller/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/controller/UserController.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.user.controller; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; @@ -56,4 +55,4 @@ public void deleteUser(@PathVariable("userId") final Long userId) { log.info("Пользователь с id " + userId + " удален"); userServiceImpl.deleteUser(userId); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java index 54c617a..6bc7abe 100644 --- a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java +++ b/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -13,7 +13,6 @@ @Valid @AllArgsConstructor public class UserDto { - private Long id; @NotBlank(groups = OnCreate.class, message = "Имя пользователя не может быть пустым") diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java index 9fd14e5..8905e5a 100644 --- a/src/main/java/ru/practicum/shareit/user/model/User.java +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -16,7 +16,6 @@ @Setter @Table(name = "users") public class User { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/ru/practicum/shareit/user/service/UserService.java b/src/main/java/ru/practicum/shareit/user/service/UserService.java index 30c7f8c..5f500ad 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserService.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserService.java @@ -5,7 +5,6 @@ import java.util.List; - public interface UserService { UserDto addUser(UserDto userDto); @@ -17,4 +16,4 @@ public interface UserService { User getUser(Long id); void deleteUser(Long id); -} +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java index 5a9f256..127aa73 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -1,11 +1,9 @@ package ru.practicum.shareit.user.service; -import jakarta.validation.ValidationException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import ru.practicum.shareit.exceptions.BadRequestException; import ru.practicum.shareit.exceptions.NotFoundException; import ru.practicum.shareit.user.dao.UserRepository; import ru.practicum.shareit.user.dto.UserDto; @@ -23,7 +21,6 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; - @Override @Transactional public UserDto addUser(UserDto userDto) { @@ -38,7 +35,6 @@ public UserDto updateUser(UserDto userDto) { log.warn("Пользователь с указанным id не найден"); throw new NotFoundException("Пользователь с id = " + userDto.getId() + " не найден"); } - User newUser = getUser(userDto.getId()); if (userDto.getName() != null) { newUser.setName(userDto.getName()); @@ -68,4 +64,4 @@ public User getUser(Long id) { public void deleteUser(Long id) { userRepository.deleteById(id); } -} +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6fd9fb5..01e8511 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,8 +9,8 @@ logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG #spring.datasource.driverClassName=org.postgresql.Driver #spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit -#spring.datasource.username=dbuser -#spring.datasource.password=12345 +#spring.datasource.username=ca +#spring.datasource.password=12345678 spring.datasource.driverClassName=org.h2.Driver spring.datasource.url=jdbc:h2:mem:testdb From 6c9ce8c9d8a2b6ff6afb57df96c797bd80169eae Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sun, 29 Mar 2026 18:33:40 +0300 Subject: [PATCH 09/11] checkstyle --- .../practicum/shareit/booking/service/BookingServiceImpl.java | 2 +- .../java/ru/practicum/shareit/item/service/ItemServiceImpl.java | 2 +- .../java/ru/practicum/shareit/user/service/UserServiceImpl.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java index 9a69b5a..87396bf 100644 --- a/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/service/BookingServiceImpl.java @@ -23,7 +23,7 @@ @Service @AllArgsConstructor -public class BookingServiceImpl implements BookingService{ +public class BookingServiceImpl implements BookingService { private final BookingRepository bookingRepository; private final UserRepository userRepository; diff --git a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java index cca085b..e25ce6e 100644 --- a/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/service/ItemServiceImpl.java @@ -157,7 +157,7 @@ public CommentDto addComment(Long userId, Long itemId, Comment comment) { return toCommentDto(commentRepository.save(comment)); } - private ItemDto addCommentsToItem(ItemDto itemDto, Collection comments ) { + private ItemDto addCommentsToItem(ItemDto itemDto, Collection comments) { Collection commentsDto = comments.stream() .map(CommentMapper::toCommentDto) .toList(); diff --git a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java index 127aa73..2876ea8 100644 --- a/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/user/service/UserServiceImpl.java @@ -57,7 +57,7 @@ public List getAllUsers() { @Override public User getUser(Long id) { return userRepository.findById(id) - .orElseThrow(()-> new NotFoundException("Пользователь с id = " + id + " не найден")); + .orElseThrow(() -> new NotFoundException("Пользователь с id = " + id + " не найден")); } @Override From 7628c928aa7fac504c47bb8bc8f2579bda71922f Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Sun, 29 Mar 2026 18:40:13 +0300 Subject: [PATCH 10/11] checkstyle --- pom.xml | 2 +- src/main/resources/application.properties | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 165fb32..1b18148 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ com.h2database h2 - runtime + test diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 01e8511..d95862f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,12 +7,12 @@ logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG -#spring.datasource.driverClassName=org.postgresql.Driver -#spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit -#spring.datasource.username=ca -#spring.datasource.password=12345678 - -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.url=jdbc:postgresql://0.0.0.0:5432/shareit spring.datasource.username=dbuser spring.datasource.password=12345 + +#spring.datasource.driverClassName=org.h2.Driver +#spring.datasource.url=jdbc:h2:mem:testdb +#spring.datasource.username=dbuser +#spring.datasource.password=12345 From 6adbf6f32f3f5de3541b695ce4b13d892ed3339b Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Mon, 30 Mar 2026 10:38:48 +0300 Subject: [PATCH 11/11] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8=20=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=B2=D1=88=D0=B8=D1=85=D1=81=D1=8F=20=D0=BE=D1=88=D0=B8?= =?UTF-8?q?=D0=B1=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/practicum/shareit/exceptions/ErrorHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java b/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java index 970234e..871c064 100644 --- a/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java +++ b/src/main/java/ru/practicum/shareit/exceptions/ErrorHandler.java @@ -31,4 +31,11 @@ public ErrorResponse handleInternalServerException(final InternalServerException log.warn("Ошибка сервера"); return new ErrorResponse(e.getMessage()); } -} + + @ExceptionHandler + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse handleThrowable(final Throwable e) { + log.error("Непредвиденная ошибка"); + return new ErrorResponse(e.getMessage()); + } +} \ No newline at end of file