Skip to content
Open
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
@@ -0,0 +1,52 @@
package devkor.com.teamcback.domain.report.controller;

import devkor.com.teamcback.domain.report.dto.request.UpdateReportStatusReq;
import devkor.com.teamcback.domain.report.dto.response.GetReportListRes;
import devkor.com.teamcback.domain.report.dto.response.UpdateReportStatusRes;
import devkor.com.teamcback.domain.report.entity.ReportStatus;
import devkor.com.teamcback.domain.report.service.ReportService;
import devkor.com.teamcback.global.response.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/admin/reports")
public class AdminReportController {
private final ReportService reportService;

@Operation(summary = "신고 관리를 위한 목록 조회",
description = "신고 상태에 따라 조회")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "401", description = "권한이 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
@GetMapping
public CommonResponse<GetReportListRes> getReportList(
@Parameter(name = "reportStatus", description = "신고 상태 종류") @RequestParam(required = false) ReportStatus reportStatus
) {
return CommonResponse.success(reportService.getReportList(reportStatus));
}

@Operation(summary = "신고 상태 변경",
description = "신고 상태 변경")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "401", description = "권한이 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
@PutMapping("/{reportId}")
public CommonResponse<UpdateReportStatusRes> updateReportStatus(
@Parameter(description = "변경할 신고 id") @PathVariable Long reportId,
@Parameter(description = "신고의 변경할 생태") @RequestBody UpdateReportStatusReq req
) {
return CommonResponse.success(reportService.updateReportStatus(reportId, req));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package devkor.com.teamcback.domain.report.controller;

import devkor.com.teamcback.domain.report.dto.request.CreateReviewReportReq;
import devkor.com.teamcback.domain.report.dto.response.CreateReviewReportRes;
import devkor.com.teamcback.domain.report.dto.response.GetUserReviewReportStatusRes;
import devkor.com.teamcback.domain.report.service.ReportService;
import devkor.com.teamcback.global.response.CommonResponse;
import devkor.com.teamcback.global.security.UserDetailsImpl;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/reports")
public class ReportController {

private final ReportService reportService;

@Operation(summary = "신고 작성",
description = "리뷰에 대한 신고를 작성")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "401", description = "권한이 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
@PostMapping(value = "/reviews/{reviewId}")
public CommonResponse<CreateReviewReportRes> createReviewReport(
@Parameter(description = "사용자정보") @AuthenticationPrincipal UserDetailsImpl userDetail,
@Parameter(name = "reviewId", description = "리뷰 ID") @PathVariable Long reviewId,
@Parameter(description = "리뷰 작성 내용", required = true) @Valid @RequestBody CreateReviewReportReq req) {

return CommonResponse.success(reportService.createReviewReport(userDetail == null ? null : userDetail.getUser().getUserId(), reviewId, req));
}

@Operation(summary = "사용자 리뷰 신고 여부 조회",
description = "사용자 신고된 상태인지 확인하고 알림(비회원은 조회 x)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "401", description = "권한이 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
@GetMapping(value = "/status")
public CommonResponse<GetUserReviewReportStatusRes> getUserReviewReportStatus(
@Parameter(description = "사용자정보", required = true) @AuthenticationPrincipal UserDetailsImpl userDetail)
{
return CommonResponse.success(reportService.getUserReviewReportStatus(userDetail.getUser().getUserId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package devkor.com.teamcback.domain.report.dto.request;

import devkor.com.teamcback.domain.report.entity.ReasonCategory;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

@Schema(description = "저장할 리뷰 신고 내용")
@Getter
@Setter
public class CreateReviewReportReq {
@NotNull
private ReasonCategory reasonCategory; // 신고 이유
private String content; // 신고 내용

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package devkor.com.teamcback.domain.report.dto.request;

import devkor.com.teamcback.domain.report.entity.ReportStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

@Schema(description = "수정할 신고 내용")
@Getter
@Setter
public class UpdateReportStatusReq {
@NotNull
private ReportStatus status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package devkor.com.teamcback.domain.report.dto.response;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "리뷰 신고 저장 완료")
@JsonIgnoreProperties
public class CreateReviewReportRes {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package devkor.com.teamcback.domain.report.dto.response;

import lombok.Getter;

import java.util.List;

@Getter
public class GetReportListRes {
List<GetReportRes> reportList;

public GetReportListRes(List<GetReportRes> reportList) {
this.reportList = reportList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package devkor.com.teamcback.domain.report.dto.response;

import devkor.com.teamcback.domain.report.entity.Report;
import lombok.Getter;

@Getter
public class GetReportRes {
private Long reportId;
private Long targetId;
private String targetType;
private String reasonCategory;
private String content;
private String status;
private String effectiveAt;
private String createdAt;
private Long reporterId;
private Long reporterUserId;

public GetReportRes(Report report) {
this.reportId = report.getId();
this.targetId = report.getTargetId();
this.targetType = report.getTargetType().toString();
this.reasonCategory = report.getReasonCategory().toString();
this.content = report.getContent();
this.status = report.getStatus().toString();
this.effectiveAt = report.getEffectiveAt() != null ? report.getEffectiveAt().toString() : null;
this.createdAt = report.getCreatedAt() != null ? report.getCreatedAt().toString() : null;
this.reporterId = report.getReporter().getUserId();
this.reporterUserId = report.getReportedUser().getUserId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package devkor.com.teamcback.domain.report.dto.response;

import devkor.com.teamcback.domain.review.entity.Review;
import lombok.Getter;

import java.time.format.DateTimeFormatter;
import java.util.Locale;

@Getter
public class GetReportedReviewRes {
private Long reviewId;
private String comment;
private Long placeId;
private String placeName;
private String reviewCreatedAt;
private String reasonCategory;

public GetReportedReviewRes(Review review, String reasonCategory) {
this.reviewId = review.getId();
this.placeId = review.getPlace().getId();
this.placeName = review.getPlace().getName();
this.comment = review.getComment();
this.reasonCategory = reasonCategory;

// 작성일 변환
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yy.MM.dd(E)", Locale.KOREAN);
this.reviewCreatedAt = review.getCreatedAt() != null ? review.getCreatedAt().format(formatter): "";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package devkor.com.teamcback.domain.report.dto.response;

import devkor.com.teamcback.domain.user.entity.User;
import lombok.Getter;

import java.util.List;

@Getter
public class GetUserReviewReportStatusRes {
private Long userId;
private String userName;
private boolean isReported;
private List<GetReportedReviewRes> reviewList;

public GetUserReviewReportStatusRes(User user, List<GetReportedReviewRes> reviewList) {
this.userId = user.getUserId();
this.userName = user.getUsername();
this.isReported = !reviewList.isEmpty();
this.reviewList = reviewList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package devkor.com.teamcback.domain.report.dto.response;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;

@Getter
@JsonIgnoreProperties
public class UpdateReportStatusRes {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package devkor.com.teamcback.domain.report.entity;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public enum ReasonCategory {
ABUSE_OR_DISCRIMINATION("욕설/비하"),
DEFAMATION("명예훼손"),
SPAM_OR_ADVERTISING("홍보/도배"),
INAPPROPRIATE_CONTENT("음란/선정");

private final String label;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package devkor.com.teamcback.domain.report.entity;

import devkor.com.teamcback.domain.common.entity.BaseEntity;
import devkor.com.teamcback.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDate;

@Entity
@Getter
@Table(name = "tb_report")
@NoArgsConstructor
public class Report extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
@Enumerated(EnumType.STRING)
private TargetType targetType;

@Column
private Long targetId;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private ReasonCategory reasonCategory;

@Column(length = 300)
private String content;

@Setter
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private ReportStatus status;

@Setter
@Column
private LocalDate effectiveAt; // 신고 정지 시작일

@ManyToOne
@JoinColumn(name = "reporter_id")
private User reporter;

@ManyToOne
@JoinColumn(name = "reported_user_id")
private User reportedUser;

public Report(TargetType targetType, Long targetId, ReasonCategory reasonCategory, String content, ReportStatus status, User reporter, User reportedUser) {
this.targetType = targetType;
this.targetId = targetId;
this.reasonCategory = reasonCategory;
this.content = content;
this.status = status;
this.reporter = reporter;
this.reportedUser = reportedUser;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package devkor.com.teamcback.domain.report.entity;

public enum ReportStatus {
PENDING,
RESOLVED,
REJECTED,
EXPIRED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package devkor.com.teamcback.domain.report.entity;

public enum TargetType {
REVIEW
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package devkor.com.teamcback.domain.report.repository;

import devkor.com.teamcback.domain.report.entity.Report;
import devkor.com.teamcback.domain.report.entity.ReportStatus;
import devkor.com.teamcback.domain.report.entity.TargetType;
import devkor.com.teamcback.domain.user.entity.User;

import java.util.List;

public interface CustomReportRepository {
List<Report> findUniqueReportsForUserReviewReportStatus(User user, TargetType type, ReportStatus status);
}
Loading