Skip to content

Commit

Permalink
[FEAT] 모임 게시글 댓글 작성 API 마이그레이션 및 알림 작업 (#148)
Browse files Browse the repository at this point in the history
* [FEAT] 모임 게시글 댓글 작성 API 마이그레이션 및 푸시 알림 구현 #118

* [INFRA] 게시글 댓글 작성 API v2 라우팅 규칙 변경 #118

* [INFRA] 댓글 작성 API와 게시글 작성 API 라우팅 규칙 수정 #118
  • Loading branch information
yeseul106 authored Apr 3, 2024
1 parent a5868f1 commit c50f282
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 132 deletions.
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ services:
caddy.route_3.reverse_proxy: "{{ upstreams 4000 }}"
caddy.route_4: /meeting/v2/*
caddy.route_4.reverse_proxy: "{{ upstreams 4000 }}"
caddy.route_5: /post/v2/*
caddy.route_5: /post/v2
caddy.route_5.reverse_proxy: "{{ upstreams 4000 }}"
caddy.route_6: /comment/v2
caddy.route_6.reverse_proxy: "{{ upstreams 4000 }}"

nestjs:
build:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.sopt.makers.crew.main.comment.v2;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.security.Principal;
import lombok.RequiredArgsConstructor;
import org.sopt.makers.crew.main.comment.v2.dto.request.CommentV2CreateCommentBodyDto;
import org.sopt.makers.crew.main.comment.v2.dto.response.CommentV2CreateCommentResponseDto;
import org.sopt.makers.crew.main.comment.v2.service.CommentV2Service;
import org.sopt.makers.crew.main.common.util.UserUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/comment/v2")
@RequiredArgsConstructor
@Tag(name = "댓글/대댓글")
public class CommentV2Controller {

private final CommentV2Service commentV2Service;

@Operation(summary = "모임 게시글 댓글 작성")
@PostMapping()
@ResponseStatus(HttpStatus.CREATED)
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "성공"),
})
public ResponseEntity<CommentV2CreateCommentResponseDto> createComment(
@Valid @RequestBody CommentV2CreateCommentBodyDto requestBody, Principal principal) {
Integer userId = UserUtil.getUserId(principal);
return ResponseEntity.ok(commentV2Service.createComment(requestBody, userId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.sopt.makers.crew.main.comment.v2.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
@Schema(description = "댓글 생성 request body dto")
public class CommentV2CreateCommentBodyDto {

@Schema(example = "1", required = true, description = "게시글 ID")
@NotNull
private Integer postId;

@Schema(example = "알고보면 쓸데있는 개발 프로세스", required = true, description = "댓글 내용")
@NotEmpty
private String contents;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.makers.crew.main.comment.v2.dto.response;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(staticName = "of")
public class CommentV2CreateCommentResponseDto {

/**
* 생성된 댓글 id
*/
private Integer commentId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.makers.crew.main.comment.v2.service;

import org.sopt.makers.crew.main.comment.v2.dto.request.CommentV2CreateCommentBodyDto;
import org.sopt.makers.crew.main.comment.v2.dto.response.CommentV2CreateCommentResponseDto;

public interface CommentV2Service {

CommentV2CreateCommentResponseDto createComment(CommentV2CreateCommentBodyDto requestBody,
Integer userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.sopt.makers.crew.main.comment.v2.service;

import static org.sopt.makers.crew.main.internal.notification.PushNotificationEnums.NEW_COMMENT_PUSH_NOTIFICATION_TITLE;
import static org.sopt.makers.crew.main.internal.notification.PushNotificationEnums.PUSH_NOTIFICATION_CATEGORY;

import lombok.RequiredArgsConstructor;
import org.sopt.makers.crew.main.comment.v2.dto.request.CommentV2CreateCommentBodyDto;
import org.sopt.makers.crew.main.comment.v2.dto.response.CommentV2CreateCommentResponseDto;
import org.sopt.makers.crew.main.entity.comment.Comment;
import org.sopt.makers.crew.main.entity.comment.CommentRepository;
import org.sopt.makers.crew.main.entity.post.Post;
import org.sopt.makers.crew.main.entity.post.PostRepository;
import org.sopt.makers.crew.main.entity.user.User;
import org.sopt.makers.crew.main.entity.user.UserRepository;
import org.sopt.makers.crew.main.internal.notification.PushNotificationService;
import org.sopt.makers.crew.main.internal.notification.dto.PushNotificationRequestDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CommentV2ServiceImpl implements CommentV2Service {

private final PostRepository postRepository;
private final UserRepository userRepository;
private final CommentRepository commentRepository;
private final PushNotificationService pushNotificationService;

@Value("${push-notification.web-url}")
private String pushWebUrl;

/**
* 모임 게시글 댓글 작성
*
* @throws 400 존재하지 않는 게시글일 떄
* @apiNote 모임에 속한 유저만 작성 가능
*/
@Override
@Transactional

public CommentV2CreateCommentResponseDto createComment(CommentV2CreateCommentBodyDto requestBody,
Integer userId) {
Post post = postRepository.findByIdOrThrow(requestBody.getPostId());
User user = userRepository.findByIdOrThrow(userId);

Comment comment = Comment.builder()
.contents(requestBody.getContents())
.user(user)
.post(post)
.build();

Comment savedComment = commentRepository.save(comment);

User PostWriter = post.getUser();
String[] userIds = {String.valueOf(PostWriter.getOrgId())};

String pushNotificationContent = String.format("[%s의 댓글] : \"%s\"",
user.getName(), requestBody.getContents());
String pushNotificationWeblink = pushWebUrl + "/post?id=" + post.getId();

PushNotificationRequestDto pushRequestDto = PushNotificationRequestDto.of(userIds,
NEW_COMMENT_PUSH_NOTIFICATION_TITLE.getValue(),
pushNotificationContent,
PUSH_NOTIFICATION_CATEGORY.getValue(), pushNotificationWeblink);

pushNotificationService.sendPushNotification(pushRequestDto);

return CommentV2CreateCommentResponseDto.of(savedComment.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public enum ErrorStatus {
* 204 NO_CONTENT
*/
NO_CONTENT_EXCEPTION("참여한 모임이 없습니다."),

/**
* 400 BAD_REQUEST
*/
VALIDATION_EXCEPTION("CR-001"), // errorCode는 예시, 추후 변경 예정 -> 잘못된 요청입니다.
VALIDATION_REQUEST_MISSING_EXCEPTION("요청값이 입력되지 않았습니다."),
NOT_FOUND_MEETING("모임이 없습니다."),
NOT_FOUND_POST("존재하지 않는 게시글입니다."),

/**
* 401 UNAUTHORIZED
Expand Down
Loading

0 comments on commit c50f282

Please sign in to comment.