diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateApi.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateApi.java index 70aaaf8..ac88d29 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateApi.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateApi.java @@ -1,11 +1,11 @@ package com.yapp.ndgl.application.domains.travel.controller; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import com.yapp.ndgl.application.domains.auth.annotation.CurrentUuid; import com.yapp.ndgl.application.domains.travel.controller.dto.CreateUserSuggestedTemplateRequest; +import com.yapp.ndgl.application.domains.travel.controller.dto.SubscribeUserSuggestedTemplateRequest; import com.yapp.ndgl.common.response.ErrorResponse; import com.yapp.ndgl.common.response.SuccessResponse; @@ -31,21 +31,6 @@ public interface UserSuggestedTemplateApi { """, security = @SecurityRequirement(name = "bearerAuth") ) - @io.swagger.v3.oas.annotations.parameters.RequestBody( - content = @Content( - examples = @ExampleObject( - name = "요청 예시", - value = """ - { - "video_link": "https://youtu.be/abc12345678", - "recommend_reason": "산정호수 일출이 정말 아름다워요. 새벽 5시에 가면 혼자 볼 수 있어요.", - "category": "UNCATEGORIZED", - "region": "UNDEFINED" - } - """ - ) - ) - ) @ApiResponses({ @ApiResponse( responseCode = "200", @@ -203,8 +188,9 @@ ResponseEntity> createUserSuggestedTemplate( summary = "게시 알림 구독", description = """ 다른 사용자가 이미 요청한 영상(TRAVEL-03-003)에 대해 게시 알림을 신청합니다. + 영상 링크로 요청하면 서버가 해당 영상의 PENDING 상태 제안 템플릿을 찾아 구독자로 등록합니다. 영상이 ACCEPTED 처리되면 구독자 전체에게 FCM 알림이 발송됩니다. - PENDING 상태인 영상에만 구독 신청이 가능합니다. ACCEPTED/DENIED 상태이면 400을 반환합니다. + 동일 영상에 PENDING 상태의 제안이 없으면(미등록 또는 이미 처리됨) 404를 반환합니다. """, security = @SecurityRequirement(name = "bearerAuth") ) @@ -295,7 +281,7 @@ ResponseEntity> createUserSuggestedTemplate( ) }) ResponseEntity> subscribe( - @PathVariable("id") Long templateId, - @CurrentUuid String uuid + @CurrentUuid String uuid, + @RequestBody @Valid final SubscribeUserSuggestedTemplateRequest request ); } diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateController.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateController.java index d2ba723..fbccb5e 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateController.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/UserSuggestedTemplateController.java @@ -2,7 +2,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -10,6 +9,7 @@ import com.yapp.ndgl.application.domains.auth.annotation.CurrentUuid; import com.yapp.ndgl.application.domains.travel.controller.dto.CreateUserSuggestedTemplateRequest; +import com.yapp.ndgl.application.domains.travel.controller.dto.SubscribeUserSuggestedTemplateRequest; import com.yapp.ndgl.application.domains.travel.facade.UserSuggestedTemplateFacade; import com.yapp.ndgl.common.response.SuccessResponse; @@ -35,12 +35,12 @@ public ResponseEntity> createUserSuggestedTemplate( } @Override - @PostMapping("/{id}/subscribe") + @PostMapping("/subscribe") public ResponseEntity> subscribe( - @PathVariable("id") final Long templateId, - @CurrentUuid String uuid + @CurrentUuid String uuid, + @Valid @RequestBody final SubscribeUserSuggestedTemplateRequest request ) { - userSuggestedTemplateFacade.subscribe(templateId, uuid); + userSuggestedTemplateFacade.subscribe(uuid, request); return ResponseEntity.ok(SuccessResponse.noContent()); } } diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/AdminUserSuggestedTemplateResponse.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/AdminUserSuggestedTemplateResponse.java index 190d603..dc9bb5d 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/AdminUserSuggestedTemplateResponse.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/AdminUserSuggestedTemplateResponse.java @@ -1,8 +1,8 @@ package com.yapp.ndgl.application.domains.travel.controller.dto; import java.time.LocalDateTime; +import java.util.List; -import com.yapp.ndgl.common.type.DomesticRegion; import com.yapp.ndgl.common.type.SuggestionStatus; import com.yapp.ndgl.common.type.TravelCategory; import com.yapp.ndgl.domain.travel.UserSuggestedTemplate; @@ -13,8 +13,7 @@ public record AdminUserSuggestedTemplateResponse( String videoLink, String recommendReason, String suggesterUuid, - TravelCategory category, - DomesticRegion region, + List category, SuggestionStatus status, LocalDateTime createdAt ) { @@ -26,8 +25,7 @@ public static AdminUserSuggestedTemplateResponse toResponse(final UserSuggestedT domain.getVideoLink(), domain.getRecommendReason(), domain.getSuggesterUuid(), - domain.getCategory(), - domain.getRegion(), + domain.getCategory().stream().map(TravelCategory::getLabel).toList(), domain.getStatus(), domain.getCreatedAt() ); diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/CreateUserSuggestedTemplateRequest.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/CreateUserSuggestedTemplateRequest.java index 1874904..09b8cd5 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/CreateUserSuggestedTemplateRequest.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/CreateUserSuggestedTemplateRequest.java @@ -1,29 +1,25 @@ package com.yapp.ndgl.application.domains.travel.controller.dto; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.yapp.ndgl.common.type.DomesticRegion; +import java.util.List; + import com.yapp.ndgl.common.type.TravelCategory; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.Size; public record CreateUserSuggestedTemplateRequest( @Schema(description = "YouTube 영상 링크", example = "https://youtu.be/abc12345678", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "영상 링크는 필수입니다.") - @JsonProperty("video_link") String videoLink, - @Schema(description = "추천 이유", example = "산정호수 일출 명소", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "추천 이유는 필수입니다.") + @Schema(description = "추천 이유 (선택)", example = "산정호수 일출 명소") @Size(max = 1000, message = "추천 이유는 1000자 이하여야 합니다.") - @JsonProperty("recommend_reason") String recommendReason, - @Schema(description = "여행 카테고리 (선택)", example = "UNCATEGORIZED") - TravelCategory category, - - @Schema(description = "국내 지역 (선택)", example = "UNDEFINED") - DomesticRegion region + @Schema(description = "여행 카테고리 (복수 선택)", example = "[\"FOOD\"]", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "카테고리는 최소 한 개 이상 선택해야 합니다.") + List category ) { } diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/SubscribeUserSuggestedTemplateRequest.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/SubscribeUserSuggestedTemplateRequest.java new file mode 100644 index 0000000..a11eff0 --- /dev/null +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/SubscribeUserSuggestedTemplateRequest.java @@ -0,0 +1,11 @@ +package com.yapp.ndgl.application.domains.travel.controller.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; + +public record SubscribeUserSuggestedTemplateRequest( + @Schema(description = "YouTube 영상 링크", example = "https://youtu.be/abc12345678", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "영상 링크는 필수입니다.") + String videoLink +) { +} diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/UserSuggestedTemplateResponse.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/UserSuggestedTemplateResponse.java deleted file mode 100644 index c6c70a1..0000000 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/controller/dto/UserSuggestedTemplateResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.yapp.ndgl.application.domains.travel.controller.dto; - -import com.yapp.ndgl.common.type.DomesticRegion; -import com.yapp.ndgl.common.type.SuggestionStatus; -import com.yapp.ndgl.common.type.TravelCategory; -import com.yapp.ndgl.domain.travel.UserSuggestedTemplate; - -import io.swagger.v3.oas.annotations.media.Schema; - -public record UserSuggestedTemplateResponse( - @Schema(description = "제안 템플릿 ID", example = "1") - Long id, - - @Schema(description = "영상 링크") - String videoLink, - - @Schema(description = "추천 이유") - String recommendReason, - - @Schema(description = "제안자 UUID") - String suggesterUuid, - - @Schema(description = "여행 카테고리") - TravelCategory category, - - @Schema(description = "국내 지역") - DomesticRegion region, - - @Schema(description = "검토 상태") - SuggestionStatus status -) { - - public static UserSuggestedTemplateResponse from(final UserSuggestedTemplate domain) { - return new UserSuggestedTemplateResponse( - domain.getId(), - domain.getVideoLink(), - domain.getRecommendReason(), - domain.getSuggesterUuid(), - domain.getCategory(), - domain.getRegion(), - domain.getStatus() - ); - } -} diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateCreatedEvent.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateCreatedEvent.java index ae18ec1..c70d0b1 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateCreatedEvent.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateCreatedEvent.java @@ -1,12 +1,13 @@ package com.yapp.ndgl.application.domains.travel.event; +import java.util.List; + public record UserSuggestedTemplateCreatedEvent( Long templateId, String videoId, String videoLink, String suggesterUuid, - String category, - String region, + List category, String recommendReason ) { } diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateNotification.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateNotification.java index 210f787..6ed18f1 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateNotification.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/UserSuggestedTemplateNotification.java @@ -11,6 +11,7 @@ import com.yapp.ndgl.clients.discord.request.DiscordEmbed; import com.yapp.ndgl.clients.discord.request.DiscordEmbed.Field; import com.yapp.ndgl.clients.discord.request.DiscordEmbed.Image; +import com.yapp.ndgl.common.util.TextUtils; import lombok.RequiredArgsConstructor; @@ -20,6 +21,8 @@ public final class UserSuggestedTemplateNotification implements DiscordNotificat private static final int EMBED_COLOR = 5763719; private static final String CONTENT_HEADER = "## 🎬 새로운 영상이 요청되었어요. 지금 확인해보세요!"; private static final String EMBED_TITLE = "영상 보기"; + private static final String EMPTY_PLACEHOLDER = "-"; + private static final String CATEGORY_DELIMITER = ", "; private final UserSuggestedTemplateCreatedEvent event; @@ -41,13 +44,12 @@ public String createContent() { public List createEmbeds() { List fields = List.of( - Field.of("카테고리", emptyIfBlank(event.category()), true), - Field.of("지역", emptyIfBlank(event.region()), true), + Field.of("카테고리", TextUtils.joinOrDefault(event.category(), CATEGORY_DELIMITER, EMPTY_PLACEHOLDER), true), Field.of("템플릿 ID", "#" + event.templateId(), true), Field.of("제안자", maskUuid(event.suggesterUuid()), false) ); - String description = StringUtils.hasText(event.recommendReason()) ? event.recommendReason() : null; + String description = TextUtils.defaultIfBlank(event.recommendReason(), null); Image image = StringUtils.hasText(event.videoId()) ? Image.of(DiscordPayloadConstraints.YOUTUBE_THUMBNAIL_URL_FORMAT.formatted(event.videoId())) : null; @@ -64,13 +66,9 @@ public List createEmbeds() { return List.of(embed); } - private static String emptyIfBlank(final String value) { - return StringUtils.hasText(value) ? value : "-"; - } - private static String maskUuid(final String uuid) { if (!StringUtils.hasText(uuid)) { - return "-"; + return EMPTY_PLACEHOLDER; } if (uuid.length() <= 8) { return uuid; diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/publisher/UserSuggestedTemplateEventPublisher.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/publisher/UserSuggestedTemplateEventPublisher.java index cf2ea92..701b587 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/publisher/UserSuggestedTemplateEventPublisher.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/event/publisher/UserSuggestedTemplateEventPublisher.java @@ -1,10 +1,13 @@ package com.yapp.ndgl.application.domains.travel.event.publisher; +import java.util.List; + import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; import com.yapp.ndgl.application.domains.travel.controller.dto.CreateUserSuggestedTemplateRequest; import com.yapp.ndgl.application.domains.travel.event.UserSuggestedTemplateCreatedEvent; +import com.yapp.ndgl.common.type.TravelCategory; import lombok.RequiredArgsConstructor; @@ -20,8 +23,9 @@ public void publish( final String uuid, final CreateUserSuggestedTemplateRequest request ) { - String category = request.category() != null ? request.category().name() : null; - String region = request.region() != null ? request.region().name() : null; + List category = request.category().stream() + .map(TravelCategory::name) + .toList(); UserSuggestedTemplateCreatedEvent event = new UserSuggestedTemplateCreatedEvent( templateId, @@ -29,7 +33,6 @@ public void publish( request.videoLink(), uuid, category, - region, request.recommendReason() ); diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/facade/UserSuggestedTemplateFacade.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/facade/UserSuggestedTemplateFacade.java index 4e99ae6..fdc00f7 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/facade/UserSuggestedTemplateFacade.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/facade/UserSuggestedTemplateFacade.java @@ -3,6 +3,7 @@ import com.yapp.ndgl.application.common.annotation.Facade; import com.yapp.ndgl.application.domains.travel.controller.dto.AdminUserSuggestedTemplateResponse; import com.yapp.ndgl.application.domains.travel.controller.dto.CreateUserSuggestedTemplateRequest; +import com.yapp.ndgl.application.domains.travel.controller.dto.SubscribeUserSuggestedTemplateRequest; import com.yapp.ndgl.application.domains.travel.event.publisher.UserSuggestedTemplateEventPublisher; import com.yapp.ndgl.application.domains.travel.service.UserSuggestedTemplateService; import com.yapp.ndgl.application.utils.YoutubeUrlParser; @@ -30,8 +31,9 @@ public void createUserSuggestedTemplate( userSuggestedTemplateEventPublisher.publish(templateId, videoId, uuid, request); } - public void subscribe(final Long templateId, final String uuid) { - userSuggestedTemplateService.subscribe(templateId, uuid); + public void subscribe(final String uuid, final SubscribeUserSuggestedTemplateRequest request) { + String videoId = YoutubeUrlParser.extractVideoId(request.videoLink()); + userSuggestedTemplateService.subscribe(videoId, uuid); } public PageResponse readUserSuggestedTemplatesForAdmin( diff --git a/application/src/main/java/com/yapp/ndgl/application/domains/travel/service/UserSuggestedTemplateService.java b/application/src/main/java/com/yapp/ndgl/application/domains/travel/service/UserSuggestedTemplateService.java index d139e68..045708e 100644 --- a/application/src/main/java/com/yapp/ndgl/application/domains/travel/service/UserSuggestedTemplateService.java +++ b/application/src/main/java/com/yapp/ndgl/application/domains/travel/service/UserSuggestedTemplateService.java @@ -54,8 +54,7 @@ public Long createUserSuggestedTemplate( request.videoLink(), request.recommendReason(), uuid, - request.category(), - request.region() + request.category() ) ); @@ -63,9 +62,14 @@ public Long createUserSuggestedTemplate( return template.getId(); } - public void subscribe(final Long templateId, final String uuid) { - log.info("사용자 제안 여행 템플릿 구독을 신청합니다. templateId={}, subscriberUuid={}", templateId, uuid); - userSuggestedTemplateDomainService.subscribe(templateId, uuid); + public void subscribe(final String videoId, final String uuid) { + UserSuggestedTemplate template = userSuggestedTemplateDomainService + .findByVideoIdAndStatus(videoId, SuggestionStatus.PENDING) + .orElseThrow(() -> new GlobalException(TravelErrorCode.NOT_FOUND_SUGGESTED_TEMPLATE)); + + log.info("사용자 제안 여행 템플릿 구독을 신청합니다. videoId={}, templateId={}, subscriberUuid={}", + videoId, template.getId(), uuid); + userSuggestedTemplateDomainService.subscribe(template.getId(), uuid); } public PageResponse readUserSuggestedTemplatesForAdmin( diff --git a/application/src/main/resources/logback-spring.xml b/application/src/main/resources/logback-spring.xml index 769d485..83a0a09 100644 --- a/application/src/main/resources/logback-spring.xml +++ b/application/src/main/resources/logback-spring.xml @@ -1,7 +1,7 @@ - + diff --git a/application/src/test/java/com/yapp/ndgl/application/domains/travel/UserSuggestedTemplateConcurrencyTest.java b/application/src/test/java/com/yapp/ndgl/application/domains/travel/UserSuggestedTemplateConcurrencyTest.java index 90884cf..b27d231 100644 --- a/application/src/test/java/com/yapp/ndgl/application/domains/travel/UserSuggestedTemplateConcurrencyTest.java +++ b/application/src/test/java/com/yapp/ndgl/application/domains/travel/UserSuggestedTemplateConcurrencyTest.java @@ -16,7 +16,6 @@ import com.yapp.ndgl.application.domains.travel.controller.dto.CreateUserSuggestedTemplateRequest; import com.yapp.ndgl.application.domains.travel.facade.UserSuggestedTemplateFacade; import com.yapp.ndgl.application.executor.ConcurrencyExecutor; -import com.yapp.ndgl.common.type.DomesticRegion; import com.yapp.ndgl.common.type.SuggestionStatus; import com.yapp.ndgl.common.type.TravelCategory; import com.yapp.ndgl.domain.travel.entity.UserSuggestedTemplateEntity; @@ -46,8 +45,7 @@ void cleanup() { CreateUserSuggestedTemplateRequest request = new CreateUserSuggestedTemplateRequest( TEST_VIDEO_LINK, "동시성 테스트 추천 이유", - TravelCategory.UNCATEGORIZED, - DomesticRegion.UNDEFINED + List.of(TravelCategory.FOOD) ); AtomicInteger successCount = new AtomicInteger(0); diff --git a/common/src/main/java/com/yapp/ndgl/common/type/DomesticRegion.java b/common/src/main/java/com/yapp/ndgl/common/type/DomesticRegion.java deleted file mode 100644 index 39dd847..0000000 --- a/common/src/main/java/com/yapp/ndgl/common/type/DomesticRegion.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.yapp.ndgl.common.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum DomesticRegion { - UNDEFINED("미지정"); - - private final String label; -} diff --git a/common/src/main/java/com/yapp/ndgl/common/type/TravelCategory.java b/common/src/main/java/com/yapp/ndgl/common/type/TravelCategory.java index a8aece8..aa40559 100644 --- a/common/src/main/java/com/yapp/ndgl/common/type/TravelCategory.java +++ b/common/src/main/java/com/yapp/ndgl/common/type/TravelCategory.java @@ -6,7 +6,14 @@ @Getter @RequiredArgsConstructor public enum TravelCategory { - UNCATEGORIZED("미분류"); + FOOD("맛집"), + CAFE("카페/디저트"), + HEALING("힐링/풍경"), + ATTRACTION("명소"), + LOCAL("로컬"), + SHOPPING("쇼핑"), + ACTIVITY("액티비티/체험"), + BUDGET("가성비"); private final String label; } diff --git a/common/src/main/java/com/yapp/ndgl/common/util/TextUtils.java b/common/src/main/java/com/yapp/ndgl/common/util/TextUtils.java index 14fb9d5..6fbcd19 100644 --- a/common/src/main/java/com/yapp/ndgl/common/util/TextUtils.java +++ b/common/src/main/java/com/yapp/ndgl/common/util/TextUtils.java @@ -1,5 +1,7 @@ package com.yapp.ndgl.common.util; +import java.util.Collection; + import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -22,4 +24,32 @@ public static String truncate(final String text, final int max) { } return text.substring(0, max - 1) + "…"; } + + /** + * 공백/빈 문자열이면 fallback을 반환한다. + * + * @param value 원본 텍스트 (nullable) + * @param fallback 비어 있을 때 반환할 값 + */ + public static String defaultIfBlank(final String value, final String fallback) { + return (value != null && !value.isBlank()) ? value : fallback; + } + + /** + * 컬렉션을 구분자로 join한다. null이거나 비어 있으면 fallback을 반환한다. + * + * @param items join 대상 (nullable) + * @param delimiter 구분자 + * @param fallback 비어 있을 때 반환할 값 + */ + public static String joinOrDefault( + final Collection items, + final String delimiter, + final String fallback + ) { + if (items == null || items.isEmpty()) { + return fallback; + } + return String.join(delimiter, items); + } } diff --git a/domain/domain-rdb/src/main/java/com/yapp/ndgl/domain/travel/entity/UserSuggestedTemplateEntity.java b/domain/domain-rdb/src/main/java/com/yapp/ndgl/domain/travel/entity/UserSuggestedTemplateEntity.java index 13fd8a4..1ec6355 100644 --- a/domain/domain-rdb/src/main/java/com/yapp/ndgl/domain/travel/entity/UserSuggestedTemplateEntity.java +++ b/domain/domain-rdb/src/main/java/com/yapp/ndgl/domain/travel/entity/UserSuggestedTemplateEntity.java @@ -1,6 +1,10 @@ package com.yapp.ndgl.domain.travel.entity; -import com.yapp.ndgl.common.type.DomesticRegion; +import java.util.List; + +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + import com.yapp.ndgl.common.type.SuggestionStatus; import com.yapp.ndgl.common.type.TravelCategory; import com.yapp.ndgl.domain.common.entity.BaseEntity; @@ -27,20 +31,16 @@ public class UserSuggestedTemplateEntity extends BaseEntity { @Column(name = "video_link", nullable = false, length = 500) private String videoLink; - @Column(name = "recommend_reason", nullable = false, length = 1000) + @Column(name = "recommend_reason", length = 1000) private String recommendReason; // NOTE: 사용자 시스템 정비 시 식별자 변경 가능성 있음 (UUID → User PK) @Column(name = "suggester_uuid", nullable = false, length = 64) private String suggesterUuid; - @Enumerated(EnumType.STRING) - @Column(name = "category", length = 50) - private TravelCategory category; - - @Enumerated(EnumType.STRING) - @Column(name = "region", length = 50) - private DomesticRegion region; + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "category", nullable = false, columnDefinition = "json") + private List category; @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false, length = 20) @@ -52,8 +52,7 @@ public UserSuggestedTemplateEntity( final String videoLink, final String recommendReason, final String suggesterUuid, - final TravelCategory category, - final DomesticRegion region, + final List category, final SuggestionStatus status ) { this.videoId = videoId; @@ -61,7 +60,6 @@ public UserSuggestedTemplateEntity( this.recommendReason = recommendReason; this.suggesterUuid = suggesterUuid; this.category = category; - this.region = region; this.status = status == null ? SuggestionStatus.PENDING : status; } } diff --git a/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/UserSuggestedTemplate.java b/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/UserSuggestedTemplate.java index 72b8c56..f479fb8 100644 --- a/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/UserSuggestedTemplate.java +++ b/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/UserSuggestedTemplate.java @@ -1,8 +1,8 @@ package com.yapp.ndgl.domain.travel; import java.time.LocalDateTime; +import java.util.List; -import com.yapp.ndgl.common.type.DomesticRegion; import com.yapp.ndgl.common.type.SuggestionStatus; import com.yapp.ndgl.common.type.TravelCategory; @@ -18,8 +18,7 @@ public class UserSuggestedTemplate { private String videoLink; private String recommendReason; private String suggesterUuid; - private TravelCategory category; - private DomesticRegion region; + private List category; private SuggestionStatus status; private LocalDateTime createdAt; @@ -28,8 +27,7 @@ public static UserSuggestedTemplate of( final String videoLink, final String recommendReason, final String suggesterUuid, - final TravelCategory category, - final DomesticRegion region + final List category ) { return UserSuggestedTemplate.builder() .videoId(videoId) @@ -37,7 +35,6 @@ public static UserSuggestedTemplate of( .recommendReason(recommendReason) .suggesterUuid(suggesterUuid) .category(category) - .region(region) .status(SuggestionStatus.PENDING) .build(); } diff --git a/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/mapper/UserSuggestedTemplateMapper.java b/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/mapper/UserSuggestedTemplateMapper.java index efd09e2..024d9ce 100644 --- a/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/mapper/UserSuggestedTemplateMapper.java +++ b/domain/domain-service/src/main/java/com/yapp/ndgl/domain/travel/mapper/UserSuggestedTemplateMapper.java @@ -16,7 +16,6 @@ public static UserSuggestedTemplate toDomain(final UserSuggestedTemplateEntity e .recommendReason(entity.getRecommendReason()) .suggesterUuid(entity.getSuggesterUuid()) .category(entity.getCategory()) - .region(entity.getRegion()) .status(entity.getStatus()) .createdAt(entity.getCreatedAt()) .build(); @@ -29,7 +28,6 @@ public static UserSuggestedTemplateEntity toEntity(final UserSuggestedTemplate d .recommendReason(domain.getRecommendReason()) .suggesterUuid(domain.getSuggesterUuid()) .category(domain.getCategory()) - .region(domain.getRegion()) .status(domain.getStatus()) .build(); }