Skip to content

Commit 21ee51c

Browse files
authored
Merge pull request #6 from eunhye-ahn/feature/comment-core-0522
[BE] 댓글 : 생성/조회/삭제 API 개발
2 parents bea3640 + 25835ef commit 21ee51c

File tree

6 files changed

+289
-0
lines changed

6 files changed

+289
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.example.polls.controller;
2+
3+
import com.example.polls.payload.Request.CommentRequest;
4+
import com.example.polls.payload.Response.ApiResponse;
5+
import com.example.polls.payload.Response.CommentResponse;
6+
import com.example.polls.payload.Response.PagedResponse;
7+
import com.example.polls.security.UserPrincipal;
8+
import com.example.polls.service.CommentService;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
12+
import org.springframework.web.bind.annotation.*;
13+
14+
import javax.validation.Valid;
15+
16+
@RestController
17+
@RequestMapping("/api/polls/{pollId}/comments")
18+
@RequiredArgsConstructor
19+
public class CommentController {
20+
21+
private final CommentService commentService;
22+
23+
@PostMapping
24+
public ResponseEntity<CommentResponse> createComment(
25+
@PathVariable Long pollId,
26+
@Valid @RequestBody CommentRequest commentRequest,
27+
@AuthenticationPrincipal UserPrincipal userPrincipal){
28+
29+
CommentResponse commentResponse = commentService.createComment(
30+
pollId, commentRequest, userPrincipal.getId());
31+
32+
return ResponseEntity.ok(commentResponse);
33+
}
34+
35+
@GetMapping
36+
public ResponseEntity<PagedResponse<CommentResponse>> getAllComments(
37+
@PathVariable Long pollId,
38+
@AuthenticationPrincipal UserPrincipal userPrincipal,
39+
@RequestParam(value = "page", defaultValue = "0") int page,
40+
@RequestParam(value = "size", defaultValue = "10") int size){
41+
42+
PagedResponse<CommentResponse> response = commentService.getAllComment(pollId, userPrincipal.getId(), page, size);
43+
44+
return ResponseEntity.ok(response);
45+
}
46+
47+
@DeleteMapping("/{commentId}")
48+
public ResponseEntity<ApiResponse> deleteComment(
49+
@PathVariable Long commentId,
50+
@AuthenticationPrincipal UserPrincipal userPrincipal){
51+
52+
ApiResponse response = commentService.deleteComment(commentId, userPrincipal.getId());
53+
return ResponseEntity.ok(response);
54+
}
55+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.example.polls.model;
2+
3+
import com.example.polls.model.audit.DateAudit;
4+
import org.springframework.data.domain.Auditable;
5+
6+
import javax.persistence.*;
7+
import javax.validation.constraints.NotBlank;
8+
import java.time.LocalDateTime;
9+
10+
@Entity
11+
@Table(name = "poll_comments")
12+
public class Comment extends DateAudit {
13+
@Id
14+
@GeneratedValue(strategy = GenerationType.IDENTITY)
15+
private Long id;
16+
17+
@NotBlank
18+
private String content;
19+
20+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
21+
@JoinColumn(name = "poll_id", nullable = false)
22+
private Poll poll;
23+
24+
@ManyToOne(fetch = FetchType.LAZY)
25+
@JoinColumn(name = "user_id", nullable = false)
26+
private User user;
27+
28+
public Long getId() {
29+
return id;
30+
}
31+
32+
public void setId(Long id) {
33+
this.id = id;
34+
}
35+
36+
public String getContent() {
37+
return content;
38+
}
39+
40+
public void setContent(String content) {
41+
this.content = content;
42+
}
43+
44+
public Poll getPoll() {
45+
return poll;
46+
}
47+
48+
public void setPoll(Poll poll) {
49+
this.poll = poll;
50+
}
51+
52+
public User getUser() {
53+
return user;
54+
}
55+
56+
public void setUser(User user) {
57+
this.user = user;
58+
}
59+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.example.polls.payload.Request;
2+
3+
import javax.validation.constraints.NotBlank;
4+
5+
public class CommentRequest {
6+
@NotBlank
7+
private String content;
8+
9+
public String getContent() {
10+
return content;
11+
}
12+
public void setContent(String content) {
13+
this.content = content;
14+
}
15+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.example.polls.payload.Response;
2+
3+
public class CommentResponse {
4+
5+
private Long id;
6+
private Long userId;
7+
private String content;
8+
private String createdAt;
9+
10+
public CommentResponse(Long id, Long userId, String content, String createdAt) {
11+
this.id = id;
12+
this.userId = userId;
13+
this.content = content;
14+
this.createdAt = createdAt;
15+
}
16+
17+
public Long getId() {
18+
return id;
19+
}
20+
21+
public Long getUserId() {
22+
return userId;
23+
}
24+
25+
public String getContent() {
26+
return content;
27+
}
28+
29+
public String getCreatedAt() {
30+
return createdAt;
31+
}
32+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.example.polls.repository;
2+
3+
import com.example.polls.model.Comment;
4+
import org.springframework.data.domain.Page;
5+
import org.springframework.data.domain.Pageable;
6+
import org.springframework.data.jpa.repository.JpaRepository;
7+
8+
9+
import java.util.List;
10+
11+
public interface CommentRepository extends JpaRepository<Comment, Long> {
12+
13+
List<Comment> findByPollIdOrderByCreatedAtDesc(Long pollId);
14+
15+
Page<Comment> findByPollId(Long pollId, Pageable pageable);
16+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package com.example.polls.service;
2+
3+
4+
import com.example.polls.exception.ResourceNotFoundException;
5+
import com.example.polls.model.Comment;
6+
import com.example.polls.model.Poll;
7+
import com.example.polls.model.User;
8+
import com.example.polls.payload.Request.CommentRequest;
9+
import com.example.polls.payload.Response.ApiResponse;
10+
import com.example.polls.payload.Response.CommentResponse;
11+
import com.example.polls.payload.Response.PagedResponse;
12+
import com.example.polls.repository.CommentRepository;
13+
import com.example.polls.repository.PollRepository;
14+
import com.example.polls.repository.UserRepository;
15+
import lombok.RequiredArgsConstructor;
16+
import org.springframework.data.domain.Page;
17+
import org.springframework.data.domain.PageRequest;
18+
import org.springframework.data.domain.Pageable;
19+
import org.springframework.data.domain.Sort;
20+
import org.springframework.stereotype.Service;
21+
22+
import java.time.Instant;
23+
import java.time.LocalDateTime;
24+
import java.time.ZoneId;
25+
import java.time.format.DateTimeFormatter;
26+
import java.util.List;
27+
import java.util.stream.Collectors;
28+
29+
@Service
30+
@RequiredArgsConstructor
31+
public class CommentService {
32+
private final CommentRepository commentRepository;
33+
private final PollRepository pollRepository;
34+
private final UserRepository userRepository;
35+
36+
public CommentResponse createComment(Long pollId, CommentRequest commentRequest, Long userId){
37+
Poll poll = pollRepository.findById(pollId)
38+
.orElseThrow(()-> new ResourceNotFoundException("Poll", "id", pollId));
39+
40+
User user = userRepository.findById(userId)
41+
.orElseThrow(()-> new ResourceNotFoundException("User", "id", userId));
42+
43+
Comment comment = new Comment();
44+
comment.setContent(commentRequest.getContent());
45+
comment.setPoll(poll);
46+
comment.setUser(user);
47+
48+
Comment savedComment = commentRepository.save(comment);
49+
50+
// 5. 응답 DTO 생성
51+
52+
Instant createdAt = savedComment.getCreatedAt();
53+
LocalDateTime ldt = LocalDateTime.ofInstant(createdAt, ZoneId.systemDefault());
54+
String createdAtFormatted = ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
55+
56+
57+
return new CommentResponse(
58+
savedComment.getId(),
59+
user.getId(),
60+
savedComment.getContent(),
61+
createdAtFormatted
62+
);
63+
64+
}
65+
66+
public PagedResponse<CommentResponse> getAllComment(Long pollId, Long userId, int page, int size) {
67+
68+
69+
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
70+
Page<Comment> comments = commentRepository.findByPollId(pollId, pageable);
71+
72+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
73+
74+
List<CommentResponse> commentResponses = comments.getContent().stream()
75+
.map(comment -> {
76+
String createdAtFormatted = LocalDateTime.ofInstant(
77+
comment.getCreatedAt(), ZoneId.systemDefault()
78+
).format(formatter);
79+
80+
return new CommentResponse(
81+
comment.getId(),
82+
comment.getUser().getId(),
83+
comment.getContent(),
84+
createdAtFormatted
85+
86+
);
87+
})
88+
.collect(Collectors.toList());
89+
90+
return new PagedResponse<>(
91+
commentResponses,
92+
comments.getNumber(),
93+
comments.getSize(),
94+
comments.getTotalElements(),
95+
comments.getTotalPages(),
96+
comments.isLast());
97+
98+
}
99+
100+
public ApiResponse deleteComment(Long commentId, Long userId) {
101+
Comment comment = commentRepository.findById(commentId)
102+
.orElseThrow(()-> new ResourceNotFoundException("Comment", "id", commentId));
103+
104+
if(!comment.getUser().getId().equals(userId)){
105+
throw new ResourceNotFoundException("Comment", "id", commentId);
106+
}
107+
108+
commentRepository.delete(comment);
109+
110+
return new ApiResponse(true, "comment deleted");
111+
}
112+
}

0 commit comments

Comments
 (0)