Skip to content

Commit

Permalink
Merge pull request #41 from Central-MakeUs/refactor/39
Browse files Browse the repository at this point in the history
Refactor/39: 이벤트 관련 API 리팩토링-2
  • Loading branch information
yxhwxn authored Aug 15, 2024
2 parents 47c94a7 + b388518 commit 535e487
Show file tree
Hide file tree
Showing 20 changed files with 176 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public ResponseEntity<ApiResponse<CommentResponseDTO.CrawledCommentListDTO>> get
}

@PostMapping("/draft-winners")
@Operation(summary = "조건별 당첨자 추첨 API(댓글 이벤트)", description = "주어진 조건에 따라 이벤트의 당첨자를 추첨합니다.")
@Operation(summary = "당첨자 랜덤 추첨 결과 리스트 조회 API(댓글 이벤트)", description = "주어진 조건에 따라 이벤트의 당첨자를 추첨합니다.")
public ResponseEntity<ApiResponse<CommentResponseDTO.WinnerResponseDTO>> drawWinners(
@RequestBody @Valid CommentRequestDTO.WinnerRequestDTO request,
@CurrentAccount Account account) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,14 @@ public static class WinnerResponseDTO {
private String endDate;
private List<CommentDetailDTO> winners;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class CommentEventWinners {
private String author;
private String commentText;
private String commentDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,13 @@ public static CrawlResponseDTO.CrawlResultDTO toCrawlResultDTO(LocalDateTime cra
.totalCommentCount(totalCommentCount)
.build();
}

public static CommentResponseDTO.CommentEventWinners toCommentEventWinners(Comment comment) {
return CommentResponseDTO.CommentEventWinners.builder()
.author(comment.getAuthor())
.commentText(comment.getCommentText())
.commentDate(comment.getCommentDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.build();
}
}

8 changes: 8 additions & 0 deletions src/main/java/com/cmc/suppin/event/crawl/domain/Comment.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@ public class Comment extends BaseDateTimeEntity {
@Column(nullable = false)
private LocalDateTime crawlTime;

@Builder.Default
@Column(nullable = false)
private boolean isWinner = false;

public void setCrawlTime(LocalDateTime crawlTime) {
this.crawlTime = crawlTime;
}

public void setIsWinner(boolean isWinner) {
this.isWinner = isWinner;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ public interface CommentRepository extends JpaRepository<Comment, Long> {
List<Comment> findByEventIdAndCommentDateBetween(Long eventId, LocalDateTime start, LocalDateTime end);

List<Comment> findByEventIdAndCommentTextContaining(Long eventId, String keyword);

List<Comment> findByEventIdAndIsWinnerTrue(Long eventId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public CommentResponseDTO.CrawledCommentListDTO getComments(Long eventId, String
}

// 당첨자 조건별 랜덤 추첨(댓글 이벤트)
@Transactional
public CommentResponseDTO.WinnerResponseDTO drawWinners(CommentRequestDTO.WinnerRequestDTO request, String userId) {
Member member = memberRepository.findByUserIdAndStatusNot(userId, UserStatus.DELETED)
.orElseThrow(() -> new IllegalArgumentException("Member not found"));
Expand All @@ -77,6 +78,12 @@ public CommentResponseDTO.WinnerResponseDTO drawWinners(CommentRequestDTO.Winner
Collections.shuffle(filteredComments);
List<Comment> winners = filteredComments.stream().limit(request.getWinnerCount()).collect(Collectors.toList());

// 당첨된 댓글의 isWinner 값을 true로 업데이트
winners.forEach(winner -> {
winner.setIsWinner(true);
commentRepository.save(winner); // 업데이트된 Comment 엔티티를 저장
});

return CommentConverter.toWinnerResponseDTO(winners, request);
}

Expand All @@ -102,4 +109,15 @@ public List<CommentResponseDTO.CommentDetailDTO> filterWinnersByKeyword(List<Com
.collect(Collectors.toList());
}

public List<CommentResponseDTO.CommentEventWinners> getCommentEventWinners(Long eventId, String userId) {
Member member = memberRepository.findByUserIdAndStatusNot(userId, UserStatus.DELETED)
.orElseThrow(() -> new IllegalArgumentException("Member not found"));

List<Comment> winners = commentRepository.findByEventIdAndIsWinnerTrue(eventId);

return winners.stream()
.map(CommentConverter::toCommentEventWinners)
.collect(Collectors.toList());
}

}
17 changes: 12 additions & 5 deletions src/main/java/com/cmc/suppin/event/crawl/service/CrawlService.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand All @@ -46,8 +47,9 @@ public String checkExistingComments(String url, String userId) {

List<Comment> existingComments = commentRepository.findByUrl(url);
if (!existingComments.isEmpty()) {
LocalDateTime firstCommentDate = existingComments.get(0).getCreatedAt();
return "동일한 URL의 댓글을 " + firstCommentDate.toLocalDate() + " 일자에 수집한 이력이 있습니다.";
LocalDateTime firstCommentDate = existingComments.get(0).getCrawlTime();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
return "동일한 URL의 댓글을 " + firstCommentDate.format(formatter) + " 일자에 수집한 이력이 있습니다.";
}

return null;
Expand All @@ -63,10 +65,14 @@ public CrawlResponseDTO.CrawlResultDTO crawlYoutubeComments(String url, Long eve
if (forceUpdate) {
// 기존 댓글 삭제
commentRepository.deleteByUrlAndEventId(url, eventId);

// 삭제 후, 확인을 위한 로그 출력 또는 추가 검증
List<Comment> deletedComments = commentRepository.findByUrlAndEventId(url, eventId);
if (!deletedComments.isEmpty()) {
throw new RuntimeException("기존 댓글 삭제에 실패했습니다.");
}
} else {
// 기존 댓글이 존재하는 경우: 크롤링을 중지하고 예외를 던집니다.
// 기존 댓글이 존재하지 않는 경우: 새로운 댓글을 크롤링하고 이를 DB에 저장합니다.

List<Comment> existingComments = commentRepository.findByUrlAndEventId(url, eventId);
if (!existingComments.isEmpty()) {
throw new CrawlException(CrawlErrorCode.DUPLICATE_URL);
Expand Down Expand Up @@ -110,7 +116,7 @@ public CrawlResponseDTO.CrawlResultDTO crawlYoutubeComments(String url, Long eve
while (System.currentTimeMillis() < endTime) {
jsExecutor.executeScript("window.scrollTo(0, document.documentElement.scrollHeight);");

Thread.sleep(1000); // 1초 대기
Thread.sleep(3000); // 3초 대기

String pageSource = driver.getPageSource();
Document doc = Jsoup.parse(pageSource);
Expand Down Expand Up @@ -149,5 +155,6 @@ public CrawlResponseDTO.CrawlResultDTO crawlYoutubeComments(String url, Long eve
}
return CommentConverter.toCrawlResultDTO(LocalDateTime.now(), uniqueComments.size());
}

}

26 changes: 26 additions & 0 deletions src/main/java/com/cmc/suppin/event/events/controller/EventApi.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.cmc.suppin.event.events.controller;

import com.cmc.suppin.event.crawl.controller.dto.CommentResponseDTO;
import com.cmc.suppin.event.crawl.service.CommentService;
import com.cmc.suppin.event.events.controller.dto.EventRequestDTO;
import com.cmc.suppin.event.events.controller.dto.EventResponseDTO;
import com.cmc.suppin.event.events.converter.EventConverter;
import com.cmc.suppin.event.events.domain.Event;
import com.cmc.suppin.event.events.service.EventService;
import com.cmc.suppin.event.survey.controller.dto.SurveyResponseDTO;
import com.cmc.suppin.event.survey.service.SurveyService;
import com.cmc.suppin.global.response.ApiResponse;
import com.cmc.suppin.global.response.ResponseCode;
import com.cmc.suppin.global.security.reslover.Account;
Expand All @@ -29,6 +33,8 @@
public class EventApi {

private final EventService eventService;
private final CommentService commentService;
private final SurveyService surveyService;

@GetMapping("/all")
@Operation(summary = "전체 이벤트 조회 API", description = "사용자의 모든 이벤트와 설문 및 댓글 수를 조회합니다.")
Expand Down Expand Up @@ -66,4 +72,24 @@ public ResponseEntity<ApiResponse<Void>> deleteEvent(@PathVariable("eventId") Lo
eventService.deleteEvent(eventId, account.userId());
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
}

@GetMapping("/comment-winners")
@Operation(summary = "댓글 이벤트 당첨자 조회 API", description = "댓글 이벤트의 당첨자 리스트를 조회합니다.")
public ResponseEntity<ApiResponse<List<CommentResponseDTO.CommentEventWinners>>> getCommentEventWinners(
@RequestParam("eventId") Long eventId,
@CurrentAccount Account account) {

List<CommentResponseDTO.CommentEventWinners> winners = commentService.getCommentEventWinners(eventId, account.userId());
return ResponseEntity.ok(ApiResponse.of(winners));
}

@GetMapping("/survey-winners")
@Operation(summary = "설문 이벤트 당첨자 조회 API", description = "설문 이벤트의 당첨자 리스트를 조회합니다.")
public ResponseEntity<ApiResponse<List<SurveyResponseDTO.SurveyEventWinners>>> getSurveyEventWinners(
@RequestParam("surveyId") Long surveyId,
@CurrentAccount Account account) {

List<SurveyResponseDTO.SurveyEventWinners> winners = surveyService.getSurveyEventWinners(surveyId, account.userId());
return ResponseEntity.ok(ApiResponse.of(winners));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public ResponseEntity<ApiResponse<SurveyResponseDTO.SurveyResultDTO>> getSurvey(
if (uuid != null) {
response = surveyService.getSurveyByUuid(uuid);
} else if (surveyId != null) {
response = surveyService.getSurvey(surveyId);
response = surveyService.getSurveyBySurveyId(surveyId);
} else {
throw new IllegalArgumentException("Either surveyId or uuid must be provided");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

public class SurveyRequestDTO {
Expand All @@ -22,6 +22,7 @@ public class SurveyRequestDTO {
public static class SurveyCreateDTO {
@NotNull
private Long eventId;
private String consentFormHtml; // 개인정보 수집 동의서 HTML 필드
private List<PersonalInfoOptionDTO> personalInfoOptionList;
private List<QuestionDTO> questionList;

Expand Down Expand Up @@ -107,9 +108,11 @@ public static class RandomSelectionRequestDTO {
@NotNull
private Integer winnerCount;
@NotNull
private LocalDateTime startDate;
@Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String startDate;
@NotNull
private LocalDateTime endDate;
@Pattern(regexp = "\\d{4}\\. \\d{2}\\. \\d{2} \\d{2}:\\d{2}", message = "날짜 형식은 yyyy. MM. dd HH:mm 이어야 합니다.")
private String endDate;
@NotNull
private Integer minLength;
@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static class SurveyResultDTO {
private String startDate;
private String endDate;
private String announcementDate;
private String consentFormHtml;
private List<PersonalInfoOptionDTO> personalInfoOptions;
private List<QuestionDTO> questions;

Expand Down Expand Up @@ -128,4 +129,14 @@ public static class AnswerDetailDTO {
private List<String> selectedOptions; // 객관식 질문의 경우 선택된 옵션 리스트
}
}


@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyEventWinners {
private String name;
private List<WinnerDetailDTO.AnswerDetailDTO> answers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
import com.cmc.suppin.event.survey.domain.*;
import org.springframework.data.domain.Page;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

public class SurveyConverter {

public static Survey toSurveyEntity(Event event, String uuid) {
public static Survey toSurveyEntity(Event event, String uuid, String consentFormHtml) {
return Survey.builder()
.event(event)
.uuid(uuid)
.consentFormHtml(consentFormHtml)
.build();
}

Expand Down Expand Up @@ -68,11 +71,13 @@ public static SurveyResponseDTO.SurveyResultDTO toSurveyResultDTO(Survey survey,
.startDate(event.getStartDate().toString())
.endDate(event.getEndDate().toString())
.announcementDate(event.getAnnouncementDate().toString())
.consentFormHtml(survey.getConsentFormHtml())
.personalInfoOptions(personalInfoOptions)
.questions(questions)
.build();
}


public static SurveyResponseDTO.SurveyAnswerResultDTO toSurveyAnswerResultDTO(Question question, Page<Answer> answersPage) {
List<SurveyResponseDTO.SurveyAnswerResultDTO.AnswerDTO> answers = answersPage.stream()
.map(answer -> SurveyResponseDTO.SurveyAnswerResultDTO.AnswerDTO.builder()
Expand Down Expand Up @@ -120,10 +125,12 @@ public static AnswerOption toAnswerOption(SurveyRequestDTO.SurveyAnswerDTO.Answe
}

public static SurveyResponseDTO.RandomSelectionResponseDTO.SelectionCriteriaDTO toSelectionCriteriaDTO(SurveyRequestDTO.RandomSelectionRequestDTO request) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy. MM. dd HH:mm");

return SurveyResponseDTO.RandomSelectionResponseDTO.SelectionCriteriaDTO.builder()
.winnerCount(request.getWinnerCount())
.startDate(request.getStartDate())
.endDate(request.getEndDate())
.startDate(LocalDateTime.parse(request.getStartDate(), formatter))
.endDate(LocalDateTime.parse(request.getEndDate(), formatter))
.minLength(request.getMinLength())
.keywords(request.getKeywords())
.build();
Expand Down Expand Up @@ -154,4 +161,20 @@ public static SurveyResponseDTO.WinnerDetailDTO toWinnerDetailDTO(AnonymousParti
.answers(answers)
.build();
}

public static SurveyResponseDTO.SurveyEventWinners toSurveyEventWinners(AnonymousParticipant participant) {
return SurveyResponseDTO.SurveyEventWinners.builder()
.name(participant.getName())
.answers(participant.getAnswerList().stream()
.map(answer -> SurveyResponseDTO.WinnerDetailDTO.AnswerDetailDTO.builder()
.questionText(answer.getQuestion().getQuestionText())
.answerText(answer.getAnswerText())
.selectedOptions(answer.getAnswerOptionList().stream()
.map(answerOption -> answerOption.getQuestionOption().getOptionText())
.collect(Collectors.toList()))
.build())
.collect(Collectors.toList()))
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class AnonymousParticipant extends BaseDateTimeEntity {
private Survey survey;

@OneToMany(mappedBy = "anonymousParticipant")
@Builder.Default
private List<Answer> answerList = new ArrayList<>();

private String name;
Expand All @@ -41,11 +42,19 @@ public class AnonymousParticipant extends BaseDateTimeEntity {
@Column(nullable = false)
private Boolean isAgreed;

private Boolean isWinner;
@Builder.Default
@Column(nullable = false)
private Boolean isWinner = false;

private Boolean isChecked;
@Builder.Default
@Column(nullable = false)
private Boolean isChecked = false;

public void setIsWinner(Boolean isWinner) {
this.isWinner = isWinner;
}

public void setIsChecked(Boolean isChecked) {
this.isChecked = isChecked;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class Answer extends BaseDateTimeEntity {
private AnonymousParticipant anonymousParticipant;

@OneToMany(mappedBy = "answer")
@Builder.Default
private List<AnswerOption> answerOptionList = new ArrayList<>();

@Column(columnDefinition = "TEXT")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ public class Question {
private Survey survey;

@OneToMany(mappedBy = "question")
@Builder.Default
private List<QuestionOption> questionOptionList = new ArrayList<>();

@OneToMany(mappedBy = "question")
@Builder.Default
private List<Answer> answerList = new ArrayList<>();

@Enumerated(EnumType.STRING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class QuestionOption {
private String optionText;

@OneToMany(mappedBy = "questionOption")
@Builder.Default
private List<AnswerOption> answerOptionList = new ArrayList<>();

}
Expand Down
Loading

0 comments on commit 535e487

Please sign in to comment.