Skip to content

Commit

Permalink
Merge pull request #33 from saneci/feature/check_for_book_overdue
Browse files Browse the repository at this point in the history
Check for book overdue
  • Loading branch information
saneci authored Feb 14, 2024
2 parents 518d493 + 59a7d9a commit ec652f9
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# Project
target
*.properties
src/main/resources/*.properties

# Compiled class file
*.class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public String getBookById(@PathVariable("id") Long id, Model model, @ModelAttrib
@PatchMapping("/{id}/assign")
public String assignBookToTheReader(@PathVariable("id") Long id, @ModelAttribute("person") Person person) {
log.debug("assignBookToTheReader: start processing");
bookService.updatePersonId(id, person.getId());
bookService.updatePersonId(id, person);
log.debug("assignBookToTheReader: finish processing");

return REDIRECT_TO_BOOK.replace("{id}", String.valueOf(id));
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/ru/saneci/booklibrary/domain/Book.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;

import java.time.LocalDateTime;

@Entity
@Table(name = "book")
public class Book {
Expand All @@ -21,7 +24,7 @@ public class Book {
@Column(name = "id")
private Long id;

@Pattern(regexp = "([А-Я]|[A-Z]).{1,100}",
@Pattern(regexp = "([А-ЯA-Z]).{1,100}",
message = "Название книги должно начинаться с заглавной буквы и содержать от 2 до 100 символов")
@Column(name = "title")
private String title;
Expand All @@ -35,6 +38,12 @@ public class Book {
@Column(name = "publish_year")
private int publishYear;

@Column(name = "given_at")
private LocalDateTime givenAt;

@Transient
private boolean isOverdue;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", referencedColumnName = "id")
private Person person;
Expand Down Expand Up @@ -80,6 +89,22 @@ public void setPublishYear(int publishYear) {
this.publishYear = publishYear;
}

public LocalDateTime getGivenAt() {
return givenAt;
}

public void setGivenAt(LocalDateTime givenAt) {
this.givenAt = givenAt;
}

public boolean isOverdue() {
return isOverdue;
}

public void setOverdue(boolean overdue) {
isOverdue = overdue;
}

public Person getPerson() {
return person;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package ru.saneci.booklibrary.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import ru.saneci.booklibrary.domain.Book;
import ru.saneci.booklibrary.domain.Person;

import java.util.List;
import java.util.Optional;
Expand All @@ -16,9 +14,5 @@ public interface BookRepository extends JpaRepository<Book, Long> {
@Query("select b from Book b left join fetch b.person where b.id = ?1")
Optional<Book> findBookWithPersonById(Long id);

@Modifying
@Query("update Book b set b.person = ?1 where b.id = ?2")
int updatePersonId(Person person, Long bookId);

List<Book> findAllByTitleContainsIgnoreCase(String title);
}
31 changes: 15 additions & 16 deletions src/main/java/ru/saneci/booklibrary/service/BookService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import ru.saneci.booklibrary.domain.Book;
import ru.saneci.booklibrary.domain.Person;
import ru.saneci.booklibrary.repository.BookRepository;
import ru.saneci.booklibrary.repository.PersonRepository;

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

Expand All @@ -20,12 +20,10 @@
public class BookService {

private final BookRepository bookRepository;
private final PersonRepository personRepository;

@Autowired
public BookService(BookRepository bookRepository, PersonRepository personRepository) {
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
this.personRepository = personRepository;
}

public List<Book> findAll(String title) {
Expand Down Expand Up @@ -53,21 +51,22 @@ public void save(Book book) {

@Transactional
public void update(Book book) {
if (book.getPerson() == null) {
bookRepository.findBookWithPersonById(book.getId()).ifPresent(b -> book.setPerson(b.getPerson()));
}
bookRepository.save(book);
bookRepository.findById(book.getId()).ifPresent(b -> {
b.setTitle(book.getTitle());
b.setAuthor(book.getAuthor());
b.setPublishYear(book.getPublishYear());
});
}

@Transactional
public void updatePersonId(Long bookId, Long personId) {
Person person = null;

if (personId != null) {
person = personRepository.getReferenceById(personId);
}

bookRepository.updatePersonId(person, bookId);
public void updatePersonId(Long bookId, Person person) {
bookRepository.findById(bookId).ifPresent(b -> {
b.setPerson(person);
if (person != null)
b.setGivenAt(LocalDateTime.now());
else
b.setGivenAt(null);
});
}

@Transactional
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/ru/saneci/booklibrary/service/PersonService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package ru.saneci.booklibrary.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.saneci.booklibrary.domain.Book;
import ru.saneci.booklibrary.domain.Person;
import ru.saneci.booklibrary.repository.PersonRepository;

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

Expand All @@ -14,6 +17,9 @@ public class PersonService {

private final PersonRepository personRepository;

@Value("${spring.application.days_until_book_overdue}")
private int daysToBookOverdue;

public PersonService(PersonRepository personRepository) {
this.personRepository = personRepository;
}
Expand All @@ -27,7 +33,19 @@ public Optional<Person> findById(Long id) {
}

public Optional<Person> findPersonWithBooksById(Long id) {
return personRepository.findPersonWithBooksById(id);
Optional<Person> person = personRepository.findPersonWithBooksById(id);

if (person.isPresent()) {
List<Book> bookList = person.get().getBookList();
LocalDateTime overdueDateTime = LocalDateTime.now().minusDays(daysToBookOverdue);
bookList.forEach(book -> {
if (book.getGivenAt() != null && book.getGivenAt().isBefore(overdueDateTime)) {
book.setOverdue(true);
}
});
}

return person;
}

@Transactional
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/application.properties.origin
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ spring.datasource.url=jdbc:postgresql://[database_host]:[database_port]/[databas
spring.datasource.username=
spring.datasource.password=
spring.datasource.format_sql=false
spring.datasource.highlight_sql=true
spring.datasource.highlight_sql=true

spring.application.days_until_book_overdue=10
2 changes: 2 additions & 0 deletions src/main/resources/db/migration/r-2024-1/deploy-24-1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE book
ADD COLUMN given_at timestamp;
2 changes: 2 additions & 0 deletions src/main/resources/db/migration/r-2024-1/rollback-24-1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE book
DROP COLUMN given_at;
12 changes: 11 additions & 1 deletion src/main/webapp/WEB-INF/views/people/person.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ <h5 class="card-title" th:text="${person.getName() + ', ' + person.getBirthdayYe
<div th:if="${!person.getBookList().isEmpty()}">
<h6 class="card-text">Книги:</h6>
<ol class="list-group list-group-numbered">
<li class="list-group-item list-group-item-action" th:each="book : ${person.getBookList()}">
<li class="list-group-item list-group-item-action" th:each="book : ${person.getBookList()}"
th:classappend="${book.isOverdue()} ? 'bg-danger-subtle'">
<a class="stretched-link link-dark text-decoration-none"
th:href="@{/books/{id}(id=${book.getId()})}"
th:text="${book.getTitle() + ', ' + book.getAuthor() + ', ' + book.getPublishYear()}">Book</a>
Expand All @@ -43,5 +44,14 @@ <h6 class="card-text">Книги:</h6>
</div>
<div th:replace="fragments/modal :: deleteConfirmationModal(${person.getName()}, @{/people/{id}(id=${person.getId()})})"></div>
</section>
<section id="customJavaScript">
<script>
document.querySelectorAll(".bg-danger-subtle")
.forEach(element => {
element.setAttribute("data-bs-toggle", "tooltip");
element.setAttribute("data-bs-title", 'Книга просрочена');
})
</script>
</section>
</body>
</html>
5 changes: 4 additions & 1 deletion src/test/java/ru/saneci/booklibrary/BaseControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public abstract class BaseControllerTest {
getContainerInitDatabasePath("deploy-23-1.sql"))
.withCopyFileToContainer(
getDatabaseMigrationFile("r-2023-2/deploy-23-2.sql"),
getContainerInitDatabasePath("deploy-23-2.sql"));
getContainerInitDatabasePath("deploy-23-2.sql"))
.withCopyFileToContainer(
getDatabaseMigrationFile("r-2024-1/deploy-24-1.sql"),
getContainerInitDatabasePath("deploy-24-1.sql"));
}

private static MountableFile getDatabaseMigrationFile(String fileName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ void whenGetAllReaders_thenPeopleViewShouldContainRightLayout() throws Exception
.andExpect(xpath("//*[@id='peopleList']/table").exists());
}

// ------------------------------------------------ getReaderById --------------------------------------------------

@Test
void whenGetReaderById_thenPersonViewShouldContainRightLayout() throws Exception {
mockMvc.perform(get("/people/{id}", 1))
Expand All @@ -47,6 +49,24 @@ void whenGetReaderByIdModelAttributeBookListIsEmpty_thenViewPersonShouldContainA
.andExpect(xpath("//*[@id='personInfo']/div/div/div/p").string("Человек пока не взял не одной книги"));
}

@Test
@Sql(scripts = "/sql/people_controller/create-overdue-book.sql")
void whenGetReaderByIdReturnOverdueBook_thenThisBookShouldBeHighlightedInRed() throws Exception {
mockMvc.perform(get("/people/{id}", 1))
.andExpect(status().isOk())
.andExpect(xpath("//*[@id='personInfo']/div/div/div/ol/li[contains(@class, 'bg-danger-subtle')]").exists());
}

@Test
@Sql(scripts = "/sql/people_controller/create-not-overdue-book.sql")
void whenGetReaderByIdReturnNotOverdueBook_thenThisBookShouldNotBeHighlightedInRed() throws Exception {
mockMvc.perform(get("/people/{id}", 1))
.andExpect(status().isOk())
.andExpect(xpath("//*[@id='personInfo']/div/div/div/ol/li[contains(@class, 'bg-danger-subtle')]").doesNotExist());
}

// -----------------------------------------------getNewPeopleView -------------------------------------------------

@Test
void whenGetNewPeopleView_thenNewViewShouldContainRightLayout() throws Exception {
mockMvc.perform(get("/people/new"))
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
spring.application.days_until_book_overdue=10
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
truncate book, person;

insert into person (id, name, birthday_year) values (1, 'Test User Name', 2020);

insert into book (id, person_id, title, author, publish_year, given_at)
values (1, 1, 'Test Book', 'Test Author', 1234, now() - interval '9 days');
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
truncate book, person;

insert into person (id, name, birthday_year) values (1, 'Test User Name', 2020);

insert into book (id, person_id, title, author, publish_year, given_at)
values (1, 1, 'Test Book', 'Test Author', 1234, now() - interval '10 days');

0 comments on commit ec652f9

Please sign in to comment.