diff --git a/build.gradle b/build.gradle index 5ae542b7..9a9f417e 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,12 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly('io.jsonwebtoken:jjwt-jackson:0.11.5') // jackson으로 jwt 파싱 + + // querydsl 관련 + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" } tasks.named('test') { diff --git a/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java b/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java index 8c9515b8..e3d44bb8 100644 --- a/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java @@ -27,7 +27,9 @@ public enum ErrorStatus implements BaseErrorCode { _OTP_NOT_VALID(HttpStatus.BAD_REQUEST, "OTP4001", "인증번호가 유효하지 않습니다."), _PHONE_NUMBER_NOT_VALID(HttpStatus.BAD_REQUEST, "AUTH4001", "전화번호 형식이 유효하지 않습니다. (예: 01012341234)"), - _FAQ_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ4004", "해당 FAQ가 존재하지 않습니다."); + _FAQ_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ4004", "해당 FAQ가 존재하지 않습니다."), + _SEARCH_KEYWORD_NOT_FOUND(HttpStatus.NOT_FOUND, "SEARCH_KEYWORD4004", "해당 SearchKeyword가 존재하지 않습니다."), + _FAQ_KEYWORD_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ_KEYWORD4004", "해당 FaqKeyword가 존재하지 않습니다."); private HttpStatus httpStatus; diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqApi.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqApi.java index f3e0b134..8485960f 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqApi.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqApi.java @@ -17,6 +17,7 @@ import jakarta.validation.Valid; import org.springframework.data.domain.Pageable; import org.springframework.http.MediaType; +import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; @@ -70,7 +71,7 @@ ApiResponse postFaq(@ExistUser @RequestParam Long userId, } ) - ApiResponse findByPaging(Pageable pageable); + ApiResponse findByPaging(Pageable pageable, String SearchCondition); @Operation(summary = "[User] FAQ 수정 API", description = "FAQ를 수정하는 API입니다.", requestBody = @RequestBody( @@ -112,4 +113,9 @@ ApiResponse modifyFaq(@PathVariable @ExistFaq Long faqId, } ) ApiResponse deleteFaq(@ExistFaq Long faqId); + + ApiResponse addKeyword(@ExistFaq Long faqId, Long searchKeywordId); + + ApiResponse deleteKeyword(@ExistFaq Long faqId, Long searchKeywordId); + } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqController.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqController.java index c8da6681..c15fe5d2 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqController.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/controller/FaqController.java @@ -7,10 +7,12 @@ import com.bbteam.budgetbuddies.domain.faq.validation.ExistFaq; import com.bbteam.budgetbuddies.domain.user.validation.ExistUser; import jakarta.validation.Valid; +import jakarta.validation.constraints.Null; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.lang.Nullable; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -37,8 +39,9 @@ public ApiResponse findFaq(@PathVariable @ExistF @Override @GetMapping("/all") - public ApiResponse> findByPaging(@ParameterObject Pageable pageable) { - return ApiResponse.onSuccess(faqService.findAllWithPaging(pageable)); + public ApiResponse> findByPaging(@ParameterObject Pageable pageable, + @RequestParam @Nullable String searchCondition) { + return ApiResponse.onSuccess(faqService.searchFaq(pageable, searchCondition)); } @Override @@ -54,4 +57,16 @@ public ApiResponse deleteFaq(@PathVariable @ExistFaq Long faqId) { faqService.deleteFaq(faqId); return ApiResponse.onSuccess("Delete Success"); } + + @Override + @PostMapping("/{faqId}/keyword") + public ApiResponse addKeyword(@PathVariable @ExistFaq Long faqId, @RequestParam Long searchKeywordId) { + return ApiResponse.onSuccess(faqService.addKeyword(faqId, searchKeywordId)); + } + + @Override + @DeleteMapping("/{faqId}/keyword") + public ApiResponse deleteKeyword(@PathVariable @ExistFaq Long faqId, @RequestParam Long searchKeywordId) { + return ApiResponse.onSuccess(faqService.removeKeyword(faqId, searchKeywordId)); + } } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepository.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepository.java index 4ab1c63e..d9c6cf4f 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepository.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepository.java @@ -3,7 +3,7 @@ import com.bbteam.budgetbuddies.domain.faq.entity.Faq; import org.springframework.data.jpa.repository.JpaRepository; -public interface FaqRepository extends JpaRepository { +public interface FaqRepository extends JpaRepository, FaqSearchRepository { } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepository.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepository.java new file mode 100644 index 00000000..b54ab5be --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepository.java @@ -0,0 +1,10 @@ +package com.bbteam.budgetbuddies.domain.faq.repository; + +import com.bbteam.budgetbuddies.domain.faq.entity.Faq; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface FaqSearchRepository { + + Page searchFaq(Pageable pageable, String searchCondition); +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepositoryImpl.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepositoryImpl.java new file mode 100644 index 00000000..1e3116ab --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqSearchRepositoryImpl.java @@ -0,0 +1,61 @@ +package com.bbteam.budgetbuddies.domain.faq.repository; + +import com.bbteam.budgetbuddies.domain.faq.entity.Faq; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.QSearchKeyword; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +import static com.bbteam.budgetbuddies.domain.faq.entity.QFaq.*; +import static com.bbteam.budgetbuddies.domain.faqkeyword.domain.QFaqKeyword.*; +import static com.bbteam.budgetbuddies.domain.searchkeyword.domain.QSearchKeyword.*; + +public class FaqSearchRepositoryImpl implements FaqSearchRepository{ + + private final JPAQueryFactory queryFactory; + + public FaqSearchRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public Page searchFaq(Pageable pageable, String searchCondition) { + List result = queryFactory.select(faq) + .from(faq) + .where(faq.id.in( + JPAExpressions + .select(faqKeyword.faq.id) + .from(faqKeyword) + .join(searchKeyword).on(keywordMatch(searchCondition)) + )) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + Long total = queryFactory.select(faq.count()) + .from(faq) + .where(faq.id.in( + JPAExpressions + .select(faqKeyword.faq.id) + .from(faqKeyword) + .join(searchKeyword).on(keywordMatch(searchCondition)) + )) + .fetchOne(); + + return new PageImpl<>(result, pageable, total); + + } + + private BooleanExpression keywordMatch(String searchCondition) { + return searchCondition != null ? searchKeyword.keyword.contains(searchCondition) : null; + } + +} + diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqService.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqService.java index eb6a3718..f334dac5 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqService.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqService.java @@ -2,6 +2,7 @@ import com.bbteam.budgetbuddies.domain.faq.dto.FaqRequestDto; import com.bbteam.budgetbuddies.domain.faq.dto.FaqResponseDto; +import com.bbteam.budgetbuddies.domain.faqkeyword.dto.FaqKeywordResponseDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -11,9 +12,15 @@ public interface FaqService { Page findAllWithPaging(Pageable pageable); + Page searchFaq(Pageable pageable, String searchCondition); + FaqResponseDto.FaqPostResponse postFaq(FaqRequestDto.FaqPostRequest dto, Long userId); FaqResponseDto.FaqModifyResponse modifyFaq(FaqRequestDto.FaqModifyRequest dto, Long faqId); String deleteFaq(Long faqId); + + FaqKeywordResponseDto addKeyword(Long faqId, Long searchKeywordId); + + String removeKeyword(Long faqId, Long searchKeywordId); } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceImpl.java b/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceImpl.java index a28ccba8..6b732095 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceImpl.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceImpl.java @@ -7,6 +7,11 @@ import com.bbteam.budgetbuddies.domain.faq.dto.FaqResponseDto; import com.bbteam.budgetbuddies.domain.faq.entity.Faq; import com.bbteam.budgetbuddies.domain.faq.repository.FaqRepository; +import com.bbteam.budgetbuddies.domain.faqkeyword.domain.FaqKeyword; +import com.bbteam.budgetbuddies.domain.faqkeyword.dto.FaqKeywordResponseDto; +import com.bbteam.budgetbuddies.domain.faqkeyword.repository.FaqKeywordRepository; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.repository.SearchKeywordRepository; import com.bbteam.budgetbuddies.domain.user.entity.User; import com.bbteam.budgetbuddies.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; @@ -22,6 +27,8 @@ public class FaqServiceImpl implements FaqService{ private final FaqRepository faqRepository; private final UserRepository userRepository; + private final FaqKeywordRepository faqKeywordRepository; + private final SearchKeywordRepository searchKeywordRepository; @Override public FaqResponseDto.FaqFindResponse findOneFaq(Long faqId) { @@ -62,4 +69,36 @@ public String deleteFaq(Long faqId) { private Faq findFaq(Long faqId) { return faqRepository.findById(faqId).orElseThrow(() -> new GeneralException(ErrorStatus._FAQ_NOT_FOUND)); } + + @Override + public Page searchFaq(Pageable pageable, String searchCondition) { + return faqRepository.searchFaq(pageable, searchCondition).map(FaqConverter::entityToFind); + } + + @Override + @Transactional + public FaqKeywordResponseDto addKeyword(Long faqId, Long searchKeywordId) { + Faq faq = findFaq(faqId); + SearchKeyword searchKeyword = searchKeywordRepository.findById(searchKeywordId).orElseThrow(() -> new GeneralException(ErrorStatus._SEARCH_KEYWORD_NOT_FOUND)); + + FaqKeyword faqKeyword = FaqKeyword.builder() + .searchKeyword(searchKeyword) + .faq(faq) + .build(); + + faqKeywordRepository.save(faqKeyword); + return FaqKeywordResponseDto.toDto(faqKeyword); + } + + @Override + @Transactional + public String removeKeyword(Long faqId, Long searchKeywordId) { + Faq faq = findFaq(faqId); + SearchKeyword searchKeyword = searchKeywordRepository.findById(searchKeywordId).orElseThrow(() -> new GeneralException(ErrorStatus._SEARCH_KEYWORD_NOT_FOUND)); + + FaqKeyword faqKeyword = faqKeywordRepository.findByFaqAndSearchKeyword(faq, searchKeyword).orElseThrow(() -> new GeneralException(ErrorStatus._FAQ_KEYWORD_NOT_FOUND)); + faqKeywordRepository.delete(faqKeyword); + + return "ok"; + } } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/domain/FaqKeyword.java b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/domain/FaqKeyword.java new file mode 100644 index 00000000..6f5e9f14 --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/domain/FaqKeyword.java @@ -0,0 +1,32 @@ +package com.bbteam.budgetbuddies.domain.faqkeyword.domain; + +import com.bbteam.budgetbuddies.common.BaseEntity; +import com.bbteam.budgetbuddies.domain.faq.entity.Faq; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.*; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@SuperBuilder +public class FaqKeyword extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "faq_id") + @NotFound(action = NotFoundAction.IGNORE) + private Faq faq; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "search_keyword_id") + @NotFound(action = NotFoundAction.IGNORE) + private SearchKeyword searchKeyword; + +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/dto/FaqKeywordResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/dto/FaqKeywordResponseDto.java new file mode 100644 index 00000000..da6ef042 --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/dto/FaqKeywordResponseDto.java @@ -0,0 +1,21 @@ +package com.bbteam.budgetbuddies.domain.faqkeyword.dto; + +import com.bbteam.budgetbuddies.domain.faqkeyword.domain.FaqKeyword; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class FaqKeywordResponseDto { + + private Long faqId; + private Long searchKeywordId; + + private String faqTitle; + private String keyword; + + public static FaqKeywordResponseDto toDto(FaqKeyword faqKeyword) { + return new FaqKeywordResponseDto(faqKeyword.getFaq().getId(), faqKeyword.getSearchKeyword().getId(), + faqKeyword.getFaq().getTitle(), faqKeyword.getSearchKeyword().getKeyword()); + } +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/repository/FaqKeywordRepository.java b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/repository/FaqKeywordRepository.java new file mode 100644 index 00000000..c0606ba0 --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/faqkeyword/repository/FaqKeywordRepository.java @@ -0,0 +1,12 @@ +package com.bbteam.budgetbuddies.domain.faqkeyword.repository; + +import com.bbteam.budgetbuddies.domain.faq.entity.Faq; +import com.bbteam.budgetbuddies.domain.faqkeyword.domain.FaqKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface FaqKeywordRepository extends JpaRepository { + Optional findByFaqAndSearchKeyword(Faq faq, SearchKeyword searchKeyword); +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/controller/SearchKeywordController.java b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/controller/SearchKeywordController.java new file mode 100644 index 00000000..45786bbe --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/controller/SearchKeywordController.java @@ -0,0 +1,48 @@ +package com.bbteam.budgetbuddies.domain.searchkeyword.controller; + +import com.bbteam.budgetbuddies.apiPayload.ApiResponse; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.service.SearchKeywordService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/search-keyword") +public class SearchKeywordController { + + private final SearchKeywordService searchKeywordService; + + @PostMapping("") + public ApiResponse saveKeyword(String keyword) { + + return ApiResponse.onSuccess(searchKeywordService.saveKeyword(keyword)); + } + + @GetMapping("") + public ApiResponse findOne(Long searchKeywordId) { + return ApiResponse.onSuccess(searchKeywordService.findOne(searchKeywordId)); + } + + @GetMapping("/all") + public ApiResponse> findAll(Pageable pageable) { + return ApiResponse.onSuccess(searchKeywordService.findAll(pageable)); + } + + @PutMapping("") + public ApiResponse modifyOne(Long searchKeywordId, String newKeyword) { + return ApiResponse.onSuccess((searchKeywordService.modifyOne(searchKeywordId, newKeyword))); + } + + @DeleteMapping("") + public ApiResponse deleteOne(Long searchKeywordId) { + searchKeywordService.deleteOne(searchKeywordId); + return ApiResponse.onSuccess("OK"); + } + + + + +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/domain/SearchKeyword.java b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/domain/SearchKeyword.java new file mode 100644 index 00000000..970d72f4 --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/domain/SearchKeyword.java @@ -0,0 +1,23 @@ +package com.bbteam.budgetbuddies.domain.searchkeyword.domain; + +import com.bbteam.budgetbuddies.common.BaseEntity; +import jakarta.persistence.Entity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SearchKeyword extends BaseEntity { + + private String keyword; + + public void changeKeyword(String newKeyword) { + this.keyword = newKeyword; + } + +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/repository/SearchKeywordRepository.java b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/repository/SearchKeywordRepository.java new file mode 100644 index 00000000..1fcea8b7 --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/repository/SearchKeywordRepository.java @@ -0,0 +1,7 @@ +package com.bbteam.budgetbuddies.domain.searchkeyword.repository; + +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SearchKeywordRepository extends JpaRepository { +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/service/SearchKeywordService.java b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/service/SearchKeywordService.java new file mode 100644 index 00000000..b960855d --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/searchkeyword/service/SearchKeywordService.java @@ -0,0 +1,44 @@ +package com.bbteam.budgetbuddies.domain.searchkeyword.service; + +import com.bbteam.budgetbuddies.apiPayload.code.status.ErrorStatus; +import com.bbteam.budgetbuddies.apiPayload.exception.GeneralException; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.repository.SearchKeywordRepository; +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; + +@Service +@Transactional +@RequiredArgsConstructor +public class SearchKeywordService { + + private final SearchKeywordRepository searchKeywordRepository; + + public SearchKeyword saveKeyword(String keyword) { + SearchKeyword searchKeyword = SearchKeyword.builder().keyword(keyword).build(); + searchKeywordRepository.save(searchKeyword); + return searchKeyword; + } + + public SearchKeyword findOne(Long searchKeywordId) { + return searchKeywordRepository.findById(searchKeywordId).orElseThrow(() -> new GeneralException(ErrorStatus._SEARCH_KEYWORD_NOT_FOUND)); + } + + public Page findAll(Pageable pageable) { + return searchKeywordRepository.findAll(pageable); + } + + public SearchKeyword modifyOne(Long searchKeywordId, String keyword) { + SearchKeyword searchKeyword = searchKeywordRepository.findById(searchKeywordId).orElseThrow(() -> new GeneralException(ErrorStatus._SEARCH_KEYWORD_NOT_FOUND)); + searchKeyword.changeKeyword(keyword); + return searchKeyword; + } + + public void deleteOne(Long searchKeywordId) { + SearchKeyword searchKeyword = searchKeywordRepository.findById(searchKeywordId).orElseThrow(() -> new GeneralException(ErrorStatus._SEARCH_KEYWORD_NOT_FOUND)); + searchKeywordRepository.delete(searchKeyword); + } +} diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepositoryTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepositoryTest.java new file mode 100644 index 00000000..6263fd38 --- /dev/null +++ b/src/test/java/com/bbteam/budgetbuddies/domain/faq/repository/FaqRepositoryTest.java @@ -0,0 +1,101 @@ +package com.bbteam.budgetbuddies.domain.faq.repository; + +import com.bbteam.budgetbuddies.domain.faq.entity.Faq; +import com.bbteam.budgetbuddies.domain.faqkeyword.domain.FaqKeyword; +import com.bbteam.budgetbuddies.domain.faqkeyword.repository.FaqKeywordRepository; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.repository.SearchKeywordRepository; +import com.bbteam.budgetbuddies.domain.user.entity.User; +import com.bbteam.budgetbuddies.domain.user.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@Transactional +@ActiveProfiles("test") +class FaqRepositoryTest { + @Autowired + FaqRepository faqRepository; + @Autowired + FaqKeywordRepository faqKeywordRepository; + @Autowired + SearchKeywordRepository searchKeywordRepository; + @Autowired + UserRepository userRepository; + + + @Test + void searchTest() { + + User user1 = User.builder() + .name("tester1") + .email("1234") + .age(5) + .phoneNumber("123456") + .mobileCarrier("skt") + .build(); + userRepository.save(user1); + + Faq faq1 = Faq.builder() + .user(user1) + .title("test1") + .body("test1") + .build(); + faqRepository.save(faq1); + + Faq faq2 = Faq.builder() + .user(user1) + .title("test2") + .body("test2") + .build(); + faqRepository.save(faq2); + + SearchKeyword keyword1 = SearchKeyword.builder() + .keyword("러닝") + .build(); + searchKeywordRepository.save(keyword1); + + FaqKeyword faqKeyword = FaqKeyword.builder() + .searchKeyword(keyword1) + .faq(faq1) + .build(); + faqKeywordRepository.save(faqKeyword); + + SearchKeyword keyword2 = SearchKeyword.builder() + .keyword("헬스") + .build(); + searchKeywordRepository.save(keyword2); + + FaqKeyword faqKeyword2 = FaqKeyword.builder() + .searchKeyword(keyword2) + .faq(faq1) + .build(); + faqKeywordRepository.save(faqKeyword2); + + FaqKeyword faqKeyword3 = FaqKeyword.builder() + .searchKeyword(keyword1) + .faq(faq2) + .build(); + faqKeywordRepository.save(faqKeyword3); + + PageRequest pageRequest = PageRequest.of(0, 5); + + Page result1 = faqRepository.searchFaq(pageRequest, "러닝"); + + Page result2 = faqRepository.searchFaq(pageRequest, "헬스"); + + assertThat(result1.getNumberOfElements()).isEqualTo(2); + assertThat(result2.getNumberOfElements()).isEqualTo(1); + + } + + +} \ No newline at end of file diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceTest.java index 4e895c18..67d5e7b1 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/faq/service/FaqServiceTest.java @@ -4,6 +4,10 @@ import com.bbteam.budgetbuddies.domain.faq.dto.FaqResponseDto; import com.bbteam.budgetbuddies.domain.faq.entity.Faq; import com.bbteam.budgetbuddies.domain.faq.repository.FaqRepository; +import com.bbteam.budgetbuddies.domain.faqkeyword.dto.FaqKeywordResponseDto; +import com.bbteam.budgetbuddies.domain.faqkeyword.repository.FaqKeywordRepository; +import com.bbteam.budgetbuddies.domain.searchkeyword.domain.SearchKeyword; +import com.bbteam.budgetbuddies.domain.searchkeyword.repository.SearchKeywordRepository; import com.bbteam.budgetbuddies.domain.user.entity.User; import com.bbteam.budgetbuddies.domain.user.repository.UserRepository; import org.assertj.core.api.Assertions; @@ -14,6 +18,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.test.annotation.Rollback; import org.springframework.transaction.annotation.Transactional; import java.util.Optional; @@ -31,6 +36,10 @@ class FaqServiceTest { FaqRepository faqRepository; @Autowired UserRepository userRepository; + @Autowired + FaqKeywordRepository faqKeywordRepository; + @Autowired + SearchKeywordRepository searchKeywordRepository; static Long userId; static Long faqId; @@ -149,4 +158,35 @@ void deleteFaq() { assertThat(faq.isEmpty()).isTrue(); } + + @Test + void addKeywordAndRemoveKeyword() { + User user = userRepository.findById(userId).get(); + + Faq faq1 = Faq.builder() + .title("test1") + .body("test1") + .user(user) + .build(); + faqRepository.save(faq1); + + SearchKeyword searchKeyword = SearchKeyword.builder() + .keyword("testKeyword") + .build(); + searchKeywordRepository.save(searchKeyword); + faqService.addKeyword(faq1.getId(), searchKeyword.getId()); + PageRequest pageRequest = PageRequest.of(0, 1); + + Page result1 = faqService.searchFaq(pageRequest, "test"); + Assertions.assertThat(result1.getNumberOfElements()).isEqualTo(1); + + Page result2 = faqService.searchFaq(pageRequest, "no"); + Assertions.assertThat(result2.getNumberOfElements()).isEqualTo(0); + + faqService.removeKeyword(faq1.getId(), searchKeyword.getId()); + Page result3 = faqService.searchFaq(pageRequest, "test"); + Assertions.assertThat(result3.getNumberOfElements()).isEqualTo(0); + + + } } \ No newline at end of file