diff --git a/src/main/java/org/folio/sample/controller/BookController.java b/src/main/java/org/folio/sample/controller/BookController.java index 365e5d9..eebb18a 100644 --- a/src/main/java/org/folio/sample/controller/BookController.java +++ b/src/main/java/org/folio/sample/controller/BookController.java @@ -76,7 +76,8 @@ public ResponseEntity getBook(UUID bookId) { HttpStatus.OK ); } - + /** {@inheritDoc} */ + @Override public ResponseEntity updateBook(UUID bookId, BookForCreationDTO newBook) { log.info("Called PUT /books/{}", bookId); @@ -85,4 +86,14 @@ public ResponseEntity updateBook(UUID bookId, BookForCreationDTO newBoo HttpStatus.OK ); } + /** {@inheritDoc} */ + @Override + public ResponseEntity> getAllAvailable() { + log.info("Called GET /books/available"); + + return new ResponseEntity<>( + bookService.findAllAvailable().stream().map(bookMapper::toDto).toList(), + HttpStatus.OK + ); + } } diff --git a/src/main/java/org/folio/sample/domain/entity/Book.java b/src/main/java/org/folio/sample/domain/entity/Book.java index 943ee8a..6fe1d4f 100644 --- a/src/main/java/org/folio/sample/domain/entity/Book.java +++ b/src/main/java/org/folio/sample/domain/entity/Book.java @@ -45,6 +45,13 @@ public class Book implements Serializable { @Column(name = "published_date") private LocalDate publishedDate; + /** + * If the book is available + */ + @NotNull + @Column(name = "available") + private Boolean available; + public boolean isPublishedInLeapYear() { if (this.getPublishedDate().getYear() % 4 != 0) { return false; diff --git a/src/main/java/org/folio/sample/domain/mapper/BookMapper.java b/src/main/java/org/folio/sample/domain/mapper/BookMapper.java index 087adca..e1fe7be 100644 --- a/src/main/java/org/folio/sample/domain/mapper/BookMapper.java +++ b/src/main/java/org/folio/sample/domain/mapper/BookMapper.java @@ -11,8 +11,10 @@ public interface BookMapper { BookMapper INSTANCE = Mappers.getMapper(BookMapper.class); + @Mapping(source = "available", target = "isAvailable") BookDTO toDto(Book source); @Mapping(target = "id", ignore = true) + @Mapping(source = "isAvailable", target = "available") Book fromDto(BookForCreationDTO source); } diff --git a/src/main/java/org/folio/sample/repository/BookRepository.java b/src/main/java/org/folio/sample/repository/BookRepository.java index 9e19b6d..4f68500 100644 --- a/src/main/java/org/folio/sample/repository/BookRepository.java +++ b/src/main/java/org/folio/sample/repository/BookRepository.java @@ -1,12 +1,17 @@ package org.folio.sample.repository; +import java.util.List; import java.util.UUID; import org.folio.sample.domain.entity.Book; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; /** * A {@link org.springframework.data.jpa.repository.JpaRepository} of {@link org.folio.sample.domain.entity.Book} objects */ @Repository -public interface BookRepository extends JpaRepository {} +public interface BookRepository extends JpaRepository { + @Query("SELECT b FROM Book b WHERE b.available = true") + List findAllAvailable(); +} diff --git a/src/main/java/org/folio/sample/service/BookService.java b/src/main/java/org/folio/sample/service/BookService.java index 889b403..b0a0a36 100644 --- a/src/main/java/org/folio/sample/service/BookService.java +++ b/src/main/java/org/folio/sample/service/BookService.java @@ -45,4 +45,8 @@ public Book updateBook (UUID id, Book newBook){ return bookRepository.save(book); } + + public List findAllAvailable(){ + return bookRepository.findAllAvailable(); + } } diff --git a/src/main/resources/api/api.yaml b/src/main/resources/api/api.yaml index 2387f0c..9d5f822 100644 --- a/src/main/resources/api/api.yaml +++ b/src/main/resources/api/api.yaml @@ -93,3 +93,17 @@ paths: $ref: "./schemas/book.yaml" "404": description: The book was not found + /books/available: + get: + summary: Get available books + description: Get all available books + operationId: getAllAvailable + responses: + "200": + description: All available books + content: + application/json: + schema: + type: array + items: + $ref: "./schemas/book.yaml" diff --git a/src/main/resources/api/schemas/bookForCreation.yaml b/src/main/resources/api/schemas/bookForCreation.yaml index c0931c6..4f56412 100644 --- a/src/main/resources/api/schemas/bookForCreation.yaml +++ b/src/main/resources/api/schemas/bookForCreation.yaml @@ -8,6 +8,10 @@ properties: type: string format: date description: When the book was published + isAvailable: + type: boolean + description: The books availability required: - name - publishedDate + - isAvailable diff --git a/src/main/resources/db/changes/0010-add-available-column.yaml b/src/main/resources/db/changes/0010-add-available-column.yaml new file mode 100644 index 0000000..db0b4e5 --- /dev/null +++ b/src/main/resources/db/changes/0010-add-available-column.yaml @@ -0,0 +1,15 @@ +databaseChangeLog: + - changeSet: + id: 0010-add-available-column + author: chellen + comment: add available column to books table + changes: + - addColumn: + tableName: books + columns: + - column: + name: available + type: boolean + constraints: + nullable: true + defaultValueBoolean: true \ No newline at end of file diff --git a/src/test/java/org/folio/sample/integration/api/books/GetAllAvailableTest.java b/src/test/java/org/folio/sample/integration/api/books/GetAllAvailableTest.java new file mode 100644 index 0000000..a1a8d84 --- /dev/null +++ b/src/test/java/org/folio/sample/integration/api/books/GetAllAvailableTest.java @@ -0,0 +1,71 @@ +package org.folio.sample.integration.api.books; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; + +import io.restassured.common.mapper.TypeRef; +import io.restassured.response.Response; +import java.time.LocalDate; +import java.util.List; +import org.folio.sample.domain.dto.BookDTO; +import org.folio.sample.domain.dto.BookForCreationDTO; +import org.folio.sample.integration.AbstractBaseApiTest; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; + +class GetAllAvailableTest extends AbstractBaseApiTest { + + @Test + void testEmptyGet(){ + + Response response = ra() + .get(getRequestUrl("books/available")); + response.then().statusCode(is(HttpStatus.OK.value())); + + List collection = response + .body() + .as(new TypeRef>() {}); + assertThat(collection, hasSize(0)); + } + + @Test + void testGetWithBooks(){ + ra() + .body( + BookForCreationDTO + .builder() + .name("book 1") + .publishedDate(LocalDate.of(2020, 1, 1)) + .isAvailable(true) + .build() + ) + .post(getRequestUrl("books")) + .then() + .statusCode(is(HttpStatus.CREATED.value())); + + ra() + .body( + BookForCreationDTO + .builder() + .name("book 2") + .publishedDate(LocalDate.of(2020, 1, 1)) + .isAvailable(false) + .build() + ) + .post(getRequestUrl("books")) + .then() + .statusCode(is(HttpStatus.CREATED.value())); + + Response response = ra() + .get(getRequestUrl("books/available")); + response.then().statusCode(is(HttpStatus.OK.value())); + + List collection = response + .body() + .as(new TypeRef>() {}); + assertThat(collection, hasSize(1)); + assertThat(collection.get(0).getName(), is(equalTo("book 1"))); + } +} diff --git a/src/test/java/org/folio/sample/integration/api/books/UpdateBookTest.java b/src/test/java/org/folio/sample/integration/api/books/UpdateBookTest.java index f12eb7d..551dbf9 100644 --- a/src/test/java/org/folio/sample/integration/api/books/UpdateBookTest.java +++ b/src/test/java/org/folio/sample/integration/api/books/UpdateBookTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.Matchers.is; import io.restassured.response.Response; +import net.minidev.json.JSONObject; import java.time.LocalDate; import java.util.UUID; @@ -39,20 +40,25 @@ void testUpdate(){ UUID createdId = postResponse.as(BookDTO.class).getId(); + JSONObject updateInfo = new JSONObject(); + + updateInfo.put("name", "updated book"); + updateInfo.put("publishedDate", LocalDate.of(2024, 1, 1)); + updateInfo.put("isAvailable", true); + Response putResponse = ra() - .body( - BookForCreationDTO - .builder() - .name("updated book") - .publishedDate(LocalDate.of(2020, 1, 1)) - .build() - ) + .body(updateInfo) .pathParam("id", createdId) .put(getRequestUrl("books/{id}")); putResponse.then().statusCode(is(HttpStatus.OK.value())); + + Response getResponse = ra() + .pathParam("id", createdId) + .get(getRequestUrl("books/{id}")); + getResponse.then().statusCode(is(HttpStatus.OK.value())); - BookDTO book = putResponse.getBody().as(BookDTO.class); + BookDTO book = getResponse.getBody().as(BookDTO.class); assertThat(book.getName(), is(equalTo("updated book"))); - assertThat(book.getPublishedDate(), is(equalTo(LocalDate.of(2020, 1, 1)))); + assertThat(book.getPublishedDate(), is(equalTo(LocalDate.of(2024, 1, 1)))); } }