diff --git a/build.gradle b/build.gradle index b94a84b..7a4277a 100644 --- a/build.gradle +++ b/build.gradle @@ -39,11 +39,18 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-mail' + //selenium + implementation 'org.seleniumhq.selenium:selenium-java:4.1.4' + implementation 'io.github.bonigarcia:webdrivermanager:5.0.3' + implementation 'org.jsoup:jsoup:1.13.1' + testImplementation 'org.seleniumhq.selenium:selenium-java:4.22.0' + compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'junit:junit:4.13.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/src/main/java/com/cmc/suppin/answer/domain/AnonymousParticipant.java b/src/main/java/com/cmc/suppin/answer/domain/AnonymousParticipant.java index 23e80d7..111109d 100644 --- a/src/main/java/com/cmc/suppin/answer/domain/AnonymousParticipant.java +++ b/src/main/java/com/cmc/suppin/answer/domain/AnonymousParticipant.java @@ -1,13 +1,20 @@ package com.cmc.suppin.answer.domain; +import com.cmc.suppin.event.survey.domain.Survey; import com.cmc.suppin.global.domain.BaseDateTimeEntity; -import com.cmc.suppin.survey.domain.Survey; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class AnonymousParticipant extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/cmc/suppin/answer/domain/Answer.java b/src/main/java/com/cmc/suppin/answer/domain/Answer.java index cefb10d..c200f17 100644 --- a/src/main/java/com/cmc/suppin/answer/domain/Answer.java +++ b/src/main/java/com/cmc/suppin/answer/domain/Answer.java @@ -1,13 +1,20 @@ package com.cmc.suppin.answer.domain; +import com.cmc.suppin.event.survey.domain.Question; import com.cmc.suppin.global.domain.BaseDateTimeEntity; -import com.cmc.suppin.survey.domain.Question; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Answer extends BaseDateTimeEntity { @Id diff --git a/src/main/java/com/cmc/suppin/answer/domain/AnswerOption.java b/src/main/java/com/cmc/suppin/answer/domain/AnswerOption.java index 4240668..6eac119 100644 --- a/src/main/java/com/cmc/suppin/answer/domain/AnswerOption.java +++ b/src/main/java/com/cmc/suppin/answer/domain/AnswerOption.java @@ -1,10 +1,17 @@ package com.cmc.suppin.answer.domain; -import com.cmc.suppin.survey.domain.QuestionOption; +import com.cmc.suppin.event.survey.domain.QuestionOption; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class AnswerOption { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/cmc/suppin/crawl/controller/.gitkeep b/src/main/java/com/cmc/suppin/crawl/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/event/controller/.gitkeep b/src/main/java/com/cmc/suppin/event/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/event/converter/.gitkeep b/src/main/java/com/cmc/suppin/event/converter/.gitkeep deleted file mode 100644 index e69de29..0000000 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 new file mode 100644 index 0000000..4e2c37f --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/controller/CommentApi.java @@ -0,0 +1,19 @@ +package com.cmc.suppin.event.crawl.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequiredArgsConstructor +@Validated +@Tag(name = "Event-Comments", description = "Crawling Comments 관련 API") +@RequestMapping("/api/v1/comments") +public class CommentApi { + + +} 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 new file mode 100644 index 0000000..e520cb1 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/controller/CrawlApi.java @@ -0,0 +1,34 @@ +package com.cmc.suppin.event.crawl.controller; + +import com.cmc.suppin.event.crawl.controller.dto.CrawlResponseDTO; +import com.cmc.suppin.event.crawl.service.CrawlService; +import com.cmc.suppin.global.response.ApiResponse; +import com.cmc.suppin.global.response.ResponseCode; +import com.cmc.suppin.global.security.reslover.Account; +import com.cmc.suppin.global.security.reslover.CurrentAccount; +import io.swagger.v3.oas.annotations.tags.Tag; +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; + +@RestController +@Slf4j +@RequiredArgsConstructor +@Validated +@Tag(name = "Crawling", description = "Crawling 관련 API") +@RequestMapping("/api/v1/event") +public class CrawlApi { + + private final CrawlService crawlService; + + @GetMapping("/crawling/youtube/comments") + public ResponseEntity> crawlYoutubeComments(@RequestParam String url, @CurrentAccount Account account) { + crawlService.crawlYoutubeComments(url, account.userId()); + return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS)); + } +} diff --git a/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CrawlResponseDTO.java b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CrawlResponseDTO.java new file mode 100644 index 0000000..2df078c --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/controller/dto/CrawlResponseDTO.java @@ -0,0 +1,19 @@ +package com.cmc.suppin.event.crawl.controller.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class CrawlResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CrawlResultDTO { + private String author; + private String commentText; + private String date; + } +} 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 new file mode 100644 index 0000000..e66c6c0 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/converter/CommentConverter.java @@ -0,0 +1,4 @@ +package com.cmc.suppin.event.crawl.converter; + +public class CommentConverter { +} diff --git a/src/main/java/com/cmc/suppin/comment/domain/Comment.java b/src/main/java/com/cmc/suppin/event/crawl/domain/Comment.java similarity index 57% rename from src/main/java/com/cmc/suppin/comment/domain/Comment.java rename to src/main/java/com/cmc/suppin/event/crawl/domain/Comment.java index 855e686..d2fc8d5 100644 --- a/src/main/java/com/cmc/suppin/comment/domain/Comment.java +++ b/src/main/java/com/cmc/suppin/event/crawl/domain/Comment.java @@ -1,11 +1,18 @@ -package com.cmc.suppin.comment.domain; +package com.cmc.suppin.event.crawl.domain; -import com.cmc.suppin.event.domain.Event; +import com.cmc.suppin.event.events.domain.Event; import com.cmc.suppin.global.domain.BaseDateTimeEntity; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Comment extends BaseDateTimeEntity { @Id @@ -19,9 +26,14 @@ public class Comment extends BaseDateTimeEntity { @Column(columnDefinition = "TEXT", nullable = false) private String url; - @Column(columnDefinition = "VARCHAR(30)", nullable = false) - private String nickname; + + @Column(nullable = false) + private String author; + @Column(columnDefinition = "TEXT", nullable = false) private String commentText; + @Column(nullable = false) + private String commentDate; + } diff --git a/src/main/java/com/cmc/suppin/event/crawl/domain/repository/CommentRepository.java b/src/main/java/com/cmc/suppin/event/crawl/domain/repository/CommentRepository.java new file mode 100644 index 0000000..ffd5b5b --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/domain/repository/CommentRepository.java @@ -0,0 +1,12 @@ +package com.cmc.suppin.event.crawl.domain.repository; + +import com.cmc.suppin.event.crawl.domain.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface CommentRepository extends JpaRepository { + List findByEventId(Long eventId); + + List findByVideoUrl(String videoUrl); +} diff --git a/src/main/java/com/cmc/suppin/event/crawl/service/CrawlService.java b/src/main/java/com/cmc/suppin/event/crawl/service/CrawlService.java new file mode 100644 index 0000000..164f089 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/crawl/service/CrawlService.java @@ -0,0 +1,91 @@ +package com.cmc.suppin.event.crawl.service; + +import com.cmc.suppin.event.crawl.controller.dto.CrawlResponseDTO; +import com.cmc.suppin.event.crawl.domain.Comment; +import com.cmc.suppin.event.crawl.domain.repository.CommentRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Service +@Slf4j +@RequiredArgsConstructor +@Transactional +public class CrawlService { + + private final CommentRepository commentRepository; + + public List crawlYoutubeComments(String url, String userId) { + System.setProperty("webdriver.chrome.driver", "src/main/resources/drivers/chromedriver"); + + ChromeOptions options = new ChromeOptions(); + options.addArguments("--disable-gpu"); + options.addArguments("--no-sandbox"); + options.addArguments("--disable-dev-shm-usage"); + options.addArguments("--remote-allow-origins=*"); + + WebDriver driver = new ChromeDriver(options); + driver.get(url); + + List commentList = new ArrayList<>(); + Set uniqueComments = new HashSet<>(); + + try { + Thread.sleep(5000); + + long endTime = System.currentTimeMillis() + 120000; + JavascriptExecutor jsExecutor = (JavascriptExecutor) driver; + + while (System.currentTimeMillis() < endTime) { + jsExecutor.executeScript("window.scrollTo(0, document.documentElement.scrollHeight);"); + Thread.sleep(1000); + + String pageSource = driver.getPageSource(); + Document doc = Jsoup.parse(pageSource); + Elements comments = doc.select("ytd-comment-thread-renderer"); + + for (Element commentElement : comments) { + String author = commentElement.select("#author-text span").text(); + String text = commentElement.select("#content yt-attributed-string#content-text").text(); + String time = commentElement.select("#header-author #published-time-text").text().replace("(수정됨)", ""); + + if (!uniqueComments.contains(text)) { + uniqueComments.add(text); + commentList.add(new CrawlResponseDTO.CrawlResultDTO(author, text, time)); + + // 엔티티 저장 + Comment comment = Comment.builder() + .author(author) + .commentText(text) + .commentDate(time) + .url(url) + .build(); + commentRepository.save(comment); + } + } + } + + return commentList; + + } catch (InterruptedException e) { + e.printStackTrace(); + return new ArrayList<>(); + } finally { + driver.quit(); + } + } +} 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 new file mode 100644 index 0000000..eaf3042 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/controller/EventApi.java @@ -0,0 +1,37 @@ +package com.cmc.suppin.event.events.controller; + +import com.cmc.suppin.event.events.controller.dto.EventRequestDTO; +import com.cmc.suppin.event.events.service.EventService; +import com.cmc.suppin.global.response.ApiResponse; +import com.cmc.suppin.global.response.ResponseCode; +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.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.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequiredArgsConstructor +@Validated +@Tag(name = "Event", description = "Event 관련 API") +@RequestMapping("/api/v1/event") +public class EventApi { + + private final EventService eventService; + + @PostMapping("/new") + @Operation(summary = "댓글 이벤트 생성 API", description = "request : eventType, title, url, startDate, endDate") + public ResponseEntity> createEvent(@RequestBody @Valid EventRequestDTO.CommentEventCreateDTO request, @CurrentAccount Account account) { + eventService.createEvent(request, account.userId()); + return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS)); + } +} 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 new file mode 100644 index 0000000..31e2407 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/controller/dto/EventRequestDTO.java @@ -0,0 +1,23 @@ +package com.cmc.suppin.event.events.controller.dto; + +import com.cmc.suppin.global.enums.EventType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class EventRequestDTO { + + @Getter + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class CommentEventCreateDTO { + private EventType type; + private String title; + private String url; + private String startDate; + private String endDate; + private String announcementDate; + } +} diff --git a/src/main/java/com/cmc/suppin/event/events/controller/dto/EventResponseDTO.java b/src/main/java/com/cmc/suppin/event/events/controller/dto/EventResponseDTO.java new file mode 100644 index 0000000..089e6b8 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/controller/dto/EventResponseDTO.java @@ -0,0 +1,24 @@ +package com.cmc.suppin.event.events.controller.dto; + +import com.cmc.suppin.global.enums.EventType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class EventResponseDTO { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class CommentEventDetailDTO { + + private EventType type; + private String title; + private String url; + private String startDate; + private String endDate; + 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 new file mode 100644 index 0000000..d21beab --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/converter/EventConverter.java @@ -0,0 +1,34 @@ +package com.cmc.suppin.event.events.converter; + +import com.cmc.suppin.event.events.controller.dto.EventRequestDTO; +import com.cmc.suppin.event.events.controller.dto.EventResponseDTO; +import com.cmc.suppin.event.events.domain.Event; +import com.cmc.suppin.member.domain.Member; + +import java.time.LocalDateTime; + +public class EventConverter { + + public static Event toCommentEventEntity(EventRequestDTO.CommentEventCreateDTO request, Member member) { + return Event.builder() + .type(request.getType()) + .title(request.getTitle()) + .url(request.getUrl()) + .startDate(LocalDateTime.parse(request.getStartDate())) + .endDate(LocalDateTime.parse(request.getEndDate())) + .announcementDate(LocalDateTime.parse(request.getAnnouncementDate())) + .member(member) + .build(); + } + + public static EventResponseDTO.CommentEventDetailDTO toEventDetailDTO(Event event) { + return EventResponseDTO.CommentEventDetailDTO.builder() + .type(event.getType()) + .title(event.getTitle()) + .url(event.getUrl()) + .startDate(event.getStartDate().toString()) + .endDate(event.getEndDate().toString()) + .announcementDate(event.getAnnouncementDate().toString()) + .build(); + } +} diff --git a/src/main/java/com/cmc/suppin/event/domain/Event.java b/src/main/java/com/cmc/suppin/event/events/domain/Event.java similarity index 62% rename from src/main/java/com/cmc/suppin/event/domain/Event.java rename to src/main/java/com/cmc/suppin/event/events/domain/Event.java index 3affeb8..868400d 100644 --- a/src/main/java/com/cmc/suppin/event/domain/Event.java +++ b/src/main/java/com/cmc/suppin/event/events/domain/Event.java @@ -1,17 +1,25 @@ -package com.cmc.suppin.event.domain; +package com.cmc.suppin.event.events.domain; -import com.cmc.suppin.comment.domain.Comment; +import com.cmc.suppin.event.crawl.domain.Comment; +import com.cmc.suppin.event.survey.domain.Survey; import com.cmc.suppin.global.domain.BaseDateTimeEntity; +import com.cmc.suppin.global.enums.EventStatus; import com.cmc.suppin.global.enums.EventType; import com.cmc.suppin.member.domain.Member; -import com.cmc.suppin.survey.domain.Survey; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Event extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -31,20 +39,33 @@ 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) @Column(nullable = false) private EventType type; + @Column(columnDefinition = "TEXT") + private String url; + @Column private LocalDateTime startDate; + @Column private LocalDateTime endDate; + @Column private LocalDateTime announcementDate; + @Enumerated(EnumType.STRING) + private EventStatus status; + + public void setMember(Member member) { + this.member = member; + member.getEventList().add(this); + } + // Getters and Setters } diff --git a/src/main/java/com/cmc/suppin/event/events/domain/repository/EventRepository.java b/src/main/java/com/cmc/suppin/event/events/domain/repository/EventRepository.java new file mode 100644 index 0000000..e431734 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/domain/repository/EventRepository.java @@ -0,0 +1,10 @@ +package com.cmc.suppin.event.events.domain.repository; + +import com.cmc.suppin.event.events.domain.Event; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface EventRepository extends JpaRepository { + List findByMemberId(Long memberId); +} diff --git a/src/main/java/com/cmc/suppin/event/events/exception/EventException.java b/src/main/java/com/cmc/suppin/event/events/exception/EventException.java new file mode 100644 index 0000000..be45f62 --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/exception/EventException.java @@ -0,0 +1,11 @@ +package com.cmc.suppin.event.events.exception; + +import com.cmc.suppin.global.exception.BaseErrorCode; +import com.cmc.suppin.global.exception.CustomException; + +public class EventException extends CustomException { + + public EventException(BaseErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/com/cmc/suppin/event/events/service/EventService.java b/src/main/java/com/cmc/suppin/event/events/service/EventService.java new file mode 100644 index 0000000..00869ac --- /dev/null +++ b/src/main/java/com/cmc/suppin/event/events/service/EventService.java @@ -0,0 +1,28 @@ +package com.cmc.suppin.event.events.service; + +import com.cmc.suppin.event.events.controller.dto.EventRequestDTO; +import com.cmc.suppin.event.events.converter.EventConverter; +import com.cmc.suppin.event.events.domain.Event; +import com.cmc.suppin.event.events.domain.repository.EventRepository; +import com.cmc.suppin.global.enums.UserStatus; +import com.cmc.suppin.member.domain.Member; +import com.cmc.suppin.member.domain.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class EventService { + + private final EventRepository eventRepository; + private final MemberRepository memberRepository; + + public void createEvent(EventRequestDTO.CommentEventCreateDTO request, String userId) { + Member member = memberRepository.findByUserIdAndStatusNot(userId, UserStatus.DELETED) + .orElseThrow(() -> new IllegalArgumentException("Member not found")); + + Event event = EventConverter.toCommentEventEntity(request, member); + event.setMember(member); + eventRepository.save(event); + } +} diff --git a/src/main/java/com/cmc/suppin/event/exception/.gitkeep b/src/main/java/com/cmc/suppin/event/exception/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/event/service/.gitkeep b/src/main/java/com/cmc/suppin/event/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/comment/controller/.gitkeep b/src/main/java/com/cmc/suppin/event/survey/controller/.gitkeep similarity index 100% rename from src/main/java/com/cmc/suppin/comment/controller/.gitkeep rename to src/main/java/com/cmc/suppin/event/survey/controller/.gitkeep diff --git a/src/main/java/com/cmc/suppin/comment/converter/.gitkeep b/src/main/java/com/cmc/suppin/event/survey/converter/.gitkeep similarity index 100% rename from src/main/java/com/cmc/suppin/comment/converter/.gitkeep rename to src/main/java/com/cmc/suppin/event/survey/converter/.gitkeep diff --git a/src/main/java/com/cmc/suppin/survey/domain/Question.java b/src/main/java/com/cmc/suppin/event/survey/domain/Question.java similarity index 78% rename from src/main/java/com/cmc/suppin/survey/domain/Question.java rename to src/main/java/com/cmc/suppin/event/survey/domain/Question.java index 42b34c9..5df025f 100644 --- a/src/main/java/com/cmc/suppin/survey/domain/Question.java +++ b/src/main/java/com/cmc/suppin/event/survey/domain/Question.java @@ -1,13 +1,20 @@ -package com.cmc.suppin.survey.domain; +package com.cmc.suppin.event.survey.domain; import com.cmc.suppin.answer.domain.Answer; import com.cmc.suppin.global.enums.QuestionType; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Question { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/cmc/suppin/survey/domain/QuestionOption.java b/src/main/java/com/cmc/suppin/event/survey/domain/QuestionOption.java similarity index 73% rename from src/main/java/com/cmc/suppin/survey/domain/QuestionOption.java rename to src/main/java/com/cmc/suppin/event/survey/domain/QuestionOption.java index f940722..daae3eb 100644 --- a/src/main/java/com/cmc/suppin/survey/domain/QuestionOption.java +++ b/src/main/java/com/cmc/suppin/event/survey/domain/QuestionOption.java @@ -1,12 +1,19 @@ -package com.cmc.suppin.survey.domain; +package com.cmc.suppin.event.survey.domain; import com.cmc.suppin.answer.domain.AnswerOption; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class QuestionOption { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/cmc/suppin/survey/domain/Survey.java b/src/main/java/com/cmc/suppin/event/survey/domain/Survey.java similarity index 72% rename from src/main/java/com/cmc/suppin/survey/domain/Survey.java rename to src/main/java/com/cmc/suppin/event/survey/domain/Survey.java index 7fa4fb6..39053a5 100644 --- a/src/main/java/com/cmc/suppin/survey/domain/Survey.java +++ b/src/main/java/com/cmc/suppin/event/survey/domain/Survey.java @@ -1,14 +1,21 @@ -package com.cmc.suppin.survey.domain; +package com.cmc.suppin.event.survey.domain; import com.cmc.suppin.answer.domain.AnonymousParticipant; -import com.cmc.suppin.event.domain.Event; +import com.cmc.suppin.event.events.domain.Event; import com.cmc.suppin.global.domain.BaseDateTimeEntity; import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; import java.util.ArrayList; import java.util.List; @Entity +@Getter +@Builder +@DynamicInsert +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor public class Survey extends BaseDateTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/cmc/suppin/comment/exception/.gitkeep b/src/main/java/com/cmc/suppin/event/survey/exception/.gitkeep similarity index 100% rename from src/main/java/com/cmc/suppin/comment/exception/.gitkeep rename to src/main/java/com/cmc/suppin/event/survey/exception/.gitkeep diff --git a/src/main/java/com/cmc/suppin/comment/service/.gitkeep b/src/main/java/com/cmc/suppin/event/survey/service/.gitkeep similarity index 100% rename from src/main/java/com/cmc/suppin/comment/service/.gitkeep rename to src/main/java/com/cmc/suppin/event/survey/service/.gitkeep diff --git a/src/main/java/com/cmc/suppin/global/enums/EventStatus.java b/src/main/java/com/cmc/suppin/global/enums/EventStatus.java new file mode 100644 index 0000000..811b6b1 --- /dev/null +++ b/src/main/java/com/cmc/suppin/global/enums/EventStatus.java @@ -0,0 +1,6 @@ +package com.cmc.suppin.global.enums; + +public enum EventStatus { + PROCESSING, + DONE, +} diff --git a/src/main/java/com/cmc/suppin/member/domain/Member.java b/src/main/java/com/cmc/suppin/member/domain/Member.java index 0f7a5d3..87f0118 100644 --- a/src/main/java/com/cmc/suppin/member/domain/Member.java +++ b/src/main/java/com/cmc/suppin/member/domain/Member.java @@ -1,6 +1,6 @@ package com.cmc.suppin.member.domain; -import com.cmc.suppin.event.domain.Event; +import com.cmc.suppin.event.events.domain.Event; import com.cmc.suppin.global.domain.BaseDateTimeEntity; import com.cmc.suppin.global.enums.UserRole; import com.cmc.suppin.global.enums.UserStatus; @@ -13,6 +13,7 @@ @Entity @Getter +@Setter @Builder @DynamicInsert @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/com/cmc/suppin/member/service/MemberService.java b/src/main/java/com/cmc/suppin/member/service/MemberService.java index e8dde80..d886758 100644 --- a/src/main/java/com/cmc/suppin/member/service/MemberService.java +++ b/src/main/java/com/cmc/suppin/member/service/MemberService.java @@ -73,6 +73,7 @@ public Member join(MemberRequestDTO.JoinDTO request) { // DTO를 Entity로 변환 Member member = memberConverter.toEntity(request, passwordEncoder); + member.setStatus(UserStatus.ACTIVE); // 회원 정보 저장 memberRepository.save(member); diff --git a/src/main/java/com/cmc/suppin/survey/controller/.gitkeep b/src/main/java/com/cmc/suppin/survey/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/survey/converter/.gitkeep b/src/main/java/com/cmc/suppin/survey/converter/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/survey/exception/.gitkeep b/src/main/java/com/cmc/suppin/survey/exception/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/cmc/suppin/survey/service/.gitkeep b/src/main/java/com/cmc/suppin/survey/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/drivers/chromedriver b/src/main/resources/drivers/chromedriver new file mode 100755 index 0000000..03fea3d Binary files /dev/null and b/src/main/resources/drivers/chromedriver differ diff --git a/src/test/java/com/cmc/suppin/SuppinApplicationTests.java b/src/test/java/com/cmc/suppin/SuppinApplicationTests.java index d8d23ad..add6347 100644 --- a/src/test/java/com/cmc/suppin/SuppinApplicationTests.java +++ b/src/test/java/com/cmc/suppin/SuppinApplicationTests.java @@ -1,13 +1,29 @@ package com.cmc.suppin; +import com.cmc.suppin.global.enums.UserStatus; +import com.cmc.suppin.member.domain.repository.MemberRepository; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + @SpringBootTest class SuppinApplicationTests { - @Test - void contextLoads() { - } + @Autowired + private MemberRepository memberRepository; + + @Test + public void testExistsByUserIdAndStatusNot() { + // Given + String userId = "testUser"; + UserStatus status = UserStatus.DELETED; + + // When + boolean exists = memberRepository.existsByUserIdAndStatusNot(userId, status); + // Then + assertThat(exists).isFalse(); + } }