Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

voc 전체 조회 시, 필터링 시 페이지네이션 관련 추가 #216

Merged
merged 6 commits into from
Nov 20, 2024
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package intbyte4.learnsmate.voc.controller;

import intbyte4.learnsmate.common.exception.CommonException;
import intbyte4.learnsmate.member.domain.dto.MemberDTO;
import intbyte4.learnsmate.voc.domain.dto.VOCPageResponse;
import intbyte4.learnsmate.voc.domain.dto.VOCDTO;
import intbyte4.learnsmate.voc.domain.dto.VOCFilterRequestDTO;
import intbyte4.learnsmate.voc.domain.vo.request.RequestCountByCategoryVO;
import intbyte4.learnsmate.voc.domain.vo.request.RequestFilterVOCVO;
import intbyte4.learnsmate.voc.domain.vo.response.ResponseCountByCategoryVO;
import intbyte4.learnsmate.voc.domain.vo.response.ResponseFindVOCVO;
import intbyte4.learnsmate.voc.mapper.VOCMapper;
import intbyte4.learnsmate.voc.service.VOCFacade;
import intbyte4.learnsmate.voc.service.VOCService;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -28,13 +31,13 @@ public class VOCController {

private final VOCService vocService;
private final VOCFacade vocFacade;
private final VOCMapper vocMapper;

@Operation(summary = "직원 - VOC 전체 조회")
@Operation(summary = "직원 - VOC 페이지 조회")
@GetMapping("/list")
public ResponseEntity<List<ResponseFindVOCVO>> listVOC() {
List<ResponseFindVOCVO> response = vocFacade.findAllVOCs();
log.info(response.get(0).toString());
return ResponseEntity.status(HttpStatus.OK).body(response);
public ResponseEntity<VOCPageResponse<ResponseFindVOCVO>> listVOC(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "15") int size) {
VOCPageResponse<ResponseFindVOCVO> response = vocFacade.findVOCsByPage(page, size);
return ResponseEntity.ok(response);
}

@Operation(summary = "직원 - VOC 단 건 조회")
Expand Down Expand Up @@ -96,16 +99,12 @@ public ResponseEntity<List<ResponseCountByCategoryVO>> countVOCByCategory(@Reque

@Operation(summary = "VOC 필터링")
@PostMapping("/filter")
public ResponseEntity<List<VOCDTO>> filterVOC(@RequestBody VOCDTO vocDTO, MemberDTO memberDTO) {
public ResponseEntity<VOCPageResponse<ResponseFindVOCVO>> filterVOC(@RequestBody RequestFilterVOCVO request, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "15") int size) {
log.info("VOC 필터링 요청 수신");
try {
List<VOCDTO> filteredVOCList = vocService.filterVOC(vocDTO, memberDTO);

log.info("VOC 필터링 성공, 필터링된 데이터 수: {}", filteredVOCList.size());
return ResponseEntity.ok(filteredVOCList);
} catch (CommonException e) {
log.error("VOC 필터링 실패: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
VOCFilterRequestDTO dto = vocMapper.fromFilterVOtoFilterDTO(request);
VOCPageResponse<ResponseFindVOCVO> response = vocFacade.filterVOCsByPage(dto, page, size);
return ResponseEntity.ok(response);
} catch (Exception e) {
log.error("예상치 못한 오류 발생", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package intbyte4.learnsmate.voc.domain.dto;

import lombok.*;

import java.time.LocalDateTime;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Builder
public class VOCFilterRequestDTO {
private String vocCode;
private String vocContent;
private Integer vocCategoryCode;
private String memberType;
private Boolean vocAnswerStatus;
private String vocAnswerSatisfaction;
private LocalDateTime startCreateDate;
private LocalDateTime startEndDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package intbyte4.learnsmate.voc.domain.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;

@Getter
@AllArgsConstructor
public class VOCPageResponse<T> {
private List<T> content;
private long totalElements;
private int totalPages;
private int currentPage;
private int size;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package intbyte4.learnsmate.voc.domain.vo.request;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class RequestFilterVOCVO {
private String vocCode;
private String vocContent;
private Integer vocCategoryCode;
private String memberType;
private Boolean vocAnswerStatus;
private String vocAnswerSatisfaction;
private LocalDateTime startCreateDate;
private LocalDateTime startEndDate;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import intbyte4.learnsmate.member.domain.entity.Member;
import intbyte4.learnsmate.voc.domain.VOC;
import intbyte4.learnsmate.voc.domain.dto.VOCDTO;
import intbyte4.learnsmate.voc.domain.dto.VOCFilterRequestDTO;
import intbyte4.learnsmate.voc.domain.vo.request.RequestFilterVOCVO;
import intbyte4.learnsmate.voc.domain.vo.response.ResponseFindVOCVO;
import intbyte4.learnsmate.voc_category.domain.VOCCategory;
import intbyte4.learnsmate.voc_category.domain.dto.VOCCategoryDTO;
Expand Down Expand Up @@ -52,4 +54,17 @@ public VOC toEntity(VOCDTO vocDTO, VOCCategory vocCategory, Member member) {
.member(member)
.build();
}

public VOCFilterRequestDTO fromFilterVOtoFilterDTO(RequestFilterVOCVO request) {
return VOCFilterRequestDTO.builder()
.vocCode(request.getVocCode())
.vocContent(request.getVocContent())
.vocCategoryCode(request.getVocCategoryCode())
.memberType(request.getMemberType())
.vocAnswerStatus(request.getVocAnswerStatus())
.vocAnswerSatisfaction(Boolean.FALSE.equals(request.getVocAnswerStatus()) ? null : request.getVocAnswerSatisfaction())
.startCreateDate(request.getStartCreateDate())
.startEndDate(request.getStartEndDate())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package intbyte4.learnsmate.voc.repository;

import intbyte4.learnsmate.member.domain.dto.MemberDTO;
import intbyte4.learnsmate.voc.domain.VOC;
import intbyte4.learnsmate.voc.domain.dto.VOCDTO;
import intbyte4.learnsmate.voc.domain.dto.VOCFilterRequestDTO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

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

public interface VOCRepositoryCustom {
List<VOC> searchBy(VOCDTO request, MemberDTO memberDTO);
List<VOC> searchBy(VOCFilterRequestDTO dto);

Page<VOC> searchByWithPaging(VOCFilterRequestDTO dto, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,105 @@

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import intbyte4.learnsmate.member.domain.dto.MemberDTO;
import intbyte4.learnsmate.member.domain.MemberType;
import intbyte4.learnsmate.voc.domain.QVOC;
import intbyte4.learnsmate.voc.domain.VOC;
import intbyte4.learnsmate.voc.domain.dto.VOCDTO;
import intbyte4.learnsmate.voc.domain.dto.VOCFilterRequestDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

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

@Slf4j
@RequiredArgsConstructor
public class VOCRepositoryImpl implements VOCRepositoryCustom {

private final JPAQueryFactory queryFactory;
private final QVOC qVOC = QVOC.vOC;

@Override
public List<VOC> searchBy(VOCDTO request, MemberDTO memberDTO) {
public List<VOC> searchBy(VOCFilterRequestDTO dto) {
return queryFactory
.selectFrom(qVOC)
.where(
eqMemberCode(request.getMemberCode()),
searchByContents(request.getVocContent()),
searchByType(request.getVocCategoryCode()),
searchByMemberType(memberDTO),
searchByAnswerStatus(request.getVocAnswerStatus())
eqVOCCode(dto.getVocCode()),
searchByContents(dto.getVocContent()),
searchByType(dto.getVocCategoryCode()),
searchByMemberType(dto.getMemberType()),
searchByAnswerStatus(dto.getVocAnswerStatus()),
searchByAnswerSatisfaction(dto.getVocAnswerSatisfaction()),
searchByCreatedAt(dto.getStartCreateDate(), dto.getStartEndDate())
)
.fetch();
}

private BooleanExpression eqMemberCode(Long memberCode) {
return memberCode == null ? null : qVOC.member.memberCode.eq(memberCode);
@Override
public Page<VOC> searchByWithPaging(VOCFilterRequestDTO dto, Pageable pageable) {
List<VOC> content = queryFactory
.selectFrom(qVOC)
.where(
eqVOCCode(dto.getVocCode()),
searchByContents(dto.getVocContent()),
searchByType(dto.getVocCategoryCode()),
searchByMemberType(dto.getMemberType()),
searchByAnswerStatus(dto.getVocAnswerStatus()),
searchByAnswerSatisfaction(dto.getVocAnswerSatisfaction()),
searchByCreatedAt(dto.getStartCreateDate(), dto.getStartEndDate())
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

long total = queryFactory
.select(qVOC.count())
.from(qVOC)
.where(
eqVOCCode(dto.getVocCode()),
searchByContents(dto.getVocContent()),
searchByType(dto.getVocCategoryCode()),
searchByMemberType(dto.getMemberType()),
searchByAnswerStatus(dto.getVocAnswerStatus()),
searchByAnswerSatisfaction(dto.getVocAnswerSatisfaction()),
searchByCreatedAt(dto.getStartCreateDate(), dto.getStartEndDate())
)
.fetchOne();

return new PageImpl<>(content, pageable, total);
}

private BooleanExpression searchByCreatedAt(LocalDateTime startDate, LocalDateTime endDate) {
if (startDate == null && endDate == null) {
return null;
}
if (startDate != null && endDate != null) {
return qVOC.createdAt.between(startDate, endDate);
} else if (startDate != null) {
return qVOC.createdAt.goe(startDate);
} else {
return qVOC.createdAt.loe(endDate);
}
}

private BooleanExpression searchByAnswerSatisfaction(String vocAnswerSatisfaction) {
if (vocAnswerSatisfaction == null || vocAnswerSatisfaction.isBlank()) {
return null;
}
return qVOC.vocAnswerSatisfaction.eq(vocAnswerSatisfaction);
}

private BooleanExpression eqVOCCode(String vocCode) {
if (vocCode == null || vocCode.isBlank()) {
return null;
}
try {
return qVOC.vocCode.eq(vocCode);
} catch (IllegalArgumentException e) {
return null;
}
}

private BooleanExpression searchByContents(String vocContents) {
Expand All @@ -56,13 +125,22 @@ private BooleanExpression searchByType(Integer categoryCode) {
return categoryCode == null ? null : qVOC.vocCategory.vocCategoryCode.eq(categoryCode);
}

private BooleanExpression searchByMemberType(MemberDTO memberDTO) {
return (memberDTO != null && memberDTO.getMemberType() != null)
? qVOC.member.memberType.eq(memberDTO.getMemberType())
: null;
private BooleanExpression searchByMemberType(String memberType) {
if (memberType == null || memberType.isBlank()) {
return null;
}
try {
return qVOC.member.memberType.eq(MemberType.valueOf(memberType));
} catch (IllegalArgumentException e) {
return null;
}
}

private BooleanExpression searchByAnswerStatus(Boolean answerStatus) {
return answerStatus == null ? null : qVOC.vocAnswerStatus.eq(answerStatus);
if (answerStatus == null) {
return null;
}
log.info("Filtering answerStatus: {}", answerStatus);
return qVOC.vocAnswerStatus.eq(answerStatus);
}
}
Loading