diff --git a/src/main/java/com/command/itdaserver/domain/post/domain/Report.java b/src/main/java/com/command/itdaserver/domain/post/domain/Report.java new file mode 100644 index 0000000..b8eb54d --- /dev/null +++ b/src/main/java/com/command/itdaserver/domain/post/domain/Report.java @@ -0,0 +1,49 @@ +package com.command.itdaserver.domain.post.domain; + +import com.command.itdaserver.domain.post.domain.enums.ReportReason; +import com.command.itdaserver.domain.user.domain.User; +import com.command.itdaserver.global.entity.BaseIdEntity; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDateTime; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Report extends BaseIdEntity { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id", nullable = false) + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reporter_id", nullable = false) + private User reporter; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private ReportReason reason; + + @Size(max = 300) + private String detail; + + @CreationTimestamp + @Column(nullable = false, name = "created_at") + private LocalDateTime createdAt; + + public static Report create(Post post, User reporter, ReportReason reason, String detail) { + Report report = new Report(); + report.post = post; + report.reporter = reporter; + report.reason = reason; + report.detail = detail; + return report; + } +} diff --git a/src/main/java/com/command/itdaserver/domain/post/domain/enums/ReportReason.java b/src/main/java/com/command/itdaserver/domain/post/domain/enums/ReportReason.java new file mode 100644 index 0000000..47818ac --- /dev/null +++ b/src/main/java/com/command/itdaserver/domain/post/domain/enums/ReportReason.java @@ -0,0 +1,17 @@ +package com.command.itdaserver.domain.post.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ReportReason { + + SPAM("광고·홍보·스팸"), + HATE_SPEECH("욕설·비하·혐오 표현"), + OBSCENITY("음란·불쾌한 내용"), + IRRELEVANT("공고 목적과 맞지 않는 내용"), + OTHER("기타"); + + private final String displayName; +} diff --git a/src/main/java/com/command/itdaserver/domain/post/domain/repository/ReportRepository.java b/src/main/java/com/command/itdaserver/domain/post/domain/repository/ReportRepository.java new file mode 100644 index 0000000..d9777e5 --- /dev/null +++ b/src/main/java/com/command/itdaserver/domain/post/domain/repository/ReportRepository.java @@ -0,0 +1,7 @@ +package com.command.itdaserver.domain.post.domain.repository; + +import com.command.itdaserver.domain.post.domain.Report; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportRepository extends JpaRepository { +} diff --git a/src/main/java/com/command/itdaserver/domain/post/presentation/PostController.java b/src/main/java/com/command/itdaserver/domain/post/presentation/PostController.java index 7ce9fc9..b40bbb8 100644 --- a/src/main/java/com/command/itdaserver/domain/post/presentation/PostController.java +++ b/src/main/java/com/command/itdaserver/domain/post/presentation/PostController.java @@ -3,6 +3,7 @@ import com.command.itdaserver.domain.post.presentation.dto.request.CreateFormRequest; import com.command.itdaserver.domain.post.presentation.dto.request.CreatePostRequest; import com.command.itdaserver.domain.post.presentation.dto.request.SubmitAnswerRequest; +import com.command.itdaserver.domain.post.presentation.dto.request.CreateReportRequest; import com.command.itdaserver.domain.post.presentation.dto.request.UpdatePostRequest; import com.command.itdaserver.domain.post.presentation.dto.response.AnswerResponse; import com.command.itdaserver.domain.post.presentation.dto.response.ApplyFormResponse; @@ -16,6 +17,7 @@ import com.command.itdaserver.domain.post.service.GetPostsService; import com.command.itdaserver.domain.post.service.ToggleBookmarkService; import com.command.itdaserver.domain.post.service.ToggleLikeService; +import com.command.itdaserver.domain.post.service.CreateReportService; import com.command.itdaserver.domain.post.service.DeletePostService; import com.command.itdaserver.domain.post.service.UpdatePostService; import com.command.itdaserver.global.auth.CustomUserDetails; @@ -40,6 +42,7 @@ public class PostController { private final ToggleLikeService toggleLikeService; private final ToggleBookmarkService toggleBookmarkService; private final UpdatePostService updatePostService; + private final CreateReportService createReportService; private final DeletePostService deletePostService; @GetMapping @@ -104,4 +107,11 @@ public void toggleBookmark(@PathVariable Long postId, toggleBookmarkService.execute(postId, userDetails); } + @PostMapping("/{postId}/report") + public void reportPost(@PathVariable Long postId, + @AuthenticationPrincipal CustomUserDetails userDetails, + @Valid @RequestBody CreateReportRequest request) { + createReportService.execute(postId, request, userDetails); + } + } diff --git a/src/main/java/com/command/itdaserver/domain/post/presentation/dto/request/CreateReportRequest.java b/src/main/java/com/command/itdaserver/domain/post/presentation/dto/request/CreateReportRequest.java new file mode 100644 index 0000000..ce6f9f8 --- /dev/null +++ b/src/main/java/com/command/itdaserver/domain/post/presentation/dto/request/CreateReportRequest.java @@ -0,0 +1,18 @@ +package com.command.itdaserver.domain.post.presentation.dto.request; + +import com.command.itdaserver.domain.post.domain.enums.ReportReason; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CreateReportRequest { + + @NotNull(message = "신고 사유는 필수입니다.") + private ReportReason reason; + + @Size(max = 300, message = "상세설명은 최대 300자까지 입력 가능합니다.") + private String detail; +} diff --git a/src/main/java/com/command/itdaserver/domain/post/service/CreateReportService.java b/src/main/java/com/command/itdaserver/domain/post/service/CreateReportService.java new file mode 100644 index 0000000..02ed9ca --- /dev/null +++ b/src/main/java/com/command/itdaserver/domain/post/service/CreateReportService.java @@ -0,0 +1,37 @@ +package com.command.itdaserver.domain.post.service; + +import com.command.itdaserver.domain.post.domain.Post; +import com.command.itdaserver.domain.post.domain.Report; +import com.command.itdaserver.domain.post.domain.repository.PostRepository; +import com.command.itdaserver.domain.post.domain.repository.ReportRepository; +import com.command.itdaserver.domain.post.exceptions.PostNotFoundException; +import com.command.itdaserver.domain.post.presentation.dto.request.CreateReportRequest; +import com.command.itdaserver.domain.user.domain.User; +import com.command.itdaserver.domain.user.domain.repository.UserRepository; +import com.command.itdaserver.domain.user.exception.UserNotFoundException; +import com.command.itdaserver.global.auth.CustomUserDetails; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class CreateReportService { + + private final PostRepository postRepository; + private final ReportRepository reportRepository; + private final UserRepository userRepository; + + @Transactional + public void execute(Long postId, CreateReportRequest request, CustomUserDetails userDetails) { + + Post post = postRepository.findById(postId) + .orElseThrow(() -> PostNotFoundException.EXCEPTION); + + User reporter = userRepository.findByUserId(userDetails.getUserId()) + .orElseThrow(() -> UserNotFoundException.EXCEPTION); + + Report report = Report.create(post, reporter, request.getReason(), request.getDetail()); + reportRepository.save(report); + } +}