diff --git a/src/main/java/space/space_spring/controller/PostController.java b/src/main/java/space/space_spring/controller/PostController.java index 4d6e85e7..ec56825e 100644 --- a/src/main/java/space/space_spring/controller/PostController.java +++ b/src/main/java/space/space_spring/controller/PostController.java @@ -2,17 +2,26 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth; -import space.space_spring.dto.post.ReadPostsResponse; +import space.space_spring.dto.post.request.CreatePostRequest; +import space.space_spring.dto.post.response.ReadPostsResponse; import space.space_spring.entity.UserSpace; +import space.space_spring.exception.PostException; +import space.space_spring.exception.SpaceException; import space.space_spring.response.BaseResponse; import space.space_spring.service.PostService; import space.space_spring.util.userSpace.UserSpaceUtils; +import java.io.IOException; import java.util.List; import java.util.Optional; +import static space.space_spring.util.bindingResult.BindingResultUtils.getErrorMessage; + @RestController @RequiredArgsConstructor @RequestMapping("/space/{spaceId}") @@ -26,10 +35,34 @@ public BaseResponse> getBoard( @JwtLoginAuth Long userId, @PathVariable Long spaceId, @RequestParam(defaultValue = "all") String filter) { + + // TODO 1: 유저가 스페이스에 속하는지 검증 Optional userInSpace = userSpaceUtils.isUserInSpace(userId, spaceId); log.info("UserName = {}, UserSpaceAuth = {}", userInSpace.get().getUserName(), userInSpace.get().getUserSpaceAuth()); + // TODO 2: 게시글 필터링 적용하여 리스트 get List board = postService.getAllPosts(spaceId, filter); return new BaseResponse<>(board); } + @PostMapping("/board/post") + public BaseResponse createPost( + @JwtLoginAuth Long userId, + @PathVariable Long spaceId, + @ModelAttribute @Validated CreatePostRequest createPostRequest, + BindingResult bindingResult) throws IOException{ + // TODO 1: 예외처리 + if (bindingResult.hasErrors()) { +// throw new PostException(, getErrorMessage(bindingResult)); + } + // TODO 2: 유저가 스페이스에 속하는 지 검증 + Optional userInSpace = userSpaceUtils.isUserInSpace(userId, spaceId); + log.info("UserName = {}, UserSpaceAuth = {}", userInSpace.get().getUserName(), userInSpace.get().getUserSpaceAuth()); + + // TODO 3: 작성한 게시글 save 작업 수행 + postService.save(userId, spaceId, createPostRequest); + + return new BaseResponse<>("새로운 글이 작성되었습니다."); + } + + } diff --git a/src/main/java/space/space_spring/dto/post/request/CreatePostRequest.java b/src/main/java/space/space_spring/dto/post/request/CreatePostRequest.java new file mode 100644 index 00000000..3c590555 --- /dev/null +++ b/src/main/java/space/space_spring/dto/post/request/CreatePostRequest.java @@ -0,0 +1,35 @@ +package space.space_spring.dto.post.request; + +import lombok.*; +import org.springframework.web.multipart.MultipartFile; +import space.space_spring.entity.Post; +import space.space_spring.entity.PostImage; +import space.space_spring.entity.Space; +import space.space_spring.entity.User; + +import java.util.List; + +@Builder +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class CreatePostRequest { + private String title; + private String content; + private String type; // "notice" or "general" + private List postImages; + + public Post toEntity(User user, Space space, List postImages){ + return Post.builder() + .user(user) + .space(space) + .title(title) + .content(content) + .type(type) + .postImages(postImages) + .build(); + } +} + + diff --git a/src/main/java/space/space_spring/dto/post/ReadPostsResponse.java b/src/main/java/space/space_spring/dto/post/response/ReadPostsResponse.java similarity index 85% rename from src/main/java/space/space_spring/dto/post/ReadPostsResponse.java rename to src/main/java/space/space_spring/dto/post/response/ReadPostsResponse.java index 1d5e77ea..4b431813 100644 --- a/src/main/java/space/space_spring/dto/post/ReadPostsResponse.java +++ b/src/main/java/space/space_spring/dto/post/response/ReadPostsResponse.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.post; +package space.space_spring.dto.post.response; import lombok.*; import space.space_spring.entity.Post; @@ -30,11 +30,11 @@ public class ReadPostsResponse { private List postImage; private String time; private String type; - private int post_count; + private int postCount; // 댓글 및 좋아요 - private int comment_count; - private int like_count; + private int commentCount; + private int likeCount; public static ReadPostsResponse of(Post post, int postCount, UserSpace userSpace) { List postImageUrls = post.getPostImages().stream() @@ -51,9 +51,9 @@ public static ReadPostsResponse of(Post post, int postCount, UserSpace userSpace .content(post.getContent()) .time(ConvertCreatedDate.setCreatedDate(post.getCreatedAt())) .type(post.getType()) - .post_count(postCount) - .comment_count(post.getPostComments().size()) - .like_count(post.getLike()) + .postCount(postCount) + .commentCount(post.getPostComments().size()) + .likeCount(post.getLike()) .postImage(postImageUrls) .build(); } diff --git a/src/main/java/space/space_spring/entity/Post.java b/src/main/java/space/space_spring/entity/Post.java index 78d0aa90..b0fe527a 100644 --- a/src/main/java/space/space_spring/entity/Post.java +++ b/src/main/java/space/space_spring/entity/Post.java @@ -1,13 +1,16 @@ package space.space_spring.entity; import jakarta.persistence.*; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.List; @Entity @Table(name = "Posts") @Getter +@NoArgsConstructor public class Post extends BaseEntity { @Id @GeneratedValue @Column(name = "post_id") @@ -33,10 +36,19 @@ public class Post extends BaseEntity { @Column(name = "post_like") private int like; - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) private List postImages; - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) private List postComments; + @Builder + public Post(User user, Space space, String title, String content, String type, List postImages) { + this.user = user; + this.space = space; + this.title = title; + this.content = content; + this.type = type; + this.postImages = postImages; + } } diff --git a/src/main/java/space/space_spring/entity/PostImage.java b/src/main/java/space/space_spring/entity/PostImage.java index 9a56aef2..b7129dec 100644 --- a/src/main/java/space/space_spring/entity/PostImage.java +++ b/src/main/java/space/space_spring/entity/PostImage.java @@ -1,22 +1,32 @@ package space.space_spring.entity; import jakarta.persistence.*; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Entity @Table(name = "Post_Image") @Getter +@NoArgsConstructor public class PostImage extends BaseEntity{ @Id @GeneratedValue @Column(name = "post_image_id") private Long postImgId; + @Setter @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "space_post_id") private Post post; - @Column(name = "post_image") + @Column(name = "post_image_url") private String postImgUrl; + @Builder + public PostImage(String postImgUrl) { + this.postImgUrl = postImgUrl; + } + } diff --git a/src/main/java/space/space_spring/exception/PostException.java b/src/main/java/space/space_spring/exception/PostException.java new file mode 100644 index 00000000..d1dc5092 --- /dev/null +++ b/src/main/java/space/space_spring/exception/PostException.java @@ -0,0 +1,20 @@ +package space.space_spring.exception; + +import lombok.Getter; +import space.space_spring.response.status.ResponseStatus; + + +@Getter +public class PostException extends RuntimeException { + + private final ResponseStatus exceptionStatus; + public PostException(ResponseStatus exceptionStatus) { + super(exceptionStatus.getMessage()); + this.exceptionStatus = exceptionStatus; + } + public PostException(ResponseStatus exceptionStatus, String message) { + super(message); + this.exceptionStatus = exceptionStatus; + } + +} diff --git a/src/main/java/space/space_spring/service/PostService.java b/src/main/java/space/space_spring/service/PostService.java index 94f41597..dfa8b328 100644 --- a/src/main/java/space/space_spring/service/PostService.java +++ b/src/main/java/space/space_spring/service/PostService.java @@ -1,29 +1,35 @@ package space.space_spring.service; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import space.space_spring.dao.PostDao; -import space.space_spring.dao.UserSpaceDao; -import space.space_spring.dto.post.ReadPostsResponse; -import space.space_spring.entity.Post; -import space.space_spring.entity.Space; -import space.space_spring.entity.UserSpace; +import space.space_spring.dto.post.request.CreatePostRequest; +import space.space_spring.dto.post.response.ReadPostsResponse; +import space.space_spring.entity.*; import space.space_spring.util.space.SpaceUtils; +import space.space_spring.util.user.UserUtils; import space.space_spring.util.userSpace.UserSpaceUtils; +import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @Service +@Slf4j @RequiredArgsConstructor public class PostService { + private final UserUtils userUtils; private final SpaceUtils spaceUtils; private final UserSpaceUtils userSpaceUtils; private final PostDao postDao; - private final UserSpaceDao userSpaceDao; + private final S3Uploader s3Uploader; + @Transactional public List getAllPosts(Long spaceId, String filter) { // TODO 1: spaceId에 해당하는 space find @@ -49,4 +55,37 @@ public List getAllPosts(Long spaceId, String filter) { }) .collect(Collectors.toList()); } + + @Transactional + public Long save(Long userId, Long spaceId, CreatePostRequest createPostRequest) { + // TODO 1: userId에 해당하는 User find + User user = userUtils.findUserByUserId(userId); + + // TODO 2: spaceId에 해당하는 space find + Space space = spaceUtils.findSpaceBySpaceId(spaceId); + + // TODO 3: 게시글 db insert + List postImages = Optional.ofNullable(createPostRequest.getPostImages()) + .orElse(Collections.emptyList()) + .stream() + .map(file -> { + try { + log.info("Received files: {}", createPostRequest.getPostImages()); + String postImgUrl = s3Uploader.upload(file, "postImg"); + log.info("Post Image URL: {}", postImgUrl); + return PostImage.builder().postImgUrl(postImgUrl).build(); + } catch (IOException e) { + throw new RuntimeException("Failed to upload file", e); + } + }).collect(Collectors.toList()); + log.info("Uploading files: {}", postImages); + + // TODO 4: Post 객체를 생성하고, 생성된 Post 객체를 각 PostImage에 할당 + Post post = createPostRequest.toEntity(user, space, postImages); + + // TODO 5: 각 PostImage에 해당 Post를 설정 + postImages.forEach(postImage -> postImage.setPost(post)); + + return postDao.save(post).getPostId(); + } }