Skip to content

Commit c82a7f5

Browse files
authored
feat: �community CRUD 엔드포인트 생성 (#133)
* test(community): community 게시글, 댓글 controller test 추가 * feat(community): community 게시글, 댓글 controller 추가 * feat(community): community-comment boardId request 필드 -> Pathvariable * feat(community): community-comment 상세 조회 responseDto builder 추가 * refactor(community): sonar 반영 - 불필요한 import 제거 - 엔드포인트 snake -> camel * refactor(community): community 댓글 생성, 수정 requestDto @RequestPart("data") -> @RequestBody * refactor(community): community 게시글 조회 컨트롤러 @currentuser 삭제
1 parent 4b3335b commit c82a7f5

20 files changed

+728
-39
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.somemore.community.controller;
2+
3+
import com.somemore.auth.annotation.CurrentUser;
4+
import com.somemore.community.dto.request.CommunityBoardCreateRequestDto;
5+
import com.somemore.community.dto.request.CommunityBoardUpdateRequestDto;
6+
import com.somemore.community.usecase.board.CreateCommunityBoardUseCase;
7+
import com.somemore.community.usecase.board.DeleteCommunityBoardUseCase;
8+
import com.somemore.community.usecase.board.UpdateCommunityBoardUseCase;
9+
import com.somemore.global.common.response.ApiResponse;
10+
import com.somemore.imageupload.dto.ImageUploadRequestDto;
11+
import com.somemore.imageupload.usecase.ImageUploadUseCase;
12+
import io.swagger.v3.oas.annotations.Operation;
13+
import io.swagger.v3.oas.annotations.tags.Tag;
14+
import jakarta.validation.Valid;
15+
import lombok.RequiredArgsConstructor;
16+
import org.springframework.security.access.annotation.Secured;
17+
import org.springframework.web.bind.annotation.*;
18+
import org.springframework.web.multipart.MultipartFile;
19+
20+
import java.util.UUID;
21+
22+
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
23+
24+
@Tag(name = "Community Board Command API", description = "커뮤니티 게시글 생성 수정 삭제 API")
25+
@RequiredArgsConstructor
26+
@RequestMapping("/api/community-board")
27+
@RestController
28+
public class CommunityBoardCommandApiController {
29+
30+
private final CreateCommunityBoardUseCase createCommunityBoardUseCase;
31+
private final UpdateCommunityBoardUseCase updateCommunityBoardUseCase;
32+
private final DeleteCommunityBoardUseCase deleteCommunityBoardUseCase;
33+
private final ImageUploadUseCase imageUploadUseCase;
34+
35+
@Secured("ROLE_VOLUNTEER")
36+
@Operation(summary = "커뮤니티 게시글 등록", description = "커뮤니티 게시글을 등록합니다.")
37+
@PostMapping(consumes = MULTIPART_FORM_DATA_VALUE)
38+
public ApiResponse<Long> createCommunityBoard(
39+
@CurrentUser UUID userId,
40+
@Valid @RequestPart("data") CommunityBoardCreateRequestDto requestDto,
41+
@RequestPart(value = "img_file", required = false) MultipartFile image
42+
) {
43+
String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image));
44+
45+
return ApiResponse.ok(
46+
201,
47+
createCommunityBoardUseCase.createCommunityBoard(requestDto, userId, imgUrl),
48+
"커뮤니티 게시글 등록 성공"
49+
);
50+
}
51+
52+
@Secured("ROLE_VOLUNTEER")
53+
@Operation(summary = "커뮤니티 게시글 수정", description = "커뮤니티 게시글을 수정합니다.")
54+
@PutMapping(value = "/{id}", consumes = MULTIPART_FORM_DATA_VALUE)
55+
public ApiResponse<String> updateCommunityBoard(
56+
@CurrentUser UUID userId,
57+
@PathVariable Long id,
58+
@Valid @RequestPart("data") CommunityBoardUpdateRequestDto requestDto,
59+
@RequestPart(value = "img_file", required = false) MultipartFile image
60+
) {
61+
String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image));
62+
updateCommunityBoardUseCase.updateCommunityBoard(requestDto, id, userId, imgUrl);
63+
64+
return ApiResponse.ok("커뮤니티 게시글 수정 성공");
65+
}
66+
67+
@Secured("ROLE_VOLUNTEER")
68+
@Operation(summary = "커뮤니티 게시글 삭제", description = "커뮤니티 게시글을 삭제합니다.")
69+
@DeleteMapping(value = "/{id}")
70+
public ApiResponse<String> deleteCommunityBoard(
71+
@CurrentUser UUID userId,
72+
@PathVariable Long id
73+
) {
74+
deleteCommunityBoardUseCase.deleteCommunityBoard(userId, id);
75+
76+
return ApiResponse.ok("커뮤니티 게시글 삭제 성공");
77+
}
78+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.somemore.community.controller;
2+
3+
import com.somemore.community.dto.response.CommunityBoardDetailResponseDto;
4+
import com.somemore.community.dto.response.CommunityBoardResponseDto;
5+
import com.somemore.community.usecase.board.CommunityBoardQueryUseCase;
6+
import com.somemore.global.common.response.ApiResponse;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.data.domain.Page;
11+
import org.springframework.data.domain.Pageable;
12+
import org.springframework.web.bind.annotation.*;
13+
14+
import java.util.UUID;
15+
16+
@Tag(name = "Community Board Query API", description = "커뮤니티 게시글 조회 관련 API")
17+
@RequiredArgsConstructor
18+
@RequestMapping("/api")
19+
@RestController
20+
public class CommunityBoardQueryApiController {
21+
22+
private final CommunityBoardQueryUseCase communityBoardQueryUseCase;
23+
24+
@GetMapping("/community-boards")
25+
@Operation(summary = "전체 커뮤니티 게시글 조회", description = "전체 커뮤니티 게시글 목록을 조회합니다.")
26+
public ApiResponse<Page<CommunityBoardResponseDto>> getAll(
27+
Pageable pageable
28+
) {
29+
return ApiResponse.ok(
30+
200,
31+
communityBoardQueryUseCase.getCommunityBoards(pageable.getPageNumber()),
32+
"전체 커뮤니티 게시글 리스트 조회 성공"
33+
);
34+
}
35+
36+
@GetMapping("/community-boards/{writerId}")
37+
@Operation(summary = "작성자별 커뮤니티 게시글 조회", description = "작성자별 커뮤니티 게시글 목록을 조회합니다.")
38+
public ApiResponse<Page<CommunityBoardResponseDto>> getByWriterId(
39+
@PathVariable UUID writerId,
40+
Pageable pageable
41+
) {
42+
return ApiResponse.ok(
43+
200,
44+
communityBoardQueryUseCase.getCommunityBoardsByWriterId(writerId, pageable.getPageNumber()),
45+
"작성자별 커뮤니티 게시글 리스트 조회 성공"
46+
);
47+
}
48+
49+
@GetMapping("/community-board/{id}")
50+
@Operation(summary = "커뮤니티 게시글 상세 조회", description = "커뮤니티 게시글의 상세 정보를 조회합니다.")
51+
public ApiResponse<CommunityBoardDetailResponseDto> getById(
52+
@PathVariable Long id
53+
) {
54+
return ApiResponse.ok(
55+
200,
56+
communityBoardQueryUseCase.getCommunityBoardDetail(id),
57+
"커뮤니티 게시글 상세 조회 성공"
58+
);
59+
}
60+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.somemore.community.controller;
2+
3+
import com.somemore.auth.annotation.CurrentUser;
4+
import com.somemore.community.dto.request.CommunityCommentCreateRequestDto;
5+
import com.somemore.community.dto.request.CommunityCommentUpdateRequestDto;
6+
import com.somemore.community.usecase.comment.CreateCommunityCommentUseCase;
7+
import com.somemore.community.usecase.comment.DeleteCommunityCommentUseCase;
8+
import com.somemore.community.usecase.comment.UpdateCommunityCommentUseCase;
9+
import com.somemore.global.common.response.ApiResponse;
10+
import io.swagger.v3.oas.annotations.Operation;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import jakarta.validation.Valid;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.security.access.annotation.Secured;
15+
import org.springframework.web.bind.annotation.*;
16+
17+
import java.util.UUID;
18+
19+
@Tag(name = "Community Comment Command API", description = "커뮤니티 댓글 생성 수정 삭제 API")
20+
@RequiredArgsConstructor
21+
@RequestMapping("/api/community-board/{boardId}")
22+
@RestController
23+
public class CommunityCommentCommandApiController {
24+
25+
private final CreateCommunityCommentUseCase createCommunityCommentUseCase;
26+
private final UpdateCommunityCommentUseCase updateCommunityCommentUseCase;
27+
private final DeleteCommunityCommentUseCase deleteCommunityCommentUseCase;
28+
29+
@Secured("ROLE_VOLUNTEER")
30+
@Operation(summary = "커뮤니티 댓글 등록", description = "커뮤니티 게시글에 댓글을 등록합니다.")
31+
@PostMapping(value = "/comment")
32+
public ApiResponse<Long> createCommunityComment(
33+
@CurrentUser UUID userId,
34+
@PathVariable Long boardId,
35+
@Valid @RequestBody CommunityCommentCreateRequestDto requestDto) {
36+
37+
return ApiResponse.ok(
38+
201,
39+
createCommunityCommentUseCase.createCommunityComment(requestDto, userId, boardId),
40+
"커뮤니티 댓글 등록 성공");
41+
}
42+
43+
@Secured("ROLE_VOLUNTEER")
44+
@Operation(summary = "커뮤니티 댓글 수정", description = "커뮤니티 댓글을 수정합니다.")
45+
@PutMapping(value = "/comment/{id}")
46+
public ApiResponse<String> updateCommunityComment(
47+
@CurrentUser UUID userId,
48+
@PathVariable Long boardId,
49+
@PathVariable Long id,
50+
@Valid @RequestBody CommunityCommentUpdateRequestDto requestDto
51+
) {
52+
updateCommunityCommentUseCase.updateCommunityComment(requestDto, id, userId, boardId);
53+
54+
return ApiResponse.ok("커뮤니티 댓글 수정 성공");
55+
}
56+
57+
@Secured("ROLE_VOLUNTEER")
58+
@Operation(summary = "커뮤니티 댓글 삭제", description = "커뮤니티 댓글을 삭제합니다.")
59+
@DeleteMapping(value = "/comment/{id}")
60+
public ApiResponse<String> deleteCommunityComment(
61+
@CurrentUser UUID userId,
62+
@PathVariable Long boardId,
63+
@PathVariable Long id
64+
) {
65+
deleteCommunityCommentUseCase.deleteCommunityComment(userId, id, boardId);
66+
67+
return ApiResponse.ok("커뮤니티 댓글 삭제 성공");
68+
}
69+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.somemore.community.controller;
2+
3+
import com.somemore.community.dto.response.CommunityCommentResponseDto;
4+
import com.somemore.community.usecase.comment.CommunityCommentQueryUseCase;
5+
import com.somemore.global.common.response.ApiResponse;
6+
import io.swagger.v3.oas.annotations.Operation;
7+
import io.swagger.v3.oas.annotations.tags.Tag;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.data.domain.Page;
10+
import org.springframework.data.domain.Pageable;
11+
import org.springframework.web.bind.annotation.GetMapping;
12+
import org.springframework.web.bind.annotation.PathVariable;
13+
import org.springframework.web.bind.annotation.RequestMapping;
14+
import org.springframework.web.bind.annotation.RestController;
15+
16+
@Tag(name = "Community Comment Query API", description = "커뮤니티 댓글 조회 API")
17+
@RequiredArgsConstructor
18+
@RequestMapping("/api/community-board")
19+
@RestController
20+
public class CommunityCommentQueryApiController {
21+
22+
private final CommunityCommentQueryUseCase communityCommentQueryUseCase;
23+
24+
@GetMapping("/{boardId}/comments")
25+
@Operation(summary = "커뮤니티 댓글 조회", description = "커뮤니티 게시글의 댓글 목록을 조회합니다.")
26+
public ApiResponse<Page<CommunityCommentResponseDto>> getByBoardId(
27+
@PathVariable Long boardId,
28+
Pageable pageable
29+
) {
30+
return ApiResponse.ok(
31+
200,
32+
communityCommentQueryUseCase.getCommunityCommentsByBoardId(boardId, pageable.getPageNumber()),
33+
"커뮤니티 게시글의 댓글 리스트 조회 성공"
34+
);
35+
}
36+
}

src/main/java/com/somemore/community/dto/request/CommunityCommentCreateRequestDto.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,21 @@
66
import io.swagger.v3.oas.annotations.media.Schema;
77
import jakarta.annotation.Nullable;
88
import jakarta.validation.constraints.NotBlank;
9-
import jakarta.validation.constraints.NotNull;
109
import lombok.Builder;
1110

1211
import java.util.UUID;
1312

1413
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
1514
@Builder
1615
public record CommunityCommentCreateRequestDto(
17-
@Schema(description = "커뮤니티 게시글 ID", example = "33")
18-
@NotNull(message = "게시글 ID는 필수 값입니다.")
19-
Long communityBoardId,
2016
@Schema(description = "커뮤니티 댓글 내용", example = "저도 함께 하고 싶습니다.")
2117
@NotBlank(message = "댓글 내용은 필수 값입니다.")
2218
String content,
2319
@Schema(description = "부모 댓글 ID", example = "1234", nullable = true)
2420
@Nullable
2521
Long parentCommentId
2622
) {
27-
public CommunityComment toEntity(UUID writerId) {
23+
public CommunityComment toEntity(UUID writerId, Long communityBoardId) {
2824
return CommunityComment.builder()
2925
.communityBoardId(communityBoardId)
3026
.writerId(writerId)

src/main/java/com/somemore/community/dto/response/CommunityBoardDetailResponseDto.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import com.fasterxml.jackson.databind.annotation.JsonNaming;
55
import com.somemore.community.domain.CommunityBoard;
66
import io.swagger.v3.oas.annotations.media.Schema;
7+
import lombok.Builder;
78

89
import java.time.LocalDateTime;
910
import java.util.UUID;
1011

12+
@Builder
1113
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
1214
@Schema(description = "커뮤니티 게시글 상세 조회 응답 DTO")
1315
public record CommunityBoardDetailResponseDto(

src/main/java/com/somemore/community/service/comment/CreateCommunityCommentService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ public class CreateCommunityCommentService implements CreateCommunityCommentUseC
2424
private final CommunityCommentRepository communityCommentRepository;
2525

2626
@Override
27-
public Long createCommunityComment(CommunityCommentCreateRequestDto requestDto, UUID writerId) {
28-
CommunityComment communityComment = requestDto.toEntity(writerId);
27+
public Long createCommunityComment(CommunityCommentCreateRequestDto requestDto, UUID writerId, Long communityBoardId) {
28+
CommunityComment communityComment = requestDto.toEntity(writerId, communityBoardId);
2929

30-
validateCommunityBoardExists(communityComment.getCommunityBoardId());
30+
validateCommunityBoardExists(communityBoardId);
3131

3232
if (requestDto.parentCommentId() != null) {
3333
validateParentCommentExists(communityComment.getParentCommentId());

src/main/java/com/somemore/community/service/comment/DeleteCommunityCommentService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class DeleteCommunityCommentService implements DeleteCommunityCommentUseC
2020
private final CommunityCommentRepository communityCommentRepository;
2121

2222
@Override
23-
public void deleteCommunityComment(UUID writerId, Long id) {
23+
public void deleteCommunityComment(UUID writerId, Long id, Long communityBoardId) {
2424

2525
CommunityComment communityComment = getCommunityCommentById(id);
2626

src/main/java/com/somemore/community/service/comment/UpdateCommunityCommentService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ public class UpdateCommunityCommentService implements UpdateCommunityCommentUseC
2323
private final CommunityBoardRepository communityBoardRepository;
2424

2525
@Override
26-
public void updateCommunityComment(CommunityCommentUpdateRequestDto requestDto, Long communityCommentId, UUID writerId) {
26+
public void updateCommunityComment(CommunityCommentUpdateRequestDto requestDto, Long communityCommentId, UUID writerId, Long communityBoardId) {
2727

2828
CommunityComment communityComment = getCommunityCommentById(communityCommentId);
2929

30-
validateCommunityBoardExists(communityComment.getCommunityBoardId());
30+
validateCommunityBoardExists(communityBoardId);
3131

3232
validateWriter(communityComment, writerId);
3333

src/main/java/com/somemore/community/usecase/comment/CreateCommunityCommentUseCase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
public interface CreateCommunityCommentUseCase {
88
Long createCommunityComment(
99
CommunityCommentCreateRequestDto requestDto,
10-
UUID writerId);
10+
UUID writerId,
11+
Long communityBoardId);
1112
}

0 commit comments

Comments
 (0)