From 4da3c11e409e67f1e1ccf6b0368ff3f3b7819a7e Mon Sep 17 00:00:00 2001 From: Jung Seonghun <80201773+seonghun-dev@users.noreply.github.com> Date: Wed, 11 Oct 2023 03:53:19 +0900 Subject: [PATCH] :recycle: feat(api): add search term recommend (#327) * :recycle: feat(api): add search term recommend * :sparkles: feat(api) : add textcolor vo and dto * :bug: fix(api) : add api to text color dto * :recycle: chore(admin): fix to var * :recycle: chore(admin): fix to builder pattern * :recycle: chore(admin): fix to protected --- .../controller/SearchRecommendController.java | 27 ++++++++++ .../search/dto/CreateSearchRecommendDto.java | 16 ++++++ .../recommend/search/dto/TextColorDto.java | 15 ++++++ .../SearchRecommendTermRepository.java | 7 +++ .../service/SearchRecommendService.java | 29 +++++++++++ .../depromeet/common/error/dto/ErrorCode.java | 4 +- .../controller/SearchRecommendController.java | 28 +++++++++++ .../SearchTermRecommendResponseDto.java | 14 ++++++ .../recommend/dto/response/TextColorDto.java | 11 +++++ .../SearchRecommendTermRepository.java | 12 +++++ .../service/SearchRecommendService.java | 33 +++++++++++++ .../V20230822__add_search_term_recommend.sql | 7 +++ backend/streetdrop-domain/build.gradle | 2 + .../recommend/search/SearchRecommendTerm.java | 49 +++++++++++++++++++ .../recommend/search/TextColorVo.java | 16 ++++++ 15 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/controller/SearchRecommendController.java create mode 100644 backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/CreateSearchRecommendDto.java create mode 100644 backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/TextColorDto.java create mode 100644 backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/repository/SearchRecommendTermRepository.java create mode 100644 backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/service/SearchRecommendService.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/controller/SearchRecommendController.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/SearchTermRecommendResponseDto.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/TextColorDto.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/repository/SearchRecommendTermRepository.java create mode 100644 backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/service/SearchRecommendService.java create mode 100644 backend/streetdrop-api/src/main/resources/db/migration/V20230822__add_search_term_recommend.sql create mode 100644 backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/SearchRecommendTerm.java create mode 100644 backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/TextColorVo.java diff --git a/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/controller/SearchRecommendController.java b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/controller/SearchRecommendController.java new file mode 100644 index 00000000..b7dfc731 --- /dev/null +++ b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/controller/SearchRecommendController.java @@ -0,0 +1,27 @@ +package com.depromeet.domains.recommend.search.controller; + +import com.depromeet.domains.recommend.search.dto.CreateSearchRecommendDto; +import com.depromeet.domains.recommend.search.service.SearchRecommendService; +import com.depromeet.domains.user.dto.ResponseDto; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/search-term/recommend") +@RequiredArgsConstructor +public class SearchRecommendController { + + private final SearchRecommendService searchRecommendService; + @PostMapping + public ResponseEntity addRecommendSearchTerm( + @RequestBody CreateSearchRecommendDto createSearchRecommendDto + ) { + var response = searchRecommendService.createSearchRecommendTerm(createSearchRecommendDto); + return ResponseDto.created(response); + } + +} diff --git a/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/CreateSearchRecommendDto.java b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/CreateSearchRecommendDto.java new file mode 100644 index 00000000..19036ccc --- /dev/null +++ b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/CreateSearchRecommendDto.java @@ -0,0 +1,16 @@ +package com.depromeet.domains.recommend.search.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class CreateSearchRecommendDto { + private String title; + private List description; + private List terms; +} diff --git a/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/TextColorDto.java b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/TextColorDto.java new file mode 100644 index 00000000..ef50606d --- /dev/null +++ b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/dto/TextColorDto.java @@ -0,0 +1,15 @@ +package com.depromeet.domains.recommend.search.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import static lombok.AccessLevel.PROTECTED; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = PROTECTED) +public class TextColorDto { + private String text; + private String color; +} diff --git a/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/repository/SearchRecommendTermRepository.java b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/repository/SearchRecommendTermRepository.java new file mode 100644 index 00000000..46eb66cf --- /dev/null +++ b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/repository/SearchRecommendTermRepository.java @@ -0,0 +1,7 @@ +package com.depromeet.domains.recommend.search.repository; + +import com.depromeet.recommend.search.SearchRecommendTerm; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SearchRecommendTermRepository extends JpaRepository { +} diff --git a/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/service/SearchRecommendService.java b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/service/SearchRecommendService.java new file mode 100644 index 00000000..275fd6c0 --- /dev/null +++ b/backend/streetdrop-admin/streetdrop-admin-server/src/main/java/com/depromeet/domains/recommend/search/service/SearchRecommendService.java @@ -0,0 +1,29 @@ +package com.depromeet.domains.recommend.search.service; + +import com.depromeet.domains.recommend.search.dto.CreateSearchRecommendDto; +import com.depromeet.domains.recommend.search.repository.SearchRecommendTermRepository; +import com.depromeet.recommend.search.SearchRecommendTerm; +import com.depromeet.recommend.search.TextColorVo; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class SearchRecommendService { + private final SearchRecommendTermRepository searchRecommendTermRepository; + + @Transactional + public int createSearchRecommendTerm(CreateSearchRecommendDto createSearchRecommendDto) { + var title = createSearchRecommendDto.getTitle(); + var description = createSearchRecommendDto.getDescription().stream() + .map(textColorDto -> new TextColorVo(textColorDto.getText(), textColorDto.getColor())) + .toList(); + var terms = createSearchRecommendDto.getTerms().stream() + .map(textColorDto -> new TextColorVo(textColorDto.getText(), textColorDto.getColor())) + .toList(); + var searchRecommendTerm = SearchRecommendTerm.builder().title(title).description(description).terms(terms).build(); + var result = searchRecommendTermRepository.save(searchRecommendTerm); + return result.getId().intValue(); + } +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/common/error/dto/ErrorCode.java b/backend/streetdrop-api/src/main/java/com/depromeet/common/error/dto/ErrorCode.java index e4e8a73e..d258f555 100644 --- a/backend/streetdrop-api/src/main/java/com/depromeet/common/error/dto/ErrorCode.java +++ b/backend/streetdrop-api/src/main/java/com/depromeet/common/error/dto/ErrorCode.java @@ -47,7 +47,9 @@ public enum ErrorCode { INVALID_INPUT_EXCEPTION(HttpStatus.BAD_REQUEST, "C-0015", "Nickname must be at least 1 character and not more than 10 characters"), - CAN_NOT_BLOCK_SELF(HttpStatus.BAD_REQUEST, "C-0016", "Can not block myself"); + CAN_NOT_BLOCK_SELF(HttpStatus.BAD_REQUEST, "C-0016", "Can not block myself"), + + SEARCH_TERM_NOT_FOUND(HttpStatus.NOT_FOUND, "C-0010", "Search Term Not Found"); private final HttpStatus status; private final String code; diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/controller/SearchRecommendController.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/controller/SearchRecommendController.java new file mode 100644 index 00000000..5538a4a6 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/controller/SearchRecommendController.java @@ -0,0 +1,28 @@ +package com.depromeet.domains.recommend.controller; + +import com.depromeet.common.dto.ResponseDto; +import com.depromeet.domains.recommend.dto.response.SearchTermRecommendResponseDto; +import com.depromeet.domains.recommend.service.SearchRecommendService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +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.RestController; + +@RestController +@RequestMapping("/search-term/recommend") +@RequiredArgsConstructor +@Tag(name = "SearchRecommend", description = "Search Recommend API") +public class SearchRecommendController { + private final SearchRecommendService searchRecommendService; + + @Operation(summary = "Recommend Search Term") + @GetMapping + public ResponseEntity recommendSearchTerm() { + var response = searchRecommendService.recommendSearchTerm(); + return ResponseDto.ok(response); + } + +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/SearchTermRecommendResponseDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/SearchTermRecommendResponseDto.java new file mode 100644 index 00000000..ff06f2b1 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/SearchTermRecommendResponseDto.java @@ -0,0 +1,14 @@ +package com.depromeet.domains.recommend.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +@Getter +public class SearchTermRecommendResponseDto { + private final List description; + private final List terms; +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/TextColorDto.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/TextColorDto.java new file mode 100644 index 00000000..21b53051 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/dto/response/TextColorDto.java @@ -0,0 +1,11 @@ +package com.depromeet.domains.recommend.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class TextColorDto { + String text; + String color; +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/repository/SearchRecommendTermRepository.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/repository/SearchRecommendTermRepository.java new file mode 100644 index 00000000..10c70457 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/repository/SearchRecommendTermRepository.java @@ -0,0 +1,12 @@ +package com.depromeet.domains.recommend.repository; + +import com.depromeet.recommend.search.SearchRecommendTerm; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface SearchRecommendTermRepository extends JpaRepository { + @Query(value = "SELECT s FROM SearchRecommendTerm s ORDER BY RAND() LIMIT 1") + Optional getRandomSearchRecommendTerm(); +} diff --git a/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/service/SearchRecommendService.java b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/service/SearchRecommendService.java new file mode 100644 index 00000000..0dc6df00 --- /dev/null +++ b/backend/streetdrop-api/src/main/java/com/depromeet/domains/recommend/service/SearchRecommendService.java @@ -0,0 +1,33 @@ +package com.depromeet.domains.recommend.service; + +import com.depromeet.common.error.dto.ErrorCode; +import com.depromeet.common.error.exception.common.BusinessException; +import com.depromeet.domains.recommend.dto.response.SearchTermRecommendResponseDto; +import com.depromeet.domains.recommend.dto.response.TextColorDto; +import com.depromeet.domains.recommend.repository.SearchRecommendTermRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SearchRecommendService { + + private final SearchRecommendTermRepository searchRecommendTermRepository; + + public SearchTermRecommendResponseDto recommendSearchTerm() { + var recommendTerm = searchRecommendTermRepository.getRandomSearchRecommendTerm() + .orElseThrow(() -> new BusinessException(ErrorCode.SEARCH_TERM_NOT_FOUND)); + + var description = recommendTerm.getDescription().stream() + .map((textColorVo) -> + new TextColorDto(textColorVo.getText(), textColorVo.getColor())) + .toList(); + + var termList = recommendTerm.getTerms().stream() + .map((textColorVo) -> + new TextColorDto(textColorVo.getText(), textColorVo.getColor())) + .toList(); + + return new SearchTermRecommendResponseDto(description, termList); + } +} diff --git a/backend/streetdrop-api/src/main/resources/db/migration/V20230822__add_search_term_recommend.sql b/backend/streetdrop-api/src/main/resources/db/migration/V20230822__add_search_term_recommend.sql new file mode 100644 index 00000000..af66a704 --- /dev/null +++ b/backend/streetdrop-api/src/main/resources/db/migration/V20230822__add_search_term_recommend.sql @@ -0,0 +1,7 @@ +CREATE TABLE search_recommend_term ( + search_recommend_term_id BIGINT NOT NULL AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + description JSON NOT NULL, + terms JSON NOT NULL, + PRIMARY KEY (search_recommend_term_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/backend/streetdrop-domain/build.gradle b/backend/streetdrop-domain/build.gradle index 65cd88f5..d4ec6e90 100644 --- a/backend/streetdrop-domain/build.gradle +++ b/backend/streetdrop-domain/build.gradle @@ -10,6 +10,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.hibernate:hibernate-spatial:6.2.2.Final' implementation 'org.locationtech.jts:jts-core' + implementation 'io.hypersistence:hypersistence-utils-hibernate-60:3.5.1' + implementation 'com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.15.2' implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta" annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" diff --git a/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/SearchRecommendTerm.java b/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/SearchRecommendTerm.java new file mode 100644 index 00000000..ef2ca9d8 --- /dev/null +++ b/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/SearchRecommendTerm.java @@ -0,0 +1,49 @@ +package com.depromeet.recommend.search; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Type; + +import java.util.List; + +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +@Getter +@NoArgsConstructor(access = PROTECTED) +@Entity +public class SearchRecommendTerm { + + @Id + @GeneratedValue(strategy = IDENTITY) + @Column(name = "search_recommend_term_id") + private Long id; + + @Column(nullable = false) + private String title; + + @Column(nullable = false, columnDefinition = "json") + @Type(value = JsonType.class) + private List description; + + @Column(nullable = false, columnDefinition = "json") + @Type(value = JsonType.class) + private List terms; + + @Column(nullable = false) + private boolean active; + + @Builder + public SearchRecommendTerm(String title, List description, List terms) { + this.title = title; + this.description = description; + this.terms = terms; + this.active = true; + } +} diff --git a/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/TextColorVo.java b/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/TextColorVo.java new file mode 100644 index 00000000..e961cda2 --- /dev/null +++ b/backend/streetdrop-domain/src/main/java/com/depromeet/recommend/search/TextColorVo.java @@ -0,0 +1,16 @@ +package com.depromeet.recommend.search; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import static lombok.AccessLevel.PROTECTED; + +@Getter +@NoArgsConstructor(access = PROTECTED) +@AllArgsConstructor +public class TextColorVo { + private String text; + + private String color; +}