Skip to content

Commit 673b55e

Browse files
authored
Merge pull request #301 from prgrms-web-devcourse-final-project/refactor#300
[refactor] 쿠키 테스트 완료. 만료 시간 복구
2 parents bd67b1d + e1a4842 commit 673b55e

File tree

13 files changed

+129
-46
lines changed

13 files changed

+129
-46
lines changed

src/main/java/com/back/domain/chatbot/service/ChatbotService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,9 @@ private String generateRecommendationMessage(String userQuestion, List<CocktailS
357357

358358
} catch (Exception e) {
359359
log.error("추천 메시지 생성 중 오류: ", e);
360-
return "🍹 요청하신 칵테일을 찾아봤어요! 쑤리가 엄선한 칵테일들을 추천해드릴게요.";
360+
return "🍹 요청하신 칵테일을 찾아봤어요! 쑤리가 엄선한 칵테일들을 추천해드릴게요." +
361+
"\n\n칵테일의 자세한 정보는 '상세보기'를 클릭해서 확인할 수 있어요.\n" +
362+
"마음에 드는 칵테일은 '킵' 버튼을 눌러 나만의 Bar에 저장해보세요!";
361363
}
362364
}
363365

src/main/java/com/back/domain/mybar/controller/MyBarController.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,15 @@ public RsData<Void> unkeep(
7777
myBarService.unkeep(userId, cocktailId);
7878
return RsData.of(200, "deleted");
7979
}
80+
81+
@DeleteMapping
82+
@Operation(summary = "내 바 전체 삭제", description = "내 바에 담긴 모든 칵테일을 소프트 삭제합니다")
83+
public RsData<Void> clearAll(
84+
@AuthenticationPrincipal SecurityUser principal
85+
) {
86+
Long userId = principal.getId();
87+
myBarService.clearAll(userId);
88+
return RsData.of(200, "cleared");
89+
}
8090
}
8191

src/main/java/com/back/domain/mybar/repository/MyBarRepository.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ public interface MyBarRepository extends JpaRepository<MyBar, Long> {
3838
/** 복원/재킵을 위해 status 무시하고 한 건 찾기 (없으면 Optional.empty) */
3939
Optional<MyBar> findByUser_IdAndCocktail_Id(Long userId, Long cocktailId);
4040

41+
@Modifying(clearAutomatically = true, flushAutomatically = true)
42+
@Query("""
43+
update MyBar m
44+
set m.status = 'DELETED', m.deletedAt = CURRENT_TIMESTAMP
45+
where m.user.id = :userId
46+
and m.status = 'ACTIVE'
47+
""")
48+
int softDeleteAllByUser(Long userId);
49+
4150
@Modifying(clearAutomatically = true, flushAutomatically = true)
4251
@Query("""
4352
update MyBar m

src/main/java/com/back/domain/mybar/service/MyBarService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,13 @@ public void unkeep(Long userId, Long cocktailId) {
123123
abvScoreService.revokeForKeep(userId);
124124
}
125125
}
126+
127+
@Transactional
128+
public void clearAll(Long userId) {
129+
int changed = myBarRepository.softDeleteAllByUser(userId);
130+
if (changed > 0) {
131+
abvScoreService.revokeForKeep(userId, changed);
132+
}
133+
}
126134
}
127135

src/main/java/com/back/domain/notification/dto/NotificationItemDto.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.back.domain.notification.entity.Notification;
44
import com.back.domain.notification.enums.NotificationType;
5+
import com.back.domain.post.post.entity.PostImage;
56
import java.time.LocalDateTime;
67
import lombok.Builder;
78
import lombok.Getter;
@@ -13,18 +14,29 @@ public class NotificationItemDto {
1314
private NotificationType type;
1415
private Long postId;
1516
private String postTitle;
17+
private String postCategoryName;
18+
private String postThumbnailUrl;
19+
private String message;
1620
private boolean read;
1721
private LocalDateTime createdAt;
1822

1923
public static NotificationItemDto from(Notification n) {
24+
String categoryName = n.getPost().getCategory() != null ? n.getPost().getCategory().getName() : null;
25+
String thumbnailUrl = n.getPost().getImages().stream()
26+
.map(PostImage::getUrl)
27+
.findFirst()
28+
.orElse(null);
29+
2030
return NotificationItemDto.builder()
2131
.id(n.getId())
2232
.type(n.getType())
2333
.postId(n.getPost().getId())
2434
.postTitle(n.getPost().getTitle())
35+
.postCategoryName(categoryName)
36+
.postThumbnailUrl(thumbnailUrl)
37+
.message(n.getMessage())
2538
.read(n.isRead())
2639
.createdAt(n.getCreatedAt())
2740
.build();
2841
}
2942
}
30-

src/main/java/com/back/domain/post/comment/service/CommentService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ public CommentResponseDto createComment(Long postId, CommentCreateRequestDto req
4747
.build();
4848

4949
// 게시글 작성자에게 알림 전송
50+
String commentMessage = String.format("%s 님이 '%s' 게시글에 댓글을 남겼습니다.", user.getNickname(), post.getTitle());
5051
notificationService.sendNotification(
5152
post.getUser(),
5253
post,
5354
NotificationType.COMMENT,
54-
user.getNickname() + " 님이 댓글을 남겼습니다."
55+
commentMessage
5556
);
5657

5758
Comment saved = commentRepository.save(comment);

src/main/java/com/back/domain/post/post/entity/Post.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ public void updateContent(String content) {
115115
this.content = content;
116116
}
117117

118+
public void addImage(PostImage image) {
119+
if (this.images == null) {
120+
this.images = new ArrayList<>();
121+
}
122+
this.images.add(image);
123+
image.updatePost(this); // 양방향 관계 유지
124+
}
125+
126+
118127
public void updateImages(List<PostImage> images) {
119128
this.images.clear();
120129
for (PostImage i : images) {
Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.back.domain.post.post.repository;
22

33
import com.back.domain.post.post.entity.Post;
4+
import com.back.domain.post.post.enums.PostStatus;
45
import java.util.List;
56
import org.springframework.data.jpa.repository.JpaRepository;
67
import org.springframework.stereotype.Repository;
@@ -9,28 +10,31 @@
910
public interface PostRepository extends JpaRepository<Post, Long> {
1011

1112
// 최신순 (카테고리 없음)
12-
List<Post> findTop10ByOrderByIdDesc();
13-
List<Post> findTop10ByIdLessThanOrderByIdDesc(Long lastId);
13+
List<Post> findTop10ByStatusNotOrderByIdDesc(PostStatus status);
14+
List<Post> findTop10ByStatusNotAndIdLessThanOrderByIdDesc(PostStatus status, Long lastId);
1415

1516
// 추천순 (카테고리 없음)
16-
List<Post> findTop10ByOrderByLikeCountDescIdDesc();
17-
List<Post> findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
18-
Integer likeCount, Integer likeCount2, Long id);
17+
List<Post> findTop10ByStatusNotOrderByLikeCountDescIdDesc(PostStatus status);
18+
List<Post> findTop10ByStatusNotAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
19+
PostStatus status, Integer likeCount, Integer likeCount2, Long id);
1920

2021
// 댓글순 (카테고리 없음)
21-
List<Post> findTop10ByOrderByCommentCountDescIdDesc();
22-
List<Post> findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
23-
Integer commentCount, Integer commentCount2, Long id);
22+
List<Post> findTop10ByStatusNotOrderByCommentCountDescIdDesc(PostStatus status);
23+
List<Post> findTop10ByStatusNotAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
24+
PostStatus status, Integer commentCount, Integer commentCount2, Long id);
2425

2526
// 최신순 (카테고리)
26-
List<Post> findTop10ByCategoryIdOrderByIdDesc(Long categoryId);
27-
List<Post> findTop10ByCategoryIdAndIdLessThanOrderByIdDesc(Long categoryId, Long id);
27+
List<Post> findTop10ByCategoryIdAndStatusNotOrderByIdDesc(Long categoryId, PostStatus status);
28+
List<Post> findTop10ByCategoryIdAndStatusNotAndIdLessThanOrderByIdDesc(Long categoryId, PostStatus status, Long id);
2829

2930
// 추천순 (카테고리)
30-
List<Post> findTop10ByCategoryIdOrderByLikeCountDescIdDesc(Long categoryId);
31-
List<Post> findTop10ByCategoryIdAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(Long categoryId, Integer likeCount, Integer likeCountEquals, Long id);
31+
List<Post> findTop10ByCategoryIdAndStatusNotOrderByLikeCountDescIdDesc(Long categoryId, PostStatus status);
32+
List<Post> findTop10ByCategoryIdAndStatusNotAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
33+
Long categoryId, PostStatus status, Integer likeCount, Integer likeCountEquals, Long id);
3234

3335
// 댓글순 (카테고리)
34-
List<Post> findTop10ByCategoryIdOrderByCommentCountDescIdDesc(Long categoryId);
35-
List<Post> findTop10ByCategoryIdAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(Long categoryId, Integer commentCount, Integer commentCountEquals, Long id);
36+
List<Post> findTop10ByCategoryIdAndStatusNotOrderByCommentCountDescIdDesc(Long categoryId, PostStatus status);
37+
List<Post> findTop10ByCategoryIdAndStatusNotAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
38+
Long categoryId, PostStatus status, Integer commentCount, Integer commentCountEquals, Long id);
3639
}
40+

src/main/java/com/back/domain/post/post/service/PostService.java

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,17 @@
2424
import com.back.global.file.dto.UploadedFileDto;
2525
import com.back.global.file.service.FileService;
2626
import com.back.global.rq.Rq;
27-
import java.util.ArrayList;
28-
import java.util.List;
29-
import java.util.Map;
30-
import java.util.NoSuchElementException;
31-
import java.util.Optional;
32-
import java.util.function.Function;
33-
import java.util.stream.Collectors;
3427
import lombok.RequiredArgsConstructor;
3528
import org.springframework.stereotype.Service;
3629
import org.springframework.transaction.annotation.Transactional;
3730
import org.springframework.transaction.support.TransactionSynchronization;
3831
import org.springframework.transaction.support.TransactionSynchronizationManager;
3932
import org.springframework.web.multipart.MultipartFile;
4033

34+
import java.util.*;
35+
import java.util.function.Function;
36+
import java.util.stream.Collectors;
37+
4138
@Service
4239
@RequiredArgsConstructor
4340
public class PostService {
@@ -82,13 +79,12 @@ public PostResponseDto createPost(PostCreateRequestDto reqBody, List<MultipartFi
8279
String url = fileService.uploadFile(image);
8380

8481
PostImage postImage = PostImage.builder()
85-
.post(post)
8682
.fileName(image.getOriginalFilename())
8783
.url(url)
8884
.sortOrder(order++)
8985
.build();
9086

91-
postImageRepository.save(postImage);
87+
post.addImage(postImage);
9288
}
9389
}
9490

@@ -264,11 +260,12 @@ public PostLikeResponseDto toggleLike(Long postId) {
264260
abvScoreService.awardForLike(user.getId());
265261

266262
// 게시글 작성자에게 알림 전송
263+
String likeMessage = String.format("%s 님이 '%s' 게시글에 추천을 남겼습니다.", user.getNickname(), post.getTitle());
267264
notificationService.sendNotification(
268265
post.getUser(),
269266
post,
270267
NotificationType.LIKE,
271-
user.getNickname() + " 님이 추천을 남겼습니다."
268+
likeMessage
272269
);
273270

274271
return new PostLikeResponseDto(postLike.getStatus());
@@ -294,23 +291,23 @@ private List<Post> findAllPosts(PostSortScrollRequestDto reqBody) {
294291
return switch (reqBody.postSortStatus()) {
295292
case POPULAR -> {
296293
if (reqBody.lastId() == null || reqBody.lastLikeCount() == null) {
297-
yield postRepository.findTop10ByOrderByLikeCountDescIdDesc();
294+
yield postRepository.findTop10ByStatusNotOrderByLikeCountDescIdDesc(PostStatus.DELETED);
298295
} else {
299-
yield postRepository.findTop10ByLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(reqBody.lastLikeCount(), reqBody.lastLikeCount(), reqBody.lastId());
296+
yield postRepository.findTop10ByStatusNotAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(PostStatus.DELETED, reqBody.lastLikeCount(), reqBody.lastLikeCount(), reqBody.lastId());
300297
}
301298
}
302299
case COMMENTS -> {
303300
if (reqBody.lastId() == null || reqBody.lastCommentCount() == null) {
304-
yield postRepository.findTop10ByOrderByCommentCountDescIdDesc();
301+
yield postRepository.findTop10ByStatusNotOrderByCommentCountDescIdDesc(PostStatus.DELETED);
305302
} else {
306-
yield postRepository.findTop10ByCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(reqBody.lastCommentCount(), reqBody.lastCommentCount(), reqBody.lastId());
303+
yield postRepository.findTop10ByStatusNotAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(PostStatus.DELETED, reqBody.lastCommentCount(), reqBody.lastCommentCount(), reqBody.lastId());
307304
}
308305
}
309306
case LATEST -> {
310307
if (reqBody.lastId() == null) {
311-
yield postRepository.findTop10ByOrderByIdDesc();
308+
yield postRepository.findTop10ByStatusNotOrderByIdDesc(PostStatus.DELETED);
312309
} else {
313-
yield postRepository.findTop10ByIdLessThanOrderByIdDesc(reqBody.lastId());
310+
yield postRepository.findTop10ByStatusNotAndIdLessThanOrderByIdDesc(PostStatus.DELETED, reqBody.lastId());
314311
}
315312
}
316313
default -> throw new IllegalArgumentException("지원하지 않는 정렬 기준: " + reqBody.postSortStatus());
@@ -322,29 +319,29 @@ private List<Post> findPostsByCategory(PostSortScrollRequestDto reqBody) {
322319
return switch (reqBody.postSortStatus()) {
323320
case POPULAR -> {
324321
if (reqBody.lastId() == null || reqBody.lastLikeCount() == null) {
325-
yield postRepository.findTop10ByCategoryIdOrderByLikeCountDescIdDesc(
326-
reqBody.categoryId());
322+
yield postRepository.findTop10ByCategoryIdAndStatusNotOrderByLikeCountDescIdDesc(
323+
reqBody.categoryId(), PostStatus.DELETED);
327324
} else {
328-
yield postRepository.findTop10ByCategoryIdAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
329-
reqBody.categoryId(), reqBody.lastLikeCount(), reqBody.lastLikeCount(),
325+
yield postRepository.findTop10ByCategoryIdAndStatusNotAndLikeCountLessThanOrLikeCountEqualsAndIdLessThanOrderByLikeCountDescIdDesc(
326+
reqBody.categoryId(), PostStatus.DELETED, reqBody.lastLikeCount(), reqBody.lastLikeCount(),
330327
reqBody.lastId());
331328
}
332329
}
333330
case COMMENTS -> {
334331
if (reqBody.lastId() == null || reqBody.lastCommentCount() == null) {
335-
yield postRepository.findTop10ByCategoryIdOrderByCommentCountDescIdDesc(
336-
reqBody.categoryId());
332+
yield postRepository.findTop10ByCategoryIdAndStatusNotOrderByCommentCountDescIdDesc(
333+
reqBody.categoryId(), PostStatus.DELETED);
337334
} else {
338-
yield postRepository.findTop10ByCategoryIdAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
339-
reqBody.categoryId(), reqBody.lastCommentCount(), reqBody.lastCommentCount(),
335+
yield postRepository.findTop10ByCategoryIdAndStatusNotAndCommentCountLessThanOrCommentCountEqualsAndIdLessThanOrderByCommentCountDescIdDesc(
336+
reqBody.categoryId(), PostStatus.DELETED, reqBody.lastCommentCount(), reqBody.lastCommentCount(),
340337
reqBody.lastId());
341338
}
342339
}
343340
case LATEST -> {
344341
if (reqBody.lastId() == null) {
345-
yield postRepository.findTop10ByCategoryIdOrderByIdDesc(reqBody.categoryId());
342+
yield postRepository.findTop10ByCategoryIdAndStatusNotOrderByIdDesc(reqBody.categoryId(), PostStatus.DELETED);
346343
} else {
347-
yield postRepository.findTop10ByCategoryIdAndIdLessThanOrderByIdDesc(reqBody.categoryId(),
344+
yield postRepository.findTop10ByCategoryIdAndStatusNotAndIdLessThanOrderByIdDesc(reqBody.categoryId(), PostStatus.DELETED,
348345
reqBody.lastId());
349346
}
350347
}

src/main/java/com/back/domain/user/service/AbvScoreService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ public void revokeForKeep(Long userId) {
5858
addScore(userId, -KEEP_SCORE);
5959
}
6060

61+
@Transactional
62+
public void revokeForKeep(Long userId, int count) {
63+
if (count <= 0) {
64+
return;
65+
}
66+
addScore(userId, -KEEP_SCORE * count);
67+
}
68+
6169
private void addScore(Long userId, double delta) {
6270
User user = userRepository.findById(userId)
6371
.orElseThrow(() -> new ServiceException(404, "사용자를 찾을 수 없습니다."));

0 commit comments

Comments
 (0)