-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 신고 기능 개발 #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat : 신고 기능 개발 #87
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @AllArgsConstructor | ||
| public class ReportChangeResponse { | ||
| private String message; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| public record ReportDetailResponse( | ||
| Long reportId, | ||
| String reporterEmail, | ||
| Long targetId, | ||
| String targetType, | ||
| String reportType, | ||
| String reportStatus, | ||
| String message, | ||
| String imageUrl, | ||
| String createdAt, | ||
| String modifiedAt | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| public record ReportListResponse( | ||
| Long reportId, | ||
| String reporterEmail, | ||
| Long targetId, | ||
| String targetType, | ||
| String reportType, | ||
| String reportStatus, | ||
| String message, | ||
| String createdAt | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
|
|
||
| public record ReportRequest( | ||
| @NotNull | ||
| Long targetId, | ||
|
|
||
| @NotBlank | ||
| String targetType, | ||
|
|
||
| @NotBlank | ||
| String reportType, | ||
|
|
||
| @NotBlank | ||
| String message, | ||
|
|
||
| String imageUrl | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| @Schema(name = "ReportResponse", description = "신고 DTO") | ||
| public record ReportResponse( | ||
| Long reportId, | ||
| String status, | ||
| String type, | ||
| String message, | ||
| String imageUrl | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package org.ezcode.codetest.application.report.dto; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import org.ezcode.codetest.domain.report.model.ReportStatus; | ||
|
|
||
| public record ReportStatusUpdateRequest( | ||
| @NotBlank | ||
| String newStatus // 예시 RESOLVED(해결됨), REJECTED(거절) | ||
| ) { | ||
| public ReportStatus toEnum() { | ||
| return ReportStatus.from(newStatus); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| package org.ezcode.codetest.application.report.port; | ||
|
|
||
|
|
||
| public interface ReportRepository { | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,97 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package org.ezcode.codetest.application.report.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.ezcode.codetest.application.report.dto.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.ezcode.codetest.domain.report.model.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.ezcode.codetest.domain.report.repository.ReportRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.ezcode.codetest.domain.user.model.entity.User; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.ezcode.codetest.domain.user.repository.UserRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.domain.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class ReportService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final UserRepository userRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ReportRepository reportRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //신규 신고 생성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public ReportResponse submitReport(Long reporterId, ReportRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| User reporter = userRepository.findUserById(reporterId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new IllegalArgumentException("신고자 없음")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ReportType reportType = ReportType.from(request.reportType()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enum 변환 시 예외 처리 추가 필요 문자열을 Enum으로 변환할 때 다음과 같이 예외 처리를 추가하세요: - ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
- ReportType reportType = ReportType.from(request.reportType());
+ ReportTargetType targetType;
+ ReportType reportType;
+
+ try {
+ targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
+ reportType = ReportType.from(request.reportType());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("유효하지 않은 신고 타입입니다: " + e.getMessage());
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 🧩 Verification correct비즈니스 로직 검증 개선 제안 자기 자신 신고 방지 로직이 있지만, AI 요약에 따르면
🏁 Script executed: #!/bin/bash
# ReportDomainService 클래스 존재 확인 및 검증 로직 조회
fd "ReportDomainService" --type f --exec cat {}Length of output: 642 비즈니스 로직 검증 개선 제안 자기 자신 신고 방지 로직이 있지만, AI 요약에 따르면
#!/bin/bash
# ReportDomainService 클래스 존재 확인 및 검증 로직 조회
fd "ReportDomainService" --type f --exec cat {}🤖 Prompt for AI Agents
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enum 변환과 검증 로직을 개선해야 합니다. Enum 변환에서 발생할 수 있는 예외 처리가 없고, 자기 자신 신고 방지 로직이 도메인 서비스에 있다고 명시되어 있지만 여기에 중복 구현되어 있습니다. +import org.ezcode.codetest.domain.report.service.ReportDomainService;
@Service
@RequiredArgsConstructor
public class ReportService {
private final UserRepository userRepository;
private final ReportRepository reportRepository;
+ private final ReportDomainService reportDomainService;
@Transactional
public ReportResponse submitReport(Long reporterId, ReportRequest request) {
User reporter = userRepository.findUserById(reporterId)
.orElseThrow(() -> new IllegalArgumentException("신고자를 찾을 수 없습니다."));
- ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
- ReportType reportType = ReportType.from(request.reportType());
-
- if (targetType == ReportTargetType.USER && reporterId.equals(request.targetId())) {
- throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다.");
- }
+ ReportTargetType targetType;
+ ReportType reportType;
+
+ try {
+ targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
+ reportType = ReportType.from(request.reportType());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("잘못된 신고 타입입니다.");
+ }
+
+ reportDomainService.validateReportSubmission(reporterId, request.targetId(), targetType);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents🛠️ Refactor suggestion Enum 변환 시 예외 처리를 개선해야 합니다.
- ReportTargetType targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
- ReportType reportType = ReportType.from(request.reportType());
+ ReportTargetType targetType;
+ ReportType reportType;
+
+ try {
+ targetType = ReportTargetType.valueOf(request.targetType().toUpperCase());
+ reportType = ReportType.from(request.reportType());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("유효하지 않은 신고 타입입니다: " + e.getMessage());
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Report report = new Report(reporter, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.targetId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.message(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.imageUrl(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reportType); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reportRepository.save(report); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new ReportResponse( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.getId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.getReportStatus().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.getReportType().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.getMessage(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.getImageUrl() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //신고 목록 페이징 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Page<ReportListResponse> getReportList(Pageable pageable) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return reportRepository.findAll(pageable) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(r -> new ReportListResponse( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReporter().getEmail(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getTargetId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getTargetType().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReportType().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReportStatus().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getMessage(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getCreatedAt().toString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 날짜 형식을 명시적으로 지정하세요.
- r.getCreatedAt().toString()
+ r.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))클래스 상단에 다음 import를 추가해야 합니다: import java.time.format.DateTimeFormatter;🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+54
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Null 안전성과 데이터 포맷팅을 개선해야 합니다. Reporter 이메일에 대한 null 체크가 없고, 날짜를 문자열로 변환할 때 적절한 포맷팅이 필요합니다. +import java.time.format.DateTimeFormatter;
+
+ private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Transactional(readOnly = true)
public Page<ReportListResponse> getReportList(Pageable pageable) {
return reportRepository.findAll(pageable)
.map(r -> new ReportListResponse(
r.getId(),
- r.getReporter().getEmail(),
+ r.getReporter() != null ? r.getReporter().getEmail() : "알 수 없음",
r.getTargetId(),
r.getTargetType().name(),
r.getReportType().name(),
r.getReportStatus().name(),
r.getMessage(),
- r.getCreatedAt().toString()
+ r.getCreatedAt().format(DATE_FORMATTER)
));
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //신고 상세 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public ReportDetailResponse getReportDetail(Long reportId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Report r = reportRepository.findById(reportId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new IllegalArgumentException("신고가 존재하지 않습니다.")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new ReportDetailResponse( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReporter().getEmail(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getTargetId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getTargetType().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReportType().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getReportStatus().name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getMessage(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getImageUrl(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getCreatedAt().toString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r.getModifiedAt().toString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+83
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 날짜 형식 통일성을 위해 DateTimeFormatter 사용을 권장합니다. 앞서 언급한 것과 동일한 이슈입니다. 일관된 날짜 형식을 위해 포맷터를 사용하세요. - r.getCreatedAt().toString(),
- r.getModifiedAt().toString()
+ r.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
+ r.getModifiedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+69
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 일관된 에러 메시지와 null 안전성을 적용해야 합니다. 에러 메시지를 일관되게 유지하고, null 안전성을 보장해야 합니다. @Transactional(readOnly = true)
public ReportDetailResponse getReportDetail(Long reportId) {
Report r = reportRepository.findById(reportId)
- .orElseThrow(() -> new IllegalArgumentException("신고가 존재하지 않습니다."));
+ .orElseThrow(() -> new IllegalArgumentException("신고를 찾을 수 없습니다."));
return new ReportDetailResponse(
r.getId(),
- r.getReporter().getEmail(),
+ r.getReporter() != null ? r.getReporter().getEmail() : "알 수 없음",
r.getTargetId(),
r.getTargetType().name(),
r.getReportType().name(),
r.getReportStatus().name(),
r.getMessage(),
r.getImageUrl(),
- r.getCreatedAt().toString(),
- r.getModifiedAt().toString()
+ r.getCreatedAt().format(DATE_FORMATTER),
+ r.getModifiedAt() != null ? r.getModifiedAt().format(DATE_FORMATTER) : null
);
}
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //신고 상태 변경 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void updateReportStatus(Long reportId, ReportStatusUpdateRequest req) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Report report = reportRepository.findById(reportId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .orElseThrow(() -> new IllegalArgumentException("신고가 존재하지 않습니다.")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ReportStatus newStatus = req.toEnum(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| report.updateStatus(newStatus); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,59 +1,58 @@ | ||
| package org.ezcode.codetest.domain.report.model; | ||
|
|
||
| import jakarta.persistence.*; | ||
| import org.ezcode.codetest.common.base.entity.BaseEntity; | ||
| import org.ezcode.codetest.domain.user.model.entity.User; | ||
|
|
||
| import jakarta.persistence.Column; | ||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.EnumType; | ||
| import jakarta.persistence.Enumerated; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.JoinColumn; | ||
| import jakarta.persistence.Table; | ||
| import lombok.AccessLevel; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import jakarta.persistence.ManyToOne; | ||
|
|
||
| @Getter | ||
| @Entity | ||
| @Table(name = "report") | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @Getter | ||
| public class Report extends BaseEntity { | ||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
|
|
||
| @Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @ManyToOne | ||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "reporter_id", nullable = false) | ||
| private User reporter; | ||
|
|
||
| @ManyToOne | ||
| @JoinColumn(name = "target_id", nullable = false) | ||
| private User target; | ||
| @Column(nullable = false) | ||
| private Long targetId; | ||
|
|
||
| @Column(nullable = false, length = 50) | ||
| @Enumerated(EnumType.STRING) | ||
| private ReportTargetType targetType; | ||
| @Column(nullable = false) | ||
| private String message; | ||
|
|
||
| @Column(nullable = false) | ||
| private String imageUrl; | ||
|
|
||
| @Enumerated(EnumType.STRING) | ||
| @Column(nullable = false) | ||
| @Column(nullable = false, length = 50) | ||
| private ReportType reportType; | ||
|
|
||
| @Column(nullable = false, length = 50) | ||
| @Enumerated(EnumType.STRING) | ||
| private ReportStatus reportStatus; | ||
|
|
||
| public Report(User reporter, User target, String message, String imageUrl, | ||
| ReportType reportType) { | ||
| public Report(User reporter, Long targetId, ReportTargetType targetType, | ||
| String message, String imageUrl, ReportType reportType) { | ||
| this.reporter = reporter; | ||
| this.target = target; | ||
| this.targetId = targetId; | ||
| this.targetType = targetType; | ||
| this.message = message; | ||
| this.imageUrl = imageUrl; | ||
| this.reportType = reportType; | ||
| this.reportStatus = ReportStatus.PENDING; | ||
| } | ||
|
|
||
| public void updateStatus(ReportStatus newStatus) { | ||
| this.reportStatus = newStatus; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package org.ezcode.codetest.domain.report.model; | ||
|
|
||
| public enum ReportTargetType { | ||
| USER, | ||
| PROBLEM, | ||
| POST, | ||
| COMMENT, | ||
| OTHER | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package org.ezcode.codetest.domain.report.repository; | ||
|
|
||
| import org.ezcode.codetest.domain.report.model.Report; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| public interface ReportRepository extends JpaRepository<Report, Long> { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,17 @@ | ||
| package org.ezcode.codetest.domain.report.service; | ||
|
|
||
| public class ReportDomainService { | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.ezcode.codetest.domain.report.model.ReportTargetType; | ||
| import org.ezcode.codetest.domain.user.model.entity.User; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class ReportDomainService{ | ||
|
|
||
| public void validate(User reporter, Long targetId, ReportTargetType targetType) { | ||
| if (targetType == ReportTargetType.USER && reporter.getId().equals(targetId)) { | ||
| throw new IllegalArgumentException("자기 자신은 신고할 수 없습니다."); | ||
| } | ||
| } | ||
| } |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
포트 인터페이스 구현 누락
application.report.port.ReportRepository는 서비스 레이어에서 의존할 포트 정의로 보이나, 메서드 시그니처가 없고 이를 구현한 인프라스트럭처 어댑터도 존재하지 않습니다. 이대로면 의존성 주입 시 빈 충돌 또는 NoSuchBeanDefinitionException이 발생할 수 있습니다.🤖 Prompt for AI Agents