Skip to content

Commit

Permalink
feat: Interview READ API
Browse files Browse the repository at this point in the history
Body:
The commit introduces multiple important enhancements to the management and access of interview data. Major changes include:

1. Revised code in the InterviewController to call the new interviewFacadeService and retrieve paginated conversations and interview questions.
2. Added a custom query in ConversationRepository to retrieve paginated conversations based on interviewId.
3. Enhanced InterviewRepository with a custom query to fetch interview details along with their associated questions.
4. Implemented methods in InterviewFacadeService and InterviewQueryService to facilitate interview data retrieval.
5. Introduced InterviewMapper to map domain objects to response DTOs to fine-tune the response mechanism and enhance application efficiency.

The changes aim to enhance application efficiency and the ability to scale by optimizing data retrieval and reducing the unnecessary burden on server resources during heavy load situations.

Caveats:

Please note: client-side changes may be required to adapt to the new paginated data retrieval APIs.

References:
Issue #XYZ123
  • Loading branch information
sichoi42 committed Jul 22, 2024
1 parent 38a45a7 commit 3c5b9dd
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -42,9 +43,9 @@ public class InterviewController {
@ApiResponse(responseCode = "200", description = "ok"),
})
@ApiErrorCodeExample(
autobiographyExceptionStatuses = {
AutobiographyExceptionStatus.AUTOBIOGRAPHY_NOT_FOUND,
AutobiographyExceptionStatus.AUTOBIOGRAPHY_NOT_OWNER,
interviewExceptionStatuses = {
InterviewExceptionStatus.INTERVIEW_NOT_FOUND,
InterviewExceptionStatus.INTERVIEW_NOT_OWNER,
}
)
@PreAuthorize("isAuthenticated()")
Expand All @@ -55,7 +56,8 @@ public InterviewConversationResponseDto getInterviewConversations(
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {
return InterviewConversationResponseDto.builder().build();
return interviewFacadeService.getConversations(memberSessionDto.getMemberId(), interviewId,
PageRequest.of(page, size));
}

@Operation(summary = "인터뷰 질문 목록 조회", description = "인터뷰 질문 목록을 조회합니다.")
Expand All @@ -74,7 +76,7 @@ public InterviewQuestionResponseDto getInterviewQuestions(
@LoginMemberInfo MemberSessionDto memberSessionDto,
@PathVariable("interviewId") @Parameter(description = "인터뷰 ID", example = "1") Long interviewId
) {
return InterviewQuestionResponseDto.builder().build();
return interviewFacadeService.getQuestions(memberSessionDto.getMemberId(), interviewId);
}

@Operation(summary = "챗봇과의 대화 내역 전송 요청", description = "챗봇과의 대화 내역을 전송합니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
@Entity
@Table(name = "interviews")
@Getter
@ToString(callSuper = true, exclude = {"autobiography", "chapter", "member"})
@ToString(callSuper = true, exclude = {"autobiography", "chapter", "member",
"interviewConversations"})
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Interview {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.lifelibrarians.lifebookshelf.interview.repository;

import com.lifelibrarians.lifebookshelf.interview.domain.Conversation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;


public interface ConversationRepository extends JpaRepository<Conversation, Long> {

@Query("select c from Conversation c where c.interview.id = :interviewId")
Page<Conversation> findAllByInterviewId(Long interviewId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package com.lifelibrarians.lifebookshelf.interview.repository;

import com.lifelibrarians.lifebookshelf.interview.domain.Interview;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface InterviewRepository extends JpaRepository<Interview, Long> {

@Query("SELECT i FROM Interview i "
+ "JOIN FETCH i.questions "
+ "JOIN FETCH i.currentQuestion "
+ "WHERE i.id = :interviewId")
Optional<Interview> findWithQuestionsById(Long interviewId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import com.lifelibrarians.lifebookshelf.exception.status.InterviewExceptionStatus;
import com.lifelibrarians.lifebookshelf.interview.domain.Interview;
import com.lifelibrarians.lifebookshelf.interview.dto.request.InterviewConversationCreateRequestDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewConversationResponseDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewQuestionResponseDto;
import com.lifelibrarians.lifebookshelf.log.Logging;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -17,7 +20,23 @@ public class InterviewFacadeService {


/*-----------------------------------------READ-----------------------------------------*/
public InterviewConversationResponseDto getConversations(Long memberId, Long interviewId,
Pageable pageable) {
Interview interview = interviewQueryService.getInterview(interviewId);
if (!interview.getMember().getId().equals(memberId)) {
throw InterviewExceptionStatus.INTERVIEW_NOT_OWNER.toServiceException();
}
return interviewQueryService.getConversations(interview, pageable);
}

public InterviewQuestionResponseDto getQuestions(Long memberId, Long interviewId) {
Interview interview = interviewQueryService.getInterview(interviewId);
if (!interview.getMember().getId().equals(memberId)) {
throw InterviewExceptionStatus.INTERVIEW_NOT_OWNER.toServiceException();
}
return interviewQueryService.getQuestions(interview.getQuestions(),
interview.getCurrentQuestion());
}

/*-----------------------------------------CUD-----------------------------------------*/
public void createConversations(Long memberId, Long interviewId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package com.lifelibrarians.lifebookshelf.interview.service;

import com.lifelibrarians.lifebookshelf.exception.status.InterviewExceptionStatus;
import com.lifelibrarians.lifebookshelf.interview.domain.Conversation;
import com.lifelibrarians.lifebookshelf.interview.domain.Interview;
import com.lifelibrarians.lifebookshelf.interview.domain.InterviewQuestion;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewConversationDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewConversationResponseDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewQuestionDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewQuestionResponseDto;
import com.lifelibrarians.lifebookshelf.interview.repository.ConversationRepository;
import com.lifelibrarians.lifebookshelf.interview.repository.InterviewRepository;
import com.lifelibrarians.lifebookshelf.log.Logging;
import com.lifelibrarians.lifebookshelf.mapper.InterviewMapper;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -16,10 +27,42 @@
public class InterviewQueryService {

private final InterviewRepository interviewRepository;
private final ConversationRepository conversationRepository;
private final InterviewMapper interviewMapper;

public Interview getInterview(Long interviewId) {
return interviewRepository.findById(
return interviewRepository.findWithQuestionsById(
interviewId)
.orElseThrow(InterviewExceptionStatus.INTERVIEW_NOT_FOUND::toServiceException);
}

public InterviewConversationResponseDto getConversations(Interview interview, Pageable pageable) {
Page<Conversation> conversations = conversationRepository.findAllByInterviewId(
interview.getId(), pageable);
List<InterviewConversationDto> conversationDtos = conversations.stream()
.map(interviewMapper::toInterviewConversationDto)
.collect(Collectors.toList());
return interviewMapper.toInterviewConversationResponseDto(
conversationDtos,
pageable.getPageNumber(),
(int) conversations.getTotalElements(),
conversations.getTotalPages(),
conversations.hasNext(),
conversations.hasPrevious()
);
}

public InterviewQuestionResponseDto getQuestions(List<InterviewQuestion> questions,
InterviewQuestion currentQuestion) {
List<InterviewQuestionDto> questionDtos = questions.stream()
.map(interviewMapper::toInterviewQuestionDto)
.collect(Collectors.toList());

return interviewMapper.toInterviewQuestionResponseDto(currentQuestion.getId(), questionDtos);
}

// public Interview getInterviewWithQuestions(Long interviewId) {
// return interviewRepository.findWithQuestionsById(interviewId)
// .orElseThrow(InterviewExceptionStatus.INTERVIEW_NOT_FOUND::toServiceException);
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.lifelibrarians.lifebookshelf.mapper;

import com.lifelibrarians.lifebookshelf.interview.domain.Conversation;
import com.lifelibrarians.lifebookshelf.interview.domain.InterviewQuestion;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewConversationDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewConversationResponseDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewQuestionDto;
import com.lifelibrarians.lifebookshelf.interview.dto.response.InterviewQuestionResponseDto;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface InterviewMapper {

@Mapping(source = "conversation.id", target = "conversationId")
InterviewConversationDto toInterviewConversationDto(Conversation conversation);

@Mapping(source = "conversationDtos", target = "results")
InterviewConversationResponseDto toInterviewConversationResponseDto(
List<InterviewConversationDto> conversationDtos,
int currentPage,
int totalElements,
int totalPages,
boolean hasNextPage,
boolean hasPreviousPage
);

@Mapping(source = "questionDtos", target = "results")
InterviewQuestionResponseDto toInterviewQuestionResponseDto(
Long currentQuestionId,
List<InterviewQuestionDto> questionDtos
);

@Mapping(source = "interviewQuestion.id", target = "questionId")
InterviewQuestionDto toInterviewQuestionDto(InterviewQuestion interviewQuestion);
}

0 comments on commit 3c5b9dd

Please sign in to comment.