Skip to content

Commit 7e11e83

Browse files
authored
Merge pull request #114 from P-ProjectGC/Feat/#57/신고사항관리
Feat/#57/신고사항관리
2 parents 35d01aa + 17b4ecc commit 7e11e83

17 files changed

Lines changed: 316 additions & 1 deletion
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package plango.admin.application.dto.request;
2+
3+
import lombok.Builder;
4+
5+
public record AdminReportUpdateStatusRequest(
6+
String status, // "WAITING" / "PROCESSING" / "COMPLETED"
7+
String adminMemo
8+
) {
9+
10+
@Builder
11+
public AdminReportUpdateStatusRequest {
12+
}
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package plango.admin.application.dto.response;
2+
3+
import lombok.Builder;
4+
import java.time.LocalDateTime;
5+
6+
public record AdminReportDetailResponse(
7+
Long reportId,
8+
Long memberId,
9+
String memberLoginId,
10+
String memberNickname,
11+
String content,
12+
String status,
13+
String adminMemo,
14+
LocalDateTime createdAt,
15+
LocalDateTime updatedAt
16+
) {
17+
18+
@Builder
19+
public AdminReportDetailResponse {
20+
}
21+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package plango.admin.application.dto.response;
2+
3+
import lombok.Builder;
4+
import java.time.LocalDateTime;
5+
6+
public record AdminReportSummaryResponse(
7+
Long reportId,
8+
Long memberId,
9+
String memberNickname,
10+
String status,
11+
LocalDateTime createdAt
12+
) {
13+
14+
@Builder
15+
public AdminReportSummaryResponse {
16+
}
17+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package plango.admin.application.mapper;
2+
3+
import java.util.List;
4+
import plango.admin.application.dto.response.AdminReportDetailResponse;
5+
import plango.admin.application.dto.response.AdminReportSummaryResponse;
6+
import plango.report.domain.entity.InconvenienceReport;
7+
8+
public class AdminReportMapper {
9+
10+
private AdminReportMapper() {
11+
}
12+
13+
public static AdminReportSummaryResponse toSummary(InconvenienceReport report) {
14+
return AdminReportSummaryResponse.builder()
15+
.reportId(report.getId())
16+
.memberId(report.getMember().getId())
17+
.memberNickname(report.getMember().getNickname())
18+
.status(report.getStatus().name())
19+
.createdAt(report.getCreatedAt())
20+
.build();
21+
}
22+
23+
public static List<AdminReportSummaryResponse> toSummaries(
24+
List<InconvenienceReport> reports
25+
) {
26+
return reports.stream()
27+
.map(AdminReportMapper::toSummary)
28+
.toList();
29+
}
30+
31+
public static AdminReportDetailResponse toDetail(InconvenienceReport report) {
32+
return AdminReportDetailResponse.builder()
33+
.reportId(report.getId())
34+
.memberId(report.getMember().getId())
35+
.memberLoginId(report.getMember().getLoginId())
36+
.memberNickname(report.getMember().getNickname())
37+
.content(report.getContent())
38+
.status(report.getStatus().name())
39+
.adminMemo(report.getAdminMemo())
40+
.createdAt(report.getCreatedAt())
41+
.updatedAt(report.getUpdatedAt())
42+
.build();
43+
}
44+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package plango.admin.application.usecase;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Service;
5+
import plango.admin.application.dto.response.AdminReportDetailResponse;
6+
import plango.admin.application.mapper.AdminReportMapper;
7+
import plango.report.domain.service.InconvenienceReportService;
8+
9+
@Service
10+
@RequiredArgsConstructor
11+
public class AdminGetReportDetailUseCase {
12+
13+
private final InconvenienceReportService reportService;
14+
15+
public AdminReportDetailResponse execute(Long reportId) {
16+
return AdminReportMapper.toDetail(reportService.getById(reportId));
17+
}
18+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package plango.admin.application.usecase;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Service;
5+
import plango.admin.application.dto.response.AdminReportSummaryResponse;
6+
import plango.admin.application.mapper.AdminReportMapper;
7+
import plango.report.domain.entity.InconvenienceReport;
8+
import plango.report.domain.service.InconvenienceReportService;
9+
10+
import java.util.List;
11+
12+
@Service
13+
@RequiredArgsConstructor
14+
public class AdminGetReportListUseCase {
15+
16+
private final InconvenienceReportService reportService;
17+
18+
public List<AdminReportSummaryResponse> execute() {
19+
List<InconvenienceReport> reports = reportService.getAllOrdered();
20+
return AdminReportMapper.toSummaries(reports);
21+
}
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package plango.admin.application.usecase;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Service;
5+
import org.springframework.transaction.annotation.Transactional;
6+
import plango.admin.application.dto.request.AdminReportUpdateStatusRequest;
7+
import plango.report.domain.entity.InconvenienceReportStatus;
8+
import plango.report.domain.service.InconvenienceReportService;
9+
10+
@Service
11+
@RequiredArgsConstructor
12+
public class AdminUpdateReportStatusUseCase {
13+
14+
private final InconvenienceReportService reportService;
15+
16+
@Transactional
17+
public void execute(Long reportId, AdminReportUpdateStatusRequest request) {
18+
InconvenienceReportStatus status = InconvenienceReportStatus.valueOf(request.status());
19+
reportService.changeStatus(reportId, status, request.adminMemo());
20+
}
21+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package plango.admin.presentation;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.tags.Tag;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.web.bind.annotation.*;
7+
import plango.admin.application.dto.request.AdminReportUpdateStatusRequest;
8+
import plango.admin.application.dto.response.AdminReportDetailResponse;
9+
import plango.admin.application.dto.response.AdminReportSummaryResponse;
10+
import plango.admin.application.usecase.AdminGetReportDetailUseCase;
11+
import plango.admin.application.usecase.AdminGetReportListUseCase;
12+
import plango.admin.application.usecase.AdminUpdateReportStatusUseCase;
13+
import plango.global.common.response.CommonResponse;
14+
import plango.global.common.response.ResponseMessage;
15+
16+
import java.util.List;
17+
18+
@Tag(
19+
name = "관리자 신고관리",
20+
description = "사용자의 불편 신고 목록 조회/상세/상태 변경 API"
21+
)
22+
@RestController
23+
@RequiredArgsConstructor
24+
@RequestMapping("/api/admin/reports")
25+
public class AdminReportController {
26+
27+
private final AdminGetReportListUseCase adminGetReportListUseCase;
28+
29+
private final AdminGetReportDetailUseCase adminGetReportDetailUseCase;
30+
31+
private final AdminUpdateReportStatusUseCase adminUpdateReportStatusUseCase;
32+
33+
@Operation(
34+
summary = "신고 목록 조회",
35+
description = "대기/처리중/완료 상태를 포함하여 전체 신고 목록을 조회합니다."
36+
)
37+
@GetMapping
38+
public CommonResponse<List<AdminReportSummaryResponse>> getReports() {
39+
List<AdminReportSummaryResponse> responses = adminGetReportListUseCase.execute();
40+
41+
return CommonResponse.success(
42+
ResponseMessage.ADMIN_REPORT_LIST_GET_SUCCESS,
43+
responses
44+
);
45+
}
46+
47+
@Operation(
48+
summary = "신고 상세 조회",
49+
description = "신고 ID(reportId)를 기준으로 상세 정보를 조회합니다."
50+
)
51+
@GetMapping("/{reportId}")
52+
public CommonResponse<AdminReportDetailResponse> getReportDetail(
53+
@PathVariable Long reportId
54+
) {
55+
AdminReportDetailResponse response = adminGetReportDetailUseCase.execute(reportId);
56+
57+
return CommonResponse.success(
58+
ResponseMessage.ADMIN_REPORT_DETAIL_GET_SUCCESS,
59+
response
60+
);
61+
}
62+
63+
@Operation(
64+
summary = "신고 상태 변경",
65+
description = "신고의 상태(WAITING / PROCESSING / COMPLETED)와 관리자 메모를 수정합니다."
66+
)
67+
@PatchMapping("/{reportId}/status")
68+
public CommonResponse<Void> updateReportStatus(
69+
@PathVariable Long reportId,
70+
@RequestBody AdminReportUpdateStatusRequest request
71+
) {
72+
adminUpdateReportStatusUseCase.execute(reportId, request);
73+
74+
return CommonResponse.success(
75+
ResponseMessage.ADMIN_REPORT_STATUS_UPDATE_SUCCESS
76+
);
77+
}
78+
}

src/main/java/plango/global/common/exception/ErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ public enum ErrorCode {
2222
ROOM_HOST_ONLY(HttpStatus.FORBIDDEN, "방장만 수행할 수 있는 작업입니다."),
2323
ROOM_SCHEDULE_NOT_FOUND(HttpStatus.BAD_REQUEST, "일정을 찾을 수 없습니다."),
2424
ADMIN_NOT_FOUND(HttpStatus.BAD_REQUEST, "관리자를 찾을 수 없습니다."), // ← int 404
25-
INVALID_ADMIN_PASSWORD(HttpStatus.BAD_REQUEST, "관리자 비밀번호가 일치하지 않습니다."); // ← int 400
25+
INVALID_ADMIN_PASSWORD(HttpStatus.BAD_REQUEST, "관리자 비밀번호가 일치하지 않습니다."),
26+
REPORT_NOT_FOUND(HttpStatus.NOT_FOUND, "신고 내역을 찾을 수 없습니다.");
2627

2728
private final HttpStatus status;
2829
private final String message;

src/main/java/plango/global/common/response/ResponseMessage.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ public enum ResponseMessage {
7070
ADMIN_MEMBER_LIST_GET_SUCCESS(0,"관리자 회원 목록 조회 성공"),
7171
ADMIN_MEMBER_DETAIL_GET_SUCCESS(0,"관리자 회원 상세 조회 성공"),
7272
ADMIN_MEMBER_UPDATE_SUCCESS(0,"관리자 회원 정보 수정 성공"),
73+
ADMIN_REPORT_LIST_GET_SUCCESS(0,"관리자 신고 목록 조회 성공"),
74+
ADMIN_REPORT_DETAIL_GET_SUCCESS(0,"관리자 신고 상세 조회 성공"),
75+
ADMIN_REPORT_STATUS_UPDATE_SUCCESS(0,"관리자 신고 상태 변경 성공"),
7376

7477
AUTH_TOKEN_REISSUE_SUCCESS(0, "토큰 재발급 성공");
7578

0 commit comments

Comments
 (0)