Skip to content

Commit

Permalink
Merge pull request #118 from depromeet/feature/#117
Browse files Browse the repository at this point in the history
Feature/#117
  • Loading branch information
JeongSangByuk authored Sep 10, 2024
2 parents 9f2f503 + 68e27d6 commit 862a17d
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.server.bbo_gak.domain.card.controller;

import com.server.bbo_gak.domain.card.dto.response.CardSearchByTagListResponse;
import com.server.bbo_gak.domain.card.dto.response.TagGetResponse;
import com.server.bbo_gak.domain.card.service.CardSearchService;
import com.server.bbo_gak.domain.user.entity.User;
import com.server.bbo_gak.global.annotation.AuthUser;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class CardSearchController {

private final CardSearchService cardSearchService;

@GetMapping("/search/cards")
public ResponseEntity<List<CardSearchByTagListResponse>> searchCardByTagList(
@AuthUser User user,
@RequestParam(value = "card-type-value-group", required = false) String cardTypeValueGroup,
@RequestParam(value = "tag-ids") List<Long> tagIdList) {
return ResponseEntity.ok(cardSearchService.searchCardByTagList(user, cardTypeValueGroup, tagIdList));
}

@GetMapping("/search/card-tag-history")
public ResponseEntity<List<TagGetResponse>> getCardTagSearchHistory(@AuthUser User user) {
return ResponseEntity.ok(cardSearchService.getCardTagSearchHistoryList(user));
}
}
17 changes: 3 additions & 14 deletions src/main/java/com/server/bbo_gak/domain/card/dao/CardDao.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.server.bbo_gak.domain.card.dao;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.server.bbo_gak.domain.card.entity.Card;
import com.server.bbo_gak.domain.card.entity.CardTypeValue;
Expand Down Expand Up @@ -28,8 +27,9 @@ public List<Card> findAllByUserIdAndCardTypeValueList(User user, CardTypeValue[]
return query.selectFrom(qCard)
.leftJoin(qCard.cardTypeList, qCardType).fetchJoin()
.where(qCard.user.id.eq(user.getId())
.and(cardTypeValueList.length == 0 ? null : qCardType.cardTypeValue.in(cardTypeValueList))
.and(qCardType.cardTypeValue.in(cardTypeValueList))
.and(createRecruitBooleanBuilder(qCard, recruitId)))
.and(recruitId == null ? null : qCard.recruit.id.eq(recruitId)))
.distinct()
.fetch();
}
Expand All @@ -43,20 +43,9 @@ public List<Card> findAllByUserIdAndCardTypeValue(User user, CardTypeValue cardT
.leftJoin(qCard.cardTypeList, qCardType).fetchJoin()
.where(qCard.user.id.eq(user.getId())
.and(qCardType.cardTypeValue.eq(cardTypeValue))
.and(createRecruitBooleanBuilder(qCard, recruitId))
.and(recruitId == null ? null : qCard.recruit.id.eq(recruitId))
)
.distinct()
.fetch();
}

private BooleanBuilder createRecruitBooleanBuilder(QCard qCard, Long recruitId) {

BooleanBuilder builder = new BooleanBuilder();

if (recruitId == null) {
return null;
}

return builder.and(qCard.recruit.id.eq(recruitId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.server.bbo_gak.domain.card.dao;

import com.server.bbo_gak.domain.card.entity.CardTagSearchHistory;
import com.server.bbo_gak.domain.user.entity.User;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CardTagSearchHistoryRepository extends JpaRepository<CardTagSearchHistory, Long> {

List<CardTagSearchHistory> findTop10ByUserOrderByCreatedDate(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.server.bbo_gak.domain.card.dto.request;

import com.server.bbo_gak.domain.card.entity.CardTypeValue;
import com.server.bbo_gak.domain.card.entity.CardTypeValueGroup;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.Size;
import java.util.List;
import java.util.Optional;

public record CardSearchByTagListRequest(

@Size(min = 1)
List<Long> tagIdList,

@Nullable
String cardTypeValueGroup
) {

public CardTypeValue[] getCardTypeValueList() {
return Optional.ofNullable(cardTypeValueGroup)
.map(cardTypeValueGroup -> CardTypeValueGroup.findByValue(cardTypeValueGroup).getCardTypeValueList())
.orElseGet(() -> new CardTypeValue[0]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.server.bbo_gak.domain.card.dto.response;

import com.server.bbo_gak.domain.card.entity.Card;
import com.server.bbo_gak.domain.card.entity.CardTypeValue;
import com.server.bbo_gak.domain.card.entity.CardTypeValueGroup;
import com.server.bbo_gak.domain.recruit.entity.Recruit;
import com.server.bbo_gak.global.utils.BaseDateTimeFormatter;
import java.util.List;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.Builder;

@Builder(access = AccessLevel.PRIVATE)
public record CardSearchByTagListResponse(
Long id,
String title,
String updatedDate,
List<TagGetResponse> tagList,
String cardTypeValueGroup,
String cardTypeValue,
String recruitTitle,
String content
) {

public static CardSearchByTagListResponse from(Card card) {

CardTypeValue cardTypeValue = card.getCardTypeList().getFirst().getCardTypeValue();

return CardSearchByTagListResponse.builder()
.id(card.getId())
.title(card.getTitle())
.updatedDate(card.getUpdatedDate().format(BaseDateTimeFormatter.getLocalDateTimeFormatter()))
.tagList(
card.getCardTagList().stream()
.map(cardTag -> TagGetResponse.from(cardTag.getTag()))
.toList()
)
.cardTypeValueGroup(CardTypeValueGroup.findByCardTypeValue(cardTypeValue).getValue())
.recruitTitle(Optional.ofNullable(card.getRecruit()).map(Recruit::getTitle).orElse(null))
.cardTypeValue(cardTypeValue.getValue())
.content(card.getContent())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.server.bbo_gak.domain.card.entity;

import com.server.bbo_gak.domain.user.entity.User;
import com.server.bbo_gak.global.common.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;

@Getter
@Entity
@SQLRestriction("deleted = false")
@SQLDelete(sql = "UPDATE card_tag_search_history SET deleted = true WHERE card_tag_search_history_id = ?")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CardTagSearchHistory extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "card_tag_search_history_id")
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "tag_id")
private Tag tag;

public CardTagSearchHistory(User user, Tag tag) {
this.user = user;
this.tag = tag;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.server.bbo_gak.domain.card.service;

import com.server.bbo_gak.domain.card.dao.CardDao;
import com.server.bbo_gak.domain.card.dao.CardTagSearchHistoryRepository;
import com.server.bbo_gak.domain.card.dao.TagRepository;
import com.server.bbo_gak.domain.card.dto.response.CardSearchByTagListResponse;
import com.server.bbo_gak.domain.card.dto.response.TagGetResponse;
import com.server.bbo_gak.domain.card.entity.Card;
import com.server.bbo_gak.domain.card.entity.CardTagSearchHistory;
import com.server.bbo_gak.domain.card.entity.CardTypeValue;
import com.server.bbo_gak.domain.card.entity.CardTypeValueGroup;
import com.server.bbo_gak.domain.card.entity.Tag;
import com.server.bbo_gak.domain.user.entity.User;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class CardSearchService {

private final CardTagSearchHistoryRepository cardTagSearchHistoryRepository;
private final TagRepository tagRepository;
private final CardDao cardDao;

@Transactional
public List<CardSearchByTagListResponse> searchCardByTagList(User user, String cardTypeValueGroup,
List<Long> tagIdList) {

List<Tag> tagList = tagRepository.findAllById(tagIdList);

List<Card> cards = cardDao.findAllByUserIdAndCardTypeValueList(user, getCardTypeValueList(cardTypeValueGroup),
null);

cardTagSearchHistoryRepository.saveAll(tagList.stream()
.map(tag -> new CardTagSearchHistory(user, tag))
.toList());

// TODO 필터링 로직 디비로 가게 하기
return cards.stream()
.filter(card -> tagList.isEmpty() || card.isTagListContain(tagList))
.sorted(Comparator.comparing(Card::getUpdatedDate).reversed())
.map(CardSearchByTagListResponse::from)
.collect(Collectors.toList());
}

@Transactional(readOnly = true)
public List<TagGetResponse> getCardTagSearchHistoryList(User user) {
return cardTagSearchHistoryRepository.findTop10ByUserOrderByCreatedDate(user).stream()
.map(cardTagSearchHistory -> TagGetResponse.from(cardTagSearchHistory.getTag()))
.toList();
}

private CardTypeValue[] getCardTypeValueList(String cardTypeValueGroupInput) {
return Optional.ofNullable(cardTypeValueGroupInput)
.map(cardTypeValueGroup -> CardTypeValueGroup.findByValue(cardTypeValueGroup).getCardTypeValueList())
.orElseGet(() -> new CardTypeValue[0]);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,9 @@ public List<CardListGetResponse> getCardList(User user, String cardTypeValue, Li
List<Card> cards = cardDao.findAllByUserIdAndCardTypeValue(user, CardTypeValue.findByValue(cardTypeValue),
null);

// TODO 필터링 로직 디비로 가게 하기
return cards.stream()
.filter(card -> {

if (tagList.isEmpty()) {
return true;
}

return card.isTagListContain(tagList);
})
.filter(card -> tagList.isEmpty() || card.isTagListContain(tagList))
.sorted(Comparator.comparing(Card::getUpdatedDate).reversed())
.map(card -> CardListGetResponse.of(card, card.getCardTagList()))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
import com.server.bbo_gak.domain.card.entity.Card;
import com.server.bbo_gak.domain.card.entity.CardTag;
import com.server.bbo_gak.domain.card.entity.CardTypeValue;
import com.server.bbo_gak.domain.card.entity.CardTypeValueGroup;
import com.server.bbo_gak.domain.card.entity.Tag;
import com.server.bbo_gak.domain.recruit.dao.RecruitRepository;
import com.server.bbo_gak.domain.recruit.entity.Recruit;
import com.server.bbo_gak.domain.user.entity.Job;
import com.server.bbo_gak.domain.user.entity.User;
import com.server.bbo_gak.global.error.exception.BusinessException;
import com.server.bbo_gak.global.error.exception.ErrorCode;
import com.server.bbo_gak.global.error.exception.InvalidValueException;
import com.server.bbo_gak.global.error.exception.NotFoundException;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -109,16 +107,4 @@ private void validateTagDuplicated(Long tagId, Card card) {
}
}
}

private CardTypeValueGroup getRecruitCardTypeValueGroup(String type) {
CardTypeValueGroup cardTypeValueGroup = CardTypeValueGroup.findByCardTypeValue(CardTypeValue.findByValue(type));

if (cardTypeValueGroup.equals(CardTypeValueGroup.RECRUIT)) {
throw new InvalidValueException(ErrorCode.RECRUIT_CARD_TYPE_NOT_MATCHED);
}

return cardTypeValueGroup;
}


}
Loading

0 comments on commit 862a17d

Please sign in to comment.