Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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",
Expand Down Expand Up @@ -203,8 +188,9 @@ ResponseEntity<SuccessResponse<?>> createUserSuggestedTemplate(
summary = "게시 알림 구독",
description = """
다른 사용자가 이미 요청한 영상(TRAVEL-03-003)에 대해 게시 알림을 신청합니다.
영상 링크로 요청하면 서버가 해당 영상의 PENDING 상태 제안 템플릿을 찾아 구독자로 등록합니다.
영상이 ACCEPTED 처리되면 구독자 전체에게 FCM 알림이 발송됩니다.
PENDING 상태인 영상에만 구독 신청이 가능합니다. ACCEPTED/DENIED 상태이면 400을 반환합니다.
동일 영상에 PENDING 상태의 제안이 없으면(미등록 또는 이미 처리됨) 404를 반환합니다.
""",
security = @SecurityRequirement(name = "bearerAuth")
)
Expand Down Expand Up @@ -295,7 +281,7 @@ ResponseEntity<SuccessResponse<?>> createUserSuggestedTemplate(
)
})
ResponseEntity<SuccessResponse<?>> subscribe(
@PathVariable("id") Long templateId,
@CurrentUuid String uuid
@CurrentUuid String uuid,
@RequestBody @Valid final SubscribeUserSuggestedTemplateRequest request
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

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;
import org.springframework.web.bind.annotation.RestController;

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;

Expand All @@ -35,12 +35,12 @@ public ResponseEntity<SuccessResponse<?>> createUserSuggestedTemplate(
}

@Override
@PostMapping("/{id}/subscribe")
@PostMapping("/subscribe")
public ResponseEntity<SuccessResponse<?>> 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());
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,8 +13,7 @@ public record AdminUserSuggestedTemplateResponse(
String videoLink,
String recommendReason,
String suggesterUuid,
TravelCategory category,
DomesticRegion region,
List<String> category,
SuggestionStatus status,
LocalDateTime createdAt
) {
Expand All @@ -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()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TravelCategory> category
Comment thread
WooJJam marked this conversation as resolved.
) {
}
Original file line number Diff line number Diff line change
@@ -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
) {
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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<String> category,
String recommendReason
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -41,13 +44,12 @@ public String createContent() {
public List<DiscordEmbed> createEmbeds() {

List<Field> 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;

Expand All @@ -64,13 +66,9 @@ public List<DiscordEmbed> 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -20,16 +23,16 @@ 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<String> category = request.category().stream()
.map(TravelCategory::name)
.toList();
Comment thread
WooJJam marked this conversation as resolved.

UserSuggestedTemplateCreatedEvent event = new UserSuggestedTemplateCreatedEvent(
templateId,
videoId,
request.videoLink(),
uuid,
category,
region,
request.recommendReason()
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<AdminUserSuggestedTemplateResponse> readUserSuggestedTemplatesForAdmin(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,22 @@ public Long createUserSuggestedTemplate(
request.videoLink(),
request.recommendReason(),
uuid,
request.category(),
request.region()
request.category()
)
);

log.info("새로운 여행 영상을 요청하였습니다. userId={}, templateId={}, videoId={}", uuid, template.getId(), videoId);
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<AdminUserSuggestedTemplateResponse> readUserSuggestedTemplatesForAdmin(
Expand Down
2 changes: 1 addition & 1 deletion application/src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="ndgl"/>
<springProperty scope="context" name="LOG_PATH" source="LOG_PATH" defaultValue="logs"/>
<property name="LOG_PATH" value="${LOG_PATH:-logs}"/>
Comment thread
WooJJam marked this conversation as resolved.

<property name="CONSOLE_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 0 additions & 12 deletions common/src/main/java/com/yapp/ndgl/common/type/DomesticRegion.java

This file was deleted.

Loading