개발 기록/도서관 관리 시스템

[Library Management System] 25.09.06 (39일)

dev.jelee 2025. 9. 6. 23:33

[ 작업한 내용 ]

1. 도서 대출 등록 기능 추가

1-1) Loan 엔티티

- id, user, book, loanDate, dueDate, returnDate, extended, status

- user와 book은 각 User, Book 엔티티와 연결. 

--- `@ManyToOne(optional = false)`를 사용하여 1대 다 관계를 정의해주고 반드시 값이 존재해야한다. `null`이면 안된다라는 것을 `optional = false`로 설정하기.

--- `@JoinColumn(name = ...)`을 사용하여 db의 실제 컬럼명을 추가해주기.

--- `@prePersist`를 사용하여 도서 대출 등록 시 자동으로 loanDate, dueDate, returnDate, extended, status 값 지정.


1-2) LoanStatus enum

- LOANED, RETURNED, OVERDUE, LOST


1-3. messages.properties

- 에러, 성공 메시지.

error.loan.not_found=해당 대출 기록을 찾을 수 없습니다.
error.loan.already_borrowed=이미 대출 중인 도서입니다.
error.loan.limit_exceeded=대출 가능 권수를 초과하였습니다.
error.loan.user_not_eligible=해당 사용자는 도서 대출이 불가능한 상태입니다.

success.loan.created=도서가 성공적으로 대출되었습니다.

 


1-4) LoanSuccessCode

- 도서 대출 등록 시 성공 코드.

LOAN_CRATED_SUCCESS(HttpStatus.CREATED, "LOAN_200", "success.loan.created");

1-5) LoanErrorCode

- 도서 대출 등록 시 발생하는 예외 상황에 사용할 에러코드.

LOAN_NOT_FOUND(HttpStatus.NOT_FOUND, "LOAN_404", "error.loan.not_found");
LOAN_ALREADY_BORROWED(HttpStatus.CONFLICT, "LOAN_407", "error.loan.already_borrowed");
LOAN_LIMIT_EXCEEDED(HttpStatus.BAD_REQUEST, "LOAN_406", "error.loan.limit_exceeded");
USER_NOT_ELIGIBLE_FOR_LOAN(HttpStatus.FORBIDDEN, "LOAN_408", "error.loan.user_not_eligible");

1-6) AdminLoanCreateReqDTO

- 도서 대출 등록 시 요청받는 값.

- userId, bookId 필드.


1-7) AdminLoanCreateResDTO

- 도서 대출 등록 시 응답(반환) 값.

- id, borrower, borrwedBook

- Loan 엔티티를 파라미터로 받는 생성자 함수를 생성.


1-8) BorrowerDTO

- 사용자의 id와 usernmae만 관리하기 위해 DTO 생성

- id, username


1-9) BookSimpleDTO

- 책의 id와 title, status 관리하기 위해 DTO 생성

- id, title, status


1-10) AdminLoanController

- `POST` 방식의 HTTP 요청을 처리하며, 요청 본문(@RequestBody)에서 `AdminLoanCreateReqDTO` 데이터를 입력받는다.

- Service 계층으로 요청받은 DTO를 전달하여, 대출 등록 비즈니스 로직을 처리한 후, 응답 DTO인 `AdminLoanCreateResDTO`타입의 `responseDTO`에 반환 받는 값을 담는다.

- 성공메시지와 responseDTO를 클라이언트 측으로 반환한다.


1-11) AdminLoanService

- Conroller 계층으로 전달받은 `AdminLoanCreateRes DTO`타입의 `requestDTO`를 가지고 Repository 계층으로 Book과 User 데이터를 요청하고, 조회하여 가져온 데이터는 각 Book 엔티티의 book과 User 엔티티의 user에 담는다. 만약에 찾는 데이터가 없다면 예외를 발생시킨다.

--- 요청하는 데이터는 다음과 같다.

--- `findById(requestDTO.getBookId())`와 `.findByIdrequestDTO.getUserId())`

- 도서 대출 가능 여부 확인을 위해 book의 상태가 `AVAILABLE(대출 가능 상태)`인지 확인하고, 대출 가능 상태가 아니라면 예외를 발생시킨다.

- 사용자의 상태가 유효한지를 체크하기.

- 한 사람당 대출이 가능한 도서는 3권이 최대이다. 하나의 `userId`가 Loan의 `status`가 `LOANED`인 것을 찾아서 현재 몇 권을 대출한 상태인지 체크를하고 3권 이상이라면 예외를 발생시킨다.

- `.builder()`를 사용하여 대출 엔티티를 생성하고 Repository의 .save()를 사용하여 DB에 저장한다.

- 도서 상태 변경을 위해 `.setStatus()`를 사용하여 `BORROWED`로 상태를 저장해준다.

--- 도서 상태 변경을 하려면 JPA 특성상 @Transactional 어노테이션을 필수로 사용한다.

- Controller 계층으로 loan의 데이터를 가지고 AdminLoanCreateResDTO 인스턴스를 생성하여 반환한다.


1-12) AdminLoanRepository

- JpaRepository를 상속받는다.

- 사용자의 도서 대출건 수를 조회하기 위한 `countByUserAndStatus()` 메서드를 생성.


commit.
도서 대출 등록 성공(좌), 도서 대출 실패-이미 대출 중인 경우(중간), 도서 대출 실패-유효한 사용자가 아닌 경우(우)