diff --git a/src/main/java/com/cmc/suppin/event/crawl/controller/CommentApi.java b/src/main/java/com/cmc/suppin/event/crawl/controller/CommentApi.java
index b786930..881fda9 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/controller/CommentApi.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/controller/CommentApi.java
@@ -1,20 +1,20 @@
package com.cmc.suppin.event.crawl.controller;
+import com.cmc.suppin.event.crawl.controller.dto.CommentRequestDTO;
import com.cmc.suppin.event.crawl.controller.dto.CommentResponseDTO;
import com.cmc.suppin.event.crawl.service.CommentService;
import com.cmc.suppin.global.response.ApiResponse;
import com.cmc.suppin.global.security.reslover.Account;
import com.cmc.suppin.global.security.reslover.CurrentAccount;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
-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;
+import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -30,31 +30,25 @@ public class CommentApi {
@GetMapping("/list")
@Operation(summary = "크롤링된 전체 댓글 조회 API",
- description = "주어진 이벤트 ID와 URL의 댓글을 페이지네이션하여 이벤트의 endDate 전에 작성된 댓글들만 조회합니다.
" +
- "Request: eventId: 조회할 이벤트의 ID, url: 댓글을 조회할 유튜브 URL, page: 조회할 페이지 번호 (1부터 시작), " +
- "size: 한 페이지당 댓글 수, Authorization: JWT 토큰을 포함한 인증 헤더
" +
- "Response: totalCommentCount: 전체 댓글 수, participantCount: 현재 페이지에서 가져온 댓글 수, crawlTime: 댓글 조회(크롤링) 요청 시간, comments: 각 댓글의 상세 정보 배열" +
- "author: 댓글 작성자, commentText: 댓글 내용, commentDate: 댓글 작성 시간")
+ description = "주어진 이벤트 ID와 URL의 댓글을 페이지네이션하여 이벤트의 endDate 전에 작성된 댓글들만 조회합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> getComments(
@RequestParam Long eventId,
@RequestParam String url,
+ @Parameter(description = "조회할 페이지 번호 (1부터 시작)")
@RequestParam int page,
+ @Parameter(description = "한 페이지당 댓글 수")
@RequestParam int size,
@CurrentAccount Account account) {
CommentResponseDTO.CrawledCommentListDTO comments = commentService.getComments(eventId, url, page, size, account.userId());
return ResponseEntity.ok(ApiResponse.of(comments));
}
- @GetMapping("/draft-winners")
- @Operation(summary = "조건별 당첨자 추첨 API", description = "주어진 조건에 따라 이벤트의 당첨자를 추첨합니다.")
+ @PostMapping("/draft-winners")
+ @Operation(summary = "조건별 당첨자 추첨 API(댓글 이벤트)", description = "주어진 조건에 따라 이벤트의 당첨자를 추첨합니다.")
public ResponseEntity> drawWinners(
- @RequestParam Long eventId,
- @RequestParam String startDate,
- @RequestParam String endDate,
- @RequestParam int winnerCount,
- @RequestParam List keywords,
+ @RequestBody @Valid CommentRequestDTO.WinnerRequestDTO request,
@CurrentAccount Account account) {
- CommentResponseDTO.WinnerResponseDTO winners = commentService.drawWinners(eventId, startDate, endDate, winnerCount, keywords, account.userId());
+ CommentResponseDTO.WinnerResponseDTO winners = commentService.drawWinners(request, account.userId());
return ResponseEntity.ok(ApiResponse.of(winners));
}
diff --git a/src/main/java/com/cmc/suppin/event/crawl/controller/CrawlApi.java b/src/main/java/com/cmc/suppin/event/crawl/controller/CrawlApi.java
index 9acadaf..000a95e 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/controller/CrawlApi.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/controller/CrawlApi.java
@@ -27,8 +27,12 @@ public class CrawlApi {
@GetMapping("/comments/checkUrl")
@Operation(summary = "크롤링 중복 검증 API",
description = "주어진 URL과 eventId로 중복된 댓글 수집 이력이 있는지 확인합니다.
" +
- "Request: url: 중복 검증할 URL, eventId: 중복 검증할 이벤트 ID, Authorization: JWT 토큰을 포함한 인증 헤더
" +
- "Response: 중복된 댓글 수집 이력이 있을 경우 message 출력, 없을 경우 null")
+ "Request
" +
+ "- url: 중복 검증할 URL
" +
+ "- eventId: 댓글 이벤트 생성 후 입력 받은 eventId
" +
+ "Response
" +
+ "- 요청된 URL과 중복된 댓글 수집 이력이 있을 경우 '검증 및 확인되었습니다.' 출력
" +
+ "- 요청된 URL과 중복된 댓글 수집 이력이 없을 경우 '수집 이력이 없습니다.' 출력")
public ResponseEntity> checkExistingComments(@RequestParam String url, @RequestParam Long eventId, @CurrentAccount Account account) {
String message = crawlService.checkExistingComments(url, eventId, account.userId());
if (message != null) {
@@ -40,9 +44,11 @@ public ResponseEntity> checkExistingComments(@RequestParam S
// 유튜브 댓글 크롤링(DB 저장)
@PostMapping("/crawling/comments")
@Operation(summary = "유튜브 댓글 크롤링 API",
- description = "주어진 URL의 유튜브 댓글을 크롤링하여 DB에 저장합니다.
" +
+ description = "주어진 URL의 유튜브 댓글을 크롤링하여 해당 댓글 데이터를 DB에 저장합니다.
" +
"Request: url: 크롤링할 URL, eventId: 댓글을 수집할 eventId, forceUpdate: 댓글을 강제로 업데이트할지 여부(Boolean), Authorization: JWT 토큰을 포함한 인증 헤더
" +
- "forceUpdate 입력 값이 false일 때 설명
" +
+ "
" +
+ "- 동일한 URL에 대한 댓글 크롤링 요청이지만, 강제로 업데이트하겠다는 의미이기 때문에, 기존 댓글 데이터를 삭제하고 새로 등록합니다.
" +
+ "
" +
"- DB에 기존 댓글이 존재하는 경우: 크롤링을 중지하고 예외를 던집니다.
" +
"- DB에 기존 댓글이 존재하지 않는 경우: 새로운 댓글을 크롤링하고 이를 DB에 저장합니다.")
public ResponseEntity> crawlYoutubeComments(@RequestParam String url, @RequestParam Long eventId, @RequestParam boolean forceUpdate, @CurrentAccount Account account) {
diff --git a/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentRequestDTO.java b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentRequestDTO.java
index c3b1028..6dd74de 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentRequestDTO.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentRequestDTO.java
@@ -1,5 +1,6 @@
package com.cmc.suppin.event.crawl.controller.dto;
+import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@@ -26,9 +27,14 @@ public static class CommentListRequestDTO {
@Builder
public static class WinnerRequestDTO {
private Long eventId;
+ private int winnerCount;
+ private int minLength;
+
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String startDate;
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String endDate;
- private int winnerCount;
+
private List keywords;
}
}
diff --git a/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentResponseDTO.java b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentResponseDTO.java
index 30862ca..a8f5fcf 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentResponseDTO.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CommentResponseDTO.java
@@ -36,6 +36,7 @@ public static class CommentDetailDTO {
@Builder
public static class WinnerResponseDTO {
private int winnerCount;
+ private int minLength;
private String startDate;
private String endDate;
private List winners;
diff --git a/src/main/java/com/cmc/suppin/event/crawl/converter/CommentConverter.java b/src/main/java/com/cmc/suppin/event/crawl/converter/CommentConverter.java
index fb09af0..89871b6 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/converter/CommentConverter.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/converter/CommentConverter.java
@@ -1,5 +1,6 @@
package com.cmc.suppin.event.crawl.converter;
+import com.cmc.suppin.event.crawl.controller.dto.CommentRequestDTO;
import com.cmc.suppin.event.crawl.controller.dto.CommentResponseDTO;
import com.cmc.suppin.event.crawl.domain.Comment;
import com.cmc.suppin.event.events.domain.Event;
@@ -42,15 +43,16 @@ public static CommentResponseDTO.CrawledCommentListDTO toCommentListDTO(List winners, int winnerCount, String startDate, String endDate) {
+ public static CommentResponseDTO.WinnerResponseDTO toWinnerResponseDTO(List winners, CommentRequestDTO.WinnerRequestDTO request) {
List winnerDetails = winners.stream()
.map(CommentConverter::toCommentDetailDTO)
.collect(Collectors.toList());
return CommentResponseDTO.WinnerResponseDTO.builder()
- .winnerCount(winnerCount)
- .startDate(startDate)
- .endDate(endDate)
+ .winnerCount(request.getWinnerCount())
+ .minLength(request.getMinLength())
+ .startDate(request.getStartDate())
+ .endDate(request.getEndDate())
.winners(winnerDetails)
.build();
}
diff --git a/src/main/java/com/cmc/suppin/event/crawl/service/CommentService.java b/src/main/java/com/cmc/suppin/event/crawl/service/CommentService.java
index d3cf147..8093176 100644
--- a/src/main/java/com/cmc/suppin/event/crawl/service/CommentService.java
+++ b/src/main/java/com/cmc/suppin/event/crawl/service/CommentService.java
@@ -1,5 +1,6 @@
package com.cmc.suppin.event.crawl.service;
+import com.cmc.suppin.event.crawl.controller.dto.CommentRequestDTO;
import com.cmc.suppin.event.crawl.controller.dto.CommentResponseDTO;
import com.cmc.suppin.event.crawl.converter.CommentConverter;
import com.cmc.suppin.event.crawl.domain.Comment;
@@ -18,9 +19,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
@@ -49,41 +48,36 @@ public CommentResponseDTO.CrawledCommentListDTO getComments(Long eventId, String
int totalComments = commentRepository.countByEventIdAndUrl(eventId, url);
- String crawlTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+ String crawlTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm"));
return CommentConverter.toCommentListDTO(comments.getContent(), crawlTime, totalComments);
}
- // 당첨자 조건별 랜덤 추첨
- public CommentResponseDTO.WinnerResponseDTO drawWinners(Long eventId, String startDate, String endDate, int winnerCount, List keywords, String userId) {
+ // 당첨자 조건별 랜덤 추첨(댓글 이벤트)
+ public CommentResponseDTO.WinnerResponseDTO drawWinners(CommentRequestDTO.WinnerRequestDTO request, String userId) {
Member member = memberRepository.findByUserIdAndStatusNot(userId, UserStatus.DELETED)
.orElseThrow(() -> new IllegalArgumentException("Member not found"));
- Event event = eventRepository.findByIdAndMemberId(eventId, member.getId())
+ Event event = eventRepository.findByIdAndMemberId(request.getEventId(), member.getId())
.orElseThrow(() -> new IllegalArgumentException("Event not found"));
- // String을 LocalDate로 변환하고 LocalDateTime으로 변환
- DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
- LocalDate start = LocalDate.parse(startDate, dateFormatter);
- LocalDate end = LocalDate.parse(endDate, dateFormatter);
-
- // LocalDateTime으로 변환
- LocalDateTime startDateTime = start.atStartOfDay();
- LocalDateTime endDateTime = end.atTime(LocalTime.MAX);
+ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
+ LocalDateTime startDateTime = LocalDateTime.parse(request.getStartDate(), dateTimeFormatter);
+ LocalDateTime endDateTime = LocalDateTime.parse(request.getEndDate(), dateTimeFormatter);
- // 당첨자 추첨 로직
List comments = commentRepository.findByEventIdAndCommentDateBetween(event.getId(), startDateTime, endDateTime);
- // 키워드 필터링(OR 로직)
+ // 키워드 필터링(OR 로직) 및 minLength 필터링 추가
List filteredComments = comments.stream()
- .filter(comment -> keywords.stream().anyMatch(keyword -> comment.getCommentText().contains(keyword)))
+ .filter(comment -> request.getKeywords().stream().anyMatch(keyword -> comment.getCommentText().contains(keyword)))
+ .filter(comment -> comment.getCommentText().length() >= request.getMinLength())
.collect(Collectors.toList());
// 랜덤 추첨
Collections.shuffle(filteredComments);
- List winners = filteredComments.stream().limit(winnerCount).collect(Collectors.toList());
+ List winners = filteredComments.stream().limit(request.getWinnerCount()).collect(Collectors.toList());
- return CommentConverter.toWinnerResponseDTO(winners, winnerCount, startDate, endDate);
+ return CommentConverter.toWinnerResponseDTO(winners, request);
}
diff --git a/src/main/java/com/cmc/suppin/event/events/controller/EventApi.java b/src/main/java/com/cmc/suppin/event/events/controller/EventApi.java
index 962b9e8..a02b7a8 100644
--- a/src/main/java/com/cmc/suppin/event/events/controller/EventApi.java
+++ b/src/main/java/com/cmc/suppin/event/events/controller/EventApi.java
@@ -31,17 +31,14 @@ public class EventApi {
private final EventService eventService;
@GetMapping("/all")
- @Operation(summary = "전체 이벤트 조회 API", description = "로그인한 사용자의 모든 이벤트와 설문 및 댓글 수를 조회합니다., JWT 토큰만 주시면 됩니다.")
+ @Operation(summary = "전체 이벤트 조회 API", description = "사용자의 모든 이벤트와 설문 및 댓글 수를 조회합니다.")
public ResponseEntity>> getAllEventsWithCounts(@CurrentAccount Account account) {
List events = eventService.getAllEvents(account.userId());
return ResponseEntity.ok(ApiResponse.of(events));
}
@PostMapping("/new/comment/crawling")
- @Operation(summary = "댓글 이벤트 생성 API",
- description = "Request : type(ENUM 타입으로, 'COMMENT와 SURVEY' 둘 중 하나를 입력해주시면 됩니다), " +
- "title, description, url, startDate(yyyy-MM-dd), endDate(yyyy-MM-dd), announcementDate(yyyy-MM-dd)
" +
- "Response로 제공되는 eventId를 이용하여 타 API들을 호출해주시면 됩니다.")
+ @Operation(summary = "댓글 이벤트 생성 API", description = "댓글 이벤트를 생성합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.")
public ResponseEntity> createCommentEvent(@RequestBody @Valid EventRequestDTO.CommentEventCreateDTO request, @CurrentAccount Account account) {
Event event = eventService.createCommentEvent(request, account.userId());
EventResponseDTO.EventInfoDTO response = EventConverter.toEventInfoDTO(event);
@@ -49,10 +46,7 @@ public ResponseEntity> createCommentE
}
@PostMapping("/new/survey")
- @Operation(summary = "설문조사 이벤트 생성 API",
- description = "Request : type(ENUM 타입으로, 'COMMENT와 SURVEY' 둘 중 하나를 입력해주시면 됩니다), " +
- "title, description, startDate(yyyy-MM-dd), endDate(yyyy-MM-dd), announcementDate(yyyy-MM-dd)
" +
- "Response로 제공되는 eventId를 이용하여 타 API들을 호출해주시면 됩니다.")
+ @Operation(summary = "설문 이벤트 생성 API", description = "설문 이벤트를 생성합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.")
public ResponseEntity> createSurveyEvent(@RequestBody @Valid EventRequestDTO.SurveyEventCreateDTO request, @CurrentAccount Account account) {
Event event = eventService.createSurveyEvent(request, account.userId());
EventResponseDTO.EventInfoDTO response = EventConverter.toEventInfoDTO(event);
diff --git a/src/main/java/com/cmc/suppin/event/events/controller/dto/EventRequestDTO.java b/src/main/java/com/cmc/suppin/event/events/controller/dto/EventRequestDTO.java
index 7a221b6..bafffd1 100644
--- a/src/main/java/com/cmc/suppin/event/events/controller/dto/EventRequestDTO.java
+++ b/src/main/java/com/cmc/suppin/event/events/controller/dto/EventRequestDTO.java
@@ -3,6 +3,7 @@
import com.cmc.suppin.global.enums.EventType;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@@ -17,17 +18,23 @@ public class EventRequestDTO {
public static class CommentEventCreateDTO {
@NotNull
private EventType type;
+
@NotEmpty
private String title;
- @NotEmpty
+
private String description;
+
@NotEmpty
private String url;
+
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String startDate;
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String endDate;
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String announcementDate;
}
@@ -38,15 +45,21 @@ public static class CommentEventCreateDTO {
public static class SurveyEventCreateDTO {
@NotNull
private EventType type;
+
@NotEmpty
private String title;
+
@NotEmpty
private String description;
+
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String startDate;
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String endDate;
@NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String announcementDate;
}
@@ -60,8 +73,15 @@ public static class EventUpdateDTO {
private String title;
private String description;
private String url;
+
+ @NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String startDate;
+ @NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String endDate;
+ @NotEmpty
+ @Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String announcementDate;
}
}
diff --git a/src/main/java/com/cmc/suppin/event/events/converter/EventConverter.java b/src/main/java/com/cmc/suppin/event/events/converter/EventConverter.java
index ae76d93..c0e1bfd 100644
--- a/src/main/java/com/cmc/suppin/event/events/converter/EventConverter.java
+++ b/src/main/java/com/cmc/suppin/event/events/converter/EventConverter.java
@@ -6,41 +6,41 @@
import com.cmc.suppin.global.enums.EventType;
import com.cmc.suppin.member.domain.Member;
-import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
public class EventConverter {
public static Event toCommentEventEntity(EventRequestDTO.CommentEventCreateDTO request, Member member) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
return Event.builder()
.type(EventType.COMMENT)
.title(request.getTitle())
.description(request.getDescription())
.url(request.getUrl())
- .startDate(LocalDate.parse(request.getStartDate(), formatter).atStartOfDay())
- .endDate(LocalDate.parse(request.getEndDate(), formatter).atStartOfDay())
- .announcementDate(LocalDate.parse(request.getAnnouncementDate(), formatter).atStartOfDay())
+ .startDate(LocalDateTime.parse(request.getStartDate(), formatter))
+ .endDate(LocalDateTime.parse(request.getEndDate(), formatter))
+ .announcementDate(LocalDateTime.parse(request.getAnnouncementDate(), formatter))
.member(member)
.build();
}
public static Event toSurveyEventEntity(EventRequestDTO.SurveyEventCreateDTO request, Member member) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
return Event.builder()
.type(EventType.SURVEY)
.title(request.getTitle())
.description(request.getDescription())
- .startDate(LocalDate.parse(request.getStartDate(), formatter).atStartOfDay())
- .endDate(LocalDate.parse(request.getEndDate(), formatter).atStartOfDay())
- .announcementDate(LocalDate.parse(request.getAnnouncementDate(), formatter).atStartOfDay())
+ .startDate(LocalDateTime.parse(request.getStartDate(), formatter))
+ .endDate(LocalDateTime.parse(request.getEndDate(), formatter))
+ .announcementDate(LocalDateTime.parse(request.getAnnouncementDate(), formatter))
.member(member)
.build();
}
public static EventResponseDTO.CommentEventDetailDTO toEventDetailDTO(Event event) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
return EventResponseDTO.CommentEventDetailDTO.builder()
.type(event.getType())
.title(event.getTitle())
@@ -52,13 +52,18 @@ public static EventResponseDTO.CommentEventDetailDTO toEventDetailDTO(Event even
}
public static EventResponseDTO.EventInfoDTO toEventInfoDTO(Event event) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
Optional url = Optional.empty();
if (event.getType() == EventType.COMMENT) {
url = Optional.ofNullable(event.getUrl());
}
+ // 설문 응답 수 합산
+ int surveyAnswerCount = event.getSurveyList().stream()
+ .mapToInt(survey -> survey.getAnonymousParticipantList().size())
+ .sum();
+
return EventResponseDTO.EventInfoDTO.builder()
.eventId(event.getId())
.type(event.getType())
@@ -67,20 +72,20 @@ public static EventResponseDTO.EventInfoDTO toEventInfoDTO(Event event) {
.startDate(event.getStartDate().format(formatter))
.endDate(event.getEndDate().format(formatter))
.announcementDate(event.getAnnouncementDate().format(formatter))
- .surveyCount(event.getSurveyList().size())
+ .surveyCount(surveyAnswerCount)
.commentCount(event.getCommentList().size())
.status(event.getStatus())
.build();
}
public static Event toUpdatedEventEntity(EventRequestDTO.EventUpdateDTO request, Member member) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");
Event.EventBuilder eventBuilder = Event.builder()
.title(request.getTitle())
.description(request.getDescription())
- .startDate(LocalDate.parse(request.getStartDate(), formatter).atStartOfDay())
- .endDate(LocalDate.parse(request.getEndDate(), formatter).atStartOfDay())
- .announcementDate(LocalDate.parse(request.getAnnouncementDate(), formatter).atStartOfDay())
+ .startDate(LocalDateTime.parse(request.getStartDate(), formatter))
+ .endDate(LocalDateTime.parse(request.getEndDate(), formatter))
+ .announcementDate(LocalDateTime.parse(request.getAnnouncementDate(), formatter))
.member(member);
// Only set URL if the event type is COMMENT
diff --git a/src/main/java/com/cmc/suppin/event/events/domain/Event.java b/src/main/java/com/cmc/suppin/event/events/domain/Event.java
index cf9d9a6..bd3e0e0 100644
--- a/src/main/java/com/cmc/suppin/event/events/domain/Event.java
+++ b/src/main/java/com/cmc/suppin/event/events/domain/Event.java
@@ -41,7 +41,7 @@ public class Event extends BaseDateTimeEntity {
@Column(columnDefinition = "VARCHAR(100)", nullable = false)
private String title;
- @Column(columnDefinition = "TEXT", nullable = false)
+ @Column(columnDefinition = "TEXT")
private String description;
@Enumerated(EnumType.STRING)
diff --git a/src/main/java/com/cmc/suppin/event/survey/controller/SurveyApi.java b/src/main/java/com/cmc/suppin/event/survey/controller/SurveyApi.java
index 16062b4..d8187f4 100644
--- a/src/main/java/com/cmc/suppin/event/survey/controller/SurveyApi.java
+++ b/src/main/java/com/cmc/suppin/event/survey/controller/SurveyApi.java
@@ -8,6 +8,7 @@
import com.cmc.suppin.global.security.reslover.Account;
import com.cmc.suppin.global.security.reslover.CurrentAccount;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@@ -27,33 +28,34 @@ public class SurveyApi {
private final SurveyService surveyService;
@PostMapping("/create")
- @Operation(summary = "설문지 생성 API", description = "QuestionType(Enum): SUBJECTIVE(주관식), SINGLE_CHOICE(객관식(단일 선택)), MULTIPLE_CHOICE(객관식(복수 선택))")
+ @Operation(summary = "설문지 생성 API", description = "설문지를 생성합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> createSurvey(@RequestBody @Valid SurveyRequestDTO.SurveyCreateDTO request, @CurrentAccount Account account) {
SurveyResponseDTO.SurveyCreateResponse response = surveyService.createSurvey(request, account.userId());
return ResponseEntity.ok(ApiResponse.of(response));
}
@GetMapping("/{surveyId}")
- @Operation(summary = "설문지 조회 API", description = "Request: 설문지 ID, Response: 설문지 정보
" +
- "SUBJEVTIVE: 주관식, SINGLE_CHOICE: 객관식(단일 선택), MULTIPLE_CHOICE: 객관식(복수 선택)")
+ @Operation(summary = "설문지 조회 API", description = "생성된 설문지 전체 정보를 조회합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> getSurvey(@PathVariable Long surveyId) {
SurveyResponseDTO.SurveyResultDTO response = surveyService.getSurvey(surveyId);
return ResponseEntity.ok(ApiResponse.of(response));
}
@PostMapping("/reply")
- @Operation(summary = "설문 답변 등록 API")
+ @Operation(summary = "설문 답변 등록 API", description = "익명 참가자들의 설문 응답을 등록합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> saveSurveyAnswers(@RequestBody @Valid SurveyRequestDTO.SurveyAnswerDTO request) {
surveyService.saveSurveyAnswers(request);
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
}
@GetMapping("/{surveyId}/answers/{questionId}")
- @Operation(summary = "질문별 설문 응답 결과 조회 API", description = "Request: 설문지 ID와 질문 ID, Response: 해당 질문에 대한 응답 리스트")
+ @Operation(summary = "질문별 설문 응답 결과 조회 API", description = "특정 질문에 따라 해당 질문에 대한 설문 결과를 응답합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> getSurveyAnswers(
@PathVariable Long surveyId,
@PathVariable Long questionId,
+ @Parameter(description = "페이지 번호(1부터 시작)", example = "1")
@RequestParam int page,
+ @Parameter(description = "페이지 크기", example = "10")
@RequestParam int size,
@CurrentAccount Account account) {
SurveyResponseDTO.SurveyAnswerResultDTO response = surveyService.getSurveyAnswers(surveyId, questionId, page, size, account.userId());
@@ -61,7 +63,8 @@ public ResponseEntity> getS
}
@PostMapping("/draft")
- @Operation(summary = "당첨자 랜덤 추첨 결과 리스트 조회 API(설문 이벤트)", description = "주관식 답변 중 조건을 설정하여 랜덤으로 당첨자를 추첨합니다.")
+ @Operation(summary = "당첨자 랜덤 추첨 결과 리스트 조회 API(설문 이벤트)",
+ description = "주관식 답변 중 조건을 설정하여 랜덤으로 당첨자를 추첨합니다. 추첨된 당첨자의 isWinner값이 True로 설정됩니다. " + "자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> selectRandomWinners(
@RequestBody @Valid SurveyRequestDTO.RandomSelectionRequestDTO request, @CurrentAccount Account account) {
SurveyResponseDTO.RandomSelectionResponseDTO response = surveyService.selectRandomWinners(request, account.userId());
@@ -70,7 +73,7 @@ public ResponseEntity>
// 당첨자 세부 정보 조회 API
@GetMapping("/winners/{surveyId}/{participantId}")
- @Operation(summary = "당첨자 세부 정보 조회 API", description = "설문 이벤트의 당첨자(익명 참여자) 정보를 조회하며, 해당 참여자가 응답한 모든 설문 내용을 반환합니다.")
+ @Operation(summary = "당첨자 세부 정보 조회 API", description = "설문 이벤트의 당첨자(익명 참여자) 정보를 조회하며, 해당 참여자가 응답한 모든 설문 내용을 반환합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고해주세요.")
public ResponseEntity> getWinnerDetails(
@PathVariable Long surveyId, @PathVariable Long participantId) {
SurveyResponseDTO.WinnerDetailDTO winnerDetails = surveyService.getWinnerDetails(surveyId, participantId);
@@ -78,7 +81,7 @@ public ResponseEntity> getWinnerD
}
@DeleteMapping("/winners")
- @Operation(summary = "당첨자 리스트 삭제 API", description = "해당 설문조사의 모든 당첨자들의 isWinner 값을 false로 변경합니다.")
+ @Operation(summary = "당첨자 리스트 삭제 API(당첨자 재추첨 시, 기존 당첨자 리스트를 삭제 후 진행 해야합니다.)", description = "해당 설문조사의 모든 당첨자들의 isWinner 값을 false로 변경합니다.")
public ResponseEntity> deleteWinners(@RequestParam Long surveyId) {
surveyService.deleteWinners(surveyId);
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
diff --git a/src/main/java/com/cmc/suppin/event/survey/controller/dto/SurveyResponseDTO.java b/src/main/java/com/cmc/suppin/event/survey/controller/dto/SurveyResponseDTO.java
index d4c2d65..a70df15 100644
--- a/src/main/java/com/cmc/suppin/event/survey/controller/dto/SurveyResponseDTO.java
+++ b/src/main/java/com/cmc/suppin/event/survey/controller/dto/SurveyResponseDTO.java
@@ -60,9 +60,9 @@ public static class PersonalInfoOptionDTO {
public static class SurveyAnswerResultDTO {
private Long questionId;
private String questionText;
- private List answers;
private int totalPages;
private long totalElements;
+ private List answers;
@Getter
@NoArgsConstructor
diff --git a/src/main/java/com/cmc/suppin/event/survey/service/SurveyService.java b/src/main/java/com/cmc/suppin/event/survey/service/SurveyService.java
index 8125467..aff87de 100644
--- a/src/main/java/com/cmc/suppin/event/survey/service/SurveyService.java
+++ b/src/main/java/com/cmc/suppin/event/survey/service/SurveyService.java
@@ -143,6 +143,7 @@ public SurveyResponseDTO.SurveyAnswerResultDTO getSurveyAnswers(Long surveyId, L
return SurveyConverter.toSurveyAnswerResultDTO(question, answersPage);
}
+ // 랜덤 추첨 당첨자 선정
@Transactional
public SurveyResponseDTO.RandomSelectionResponseDTO selectRandomWinners(SurveyRequestDTO.RandomSelectionRequestDTO request, String userId) {
// 사용자 식별
@@ -172,7 +173,7 @@ public SurveyResponseDTO.RandomSelectionResponseDTO selectRandomWinners(SurveyRe
.limit(request.getWinnerCount())
.collect(Collectors.toList());
- // 당첨자 업데이트 및 WinnerDTO 생성
+ // 당첨자 업데이트(isWinner -> True 설정) 및 WinnerDTO 생성
List winners = selectedWinners.stream()
.map(answer -> {
AnonymousParticipant participant = answer.getAnonymousParticipant();
diff --git a/src/main/java/com/cmc/suppin/member/controller/MemberApi.java b/src/main/java/com/cmc/suppin/member/controller/MemberApi.java
index e0170e9..9872102 100644
--- a/src/main/java/com/cmc/suppin/member/controller/MemberApi.java
+++ b/src/main/java/com/cmc/suppin/member/controller/MemberApi.java
@@ -30,7 +30,7 @@ public class MemberApi {
// 회원가입
@PostMapping("/join")
- @Operation(summary = "회원가입 API", description = "Request: termsAgree, userId, password, name, phone, email, userType, verificationCode")
+ @Operation(summary = "회원가입 API", description = "아이디 중복검사 및 이메일 인증 후, 회원으로 등록합니다. 자세한 요청 및 응답에 대한 설명은 노션 API 문서를 참고하시면 됩니다.")
public ResponseEntity> join(@RequestBody @Valid MemberRequestDTO.JoinDTO request) {
Member member = memberService.join(request);
@@ -39,7 +39,7 @@ public ResponseEntity> join(@Reques
// 이메일 인증번호 요청(회원가입 시)
@PostMapping("/join/email/auth")
- @Operation(summary = "이메일 인증번호 요청(회원가입 시) API", description = "request : email(이메일을 입력하면 해당 이메일로 인증번호 전송), response: 인증번호 전송 성공 시 true, 실패 시 false")
+ @Operation(summary = "이메일 인증번호 요청(회원가입 시) API", description = "이메일 인증번호 요청 API입니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.")
public ResponseEntity> requestEmailAuth(@RequestBody @Valid MemberRequestDTO.EmailRequestDTO request) {
memberService.requestEmailVerification(request.getEmail());
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
@@ -47,7 +47,8 @@ public ResponseEntity> requestEmailAuth(@RequestBody @Valid Me
// 이메일 인증번호 확인(회원가입 시)
@PostMapping("/join/email/verification")
- @Operation(summary = "이메일 인증번호 확인 API", description = "request : email, verificationCode(인증번호 유효기간은 5분입니다.), response: 인증번호 일치 시 true, 불일치 시 false")
+ @Operation(summary = "이메일 인증번호 확인 API", description = "올바른 이메일 인증번호인지 검증합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.
" +
+ "request : email, verificationCode(인증번호 유효기간은 5분입니다), response: 인증번호 일치 시 true, 불일치 시 false")
public ResponseEntity> verifyEmailCode(@RequestBody @Valid MemberRequestDTO.EmailVerificationDTO request) {
memberService.verifyEmailCode(request.getEmail(), request.getVerificationCode());
return ResponseEntity.ok(ApiResponse.confirm(ResponseCode.CONFIRM));
@@ -55,7 +56,8 @@ public ResponseEntity> verifyEmailCode(@RequestBody @Valid Mem
// 아이디 중복 체크
@GetMapping("/checkUserId")
- @Operation(summary = "아이디 중복 체크 API", description = "request : userId, response: 중복이면 false, 중복 아니면 true")
+ @Operation(summary = "아이디 중복 체크 API", description = "입력한 아이디가 중복된 id인지 검증합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.")
+ @io.swagger.v3.oas.annotations.responses.ApiResponse(description = "중복이면 false, 중복 아니면 true")
public ResponseEntity> checkUserId(@RequestParam String userId) {
boolean checkUserId = memberService.confirmUserId(userId);
@@ -64,7 +66,7 @@ public ResponseEntity> checkUs
// 이메일 중복 체크
@GetMapping("/checkEmail")
- @Operation(summary = "이메일 중복 체크 API", description = "request : email, response: 중복이면 false, 중복 아니면 true")
+ @Operation(summary = "이메일 중복 체크 API", description = "입력한 이메일이 중복된 이메일인지 검증합니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.")
public ResponseEntity> checkEmail(@RequestParam String email) {
boolean checkEmail = memberService.confirmEmail(email);
@@ -74,7 +76,8 @@ public ResponseEntity> chec
// 회원탈퇴
@DeleteMapping("/delete")
- @Operation(summary = "회원탈퇴 API", description = "로그인 시 발급받은 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
+ @Operation(summary = "회원탈퇴 API", description = "회원탈퇴 시 API입니다. MemberStatus가 \"DELETE\"로 변경됩니다. 자세한 요청 및 응답 형식은 노션 API 문서를 참고하시면 됩니다.
" +
+ "로그인 시 발급받은 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
public ResponseEntity> deleteMember(@CurrentAccount Account account) {
memberService.deleteMember(account.id());
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
@@ -82,7 +85,7 @@ public ResponseEntity> deleteMember(@CurrentAccount Account ac
// 로그인
@PostMapping("/login")
- @Operation(summary = "로그인 API", description = "request : userId, password")
+ @Operation(summary = "로그인 API", description = "로그인 성공 시 JWT 토큰(유효기간 7일)을 발급받습니다. request : userId, password")
public ResponseEntity> login(@RequestBody @Valid MemberRequestDTO.LoginRequestDTO request) {
MemberResponseDTO.LoginResponseDTO response = memberService.login(request);
@@ -91,7 +94,7 @@ public ResponseEntity> login(@Re
// 로그아웃
@PostMapping("/logout")
- @Operation(summary = "로그아웃 API", description = "로그인 시 발급받은 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
+ @Operation(summary = "로그아웃 API", description = "사용중인 토큰을 블랙리스트에 등록합니다(토큰 무효화). 로그인 시 발급받은 JWT 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
public ResponseEntity> logout(@CurrentAccount Account account) {
memberService.logout(account.id());
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
@@ -115,7 +118,7 @@ public ResponseEntity> checkPass
// 회원정보 상세 조회
@GetMapping("/me")
- @Operation(summary = "회원정보 상세 조회 API", description = "로그인 시 발급받은 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
+ @Operation(summary = "회원정보 상세 조회 API", description = "회원 상세 정보를 조회합니다. 로그인 시 발급받은 토큰으로 인가 필요, Authentication 헤더에 토큰을 넣어서 요청")
public ResponseEntity> getUserDetail(@CurrentAccount Account account) {
MemberResponseDTO.MemberDetailsDTO memberDetails = memberService.getMemberDetails(account.id());
return ResponseEntity.ok(ApiResponse.of(memberDetails));
diff --git a/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java b/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java
index ac427eb..cf491cd 100644
--- a/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java
+++ b/src/main/java/com/cmc/suppin/member/controller/dto/MemberResponseDTO.java
@@ -66,6 +66,7 @@ public static class MemberDetailsDTO {
private String name;
private String email;
private String phoneNumber;
+ private String userType;
private LocalDateTime createdAt;
}
}
diff --git a/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java b/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java
index 15bd279..6ecbcad 100644
--- a/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java
+++ b/src/main/java/com/cmc/suppin/member/converter/MemberConverter.java
@@ -69,6 +69,7 @@ public static MemberResponseDTO.MemberDetailsDTO toMemberDetailsDTO(Member membe
.name(member.getName())
.email(member.getEmail())
.phoneNumber(member.getPhoneNumber())
+ .userType(member.getUserType())
.createdAt(member.getCreatedAt())
.build();
}