diff --git a/src/main/java/com/assu/server/domain/auth/controller/AuthController.java b/src/main/java/com/assu/server/domain/auth/controller/AuthController.java index 7351921e..d046fca6 100644 --- a/src/main/java/com/assu/server/domain/auth/controller/AuthController.java +++ b/src/main/java/com/assu/server/domain/auth/controller/AuthController.java @@ -84,7 +84,8 @@ public BaseResponse checkAuthNumber( return BaseResponse.onSuccess(SuccessStatus.VERIFY_AUTH_NUMBER_SUCCESS, null); } - @Operation(summary = "전화번호 중복 체크 API", description = "# [v1.0 (2025-01-15)]\n" + + @Operation(summary = "전화번호 중복 체크 API", + description = "# [v1.0 (2025-09-18)](https://clumsy-seeder-416.notion.site/2551197c19ed808a9757f7f0fc4cf09b?source=copy_link)\n" + "- 입력한 전화번호가 이미 가입된 사용자가 있는지 확인합니다.\n" + "- 중복된 전화번호가 있으면 에러를 반환합니다.\n" + "\n**Request Body:**\n" + @@ -99,7 +100,8 @@ public BaseResponse checkPhoneNumberAvailability( return BaseResponse.onSuccess(SuccessStatus._OK, null); } - @Operation(summary = "이메일 중복 체크 API", description = "# [v1.0 (2025-01-15)]\n" + + @Operation(summary = "이메일 중복 체크 API", + description = "# [v1.0 (2025-09-18)](https://clumsy-seeder-416.notion.site/2551197c19ed802d8f6dd373dd045f3a?source=copy_link)\n" + "- 입력한 이메일이 이미 가입된 사용자가 있는지 확인합니다.\n" + "- 중복된 이메일이 있으면 에러를 반환합니다.\n" + "\n**Request Body:**\n" + diff --git a/src/main/java/com/assu/server/domain/common/entity/enums/ReportedStatus.java b/src/main/java/com/assu/server/domain/common/entity/enums/ReportedStatus.java new file mode 100644 index 00000000..52301eee --- /dev/null +++ b/src/main/java/com/assu/server/domain/common/entity/enums/ReportedStatus.java @@ -0,0 +1,14 @@ +package com.assu.server.domain.common.entity.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ReportedStatus { + NORMAL("정상"), + REPORTED("신고됨"), + DELETED("삭제됨"); + + private final String description; +} diff --git a/src/main/java/com/assu/server/domain/partnership/repository/PaperRepository.java b/src/main/java/com/assu/server/domain/partnership/repository/PaperRepository.java index 4f9fdf3a..d3125434 100644 --- a/src/main/java/com/assu/server/domain/partnership/repository/PaperRepository.java +++ b/src/main/java/com/assu/server/domain/partnership/repository/PaperRepository.java @@ -37,8 +37,19 @@ Optional findTopByAdmin_IdAndPartner_IdAndIsActivatedOrderByIdDesc( Optional findTopByAdmin_IdAndPartner_IdAndIsActivatedInOrderByIdDesc(Long adminId, Long partnerId, List statuses); // Admin 기준 (SUSPEND) - @Query("select p from Paper p join fetch p.partner where p.isActivated = :status order by p.createdAt desc") - List findAllByIsActivatedWithPartner(@Param("status") ActivationStatus status); + @Query(""" +select p +from Paper p +left join fetch p.partner pt +left join fetch p.store s +where p.isActivated = :status + and p.admin.id = :adminId +order by p.createdAt desc +""") + List findAllSuspendedByAdminWithPartner( + @Param("status") ActivationStatus status, + @Param("adminId") Long adminId + ); // Partner 기준 (ACTIVE) List findByPartner_IdAndIsActivated(Long partnerId, ActivationStatus status, Sort sort); diff --git a/src/main/java/com/assu/server/domain/partnership/service/PaperQueryServiceImpl.java b/src/main/java/com/assu/server/domain/partnership/service/PaperQueryServiceImpl.java index 48d9b911..8cef7cab 100644 --- a/src/main/java/com/assu/server/domain/partnership/service/PaperQueryServiceImpl.java +++ b/src/main/java/com/assu/server/domain/partnership/service/PaperQueryServiceImpl.java @@ -19,7 +19,6 @@ import com.assu.server.domain.store.entity.Store; import com.assu.server.domain.store.repository.StoreRepository; import com.assu.server.domain.user.entity.Student; -import com.assu.server.domain.user.entity.enums.Major; import com.assu.server.global.apiPayload.code.status.ErrorStatus; import com.assu.server.global.exception.GeneralException; @@ -41,7 +40,7 @@ public PaperResponseDTO.partnershipContent getStorePaperContent(Long storeId, Me // 역할이 학생이 아닌 경우 : 이미 type별로 ui를 분기 시켜놔서 그럴일 없을 것 같긴 하지만 혹시 몰라서 처리함 if(member.getRole() != UserRole.STUDENT) - throw new GeneralException(ErrorStatus.NO_STUENT_TYPE); + throw new GeneralException(ErrorStatus.NO_STUDENT_TYPE); Student student = member.getStudentProfile(); diff --git a/src/main/java/com/assu/server/domain/partnership/service/PartnershipServiceImpl.java b/src/main/java/com/assu/server/domain/partnership/service/PartnershipServiceImpl.java index 8418f44d..b189af00 100644 --- a/src/main/java/com/assu/server/domain/partnership/service/PartnershipServiceImpl.java +++ b/src/main/java/com/assu/server/domain/partnership/service/PartnershipServiceImpl.java @@ -252,12 +252,17 @@ public PartnershipResponseDTO.WritePartnershipResponseDTO getPartnership(Long pa @Override @Transactional public List getSuspendedPapers(Long adminId) { - List suspendedPapers = paperRepository.findAllByIsActivatedWithPartner(ActivationStatus.SUSPEND); + List suspendedPapers = + paperRepository.findAllSuspendedByAdminWithPartner(ActivationStatus.SUSPEND, adminId); return suspendedPapers.stream() .map(paper -> PartnershipResponseDTO.SuspendedPaperDTO.builder() .paperId(paper.getId()) - .partnerName(paper.getPartner().getName()) + .partnerName( + paper.getPartner() != null + ? paper.getPartner().getName() + : (paper.getStore() != null ? paper.getStore().getName() : "미등록") + ) .createdAt(paper.getCreatedAt()) .build()) .toList(); @@ -400,16 +405,25 @@ public void deletePartnership(Long paperId) { Paper paper = paperRepository.findById(paperId) .orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_PAPER)); + // 1. paperContent + goods 삭제 List contentsToDelete = paperContentRepository.findByPaperId(paperId); - if (contentsToDelete != null && !contentsToDelete.isEmpty()) { - List contentIds = contentsToDelete.stream().map(PaperContent::getId).toList(); - goodsRepository.deleteAllByContentIds(contentIds); + List contentIds = contentsToDelete.stream() + .map(PaperContent::getId) + .toList(); + goodsRepository.deleteAllByContentIds(contentIds); paperContentRepository.deleteAll(contentsToDelete); } + // 2. paper 삭제 paperRepository.delete(paper); + + // 3. 임시 store 삭제 (partner가 null인 경우만) + Store store = paper.getStore(); + if (store != null && paper.getPartner() == null) { + storeRepository.delete(store); + } } @Override diff --git a/src/main/java/com/assu/server/domain/report/controller/ReportController.java b/src/main/java/com/assu/server/domain/report/controller/ReportController.java new file mode 100644 index 00000000..dbe3420d --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/controller/ReportController.java @@ -0,0 +1,70 @@ +package com.assu.server.domain.report.controller; + +import com.assu.server.domain.report.dto.ReportRequestDTO; +import com.assu.server.domain.report.dto.ReportResponseDTO; +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import com.assu.server.domain.report.service.ReportService; +import com.assu.server.global.apiPayload.BaseResponse; +import com.assu.server.global.apiPayload.code.status.SuccessStatus; +import com.assu.server.global.util.PrincipalDetails; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "Report", description = "신고 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/reports") +public class ReportController { + + private final ReportService reportService; + + @Operation(summary = "콘텐츠 신고 API", + description = "# [v1.0 (2025-09-24)](https://clumsy-seeder-416.notion.site/API-2771197c19ed80b79afbf3d8d8d82c15?source=copy_link)\n" + + "- 신고자는 본인 Member ID로 자동 설정됩니다.\n" + + "- 자기 자신의 콘텐츠를 신고할 수 없습니다.\n" + + "- 동일한 대상을 중복 신고할 수 없습니다.\n\n" + + "**Request Body:**\n" + + "- `targetType` (String, required): 신고 대상 타입 (REVIEW, SUGGESTION)\n" + + "- `targetId` (Long, required): 리뷰 ID 또는 건의글 ID\n" + + "- `reportType` (String, required): 신고 유형\n" + + " - 리뷰 신고: REVIEW_INAPPROPRIATE_CONTENT, REVIEW_FALSE_INFORMATION, REVIEW_SPAM\n" + + " - 건의글 신고: SUGGESTION_INAPPROPRIATE_CONTENT, SUGGESTION_FALSE_INFORMATION, SUGGESTION_SPAM\n\n" + + "**Response:**\n" + + "- 성공 시 201(CREATED)과 신고 ID 반환") + @PostMapping + public BaseResponse reportContent( + @AuthenticationPrincipal PrincipalDetails principalDetails, + @RequestBody @Valid ReportRequestDTO.CreateContentReportRequest request + ) { + Long reporterId = principalDetails.getMember().getId(); + ReportResponseDTO.CreateReportResponse response = reportService.reportContent(reporterId, request); + return BaseResponse.onSuccess(SuccessStatus.REPORT_SUCCESS, response); + } + + @Operation(summary = "작성자 신고 API", + description = "# [v1.0 (2025-09-24)](https://clumsy-seeder-416.notion.site/API-2771197c19ed80f8ab45e70772fcfc58?source=copy_link)\n" + + "- 신고자는 본인 Member ID로 자동 설정됩니다.\n" + + "- 자기 자신을 신고할 수 없습니다.\n" + + "- 동일한 작성자를 중복 신고할 수 없습니다.\n\n" + + "**Request Body:**\n" + + "- `targetType` (String, required): 신고 대상 타입 (REVIEW, SUGGESTION)\n" + + "- `targetId` (Long, required): 리뷰 ID 또는 건의글 ID\n" + + "- `reportType` (String, required): 신고 유형\n" + + " - 사용자 신고: USER_SPAM, USER_INAPPROPRIATE_CONTENT, USER_HARASSMENT, USER_FRAUD, USER_PRIVACY_VIOLATION, USER_OTHER\n\n" + + + "**Response:**\n" + + "- 성공 시 201(CREATED)과 신고 ID 반환") + @PostMapping("/students") + public BaseResponse reportStudent( + @AuthenticationPrincipal PrincipalDetails principalDetails, + @RequestBody @Valid ReportRequestDTO.CreateStudentReportRequest request + ) { + Long reporterId = principalDetails.getMember().getId(); + ReportResponseDTO.CreateReportResponse response = reportService.reportStudent(reporterId, request); + return BaseResponse.onSuccess(SuccessStatus.REPORT_SUCCESS, response); + } +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/report/dto/ReportRequestDTO.java b/src/main/java/com/assu/server/domain/report/dto/ReportRequestDTO.java new file mode 100644 index 00000000..932676bb --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/dto/ReportRequestDTO.java @@ -0,0 +1,42 @@ +package com.assu.server.domain.report.dto; + +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import com.assu.server.domain.report.entity.enums.ReportType; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class ReportRequestDTO { + + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CreateContentReportRequest { + @NotNull(message = "신고 대상 타입은 필수입니다.") + private ReportTargetType targetType; // REVIEW, SUGGESTION + + @NotNull(message = "신고 대상 ID는 필수입니다.") + private Long targetId; // 리뷰 ID 또는 건의글 ID + + @NotNull(message = "신고 유형은 필수입니다.") + private ReportType reportType; // REVIEW_*, SUGGESTION_* + } + + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CreateStudentReportRequest { + @NotNull(message = "신고 대상의 작성 컨텐츠의 타입은 필수입니다.") + private ReportTargetType targetType; // REVIEW, SUGGESTION + + @NotNull(message = "신고 대상의 작성 컨텐츠 ID는 필수입니다.") + private Long targetId; // 리뷰 ID 또는 건의글 ID + + @NotNull(message = "유저 신고 유형은 필수입니다.") + private ReportType reportType; // USER_* + } +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/report/dto/ReportResponseDTO.java b/src/main/java/com/assu/server/domain/report/dto/ReportResponseDTO.java new file mode 100644 index 00000000..4f506b50 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/dto/ReportResponseDTO.java @@ -0,0 +1,23 @@ +package com.assu.server.domain.report.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class ReportResponseDTO { + + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CreateReportResponse { + private Long reportId; + + public static CreateReportResponse of(Long reportId) { + return CreateReportResponse.builder() + .reportId(reportId) + .build(); + } + } +} diff --git a/src/main/java/com/assu/server/domain/report/entity/Report.java b/src/main/java/com/assu/server/domain/report/entity/Report.java new file mode 100644 index 00000000..6e2b9a12 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/entity/Report.java @@ -0,0 +1,52 @@ +package com.assu.server.domain.report.entity; + +import com.assu.server.domain.common.entity.BaseEntity; +import com.assu.server.domain.member.entity.Member; +import com.assu.server.domain.report.entity.enums.ReportStatus; +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import com.assu.server.domain.report.entity.enums.ReportType; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Report extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reporter_id", nullable = false) + private Member reporter; // 신고자 + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private ReportTargetType targetType; // 신고 대상 타입 (STUDENT_USER, REVIEW, SUGGESTION) + + @Column(nullable = false) + private Long targetId; // 신고 대상 ID (사용자 ID, 리뷰 ID, 건의 ID 등) + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reported_id") + private Member reported; // 피신고자 (사용자 신고인 경우에만) + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private ReportType reportType; // 신고 유형 + + @Enumerated(EnumType.STRING) + @Builder.Default + private ReportStatus status = ReportStatus.PENDING; // 신고 상태 + + // Todo 관리자용 업데이트 로직 추가 + // 신고 상태 업데이트 메서드 + public void updateStatus(ReportStatus status) { + this.status = status; + } +} diff --git a/src/main/java/com/assu/server/domain/report/entity/enums/ReportStatus.java b/src/main/java/com/assu/server/domain/report/entity/enums/ReportStatus.java new file mode 100644 index 00000000..f9348acb --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/entity/enums/ReportStatus.java @@ -0,0 +1,15 @@ +package com.assu.server.domain.report.entity.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ReportStatus { + PENDING("대기중"), + PROCESSED("처리완료"), + REJECTED("기각"), + UNDER_REVIEW("검토중"); + + private final String description; +} diff --git a/src/main/java/com/assu/server/domain/report/entity/enums/ReportTargetType.java b/src/main/java/com/assu/server/domain/report/entity/enums/ReportTargetType.java new file mode 100644 index 00000000..fff8958f --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/entity/enums/ReportTargetType.java @@ -0,0 +1,14 @@ +package com.assu.server.domain.report.entity.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ReportTargetType { + STUDENT_USER("학생 사용자"), + REVIEW("리뷰"), + SUGGESTION("건의글"); + + private final String description; +} diff --git a/src/main/java/com/assu/server/domain/report/entity/enums/ReportType.java b/src/main/java/com/assu/server/domain/report/entity/enums/ReportType.java new file mode 100644 index 00000000..fcd9bc6c --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/entity/enums/ReportType.java @@ -0,0 +1,28 @@ +package com.assu.server.domain.report.entity.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ReportType { + // 사용자 신고용 + STUDENT_USER_SPAM("스팸/홍보"), + STUDENT_USER_INAPPROPRIATE_CONTENT("부적절한 내용"), + STUDENT_USER_HARASSMENT("괴롭힘/욕설"), + STUDENT_USER_FRAUD("사기/부정행위"), + STUDENT_USER_PRIVACY_VIOLATION("개인정보 침해"), + STUDENT_USER_OTHER("기타"), + + // 리뷰 신고용 + REVIEW_INAPPROPRIATE_CONTENT("부적절한 내용 및 욕설이 포함된 리뷰에요"), + REVIEW_FALSE_INFORMATION("허위사실 / 거짓이 포함된 리뷰에요"), + REVIEW_SPAM("홍보 / 광고를 위한 리뷰에요"), + + // 건의글 신고용 + SUGGESTION_INAPPROPRIATE_CONTENT("부적절한 내용 및 욕설이 포함된 건의글이에요"), + SUGGESTION_FALSE_INFORMATION("허위사실 / 거짓이 포함된 건의글에요"), + SUGGESTION_SPAM("홍보/광고를 위한 건의글이에요 "); + + private final String description; +} diff --git a/src/main/java/com/assu/server/domain/report/event/ReportProcessedEvent.java b/src/main/java/com/assu/server/domain/report/event/ReportProcessedEvent.java new file mode 100644 index 00000000..44af9971 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/event/ReportProcessedEvent.java @@ -0,0 +1,15 @@ +package com.assu.server.domain.report.event; + +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import com.assu.server.domain.report.entity.enums.ReportStatus; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class ReportProcessedEvent { + private final Long reportId; + private final ReportTargetType targetType; + private final Long targetId; + private final ReportStatus status; +} diff --git a/src/main/java/com/assu/server/domain/report/exception/ReportException.java b/src/main/java/com/assu/server/domain/report/exception/ReportException.java new file mode 100644 index 00000000..2eb8749d --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/exception/ReportException.java @@ -0,0 +1,8 @@ +package com.assu.server.domain.report.exception; + +import com.assu.server.global.apiPayload.code.BaseErrorCode; +import com.assu.server.global.exception.GeneralException; + +public class ReportException extends GeneralException { + public ReportException(BaseErrorCode errorStatus) { super(errorStatus); } +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/report/repository/ReportRepository.java b/src/main/java/com/assu/server/domain/report/repository/ReportRepository.java new file mode 100644 index 00000000..155e6a90 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/repository/ReportRepository.java @@ -0,0 +1,12 @@ +package com.assu.server.domain.report.repository; + +import com.assu.server.domain.report.entity.Report; +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReportRepository extends JpaRepository { + // 특정 사용자가 특정 대상을 신고했는지 확인 + boolean existsByReporterIdAndTargetTypeAndTargetId(Long reporterId, ReportTargetType targetType, Long targetId); +} diff --git a/src/main/java/com/assu/server/domain/report/service/ReportService.java b/src/main/java/com/assu/server/domain/report/service/ReportService.java new file mode 100644 index 00000000..5ffaec7a --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/service/ReportService.java @@ -0,0 +1,13 @@ +package com.assu.server.domain.report.service; + +import com.assu.server.domain.report.dto.ReportRequestDTO; +import com.assu.server.domain.report.dto.ReportResponseDTO; + +public interface ReportService { + + // 콘텐츠 신고 생성 (리뷰, 건의글) + ReportResponseDTO.CreateReportResponse reportContent(Long reporterId, ReportRequestDTO.CreateContentReportRequest request); + + // 작성자 신고 생성 (리뷰/건의글 작성자) + ReportResponseDTO.CreateReportResponse reportStudent(Long reporterId, ReportRequestDTO.CreateStudentReportRequest request); +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/report/service/ReportServiceImpl.java b/src/main/java/com/assu/server/domain/report/service/ReportServiceImpl.java new file mode 100644 index 00000000..622a1814 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/service/ReportServiceImpl.java @@ -0,0 +1,166 @@ +package com.assu.server.domain.report.service; + +import com.assu.server.domain.member.entity.Member; +import com.assu.server.domain.member.repository.MemberRepository; +import com.assu.server.domain.report.dto.ReportRequestDTO; +import com.assu.server.domain.report.dto.ReportResponseDTO; +import com.assu.server.domain.report.entity.Report; +import com.assu.server.domain.report.entity.enums.ReportStatus; +import com.assu.server.domain.report.entity.enums.ReportTargetType; +import com.assu.server.domain.report.repository.ReportRepository; +import com.assu.server.domain.review.entity.Review; +import com.assu.server.domain.review.repository.ReviewRepository; +import com.assu.server.domain.suggestion.entity.Suggestion; +import com.assu.server.domain.suggestion.repository.SuggestionRepository; +import com.assu.server.domain.report.exception.ReportException; +import com.assu.server.domain.report.event.ReportProcessedEvent; +import com.assu.server.domain.user.entity.Student; +import com.assu.server.global.apiPayload.code.status.ErrorStatus; +import org.springframework.context.ApplicationEventPublisher; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ReportServiceImpl implements ReportService { + + private final ReportRepository reportRepository; + private final MemberRepository memberRepository; + private final ReviewRepository reviewRepository; + private final SuggestionRepository suggestionRepository; + private final ApplicationEventPublisher eventPublisher; + + @Override + @Transactional + public ReportResponseDTO.CreateReportResponse reportContent(Long reporterId, + ReportRequestDTO.CreateContentReportRequest request) { + // 신고자 존재 확인 + Member reporter = memberRepository.findById(reporterId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_MEMBER)); + + // 신고 대상 존재 확인 및 자기 자신 신고 방지 + validateContentReportTarget(reporterId, request.getTargetType(), request.getTargetId()); + + // 중복 신고 확인 + if (reportRepository.existsByReporterIdAndTargetTypeAndTargetId(reporterId, request.getTargetType(), + request.getTargetId())) { + throw new ReportException(ErrorStatus.REPORT_DUPLICATE); + } + + // 콘텐츠 신고 생성 + Report report = Report.builder() + .reporter(reporter) + .targetType(request.getTargetType()) + .targetId(request.getTargetId()) + .reported(null) // 콘텐츠 신고는 피신고자 없음 + .reportType(request.getReportType()) + .status(ReportStatus.PENDING) + .build(); + + Report savedReport = reportRepository.save(report); + + // 신고 생성 이벤트 발행 + eventPublisher.publishEvent(new ReportProcessedEvent( + savedReport.getId(), + savedReport.getTargetType(), + savedReport.getTargetId(), + savedReport.getStatus())); + + return ReportResponseDTO.CreateReportResponse.of(savedReport.getId()); + } + + @Override + @Transactional + public ReportResponseDTO.CreateReportResponse reportStudent(Long reporterId, + ReportRequestDTO.CreateStudentReportRequest request) { + // 신고자 존재 확인 + Member reporter = memberRepository.findById(reporterId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_MEMBER)); + + // 신고 대상 존재 확인 및 자기 자신 신고 방지 + Student reportedStudent = validateStudentReportTarget(reporterId, request.getTargetType(), + request.getTargetId()); + + // 중복 신고 확인 (작성자 기준) + if (reportRepository.existsByReporterIdAndTargetTypeAndTargetId( + reporterId, + ReportTargetType.STUDENT_USER, + reportedStudent.getId()) + ) { + throw new ReportException(ErrorStatus.REPORT_DUPLICATE); + } + + // 작성자 신고 생성 + Report report = Report.builder() + .reporter(reporter) + .targetType(ReportTargetType.STUDENT_USER) + .targetId(reportedStudent.getId()) + .reported(reportedStudent.getMember()) + .reportType(request.getReportType()) + .status(ReportStatus.PENDING) + .build(); + + Report savedReport = reportRepository.save(report); + + // 신고 생성 이벤트 발행 + eventPublisher.publishEvent(new ReportProcessedEvent( + savedReport.getId(), + savedReport.getTargetType(), + savedReport.getTargetId(), + savedReport.getStatus())); + + return ReportResponseDTO.CreateReportResponse.of(savedReport.getId()); + } + + // 콘텐츠 신고 대상 검증 메서드 + private void validateContentReportTarget(Long reporterId, ReportTargetType targetType, Long targetId) { + switch (targetType) { + case REVIEW: + Review review = reviewRepository.findById(targetId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_MEMBER)); + if (reporterId.equals(review.getStudent().getId())) { + throw new ReportException(ErrorStatus.REVIEW_REPORT_SELF_NOT_ALLOWED); + } + break; + case SUGGESTION: + Suggestion suggestion = suggestionRepository.findById(targetId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_SUGGESTION)); + if (reporterId.equals(suggestion.getStudent().getId())) { + throw new ReportException(ErrorStatus.SUGGESTION_REPORT_SELF_NOT_ALLOWED); + } + break; + default: + throw new ReportException(ErrorStatus.INVALID_REPORT_TYPE); + } + } + + // 작성자 신고 대상 검증 메서드 + private Student validateStudentReportTarget(Long reporterId, ReportTargetType targetType, Long targetId) { + Student student; + + switch (targetType) { + case REVIEW: + Review review = reviewRepository.findById(targetId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_MEMBER)); + student = review.getStudent(); + break; + case SUGGESTION: + Suggestion suggestion = suggestionRepository.findById(targetId) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_SUGGESTION)); + student = suggestion.getStudent(); + break; + default: + throw new ReportException(ErrorStatus.INVALID_REPORT_TYPE); + } + + // 자기 자신 신고 방지 + if (reporterId.equals(student.getId())) { + throw new ReportException(ErrorStatus.REPORT_SELF_NOT_ALLOWED); + } + + return student; + } +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/report/service/ReportStatusSyncService.java b/src/main/java/com/assu/server/domain/report/service/ReportStatusSyncService.java new file mode 100644 index 00000000..f7d94a87 --- /dev/null +++ b/src/main/java/com/assu/server/domain/report/service/ReportStatusSyncService.java @@ -0,0 +1,99 @@ +package com.assu.server.domain.report.service; + +import com.assu.server.domain.common.entity.enums.ReportedStatus; +import com.assu.server.domain.report.entity.enums.ReportStatus; +import com.assu.server.domain.report.event.ReportProcessedEvent; +import com.assu.server.domain.review.entity.Review; +import com.assu.server.domain.review.repository.ReviewRepository; +import com.assu.server.domain.suggestion.entity.Suggestion; +import com.assu.server.domain.suggestion.repository.SuggestionRepository; +import com.assu.server.domain.user.entity.Student; +import com.assu.server.domain.user.repository.StudentRepository; +import com.assu.server.domain.report.exception.ReportException; +import com.assu.server.global.apiPayload.code.status.ErrorStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ReportStatusSyncService { + + private final ReviewRepository reviewRepository; + private final SuggestionRepository suggestionRepository; + private final StudentRepository studentRepository; + + @EventListener + @Async + @Transactional + public void handleReportProcessed(ReportProcessedEvent event) { + log.info("신고 처리 이벤트 수신: Report ID: {}, Target Type: {}, Target ID: {}, Status: {}", + event.getReportId(), event.getTargetType(), event.getTargetId(), event.getStatus()); + + try { + switch (event.getTargetType()) { + case REVIEW: + syncReviewStatus(event); + break; + case SUGGESTION: + syncSuggestionStatus(event); + break; + case STUDENT_USER: + syncStudentUserStatus(event); + break; + default: + log.warn("알 수 없는 신고 대상 타입: {}", event.getTargetType()); + } + } catch (Exception e) { + log.error("신고 상태 동기화 실패: Report ID: {}, Error: {}", event.getReportId(), e.getMessage(), e); + } + } + + private void syncReviewStatus(ReportProcessedEvent event) { + Review review = reviewRepository.findById(event.getTargetId()) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_MEMBER)); + + ReportedStatus newStatus = mapReportStatusToReportedStatus(event.getStatus()); + if (newStatus != null) { + review.updateReportedStatus(newStatus); + reviewRepository.save(review); + log.info("리뷰 상태 동기화 완료: Review ID: {}, Status: {}", event.getTargetId(), newStatus); + } + } + + private void syncSuggestionStatus(ReportProcessedEvent event) { + Suggestion suggestion = suggestionRepository.findById(event.getTargetId()) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_SUGGESTION)); + + ReportedStatus newStatus = mapReportStatusToReportedStatus(event.getStatus()); + if (newStatus != null) { + suggestion.updateReportedStatus(newStatus); + suggestionRepository.save(suggestion); + log.info("건의글 상태 동기화 완료: Suggestion ID: {}, Status: {}", event.getTargetId(), newStatus); + } + } + + private void syncStudentUserStatus(ReportProcessedEvent event) { + Student student = studentRepository.findById(event.getTargetId()) + .orElseThrow(() -> new ReportException(ErrorStatus.NO_SUCH_MEMBER)); + + ReportedStatus newStatus = mapReportStatusToReportedStatus(event.getStatus()); + if (newStatus != null) { + student.updateReportedStatus(newStatus); + studentRepository.save(student); + log.info("학생 상태 동기화 완료: Student ID: {}, Status: {}", event.getTargetId(), newStatus); + } + } + + private ReportedStatus mapReportStatusToReportedStatus(ReportStatus reportStatus) { + return switch (reportStatus) { + case PROCESSED -> ReportedStatus.REPORTED; + case REJECTED -> ReportedStatus.NORMAL; + case PENDING, UNDER_REVIEW -> null; // PENDING 상태는 상태 변경하지 않음 + }; + } +} diff --git a/src/main/java/com/assu/server/domain/review/entity/Review.java b/src/main/java/com/assu/server/domain/review/entity/Review.java index a4c7a1bd..b82f758e 100644 --- a/src/main/java/com/assu/server/domain/review/entity/Review.java +++ b/src/main/java/com/assu/server/domain/review/entity/Review.java @@ -3,12 +3,15 @@ import java.util.List; import com.assu.server.domain.common.entity.BaseEntity; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import com.assu.server.domain.partner.entity.Partner; import com.assu.server.domain.store.entity.Store; import com.assu.server.domain.user.entity.Student; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -21,7 +24,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; - @Entity @Getter @NoArgsConstructor @@ -46,6 +48,7 @@ public class Review extends BaseEntity { @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List imageList = new ArrayList<>(); + public List getImageList() { if (imageList == null) { imageList = new ArrayList<>(); @@ -57,4 +60,13 @@ public List getImageList() { private String content; private String affiliation; + + @Enumerated(EnumType.STRING) + @Builder.Default + private ReportedStatus status = ReportedStatus.NORMAL; + + // 상태 업데이트 메서드 + public void updateReportedStatus(ReportedStatus status) { + this.status = status; + } } diff --git a/src/main/java/com/assu/server/domain/review/repository/ReviewRepository.java b/src/main/java/com/assu/server/domain/review/repository/ReviewRepository.java index 8648241d..97ea6fb5 100644 --- a/src/main/java/com/assu/server/domain/review/repository/ReviewRepository.java +++ b/src/main/java/com/assu/server/domain/review/repository/ReviewRepository.java @@ -2,6 +2,7 @@ import com.assu.server.domain.review.entity.Review; import com.assu.server.domain.store.entity.Store; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -13,17 +14,54 @@ public interface ReviewRepository extends JpaRepository { @Query(""" - SELECT r - FROM Review r - WHERE r.student.id = :memberId - ORDER BY r.createdAt DESC -""") + SELECT r + FROM Review r + WHERE r.student.id = :memberId + AND r.status = :status + AND r.student.status = :studentStatus + ORDER BY r.createdAt DESC + """) + Page findByMemberIdAndStatusAndStudentStatus( + @Param("memberId") Long memberId, + @Param("status") ReportedStatus status, + @Param("studentStatus") ReportedStatus studentStatus, + Pageable pageable + ); + + @Query(""" + SELECT r + FROM Review r + WHERE r.student.id = :memberId + ORDER BY r.createdAt DESC + """) Page findByMemberId(@Param("memberId") Long memberId, Pageable pageable); - // List findByStoreId(Long storeId); - Page findByStoreIdOrderByCreatedAtDesc(Long id, Pageable pageable);//최신순 정렬 + @Query(""" + SELECT r + FROM Review r + WHERE r.store.id = :storeId + AND r.status = :status + AND r.student.status = :studentStatus + ORDER BY r.createdAt DESC + """) + Page findByStoreIdAndStatusAndStudentStatus( + @Param("storeId") Long storeId, + @Param("status") ReportedStatus status, + @Param("studentStatus") ReportedStatus studentStatus, + Pageable pageable + ); + + Page findByStoreIdOrderByCreatedAtDesc(Long id, Pageable pageable);// 최신순 정렬 + Page findByStoreId(Long id, Pageable pageable); + @Query("SELECT AVG(r.rate) FROM Review r WHERE r.store.id = :storeId AND r.status = :status AND r.student.status = :studentStatus") + Float standardScoreWithStatus( + @Param("storeId") Long storeId, + @Param("status") ReportedStatus status, + @Param("studentStatus") ReportedStatus studentStatus + ); + @Query("SELECT AVG(r.rate) FROM Review r WHERE r.store.id = :storeId") Float standardScore(Long storeId); diff --git a/src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java b/src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java index df6694aa..7256cfa7 100644 --- a/src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java +++ b/src/main/java/com/assu/server/domain/review/service/ReviewServiceImpl.java @@ -14,6 +14,7 @@ import com.assu.server.domain.store.repository.StoreRepository; import com.assu.server.domain.user.repository.PartnershipUsageRepository; import com.assu.server.domain.user.repository.StudentRepository; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import com.assu.server.global.apiPayload.code.status.ErrorStatus; import com.assu.server.global.exception.DatabaseException; import com.assu.server.global.exception.GeneralException; @@ -41,7 +42,6 @@ public class ReviewServiceImpl implements ReviewService { private final AmazonS3Manager amazonS3Manager; private final PartnershipUsageRepository partnershipUsageRepository; - @Override public ReviewResponseDTO.WriteReviewResponseDTO writeReview(ReviewRequestDTO.WriteReviewRequestDTO request, Long memberId, List reviewImages) { // createReview 메서드 호출로 통합 @@ -97,7 +97,9 @@ private Review createReview(Long memberId, Long storeId, ReviewRequestDTO.WriteR } return reviewRepository.save(review); - } private String generateReviewImageKeyName(Long memberId, Long reviewId, int imageIndex) { + } + + private String generateReviewImageKeyName(Long memberId, Long reviewId, int imageIndex) { LocalDateTime now = LocalDateTime.now(); String year = String.valueOf(now.getYear()); String month = String.format("%02d", now.getMonthValue()); @@ -128,7 +130,12 @@ public Page checkPartnerReview(Long me Store store = storeRepository.findByPartner(partner) .orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_STORE)); - Page reviews = reviewRepository.findByStoreId(store.getId(), pageable); + // 신고되지 않은 리뷰와 신고되지 않은 학생이 작성한 리뷰만 조회 + Page reviews = reviewRepository.findByStoreIdAndStatusAndStudentStatus( + store.getId(), + ReportedStatus.NORMAL, + ReportedStatus.NORMAL, + pageable); for (Review review : reviews) { updateReviewImageUrls(review); @@ -146,6 +153,7 @@ public ReviewResponseDTO.DeleteReviewResponseDTO deleteReview(Long reviewId) { .build(); } + private void updateReviewImageUrls(Review review) { for (ReviewPhoto reviewPhoto : review.getImageList()) { if (reviewPhoto.getKeyName() != null) { @@ -162,7 +170,13 @@ public Page checkStoreReview(Long stor pageable = PageRequest.of(pageable.getPageNumber() - 1, pageable.getPageSize(), pageable.getSort()); Store store = storeRepository.findById(storeId).orElseThrow( () -> new DatabaseException(ErrorStatus.NO_SUCH_STORE)); - Page reviews = reviewRepository.findByStoreId(store.getId(), pageable); + + // 신고되지 않은 리뷰와 신고되지 않은 학생이 작성한 리뷰만 조회 + Page reviews = reviewRepository.findByStoreIdAndStatusAndStudentStatus( + store.getId(), + ReportedStatus.NORMAL, + ReportedStatus.NORMAL, + pageable); for (Review review : reviews) { updateReviewImageUrls(review); @@ -174,7 +188,8 @@ public Page checkStoreReview(Long stor @Override @Transactional public ReviewResponseDTO.StandardScoreResponseDTO standardScore(Long storeId) { - Float score = reviewRepository.standardScore(storeId); + // 신고되지 않은 리뷰와 신고되지 않은 학생이 작성한 리뷰만으로 평균 계산 + Float score = reviewRepository.standardScoreWithStatus(storeId, ReportedStatus.NORMAL, ReportedStatus.NORMAL); if(score == null){ score = 0f; } @@ -191,7 +206,12 @@ public ReviewResponseDTO.StandardScoreResponseDTO myStoreAverage(Long memberId) Store store = storeRepository.findByPartner(partner) .orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_STORE)); - Float score = reviewRepository.standardScore(store.getId()); + // 신고되지 않은 리뷰와 신고되지 않은 학생이 작성한 리뷰만으로 평균 계산 + Float score = reviewRepository.standardScoreWithStatus(store.getId(), ReportedStatus.NORMAL, + ReportedStatus.NORMAL); + if (score == null) { + score = 0f; + } System.out.println(store.getId()); return ReviewResponseDTO.StandardScoreResponseDTO .builder() diff --git a/src/main/java/com/assu/server/domain/suggestion/entity/Suggestion.java b/src/main/java/com/assu/server/domain/suggestion/entity/Suggestion.java index e3e6685e..228cd8a4 100644 --- a/src/main/java/com/assu/server/domain/suggestion/entity/Suggestion.java +++ b/src/main/java/com/assu/server/domain/suggestion/entity/Suggestion.java @@ -2,10 +2,12 @@ import com.assu.server.domain.admin.entity.Admin; import com.assu.server.domain.common.entity.BaseEntity; -import com.assu.server.domain.store.entity.Store; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import com.assu.server.domain.user.entity.Student; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -37,4 +39,13 @@ public class Suggestion extends BaseEntity { private String storeName; private String content; + + @Enumerated(EnumType.STRING) + @Builder.Default + private ReportedStatus status = ReportedStatus.NORMAL; + + // 신고 상태 업데이트 메서드 + public void updateReportedStatus(ReportedStatus status) { + this.status = status; + } } diff --git a/src/main/java/com/assu/server/domain/suggestion/repository/SuggestionRepository.java b/src/main/java/com/assu/server/domain/suggestion/repository/SuggestionRepository.java index b712598b..146338be 100644 --- a/src/main/java/com/assu/server/domain/suggestion/repository/SuggestionRepository.java +++ b/src/main/java/com/assu/server/domain/suggestion/repository/SuggestionRepository.java @@ -1,6 +1,7 @@ package com.assu.server.domain.suggestion.repository; import com.assu.server.domain.suggestion.entity.Suggestion; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -10,11 +11,26 @@ public interface SuggestionRepository extends JpaRepository { @Query(""" - select s - from Suggestion s - join fetch s.student st - where s.admin.id = :adminId - order by s.createdAt desc - """) + select s + from Suggestion s + join fetch s.student st + where s.admin.id = :adminId + AND s.status = :status + AND s.student.status = :studentStatus + order by s.createdAt desc + """) + List findAllSuggestionsWithStatus( + @Param("adminId") Long adminId, + @Param("status") ReportedStatus status, + @Param("studentStatus") ReportedStatus studentStatus + ); + + @Query(""" + select s + from Suggestion s + join fetch s.student st + where s.admin.id = :adminId + order by s.createdAt desc + """) List findAllSuggestions(@Param("adminId") Long adminId); } diff --git a/src/main/java/com/assu/server/domain/suggestion/service/SuggestionServiceImpl.java b/src/main/java/com/assu/server/domain/suggestion/service/SuggestionServiceImpl.java index 2995ff62..8f1896e8 100644 --- a/src/main/java/com/assu/server/domain/suggestion/service/SuggestionServiceImpl.java +++ b/src/main/java/com/assu/server/domain/suggestion/service/SuggestionServiceImpl.java @@ -10,6 +10,7 @@ import com.assu.server.domain.suggestion.repository.SuggestionRepository; import com.assu.server.domain.user.entity.Student; import com.assu.server.domain.user.repository.StudentRepository; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import com.assu.server.global.apiPayload.code.status.ErrorStatus; import com.assu.server.global.exception.DatabaseException; import jakarta.transaction.Transactional; @@ -46,8 +47,9 @@ public SuggestionResponseDTO.WriteSuggestionResponseDTO writeSuggestion(Suggesti @Override public List getSuggestions(Long adminId) { + // 신고되지 않은 건의글과 신고되지 않은 학생이 작성한 건의글만 조회 List list = suggestionRepository - .findAllSuggestions(adminId); + .findAllSuggestionsWithStatus(adminId, ReportedStatus.NORMAL, ReportedStatus.NORMAL); return SuggestionConverter.toGetSuggestionDTOList(list); } diff --git a/src/main/java/com/assu/server/domain/user/entity/Student.java b/src/main/java/com/assu/server/domain/user/entity/Student.java index e7ee2706..0c1b034d 100644 --- a/src/main/java/com/assu/server/domain/user/entity/Student.java +++ b/src/main/java/com/assu/server/domain/user/entity/Student.java @@ -1,16 +1,14 @@ package com.assu.server.domain.user.entity; +import com.assu.server.domain.common.entity.enums.ReportedStatus; import com.assu.server.domain.member.entity.Member; import com.assu.server.domain.user.entity.enums.Department; import com.assu.server.domain.user.entity.enums.EnrollmentStatus; import com.assu.server.domain.user.entity.enums.Major; import com.assu.server.domain.user.entity.enums.University; import jakarta.persistence.*; -import jakarta.validation.constraints.Pattern; import lombok.*; -import java.util.ArrayList; -import java.util.List; @Entity @Getter @@ -44,6 +42,10 @@ public class Student { @Enumerated(EnumType.STRING) private Major major; + @Enumerated(EnumType.STRING) + @Builder.Default + private ReportedStatus status = ReportedStatus.NORMAL; + public void setMember(Member member) { this.member = member; } @@ -66,4 +68,9 @@ public void updateStudentInfo(String name, Major major, EnrollmentStatus enrollm this.enrollmentStatus = enrollmentStatus; this.yearSemester = yearSemester; } + + // 신고 상태 업데이트 메서드 + public void updateReportedStatus(ReportedStatus status) { + this.status = status; + } } diff --git a/src/main/java/com/assu/server/global/apiPayload/code/status/ErrorStatus.java b/src/main/java/com/assu/server/global/apiPayload/code/status/ErrorStatus.java index 94ecae2f..f21a23ae 100644 --- a/src/main/java/com/assu/server/global/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/com/assu/server/global/apiPayload/code/status/ErrorStatus.java @@ -43,7 +43,7 @@ public enum ErrorStatus implements BaseErrorCode { // 멤버 에러 NO_SUCH_MEMBER(HttpStatus.NOT_FOUND,"MEMBER_4001","존재하지 않는 멤버 ID입니다."), - NO_STUENT_TYPE(HttpStatus.BAD_REQUEST, "MEMBER4002", "학생 타입이 아닌 멤버입니다."), + NO_STUDENT_TYPE(HttpStatus.BAD_REQUEST, "MEMBER4002", "학생 타입이 아닌 멤버입니다."), NO_SUCH_ADMIN(HttpStatus.NOT_FOUND,"MEMBER_4002","존재하지 않는 admin ID 입니다."), NO_SUCH_PARTNER(HttpStatus.NOT_FOUND,"MEMBER_4003","존재하지 않는 partner ID 입니다."), @@ -105,13 +105,21 @@ public enum ErrorStatus implements BaseErrorCode { PROFILE_IMAGE_INVALID_FORMAT(HttpStatus.BAD_REQUEST, "PROFILE_4002", "지원하지 않는 이미지 형식입니다."), PROFILE_IMAGE_TOO_LARGE(HttpStatus.BAD_REQUEST, "PROFILE_4003", "허용된 크기를 초과한 이미지입니다."), + // Suggestion 관련 에러 + NO_SUCH_SUGGESTION(HttpStatus.NOT_FOUND, "SUGGESTION_4001", "존재하지 않는 건의글입니다."), + + // 신고(Report) 관련 에러 + REPORT_DUPLICATE(HttpStatus.CONFLICT, "REPORT_4001", "이미 신고한 대상입니다."), + REPORT_SELF_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "REPORT_4002", "자신을 신고할 수 없습니다."), + REVIEW_REPORT_SELF_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "REPORT_4003", "자신의 리뷰를 신고할 수 없습니다."), + SUGGESTION_REPORT_SELF_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "REPORT_4004", "자신의 건의글을 신고할 수 없습니다."), + INVALID_REPORT_TYPE(HttpStatus.BAD_REQUEST, "REPORT_4005", "유효하지 않은 신고 타입입니다."), ; private final HttpStatus httpStatus; private final String code; private final String message; - @Override public ErrorReasonDTO getReasonHttpStatus() { return ErrorReasonDTO.builder() diff --git a/src/main/java/com/assu/server/global/apiPayload/code/status/SuccessStatus.java b/src/main/java/com/assu/server/global/apiPayload/code/status/SuccessStatus.java index 175a1a97..79f28369 100644 --- a/src/main/java/com/assu/server/global/apiPayload/code/status/SuccessStatus.java +++ b/src/main/java/com/assu/server/global/apiPayload/code/status/SuccessStatus.java @@ -23,14 +23,7 @@ public enum SuccessStatus implements BaseCode { VERIFY_AUTH_NUMBER_SUCCESS(HttpStatus.OK, "AUTH_201", "성공적으로 생성되었습니다."), //신고 성공 - REPORT_HISTORY_VIEW_SUCCESS(HttpStatus.OK, "REPORT_200", "기록 신고의 정보가 성공적으로 조회되었습니다."), - REPORT_HISTORY_SUCCESS(HttpStatus.OK, "REPORT_201", "기록을 성공적으로 신고했습니다."), - REPORT_COMMENT_VIEW_SUCCESS(HttpStatus.OK, "REPORT_200", "댓글 신고의 정보가 성공적으로 조회되었습니다."), - REPORT_COMMENT_SUCCESS(HttpStatus.OK, "REPORT_201", "댓글을 성공적으로 신고했습니다."), - REPORT_PROFILE_VIEW_SUCCESS(HttpStatus.OK, "REPORT_200", "계정 신고의 정보가 성공적으로 조회되었습니다."), - REPORT_PROFILE_SUCCESS(HttpStatus.OK, "REPORT_201", "계정을 성공적으로 신고했습니다."), - REPORT_ADMIN_VIEW_SUCCESS(HttpStatus.OK, "REPORT_200","관리자용 신고 기록이 성공적으로 조회되었습니다."), - REPORT_ADMIN_PROCESSED(HttpStatus.OK,"REPORT_204","신고가 성공적으로 처리되었습니다."), + REPORT_SUCCESS(HttpStatus.CREATED, "REPORT_201", "대상을 성공적으로 신고했습니다."), // 제휴 성공 PAPER_STORE_HISTORY_SUCCESS(HttpStatus.OK, "PAPER201", "가게 별 제휴 내용이 성공적으로 조회되었습니다."),