-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Feature] 게시물 업로드, 상세 조회을 구현한다 (#34)
* feature: Profile ID를 통한 조회 추가 * feature: Post에 검증 로직 추가 * feature: 게시물 업로드 구현 * feature: 게시물 단건 조회 구현 * chore: JPA 전략을 update로 변경
- Loading branch information
Showing
17 changed files
with
371 additions
and
9 deletions.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
src/main/java/daybyquest/global/error/exception/NotExistPostException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package daybyquest.global.error.exception; | ||
|
||
import daybyquest.global.error.ExceptionCode; | ||
|
||
public class NotExistPostException extends CustomException { | ||
|
||
public NotExistPostException() { | ||
super(ExceptionCode.NOT_EXIST_POST); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/main/java/daybyquest/post/application/GetPostService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package daybyquest.post.application; | ||
|
||
import daybyquest.post.dto.response.PostResponse; | ||
import daybyquest.post.query.PostDao; | ||
import daybyquest.post.query.PostData; | ||
import daybyquest.user.query.Profile; | ||
import daybyquest.user.query.ProfileDao; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
public class GetPostService { | ||
|
||
private final PostDao postDao; | ||
|
||
private final ProfileDao profileDao; | ||
|
||
public GetPostService(final PostDao postDao, final ProfileDao profileDao) { | ||
this.postDao = postDao; | ||
this.profileDao = profileDao; | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public PostResponse invoke(final Long loginId, final Long postId) { | ||
final PostData postData = postDao.getByPostId(loginId, postId); | ||
final Profile profile = profileDao.getById(loginId, postData.getUserId()); | ||
return PostResponse.of(postData, profile); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/daybyquest/post/application/SavePostService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package daybyquest.post.application; | ||
|
||
import daybyquest.global.utils.MultipartFileUtils; | ||
import daybyquest.image.vo.Image; | ||
import daybyquest.image.vo.ImageIdentifierGenerator; | ||
import daybyquest.image.vo.Images; | ||
import daybyquest.post.domain.Post; | ||
import daybyquest.post.domain.Posts; | ||
import daybyquest.post.dto.request.SavePostRequest; | ||
import daybyquest.user.domain.Users; | ||
import java.util.List; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@Service | ||
public class SavePostService { | ||
|
||
private static final String CATEGORY = "POST"; | ||
|
||
private final Users users; | ||
|
||
private final Posts posts; | ||
|
||
private final Images images; | ||
|
||
private final ImageIdentifierGenerator generator; | ||
|
||
public SavePostService(final Users users, final Posts posts, final Images images, | ||
final ImageIdentifierGenerator generator) { | ||
this.users = users; | ||
this.posts = posts; | ||
this.images = images; | ||
this.generator = generator; | ||
} | ||
|
||
@Transactional | ||
public Long invoke(final Long loginId, final SavePostRequest request, | ||
final List<MultipartFile> files) { | ||
users.validateExistentById(loginId); | ||
final Post post = toEntity(loginId, request, toImageList(files)); | ||
return posts.save(post); | ||
} | ||
|
||
private List<Image> toImageList(final List<MultipartFile> files) { | ||
return files.stream().map((file) -> { | ||
final String identifier = generator.generateIdentifier(CATEGORY, file.getOriginalFilename()); | ||
images.upload(identifier, MultipartFileUtils.getInputStream(file)); | ||
return new Image(identifier); | ||
}).toList(); | ||
} | ||
|
||
private Post toEntity(final Long loginId, final SavePostRequest request, final List<Image> images) { | ||
return new Post(loginId, request.getQuestId(), request.getContent(), images); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,10 @@ | |
|
||
public enum PostState { | ||
|
||
PREPARING, | ||
SUCCESS, | ||
NEED_CHECK, | ||
FAIL, | ||
NOT_DECIDED; | ||
NOT_DECIDED, | ||
DELETED; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package daybyquest.post.domain; | ||
|
||
import daybyquest.global.error.exception.NotExistPostException; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class Posts { | ||
|
||
private final PostRepository postRepository; | ||
|
||
public Posts(final PostRepository postRepository) { | ||
this.postRepository = postRepository; | ||
} | ||
|
||
public Long save(final Post post) { | ||
return postRepository.save(post).getId(); | ||
} | ||
|
||
public Post getById(final Long id) { | ||
return postRepository.findById(id).orElseThrow(NotExistPostException::new); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/daybyquest/post/dto/request/SavePostRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package daybyquest.post.dto.request; | ||
|
||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
public class SavePostRequest { | ||
|
||
private String content; | ||
|
||
private Long questId; | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/daybyquest/post/dto/response/PostResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package daybyquest.post.dto.response; | ||
|
||
import daybyquest.image.vo.Image; | ||
import daybyquest.post.query.PostData; | ||
import daybyquest.user.dto.response.ProfileResponse; | ||
import daybyquest.user.query.Profile; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
public class PostResponse { | ||
|
||
private ProfileResponse author; | ||
|
||
private Long id; | ||
|
||
private String content; | ||
|
||
private LocalDateTime updatedAt; | ||
|
||
private boolean liked; | ||
|
||
private List<String> images; | ||
|
||
public PostResponse(final ProfileResponse author, final Long id, final String content, | ||
final LocalDateTime updatedAt, final boolean liked, | ||
final List<String> images) { | ||
this.author = author; | ||
this.id = id; | ||
this.content = content; | ||
this.updatedAt = updatedAt; | ||
this.liked = liked; | ||
this.images = images; | ||
} | ||
|
||
public static PostResponse of(final PostData postData, final Profile profile) { | ||
return new PostResponse(ProfileResponse.of(profile), postData.getId(), postData.getContent(), | ||
postData.getUpdatedAt(), postData.isLiked(), | ||
postData.getImages().stream().map(Image::getImageIdentifier).toList() | ||
); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/daybyquest/post/presentation/PostCommandApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package daybyquest.post.presentation; | ||
|
||
import daybyquest.auth.Authorization; | ||
import daybyquest.auth.UserId; | ||
import daybyquest.post.application.SavePostService; | ||
import daybyquest.post.dto.request.SavePostRequest; | ||
import java.util.List; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestPart; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@RestController | ||
public class PostCommandApi { | ||
|
||
private final SavePostService savePostService; | ||
|
||
public PostCommandApi(final SavePostService savePostService) { | ||
this.savePostService = savePostService; | ||
} | ||
|
||
@PostMapping("/post") | ||
@Authorization | ||
public ResponseEntity<Long> savePost(@UserId final Long loginId, @RequestPart SavePostRequest request, | ||
@RequestPart List<MultipartFile> files) { | ||
final Long postId = savePostService.invoke(loginId, request, files); | ||
return ResponseEntity.ok(postId); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/main/java/daybyquest/post/presentation/PostQueryApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package daybyquest.post.presentation; | ||
|
||
import daybyquest.auth.Authorization; | ||
import daybyquest.auth.UserId; | ||
import daybyquest.post.application.GetPostService; | ||
import daybyquest.post.dto.response.PostResponse; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class PostQueryApi { | ||
|
||
private final GetPostService getPostService; | ||
|
||
public PostQueryApi(final GetPostService getPostService) { | ||
this.getPostService = getPostService; | ||
} | ||
|
||
@GetMapping("/post/{postId}") | ||
@Authorization | ||
public ResponseEntity<PostResponse> getPost(@UserId final Long loginId, @PathVariable final Long postId) { | ||
final PostResponse response = getPostService.invoke(loginId, postId); | ||
return ResponseEntity.ok(response); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package daybyquest.post.query; | ||
|
||
public interface PostDao { | ||
|
||
PostData getByPostId(final Long userId, final Long postId); | ||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/daybyquest/post/query/PostDaoQuerydslImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package daybyquest.post.query; | ||
|
||
import static daybyquest.image.vo.QImage.image; | ||
import static daybyquest.like.domain.QPostLike.postLike; | ||
import static daybyquest.post.domain.QPost.post; | ||
|
||
import com.querydsl.core.types.Projections; | ||
import com.querydsl.jpa.JPAExpressions; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import daybyquest.global.error.exception.NotExistPostException; | ||
import daybyquest.image.vo.Image; | ||
import java.util.List; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public class PostDaoQuerydslImpl implements PostDao { | ||
|
||
private final JPAQueryFactory factory; | ||
|
||
public PostDaoQuerydslImpl(final JPAQueryFactory factory) { | ||
this.factory = factory; | ||
} | ||
|
||
@Override | ||
public PostData getByPostId(final Long userId, final Long postId) { | ||
final PostData postData = factory.select(Projections.constructor(PostData.class, | ||
post.userId, | ||
post.id, | ||
post.content, | ||
post.updatedAt, | ||
JPAExpressions.selectFrom(postLike) | ||
.where(postLike.userId.eq(userId).and(postLike.postId.eq(postId))) | ||
.exists())) | ||
.from(post) | ||
.where(post.id.eq(postId)) | ||
.fetchOne(); | ||
if (postData == null) { | ||
throw new NotExistPostException(); | ||
} | ||
final List<Image> images = factory.select(image) | ||
.from(post) | ||
.leftJoin(post.images, image) | ||
.where(post.id.eq(postId)) | ||
.fetch(); | ||
postData.setImages(images); | ||
return postData; | ||
} | ||
} |
Oops, something went wrong.