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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
db:
image: postgres:16.1
container_name: postgres
ports:
- "5432:5432"
volumes:
- ./volumes/postgres:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=shareit
- POSTGRES_USER=sa
- POSTGRES_PASSWORD=password
healthcheck:
test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER
timeout: 5s
interval: 5s
retries: 10
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
<optional>true</optional>
</dependency>

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

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
Expand Down
49 changes: 44 additions & 5 deletions src/main/java/ru/practicum/shareit/booking/BookingController.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,51 @@
package ru.practicum.shareit.booking;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.booking.dto.BookingDto;
import ru.practicum.shareit.booking.dto.RequestBookingDto;
import ru.practicum.shareit.booking.service.BookingService;

import java.util.Collection;

import static ru.practicum.shareit.util.Constants.USER_ID_HEADER;

/**
* TODO Sprint add-bookings.
*/
@RestController
@RequestMapping(path = "/bookings")
@RequiredArgsConstructor
public class BookingController {

private final BookingService bookingService;

@PostMapping
public BookingDto create(@RequestHeader(USER_ID_HEADER) Long userId,
@RequestBody RequestBookingDto booking) {
return bookingService.create(userId, booking);
}

@PatchMapping("/{bookingId}")
public BookingDto updateStatus(@RequestHeader(USER_ID_HEADER) Long userId,
@PathVariable Long bookingId,
@RequestParam Boolean approved) {
return bookingService.updateStatus(userId, bookingId, approved);
}

@GetMapping("/{bookingId}")
public BookingDto getById(@RequestHeader(USER_ID_HEADER) Long userId,
@PathVariable Long bookingId) {
return bookingService.getById(userId, bookingId);
}

@GetMapping
public Collection<BookingDto> getAllByBooker(@RequestHeader(USER_ID_HEADER) Long userId,
@RequestParam(defaultValue = "ALL") String state) {
return bookingService.getAllByBooker(userId, state);
}

@GetMapping("/owner")
public Collection<BookingDto> getAllByOwner(@RequestHeader(USER_ID_HEADER) Long userId,
@RequestParam(defaultValue = "ALL") String state) {
return bookingService.getAllByOwner(userId, state);
}

}
29 changes: 29 additions & 0 deletions src/main/java/ru/practicum/shareit/booking/BookingState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.practicum.shareit.booking;

import lombok.Getter;
import ru.practicum.shareit.exception.ValidationException;

import java.util.Arrays;

@Getter
public enum BookingState {
ALL("ALL"),
CURRENT("CURRENT"),
PAST("PAST"),
FUTURE("FUTURE"),
WAITING("WAITING"),
REJECTED("REJECTED");

private final String value;

BookingState(String value) {
this.value = value;
}

public static BookingState from(String text) {
return Arrays.stream(values())
.filter(s -> s.value.equalsIgnoreCase(text))
.findFirst()
.orElseThrow(() -> new ValidationException("Неизвестный статус бронирования: " + text));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import lombok.Data;
import lombok.experimental.FieldDefaults;
import ru.practicum.shareit.booking.BookingStatus;
import ru.practicum.shareit.item.model.Item;
import ru.practicum.shareit.user.model.User;
import ru.practicum.shareit.item.dto.ShortItemDto;
import ru.practicum.shareit.user.dto.ShortUserDto;

import java.time.LocalDateTime;

Expand All @@ -17,7 +17,7 @@ public class BookingDto {
Long id;
LocalDateTime start;
LocalDateTime end;
Item item;
User booker;
ShortItemDto item;
ShortUserDto booker;
BookingStatus status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.practicum.shareit.booking.dto;

import jakarta.validation.constraints.FutureOrPresent;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;

import java.time.LocalDateTime;

@Data
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
public class RequestBookingDto {
Long itemId;
@FutureOrPresent
LocalDateTime start;
LocalDateTime end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ru.practicum.shareit.booking.dto;

import jakarta.validation.constraints.FutureOrPresent;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.FieldDefaults;

import java.time.LocalDateTime;

@Data
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ShortBookingDto {
@FutureOrPresent
LocalDateTime start;
LocalDateTime end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ru.practicum.shareit.booking.mapper;

import lombok.experimental.UtilityClass;
import ru.practicum.shareit.booking.dto.BookingDto;
import ru.practicum.shareit.booking.dto.RequestBookingDto;
import ru.practicum.shareit.booking.dto.ShortBookingDto;
import ru.practicum.shareit.booking.model.Booking;
import ru.practicum.shareit.item.dto.ShortItemDto;
import ru.practicum.shareit.user.dto.ShortUserDto;

@UtilityClass
public class BookingMapper {

public static BookingDto toBookingDto(Booking booking) {
return BookingDto.builder()
.id(booking.getId())
.start(booking.getStart())
.end(booking.getEnd())
.item(ShortItemDto.builder()
.id(booking.getItem().getId())
.name(booking.getItem().getName())
.build())
.booker(ShortUserDto.builder()
.id(booking.getBooker().getId())
.build())
.status(booking.getStatus())
.build();
}

public static Booking toBookingFromRequest(RequestBookingDto bookingDto) {
return Booking.builder()
.start(bookingDto.getStart())
.end(bookingDto.getEnd())
.build();
}

public static ShortBookingDto toShortBookingDto(Booking booking) {
return ShortBookingDto.builder()
.start(booking.getStart())
.end(booking.getEnd())
.build();
}
}
23 changes: 20 additions & 3 deletions src/main/java/ru/practicum/shareit/booking/model/Booking.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package ru.practicum.shareit.booking.model;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.FieldDefaults;
import ru.practicum.shareit.booking.BookingStatus;
import ru.practicum.shareit.item.model.Item;
Expand All @@ -13,11 +12,29 @@
@Data
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "bookings")
public class Booking {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;

@Column(name = "start_date")
LocalDateTime start;

@Column(name = "end_date")
LocalDateTime end;

@ManyToOne
@JoinColumn(name = "item_id")
Item item;

@ManyToOne
@JoinColumn(name = "booker_id")
User booker;

@Enumerated(EnumType.STRING)
BookingStatus status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ru.practicum.shareit.booking.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import ru.practicum.shareit.booking.BookingStatus;
import ru.practicum.shareit.booking.model.Booking;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

public interface BookingRepository extends JpaRepository<Booking, Long> {
Collection<Booking> findAllByBookerIdOrderByStartDesc(Long bookerId);

Collection<Booking> findAllByBookerIdAndStatusOrderByStartDesc(Long bookerId, BookingStatus status);

Collection<Booking> findAllByBookerIdAndEndBeforeOrderByStartDesc(Long bookerId, LocalDateTime dateTime);

Collection<Booking> findAllByBookerIdAndStartAfterOrderByStartDesc(Long bookerId, LocalDateTime dateTime);

@Query("""
SELECT b FROM Booking b
WHERE b.booker.id = :bookerId
AND b.start <= CURRENT_TIMESTAMP
AND b.end >= CURRENT_TIMESTAMP
ORDER BY b.start DESC
""")
Collection<Booking> findAllCurrentBookingsByBookerId(Long bookerId);

Collection<Booking> findAllByItemOwnerIdOrderByStartDesc(Long ownerId);

Collection<Booking> findAllByItemOwnerIdAndStatusOrderByStartDesc(Long bookerId, BookingStatus status);

Collection<Booking> findAllByItemOwnerIdAndEndBeforeOrderByStartDesc(Long bookerId, LocalDateTime dateAfterEnd);

Collection<Booking> findAllByItemOwnerIdAndStartAfterOrderByStartDesc(Long bookerId, LocalDateTime dateBeforeStart);

@Query("""
SELECT b FROM Booking b
WHERE b.item.owner.id = :ownerId
AND b.start <= CURRENT_TIMESTAMP
AND b.end >= CURRENT_TIMESTAMP
ORDER BY b.start DESC
""")
Collection<Booking> findAllCurrentBookingsByItemOwnerId(Long ownerId);

@Query("""
SELECT b FROM Booking b
WHERE b.item.id IN :itemIds
AND b.status = 'APPROVED'
AND (b.end < CURRENT_TIMESTAMP OR b.start > CURRENT_TIMESTAMP)
ORDER BY b.item.id, b.start
""")
Collection<Booking> findAllBookingsForItems(List<Long> itemIds);

@Query("""
SELECT b FROM Booking b
JOIN FETCH b.item
JOIN FETCH b.booker
WHERE b.item.id = :itemId
AND b.booker.id = :userId
AND b.status = 'APPROVED'
AND b.end < CURRENT_TIMESTAMP
""")
Collection<Booking> findPastBookingsForUserByItemId(Long userId, Long itemId);

@Query("""
SELECT b FROM Booking b
WHERE b.item.id = :itemId
AND b.status = 'APPROVED'
""")
List<Booking> findAllByItemId(Long itemId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ru.practicum.shareit.booking.service;

import ru.practicum.shareit.booking.dto.BookingDto;
import ru.practicum.shareit.booking.dto.RequestBookingDto;

import java.util.Collection;

public interface BookingService {

BookingDto create(Long userId, RequestBookingDto booking);

BookingDto updateStatus(Long userId, Long bookingId, Boolean approved);

BookingDto getById(Long userId, Long bookingId);

Collection<BookingDto> getAllByBooker(Long userId, String state);

Collection<BookingDto> getAllByOwner(Long userId, String state);
}
Loading