Skip to content

Commit

Permalink
feat: (#47) 이슈 검색 필터 구현 중
Browse files Browse the repository at this point in the history
  • Loading branch information
eNoLJ committed Jun 15, 2021
1 parent 939f641 commit 8b87782
Show file tree
Hide file tree
Showing 26 changed files with 283 additions and 39 deletions.
20 changes: 20 additions & 0 deletions BE/src/main/java/com/issuetracker/config/QueryDSLConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.issuetracker.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Configuration
public class QueryDSLConfig {

@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.issuetracker.domain.issue;

import com.issuetracker.web.dto.reqeust.SearchRequestDTO;

import java.util.List;

public interface CustomizedIssueRepository {

List<Issue> findAllIssuesFilteredBy(SearchRequestDTO searchRequest);

// List<Issue> findAllIssuesFilteredBy(SearchRequest searchRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.issuetracker.domain.issue;


import com.issuetracker.domain.user.User;
import com.issuetracker.web.dto.reqeust.SearchRequestDTO;
import com.issuetracker.web.dto.vo.Status;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;

import java.util.List;

import static com.issuetracker.domain.issue.QIssue.issue;
import static com.issuetracker.domain.user.QUser.user;
import static com.issuetracker.domain.label.QLabel.label;
import static com.issuetracker.domain.milestone.QMilestone.milestone;
import static com.issuetracker.domain.comment.QComment.comment1;
import static org.springframework.util.StringUtils.hasText;

@RequiredArgsConstructor
public class CustomizedIssueRepositoryImpl implements CustomizedIssueRepository {

private final JPAQueryFactory queryFactory;

public List<Issue> findAllIssuesFilteredBy(SearchRequestDTO searchRequest) {
return queryFactory
.select(issue)
.distinct()
.from(issue)
.leftJoin(issue.author, user)
.leftJoin(issue.labels, label)
.leftJoin(issue.milestone, milestone)
.leftJoin(issue.comments, comment1)
.where(statusEquals(searchRequest.getStatus()),
authorEquals(searchRequest.getAuthor()),
// labelEquals(labelName),
milestoneEquals(searchRequest.getMilestone()),
assigneeEquals(searchRequest.getAssignee()),
commenterEquals(searchRequest.getCommenter()))
.limit(100)
.fetch();

// return queryFactory
// .selectFrom(issue)
// .where(
// statusEquals(searchRequest.getStatus()),
// authorEquals(searchRequest.getAuthor()),
// assigneeEquals(searchRequest.getAssignee())
// )
// .fetch();
}

public BooleanExpression statusEquals(String status) {
return hasText(status) ? issue.isOpen.eq(Status.statusToBoolean(status)) : null;
}

public BooleanExpression authorEquals(String author) {
return hasText(author) ? user.userName.eq(author) : null;
}

public BooleanExpression milestoneEquals(String milestoneTitle) {
return hasText(milestoneTitle) ? milestone.title.eq(milestoneTitle) : null;
}

public BooleanExpression assigneeEquals(String assignee) {
if (!hasText(assignee)) {
return null;
}
User user = findByUserName(assignee);
if (user == null) {
return null;
}
return issue.assignees.contains(user);
}

private BooleanExpression commenterEquals(String commenter) {
if (commenter == null) {
return null;
}
return comment1.author.userName.eq(commenter);
}

private User findByUserName(String userName) {
return queryFactory.selectFrom(user)
.where(user.userName.eq(userName))
.fetchFirst();
}

// public BooleanExpression commenterEquals(User commenter) {
// return commenter != null ? issue.comments.contains(commenter) : null;
// }
//
// public BooleanExpression labelEquals(List<String> label) {
// return label!=null?
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import java.util.List;

public interface IssueRepository extends JpaRepository<Issue, Long> {
public interface IssueRepository extends JpaRepository<Issue, Long>, CustomizedIssueRepository {

List<Issue> findAllByIsOpenTrue();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class Milestone extends BaseTimeEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface MilestoneRepository extends JpaRepository<Milestone, Long> {

Optional<Milestone> findByTitle(String title);
}
2 changes: 1 addition & 1 deletion BE/src/main/java/com/issuetracker/domain/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@EqualsAndHashCode(of = "id")
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class User {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByUserName(String userName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.issuetracker.exception;

import com.issuetracker.web.dto.response.IssuesResponseDTO;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

// @ExceptionHandler(InvalidSearchRequestException.class)
// public ResponseEntity handleInvalidSearchRequestException(InvalidSearchRequestException e) {
// return ResponseEntity.ok(new IssuesResponseDTO());
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class InvalidSearchRequestException extends RuntimeException {

public InvalidSearchRequestException() {
super("Invalid status.");
super("Invalid search request.");
}
}
35 changes: 19 additions & 16 deletions BE/src/main/java/com/issuetracker/service/IssueService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import com.issuetracker.domain.milestone.Milestone;
import com.issuetracker.domain.user.User;
import com.issuetracker.exception.ElementNotFoundException;
import com.issuetracker.exception.InvalidSearchRequestException;
import com.issuetracker.web.dto.response.vo.Assignee;
import com.issuetracker.web.dto.response.vo.Count;
import com.issuetracker.web.dto.vo.Assignee;
import com.issuetracker.web.dto.vo.Count;
import com.issuetracker.web.dto.vo.SearchRequest;
import com.issuetracker.web.dto.vo.Status;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -27,27 +28,38 @@ public class IssueService {
private final MilestoneService milestoneService;
private final UserService userService;

public IssuesResponseDTO getIssues(String status) {
public IssuesResponseDTO getIssues(SearchRequestDTO searchRequestDTO) {

// SearchRequest searchRequest = new SearchRequest(
// Status.statusToBoolean(searchRequestDTO.getStatus()),
// searchRequestDTO.getAuthor(),
// userService.findNullableUserByUserName(searchRequestDTO.getAssignee()),
// userService.findNullableUserByUserName(searchRequestDTO.getCommenter()),
// searchRequestDTO.getLabel(),
// milestoneService.findNullableMilestoneByTitle(searchRequestDTO.getMilestone())
// );

Count count = Count.builder()
.label((int) labelService.count())
.milestone((int) milestoneService.count())
.openedIssue((int) issueRepository.countAllByIsOpenTrue())
.closedIssue((int) issueRepository.countAllByIsOpenFalse())
.build();
List<IssueResponseDTO> issues = filterByStatus(status).stream()

List<IssueResponseDTO> issues = issueRepository.findAllIssuesFilteredBy(searchRequestDTO).stream()
.map(issue -> IssueResponseDTO.of(issue, userService.usersToAssignees(issue), labelService.labelsToLabelDTOs(issue)))
.collect(Collectors.toList());
return IssuesResponseDTO.of(count, issues);
}

private List<Issue> filterByStatus(String status) {
boolean newStatus = statusToBoolean(status);
boolean newStatus = Status.statusToBoolean(status);
return newStatus ? issueRepository.findAllByIsOpenTrue() : issueRepository.findAllByIsOpenFalse();
}

@Transactional
public void changeIssueStatus(IssueNumbersRequestDTO requestDTO, String status) {
boolean newStatus = !statusToBoolean(status);
boolean newStatus = !Status.statusToBoolean(status);
issueRepository.updateStatusBy(newStatus, requestDTO.getIssueNumbers());
}

Expand Down Expand Up @@ -172,13 +184,4 @@ private List<CommentDTO> commentsToCommentDTOs(User user, Issue issue) {
.collect(Collectors.toList());
}

private boolean statusToBoolean(String status) {
if (status.equals("open")) {
return true;
}
if (status.equals("close")) {
return false;
}
throw new InvalidSearchRequestException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ public Milestone findMilestoneById(Long milestoneId) {
return milestoneRepository.findById(milestoneId).orElseThrow(EntityExistsException::new);
}

public Milestone findNullableMilestoneByTitle(String title) {
if (title == null) {
return null;
}
return milestoneRepository.findByTitle(title).orElse(new Milestone());
}

public List<MilestoneDTO> findAllMilestoneDTOs() {
return milestoneRepository.findAll().stream().map(MilestoneDTO::of).collect(Collectors.toList());
}
Expand Down
17 changes: 13 additions & 4 deletions BE/src/main/java/com/issuetracker/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
import com.issuetracker.auth.service.JwtService;
import com.issuetracker.domain.user.User;
import com.issuetracker.domain.user.UserRepository;
import com.issuetracker.exception.InvalidSearchRequestException;
import com.issuetracker.exception.UserNotFoundException;
import com.issuetracker.web.dto.response.UserResponseDTO;
import com.issuetracker.web.dto.response.vo.Assignee;
import com.issuetracker.web.dto.vo.Assignee;
import com.issuetracker.domain.issue.Issue;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
Expand All @@ -31,9 +33,9 @@ public List<User> findAssignees(List<Long> assigneeIdList) {

public UserResponseDTO login(String code, UserAgentDTO userAgent) {
AccessTokenResponseDTO token = oauth.getToken(code, userAgent.getUserAgent());
UserResponseDTO userInfo = oauth.getUserInfo(token.getAccessToken());
OAuthUserResponseDTO userInfo = oauth.getUserInfo(token.getAccessToken());
if (verifyUser(userInfo.getLogin())) {
User user = findByUserName(userInfo.getLogin());
User user = findUserByUserName(userInfo.getLogin());
user.update(userInfo, token.getAccessToken());
return UserResponseDTO.createUserResponseDTO(user, jwtService.createToken(userRepository.save(user)));
}
Expand Down Expand Up @@ -70,12 +72,19 @@ public List<Assignee> usersToAssignees() {
.collect(Collectors.toList());
}

private User findByUserName(String userName) {
public User findUserByUserName(String userName) {
return userRepository.findByUserName(userName).orElseThrow(
() -> new UserNotFoundException("Cannot find user by given username.")
);
}

public User findNullableUserByUserName(String userName) {
if (userName == null) {
return null;
}
return userRepository.findByUserName(userName).orElseThrow(InvalidSearchRequestException::new);
}

private boolean verifyUser(String userName) {
return userRepository.findByUserName(userName).isPresent();
}
Expand Down
4 changes: 2 additions & 2 deletions BE/src/main/java/com/issuetracker/web/IssueController.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public class IssueController {
private final Logger logger = LoggerFactory.getLogger(IssueController.class);

@GetMapping
public IssuesResponseDTO view(@RequestParam String status) {
public IssuesResponseDTO view(SearchRequestDTO requestDTO) {
logger.debug("모든 이슈 조회");
return issueService.getIssues(status);
return issueService.getIssues(requestDTO);
}

@PatchMapping
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.issuetracker.web.dto.reqeust;

import com.issuetracker.web.dto.response.vo.Assignee;
import com.issuetracker.web.dto.vo.Assignee;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.issuetracker.web.dto.reqeust;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.List;

@Getter
@Setter
@ToString
public class SearchRequestDTO {

private String status;
private String author;
private String assignee;
private String commenter;
private List<String> label;
private String milestone;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.issuetracker.web.dto.response;

import com.issuetracker.web.dto.response.vo.Assignee;
import com.issuetracker.web.dto.vo.Assignee;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.issuetracker.web.dto.response;

import com.issuetracker.web.dto.response.vo.Assignee;
import com.issuetracker.web.dto.vo.Assignee;
import com.issuetracker.domain.issue.Issue;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Loading

0 comments on commit 8b87782

Please sign in to comment.