diff --git a/README.md b/README.md new file mode 100644 index 0000000000..3ce63aa39b --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# 요구사항 문서 + +- [x] localhost:8080/admin 요청 시 어드민 메인 페이지가 응답할 수 있도록 구현한다. +- [x] 어드민 메인 페이지는 templates/admin/index.html 파일을 이용한다. +- [x] localhost:8080/admin/reservation 요청 시 아래 화면과 같이 예약 관리 페이지가 응답할 수 있도록 구현한다. +- [x] 페이지는 templates/admin/reservation-legacy.html 파일을 이용한다. +- [x] 예약 조회 API 명세를 따라 예약 관리 페이지 로드 시 호출되는 예약 목록 조회 API를 구현한다. +- [x] API 명세를 따라 예약 추가 API 와 삭제 API를 구현한다. +- [x] 예약 추가와 취소가 잘 동작한다. +- [x] 이상의 요구 사항을 데이터베이스와 연동하도록 한다. + +# API 명세 + +## 예약 조회 API + +### Request + +> GET /reservations HTTP/1.1 + +### Response + +> HTTP/1.1 200 +> +> Content-Type: application/json + +``` JSON +[ + { + "id": 1, + "name": "브라운", + "date": "2023-01-01", + "time": "10:00" + }, + { + "id": 2, + "name": "브라운", + "date": "2023-01-02", + "time": "11:00" + } +] +``` + +## 예약 추가 API + +### Request + +> POST /reservations HTTP/1.1 +> +> content-type: application/json + +```JSON +{ + "date": "2023-08-05", + "name": "브라운", + "time": "15:40" +} +``` + +### Response + +> HTTP/1.1 200 +> +> Content-Type: application/json + +```JSON +{ + "id": 1, + "name": "브라운", + "date": "2023-08-05", + "time": "15:40" +} +``` + +## 예약 취소 API + +### Request + +> DELETE /reservations/1 HTTP/1.1 + +### Response + +> HTTP/1.1 200 diff --git a/src/main/java/roomescape/RoomescapeApplication.java b/src/main/java/roomescape/RoomEscapeApplication.java similarity index 68% rename from src/main/java/roomescape/RoomescapeApplication.java rename to src/main/java/roomescape/RoomEscapeApplication.java index 7027067919..7d35e71a6b 100644 --- a/src/main/java/roomescape/RoomescapeApplication.java +++ b/src/main/java/roomescape/RoomEscapeApplication.java @@ -4,9 +4,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class RoomescapeApplication { +public class RoomEscapeApplication { public static void main(String[] args) { - SpringApplication.run(RoomescapeApplication.class, args); + SpringApplication.run(RoomEscapeApplication.class, args); } } diff --git a/src/main/java/roomescape/config/TimeFormatterConfig.java b/src/main/java/roomescape/config/TimeFormatterConfig.java new file mode 100644 index 0000000000..35c20b11b1 --- /dev/null +++ b/src/main/java/roomescape/config/TimeFormatterConfig.java @@ -0,0 +1,17 @@ +package roomescape.config; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import java.time.format.DateTimeFormatter; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TimeFormatterConfig { + private static final String TIME_FORMAT = "HH:mm"; + + @Bean + public Jackson2ObjectMapperBuilderCustomizer localTimeSerializerCustomizer() { + return builder -> builder.serializers(new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMAT))); + } +} diff --git a/src/main/java/roomescape/controller/AdminController.java b/src/main/java/roomescape/controller/AdminController.java new file mode 100644 index 0000000000..bbdf823485 --- /dev/null +++ b/src/main/java/roomescape/controller/AdminController.java @@ -0,0 +1,19 @@ +package roomescape.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/admin") +public class AdminController { + @GetMapping + public String mainPage() { + return "admin/index"; + } + + @GetMapping("/reservation") + public String reservationPage() { + return "admin/reservation-legacy"; + } +} diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java new file mode 100644 index 0000000000..debbf9db40 --- /dev/null +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -0,0 +1,48 @@ +package roomescape.controller; + +import java.util.List; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; +import roomescape.dto.ReservationResponse; +import roomescape.repository.ReservationRepository; + +@RestController +@RequestMapping("/reservations") +public class ReservationController { + private final ReservationRepository reservationRepository; + + public ReservationController(ReservationRepository reservationRepository) { + this.reservationRepository = reservationRepository; + } + + @PostMapping + public ReservationResponse saveReservation(@RequestBody ReservationRequest reservationRequest) { + Reservation reservation = reservationRepository.save(reservationRequest); + return toResponse(reservation); + } + + private ReservationResponse toResponse(Reservation reservation) { + return new ReservationResponse(reservation.getId(), + reservation.getName(), reservation.getDate(), reservation.getTime()); + } + + @GetMapping + public List findAllReservations() { + return reservationRepository.findAll() + .stream() + .map(this::toResponse) + .toList(); + } + + @DeleteMapping("/{reservationId}") + public void delete(@PathVariable long reservationId) { + reservationRepository.delete(reservationId); + } +} diff --git a/src/main/java/roomescape/domain/Reservation.java b/src/main/java/roomescape/domain/Reservation.java new file mode 100644 index 0000000000..4c0eed4877 --- /dev/null +++ b/src/main/java/roomescape/domain/Reservation.java @@ -0,0 +1,50 @@ +package roomescape.domain; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +public class Reservation implements Comparable { + private final long id; + private final String name; + private final LocalDateTime dateTime; + + public Reservation(long id, Reservation reservationBeforeSave) { + this(id, reservationBeforeSave.name, reservationBeforeSave.dateTime); + } + + public Reservation(long id, String name, LocalDateTime dateTime) { + this.id = id; + this.name = name; + this.dateTime = dateTime; + } + + public Reservation(long id, String name, LocalDate date, LocalTime time) { + this(id, name, LocalDateTime.of(date, time)); + } + + @Override + public int compareTo(Reservation other) { + return dateTime.compareTo(other.dateTime); + } + + public boolean hasSameId(long id) { + return this.id == id; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDate getDate() { + return dateTime.toLocalDate(); + } + + public LocalTime getTime() { + return dateTime.toLocalTime(); + } +} diff --git a/src/main/java/roomescape/dto/ReservationRequest.java b/src/main/java/roomescape/dto/ReservationRequest.java new file mode 100644 index 0000000000..926358e1df --- /dev/null +++ b/src/main/java/roomescape/dto/ReservationRequest.java @@ -0,0 +1,7 @@ +package roomescape.dto; + +import java.time.LocalDate; +import java.time.LocalTime; + +public record ReservationRequest(LocalDate date, String name, LocalTime time) { +} diff --git a/src/main/java/roomescape/dto/ReservationResponse.java b/src/main/java/roomescape/dto/ReservationResponse.java new file mode 100644 index 0000000000..6e9d6cfd31 --- /dev/null +++ b/src/main/java/roomescape/dto/ReservationResponse.java @@ -0,0 +1,7 @@ +package roomescape.dto; + +import java.time.LocalDate; +import java.time.LocalTime; + +public record ReservationResponse(long id, String name, LocalDate date, LocalTime time) { +} diff --git a/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java b/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java new file mode 100644 index 0000000000..8bd0547c16 --- /dev/null +++ b/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java @@ -0,0 +1,62 @@ +package roomescape.repository; + +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.Time; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; + +@Repository +public class JdbcTemplateReservationRepository implements ReservationRepository { + private final JdbcTemplate jdbcTemplate; + + public JdbcTemplateReservationRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Reservation save(ReservationRequest reservationRequest) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + Reservation reservation = fromRequest(reservationRequest); + jdbcTemplate.update(con -> { + PreparedStatement preparedStatement = con.prepareStatement( + "insert into reservation (name, date,time) values ( ?,?,? )", new String[]{"id"}); + preparedStatement.setString(1, reservation.getName()); + preparedStatement.setDate(2, Date.valueOf(reservation.getDate())); + preparedStatement.setTime(3, Time.valueOf(reservation.getTime())); + return preparedStatement; + }, keyHolder); + return new Reservation(keyHolder.getKey().longValue(), reservation); + } + + @Override + public List findAll() { + return jdbcTemplate.query("select * from reservation", (rs, rowNum) -> { + long id = rs.getLong("id"); + String name = rs.getString("name"); + LocalDate date = rs.getDate("date").toLocalDate(); + LocalTime time = rs.getTime("time").toLocalTime(); + return new Reservation(id, name, date, time); + }); + } + + @Override + public void delete(long reservationId) { + jdbcTemplate.update("delete from reservation where id = ?", reservationId); + } + + private Reservation fromRequest(ReservationRequest reservationRequest) { + long id = 1L; + String name = reservationRequest.name(); + LocalDate date = reservationRequest.date(); + LocalTime time = reservationRequest.time(); + return new Reservation(id, name, date, time); + } +} diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java new file mode 100644 index 0000000000..1ab97aef1b --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -0,0 +1,13 @@ +package roomescape.repository; + +import java.util.List; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; + +public interface ReservationRepository { + Reservation save(ReservationRequest reservationRequest); + + List findAll(); + + void delete(long reservationId); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29bb2..63c01678ab 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:product diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..c36eb34855 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS reservation +( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + date VARCHAR(255) NOT NULL, + time VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); diff --git a/src/main/resources/templates/admin/index.html b/src/main/resources/templates/admin/index.html index 417102cf1c..ca96065ec6 100644 --- a/src/main/resources/templates/admin/index.html +++ b/src/main/resources/templates/admin/index.html @@ -1,4 +1,3 @@ - @@ -15,17 +14,17 @@ LOGO diff --git a/src/main/resources/templates/admin/reservation.html b/src/main/resources/templates/admin/reservation.html index f31714eb74..f5e101fd68 100644 --- a/src/main/resources/templates/admin/reservation.html +++ b/src/main/resources/templates/admin/reservation.html @@ -15,17 +15,17 @@ LOGO diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java deleted file mode 100644 index 6f7b197915..0000000000 --- a/src/test/java/roomescape/MissionStepTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package roomescape; - -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -public class MissionStepTest { - - @Test - void 일단계() { - RestAssured.given().log().all() - .when().get("/") - .then().log().all() - .statusCode(200); - } - -} diff --git a/src/test/java/roomescape/controller/AdminControllerTest.java b/src/test/java/roomescape/controller/AdminControllerTest.java new file mode 100644 index 0000000000..8ec1965cab --- /dev/null +++ b/src/test/java/roomescape/controller/AdminControllerTest.java @@ -0,0 +1,25 @@ +package roomescape.controller; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class AdminControllerTest { + @Test + @DisplayName("관리자 메인 페이지 경로를 정해진 경로로 매핑한다.") + void mainPage() { + AdminController adminController = new AdminController(); + String mainPage = adminController.mainPage(); + Assertions.assertThat(mainPage) + .isEqualTo("admin/index"); + } + + @Test + @DisplayName("관리자 예약 정보 페이지 경로를 정해진 경로로 매핑한다.") + void reservationPage() { + AdminController adminController = new AdminController(); + String reservationPage = adminController.reservationPage(); + Assertions.assertThat(reservationPage) + .isEqualTo("admin/reservation-legacy"); + } +} diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java new file mode 100644 index 0000000000..1d6d608be6 --- /dev/null +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -0,0 +1,61 @@ +package roomescape.controller; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; +import roomescape.dto.ReservationResponse; +import roomescape.repository.CollectionReservationRepository; + +class ReservationControllerTest { + @Test + @DisplayName("예약 정보를 잘 저장하는지 확인한다.") + void saveReservation() { + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository(); + ReservationController reservationController = new ReservationController(collectionReservationRepository); + LocalDate date = LocalDate.now(); + LocalTime time = LocalTime.now(); + + ReservationResponse saveResponse = reservationController.saveReservation( + new ReservationRequest(date, "폴라", time)); + + long id = Objects.requireNonNull(saveResponse).id(); + ReservationResponse expected = new ReservationResponse(id, "폴라", date, time); + + Assertions.assertThat(saveResponse) + .isEqualTo(expected); + } + + @Test + @DisplayName("예약 정보를 잘 불러오는지 확인한다.") + void findAllReservations() { + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository(); + ReservationController reservationController = new ReservationController(collectionReservationRepository); + List allReservations = reservationController.findAllReservations(); + + Assertions.assertThat(allReservations) + .isEmpty(); + } + + @Test + @DisplayName("예약 정보를 잘 지우는지 확인한다.") + void delete() { + List reservations = List.of(new Reservation(1, "폴라", LocalDateTime.now())); + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository( + new ArrayList<>(reservations)); + ReservationController reservationController = new ReservationController(collectionReservationRepository); + + reservationController.delete(1L); + List reservationResponses = reservationController.findAllReservations(); + + Assertions.assertThat(reservationResponses) + .isEmpty(); + } +} diff --git a/src/test/java/roomescape/domain/ReservationTest.java b/src/test/java/roomescape/domain/ReservationTest.java new file mode 100644 index 0000000000..9aae6fcc91 --- /dev/null +++ b/src/test/java/roomescape/domain/ReservationTest.java @@ -0,0 +1,18 @@ +package roomescape.domain; + +import java.time.LocalDateTime; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ReservationTest { + @Test + @DisplayName("날짜를 기준으로 비교를 잘 하는지 확인.") + void compareTo() { + Reservation first = new Reservation(1L, "폴라", LocalDateTime.of(1999, 12, 1, 16, 30)); + Reservation second = new Reservation(2L, "로빈", LocalDateTime.of(1998, 1, 8, 10, 30)); + int compareTo = first.compareTo(second); + Assertions.assertThat(compareTo) + .isGreaterThan(0); + } +} diff --git a/src/test/java/roomescape/infra/DBConnectionTest.java b/src/test/java/roomescape/infra/DBConnectionTest.java new file mode 100644 index 0000000000..8f856916a1 --- /dev/null +++ b/src/test/java/roomescape/infra/DBConnectionTest.java @@ -0,0 +1,36 @@ +package roomescape.infra; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootTest +public class DBConnectionTest { + @Autowired + private JdbcTemplate jdbcTemplate; + + @Test + @DisplayName("데이터베이스 접속이 잘 되는지 확인.") + void connectToDB() { + try (Connection connection = jdbcTemplate.getDataSource().getConnection()) { + assertConnection(connection); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void assertConnection(Connection connection) { + assertAll( + () -> assertThat(connection).isNotNull(), + () -> assertThat(connection.getCatalog()).isEqualTo("TEST"), + () -> assertThat(connection.getMetaData().getTables(null, null, "RESERVATION", null).next()).isTrue() + ); + } +} diff --git a/src/test/java/roomescape/integration/AdminIntegrationTest.java b/src/test/java/roomescape/integration/AdminIntegrationTest.java new file mode 100644 index 0000000000..2ed74c0a09 --- /dev/null +++ b/src/test/java/roomescape/integration/AdminIntegrationTest.java @@ -0,0 +1,117 @@ +package roomescape.integration; + +import static org.hamcrest.Matchers.is; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import java.util.HashMap; +import java.util.Map; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class AdminIntegrationTest { + @LocalServerPort + private int port; + @Autowired + private JdbcTemplate jdbcTemplate; + + @BeforeEach + void init() { + jdbcTemplate.update("delete from reservation"); + jdbcTemplate.update("ALTER TABLE reservation alter column id restart with 1"); + RestAssured.port = port; + } + + @Test + @DisplayName("관리자 메인 페이지가 잘 접속된다.") + void adminMainPageLoad() { + RestAssured.given().log().all() + .when().get("/admin") + .then().log().all() + .statusCode(200); + } + + @Test + @DisplayName("관리자 예약 페이지가 잘 접속된다.") + void adminReservationPageLoad() { + RestAssured.given().log().all() + .when().get("/admin/reservation") + .then().log().all() + .statusCode(200); + + RestAssured.given().log().all() + .when().get("/reservations") + .then().log().all() + .statusCode(200) + .body("size()", is(0)); + } + + @Test + @DisplayName("관리자 예약 페이지가 잘 동작한다.") + void adminReservationPageWork() { + Map params = new HashMap<>(); + params.put("name", "브라운"); + params.put("date", "2023-08-05"); + params.put("time", "15:40"); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/reservations") + .then().log().all() + .statusCode(200) + .body("id", is(1)); + + RestAssured.given().log().all() + .when().get("/reservations") + .then().log().all() + .statusCode(200) + .body("size()", is(1)); + + RestAssured.given().log().all() + .when().delete("/reservations/1") + .then().log().all() + .statusCode(200); + + RestAssured.given().log().all() + .when().get("/reservations") + .then().log().all() + .statusCode(200) + .body("size()", is(0)); + } + + @Test + @DisplayName("관리자 예약 페이지가 DB와 함께 잘 동작한다.") + void adminReservationPageWorkWithDB() { + Map params = new HashMap<>(); + params.put("name", "브라운"); + params.put("date", "2023-08-05"); + params.put("time", "10:00"); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/reservations") + .then().log().all() + .statusCode(200); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + Assertions.assertThat(count).isEqualTo(1); + + RestAssured.given().log().all() + .when().delete("/reservations/1") + .then().log().all() + .statusCode(200); + + Integer countAfterDelete = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + Assertions.assertThat(countAfterDelete).isEqualTo(0); + } +} diff --git a/src/test/java/roomescape/repository/CollectionReservationRepository.java b/src/test/java/roomescape/repository/CollectionReservationRepository.java new file mode 100644 index 0000000000..6c7fbe6aea --- /dev/null +++ b/src/test/java/roomescape/repository/CollectionReservationRepository.java @@ -0,0 +1,60 @@ +package roomescape.repository; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; + +public class CollectionReservationRepository implements ReservationRepository { + private final List reservations; + private final AtomicLong atomicLong; + + public CollectionReservationRepository() { + this(new ArrayList<>()); + } + + public CollectionReservationRepository(List reservations) { + this(reservations, new AtomicLong(0)); + } + + public CollectionReservationRepository(List reservations, AtomicLong atomicLong) { + this.reservations = reservations; + this.atomicLong = atomicLong; + } + + @Override + public Reservation save(ReservationRequest reservationRequest) { + Reservation reservation = fromRequest(reservationRequest); + reservations.add(reservation); + return reservation; + } + + private Reservation fromRequest(ReservationRequest reservationRequest) { + long id = atomicLong.incrementAndGet(); + + String name = reservationRequest.name(); + LocalDate date = reservationRequest.date(); + LocalTime time = reservationRequest.time(); + LocalDateTime dateTime = LocalDateTime.of(date, time); + return new Reservation(id, name, dateTime); + } + + @Override + public List findAll() { + return reservations.stream() + .sorted() + .toList(); + } + + @Override + public void delete(long reservationId) { + reservations.stream() + .filter(reservation -> reservation.hasSameId(reservationId)) + .findAny() + .ifPresent(reservations::remove); + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000000..b53e73970d --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,2 @@ +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:test