Skip to content

Commit

Permalink
Merge pull request #20 from Alpha-mon/14-feat-board-and-comment
Browse files Browse the repository at this point in the history
14 feat board and comment
  • Loading branch information
megymj committed Oct 7, 2023
2 parents 201308f + 02e5488 commit c46e638
Show file tree
Hide file tree
Showing 42 changed files with 1,456 additions and 155 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.ai.roboadvisor.domain.community.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ai.roboadvisor.domain.community.dto.response.BoardResponse;
import org.ai.roboadvisor.domain.community.service.BoardService;
import org.ai.roboadvisor.domain.community.swagger_annotation.board.getAllPostsByType.*;
import org.ai.roboadvisor.domain.tendency.entity.Tendency;
import org.ai.roboadvisor.global.common.dto.SuccessApiResponse;
import org.ai.roboadvisor.global.exception.SuccessCode;
import org.ai.roboadvisor.global.swagger_annotation.ApiResponse_Internal_Server_Error;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Tag(name = "community] board", description = "게시글 전체 불러오기 API")
@RestController
@RequestMapping("/api/community/board")
public class BoardController {

private final BoardService boardService;

private final int PAGE_SIZE = 10;

@Operation(summary = "게시글 전체 조회", description = "게시글 전체 불러오기 API")
@getAllPostsByType_OK
@getAllPostsByType_BAD_REQUEST
@ApiResponse_Internal_Server_Error
@GetMapping()
public ResponseEntity<SuccessApiResponse<List<BoardResponse>>> getAllPostsByType(
@RequestParam("tendency") Tendency tendency, @PageableDefault(size = PAGE_SIZE, sort = {"id"},
direction = Sort.Direction.ASC) Pageable pageable) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.BOARD_ALL_VIEW_SUCCESS,
boardService.getAllPostsByType(tendency, pageable)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.ai.roboadvisor.domain.community.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ai.roboadvisor.domain.community.dto.request.CommentDeleteRequest;
import org.ai.roboadvisor.domain.community.dto.request.CommentRequest;
import org.ai.roboadvisor.domain.community.dto.request.CommentUpdateRequest;
import org.ai.roboadvisor.domain.community.dto.response.CommentResponse;
import org.ai.roboadvisor.domain.community.service.CommentService;
import org.ai.roboadvisor.domain.community.swagger_annotation.comment.delete.*;
import org.ai.roboadvisor.domain.community.swagger_annotation.comment.save.*;
import org.ai.roboadvisor.domain.community.swagger_annotation.comment.update.*;
import org.ai.roboadvisor.global.common.dto.SuccessApiResponse;
import org.ai.roboadvisor.global.exception.SuccessCode;
import org.ai.roboadvisor.global.swagger_annotation.ApiResponse_Internal_Server_Error;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RequiredArgsConstructor
@Tag(name = "community] comment", description = "댓글 작성, 수정, 삭제 API")
@RestController
@RequestMapping("/api/community/comment")
public class CommentController {

private final CommentService commentService;

@Operation(summary = "댓글 작성", description = "댓글 작성 API")
@save_CREATED
@save_BAD_REQUEST
@save_UNAUTHORIZED
@ApiResponse_Internal_Server_Error
@PostMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<CommentResponse>> save(@PathVariable("postId") Long postId,
@RequestBody CommentRequest commentRequest) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(SuccessApiResponse.success(SuccessCode.COMMENT_CREATED_SUCCESS,
commentService.save(postId, commentRequest)));
}

@Operation(summary = "댓글 수정", description = "댓글 수정 API")
@update_OK
@update_BAD_REQUEST
@update_UNAUTHORIZED
@ApiResponse_Internal_Server_Error
@PutMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<CommentResponse>> update(@PathVariable("postId") Long postId,
@RequestBody CommentUpdateRequest commentUpdateRequest) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.COMMENT_UPDATE_SUCCESS,
commentService.update(postId, commentUpdateRequest)));
}

@Operation(summary = "댓글 삭제", description = "댓글 삭제 API")
@delete_OK
@delete_BAD_REQUEST
@delete_UNAUTHORIZED
@ApiResponse_Internal_Server_Error
@DeleteMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<CommentResponse>> delete(@PathVariable("postId") Long postId,
@RequestBody CommentDeleteRequest commentDeleteRequest) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.COMMENT_DELETE_SUCCESS,
commentService.delete(postId, commentDeleteRequest)));
}
}
Original file line number Diff line number Diff line change
@@ -1,73 +1,40 @@
package org.ai.roboadvisor.domain.community.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ai.roboadvisor.domain.community.dto.request.PostDeleteRequest;
import org.ai.roboadvisor.domain.community.dto.request.PostRequest;
import org.ai.roboadvisor.domain.community.dto.response.PostResponse;
import org.ai.roboadvisor.domain.community.service.PostService;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.delete.delete_OK;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.delete.delete_UNAUTHORIZED;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.getPostById.getPostById_BAD_REQUEST;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.getPostById.getPostById_OK;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.save.save_BAD_REQUEST;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.save.save_CREATED;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.update.update_BAD_REQUEST;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.update.update_OK;
import org.ai.roboadvisor.domain.community.swagger_annotation.post.update.update_UNAUTHORIZED;
import org.ai.roboadvisor.global.common.dto.SuccessApiResponse;
import org.ai.roboadvisor.global.exception.CustomException;
import org.ai.roboadvisor.global.exception.ErrorCode;
import org.ai.roboadvisor.global.exception.SuccessCode;
import org.ai.roboadvisor.global.swagger_annotation.ApiResponse_Internal_Server_Error;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import static org.ai.roboadvisor.global.exception.ErrorIntValue.*;

@Slf4j
@RequiredArgsConstructor
@Tag(name = "community] post", description = "게시글 작성, 수정, 삭제 API")
@Tag(name = "community] post", description = "게시글 CRUD API")
@RestController
@RequestMapping("/api/community/post")
public class PostController {
private final PostService postService;

@Operation(summary = "게시글 작성", description = "게시글 작성 API")
@ApiResponse(responseCode = "201", description = """
정상 응답. data로 게시글 정보를 리턴한다.
id: 게시글 고유 번호(식별 번호), tendency: 투자 성향, nickname: 게시글 작성자 닉네임,
content: 게시글 작성 내용, time: 게시글 작성 시간, viewcount: 조회수
""",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "정상 응답 예시",
value = """
{
"code": 201,
"message": "게시글이 정상적으로 등록되었습니다",
"data": {
"id": 1,
"tendency": "SHEEP",
"nickname": "testUser",
"content": "안녕하세요",
"time": "2023-09-21 01:06:19",
"viewCount": 0
}
}
"""
)))
@ApiResponse(responseCode = "400", description = "투자 성향이 잘못 입력된 경우",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "투자 성향이 잘못 입력된 경우 예시",
value = """
{
"code": 400,
"message": "잘못된 투자 성향 형식이 입력되었습니다",
"data": null
}
"""
)))
@save_CREATED
@save_BAD_REQUEST
@ApiResponse_Internal_Server_Error
@PostMapping()
public ResponseEntity<SuccessApiResponse<PostResponse>> save(@RequestBody PostRequest postRequest) {
Expand All @@ -76,54 +43,21 @@ public ResponseEntity<SuccessApiResponse<PostResponse>> save(@RequestBody PostRe
postService.save(postRequest)));
}

@Operation(summary = "게시글 조회", description = "게시글 조회 API")
@getPostById_OK
@getPostById_BAD_REQUEST
@ApiResponse_Internal_Server_Error
@GetMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<PostResponse>> getPostById(@PathVariable("postId") Long postId) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.POST_VIEW_SUCCESS,
postService.getPostById(postId)));
}

@Operation(summary = "게시글 수정", description = "게시글 수정 API")
@ApiResponse(responseCode = "200", description = """
정상 응답
게시글이 정상적으로 수정된 경우: 응답 객체는 '게시글 작성' 과 동일하다.
""",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "정상 응답 예시",
value = """
{
"code": 200,
"message": "게시글 수정이 정상적으로 처리되었습니다",
"data": {
"id": 1,
"tendency": "LION",
"nickname": "testUser",
"content": "안녕하세요3333",
"time": "2023-09-21 01:06:20",
"viewCount": 0
}
}
"""
)))
@ApiResponse(responseCode = "400", description = "투자 성향이 잘못 입력된 경우",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "투자 성향이 잘못 입력된 경우 예시",
value = """
{
"code": 400,
"message": "잘못된 투자 성향 형식이 입력되었습니다",
"data": null
}
"""
)))
@ApiResponse(responseCode = "401", description = "게시글 수정 권한이 없는 경우",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "게시글 수정 권한이 없는 경우 예시",
value = """
{
"code": 401,
"message": "게시글 수정 혹은 삭제 권한이 존재하지 않습니다",
"data": null
}
"""
)))
@update_OK
@update_BAD_REQUEST
@update_UNAUTHORIZED
@ApiResponse_Internal_Server_Error
@PutMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<PostResponse>> update(@PathVariable("postId") Long postId, @RequestBody PostRequest postRequest) {
Expand All @@ -133,44 +67,15 @@ public ResponseEntity<SuccessApiResponse<PostResponse>> update(@PathVariable("po
}

@Operation(summary = "게시글 삭제", description = "게시글 삭제 API")
@ApiResponse(responseCode = "200", description = """
정상 응답
게시글이 정상적으로 삭제된 경우
""",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "정상 응답 예시",
value = """
{
"code": 200,
"message": "게시글 삭제가 정상적으로 처리되었습니다",
"data": null
}
"""
)))
@ApiResponse(responseCode = "401", description = "게시글 삭제 권한이 없는 경우",
content = @Content(schema = @Schema(implementation = SuccessApiResponse.class),
examples = @ExampleObject(name = "example",
description = "게시글 삭제 권한이 없는 예시",
value = """
{
"code": 401,
"message": "게시글 수정 혹은 삭제 권한이 존재하지 않습니다",
"data": null
}
"""
)))
@delete_OK
@delete_UNAUTHORIZED
@ApiResponse_Internal_Server_Error
@DeleteMapping("/{postId}")
public ResponseEntity<SuccessApiResponse<?>> delete(@PathVariable("postId") Long postId, @RequestBody PostRequest postRequest) {
int result = postService.delete(postId, postRequest);
if (result == SUCCESS.getValue()) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.POST_DELETE_SUCCESS));
} else {
throw new CustomException(ErrorCode.INTERNAL_SERVER_ERROR);
}
public ResponseEntity<SuccessApiResponse<PostResponse>> delete(@PathVariable("postId") Long postId,
@RequestBody PostDeleteRequest postDeleteRequest) {
return ResponseEntity.status(HttpStatus.OK)
.body(SuccessApiResponse.success(SuccessCode.POST_DELETE_SUCCESS,
postService.delete(postId, postDeleteRequest)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.ai.roboadvisor.domain.community.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.ai.roboadvisor.domain.community.entity.Comment;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
public class CommentDto {

private Long id;
private String nickname;
private String content;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdDateTime;

public static CommentDto fromComment(Comment comment) {
return new CommentDto(comment.getId(), comment.getNickname(),
comment.getContent(), comment.getCreatedDateTime());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.ai.roboadvisor.domain.community.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CommentDeleteRequest {

@Schema(description = "댓글 번호", example = "1")
private Long commentId;

@Schema(description = "사용자의 닉네임", example = "testUser")
@NotBlank
private String nickname;
}
Loading

0 comments on commit c46e638

Please sign in to comment.