Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 277 additions & 5 deletions src/main/java/com/back/global/init/DevInitData.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
package com.back.global.init;

import com.back.domain.notification.entity.Notification;
import com.back.domain.notification.enums.NotificationType;
import com.back.domain.notification.repository.NotificationRepository;
import com.back.domain.cocktail.entity.Cocktail;
import com.back.domain.cocktail.enums.AlcoholBaseType;
import com.back.domain.cocktail.enums.AlcoholStrength;
import com.back.domain.cocktail.enums.CocktailType;
import com.back.domain.cocktail.repository.CocktailRepository;
import com.back.domain.cocktail.service.CocktailService;
import com.back.domain.post.category.entity.Category;
import com.back.domain.post.category.repository.CategoryRepository;
import com.back.domain.post.comment.entity.Comment;
import com.back.domain.post.comment.repository.CommentRepository;
import com.back.domain.post.post.entity.Post;
import com.back.domain.post.post.entity.PostLike;
import com.back.domain.post.post.enums.PostLikeStatus;
import com.back.domain.post.post.repository.PostLikeRepository;
import com.back.domain.post.post.repository.PostRepository;
import com.back.domain.user.entity.User;
import com.back.domain.user.repository.UserRepository;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
Expand All @@ -15,19 +33,273 @@
@RequiredArgsConstructor
public class DevInitData {

private final UserRepository userRepository;
private final CategoryRepository categoryRepository;
private final PostRepository postRepository;
private final CommentRepository commentRepository;
private final PostLikeRepository postLikeRepository;
private final NotificationRepository notificationRepository;
private final CocktailRepository cocktailRepository;
private final CocktailService cocktailService;
private final com.back.domain.mybar.service.MyBarService myBarService;
private final com.back.domain.mybar.repository.MyBarRepository myBarRepository;

@Autowired
@Lazy
private DevInitData self;


@Bean
ApplicationRunner devInitDataApplicationRunner() {
return args -> {
// self.cocktailInit(); // 테스트용 데이터 삽입
self.cocktailInit();
self.userInit();
self.boardInit();
self.myBarInit();
self.notificationInit();
};
}
}

@Transactional
public void cocktailInit() {
if (cocktailRepository.count() > 0) return;

// 1) 하이볼
cocktailRepository.save(Cocktail.builder()
.cocktailName("Highball")
.cocktailNameKo("하이볼")
.alcoholStrength(AlcoholStrength.LIGHT)
.cocktailType(CocktailType.LONG)
.alcoholBaseType(AlcoholBaseType.WHISKY)
.ingredient("위스키, 탄산수, 얼음, 레몬피")
.recipe("잔에 얼음 → 위스키 → 탄산수 → 가볍게 스터")
.cocktailImgUrl("/img/cocktail/1.jpg")
.build());

// 2) 진토닉
cocktailRepository.save(Cocktail.builder()
.cocktailName("Gin and Tonic")
.cocktailNameKo("진토닉")
.alcoholStrength(AlcoholStrength.WEAK)
.cocktailType(CocktailType.LONG)
.alcoholBaseType(AlcoholBaseType.GIN)
.ingredient("진, 토닉워터, 얼음, 라임")
.recipe("잔에 얼음 → 진 → 토닉워터 → 라임")
.cocktailImgUrl("/img/cocktail/2.jpg")
.build());

// 3) 올드패션드
cocktailRepository.save(Cocktail.builder()
.cocktailName("Old Fashioned")
.cocktailNameKo("올드패션드")
.alcoholStrength(AlcoholStrength.STRONG)
.cocktailType(CocktailType.SHORT)
.alcoholBaseType(AlcoholBaseType.WHISKY)
.ingredient("버번 위스키, 설탕/시럽, 앙고스투라 비터스, 오렌지 필")
.recipe("시럽+비터스 → 위스키 → 얼음 → 스터 → 오렌지 필")
.cocktailImgUrl("/img/cocktail/3.jpg")
.build());

// 4) 모히또
cocktailRepository.save(Cocktail.builder()
.cocktailName("Mojito")
.cocktailNameKo("모히또")
.alcoholStrength(AlcoholStrength.LIGHT)
.cocktailType(CocktailType.LONG)
.alcoholBaseType(AlcoholBaseType.RUM)
.ingredient("라임, 민트, 설탕/시럽, 화이트 럼, 탄산수, 얼음")
.recipe("라임+민트+시럽 머들 → 럼 → 얼음 → 탄산수")
.cocktailImgUrl("/img/cocktail/4.jpg")
.build());
}

@Transactional
public void userInit() {
userRepository.findByNickname("사용자A").orElseGet(() ->
userRepository.save(User.builder().nickname("사용자A").role("USER").build())
);
userRepository.findByNickname("사용자B").orElseGet(() ->
userRepository.save(User.builder().nickname("사용자B").role("USER").build())
);
userRepository.findByNickname("사용자C").orElseGet(() ->
userRepository.save(User.builder().nickname("사용자C").role("USER").build())
);
}

@Transactional
public void boardInit() {
if (postRepository.count() > 0) return;

User userA = userRepository.findByNickname("사용자A").orElseThrow();
User userB = userRepository.findByNickname("사용자B").orElseThrow();
User userC = userRepository.findByNickname("사용자C").orElseThrow();

Category free = categoryRepository.findAll().stream()
.filter(c -> "자유".equals(c.getName()))
.findFirst()
.orElseGet(() -> categoryRepository.save(Category.builder()
.name("자유")
.description("자유 게시판")
.build()));

Post postA = postRepository.save(Post.builder()
.category(free)
.user(userA)
.title("A의 게시글")
.content("내용A")
.imageUrl("/img/cocktail/1.jpg")
.build());

Post postB = postRepository.save(Post.builder()
.category(free)
.user(userB)
.title("B의 게시글")
.content("내용B")
.imageUrl("/img/cocktail/2.jpg")
.build());

// 댓글: C가 A/B 게시글에 작성
commentRepository.save(Comment.builder()
.post(postA)
.user(userC)
.content("C의 댓글 on A")
.build());

commentRepository.save(Comment.builder()
.post(postB)
.user(userC)
.content("C의 댓글 on B")
.build());

// 좋아요: A→B, B→A, C→A, C→B
postLikeRepository.save(PostLike.builder()
.post(postB)
.user(userA)
.status(PostLikeStatus.LIKE)
.build());
postB.increaseLikeCount();

postLikeRepository.save(PostLike.builder()
.post(postA)
.user(userB)
.status(PostLikeStatus.LIKE)
.build());
postA.increaseLikeCount();

postLikeRepository.save(PostLike.builder()
.post(postA)
.user(userC)
.status(PostLikeStatus.LIKE)
.build());
postA.increaseLikeCount();

postLikeRepository.save(PostLike.builder()
.post(postB)
.user(userC)
.status(PostLikeStatus.LIKE)
.build());
postB.increaseLikeCount();

postRepository.save(postA);
postRepository.save(postB);

// B 사용자 soft delete (게시글/좋아요/댓글 생성 후)
User b = userRepository.findByNickname("사용자B").orElseThrow();
b.markDeleted("탈퇴한 사용자");
userRepository.save(b);
}

@Transactional
public void notificationInit() {
if (notificationRepository.count() > 0) return;

// 게시글 소유자에게 COMMENT/LIKE 알림 생성
Post postA = postRepository.findAll().stream()
.filter(p -> "A의 게시글".equals(p.getTitle()))
.findFirst().orElse(null);
Post postB = postRepository.findAll().stream()
.filter(p -> "B의 게시글".equals(p.getTitle()))
.findFirst().orElse(null);
if (postA == null || postB == null) return;

User ownerA = postA.getUser();
User ownerB = postB.getUser();

notificationRepository.save(Notification.builder()
.user(ownerA)
.post(postA)
.type(NotificationType.COMMENT)
.message("새 댓글이 달렸습니다.")
.build());

notificationRepository.save(Notification.builder()
.user(ownerA)
.post(postA)
.type(NotificationType.LIKE)
.message("게시글에 좋아요가 추가되었습니다.")
.build());

notificationRepository.save(Notification.builder()
.user(ownerA)
.post(postA)
.type(NotificationType.LIKE)
.message("게시글에 좋아요가 추가되었습니다.")
.build());

notificationRepository.save(Notification.builder()
.user(ownerB)
.post(postB)
.type(NotificationType.COMMENT)
.message("새 댓글이 달렸습니다.")
.build());

notificationRepository.save(Notification.builder()
.user(ownerB)
.post(postB)
.type(NotificationType.LIKE)
.message("게시글에 좋아요가 추가되었습니다.")
.build());

notificationRepository.save(Notification.builder()
.user(ownerB)
.post(postB)
.type(NotificationType.LIKE)
.message("게시글에 좋아요가 추가되었습니다.")
.build());
}

@Transactional
public void myBarInit() {
if (myBarRepository.count() > 0) return;

User userA = userRepository.findByNickname("사용자A").orElseThrow();
User userB = userRepository.findByNickname("사용자B").orElseThrow();
User userC = userRepository.findByNickname("사용자C").orElseThrow();

// 칵테일 참조 준비
var cocktails = cocktailRepository.findAll();
Cocktail c1 = cocktails.stream().filter(c -> "하이볼".equals(c.getCocktailNameKo())).findFirst().orElse(null);
Cocktail c2 = cocktails.stream().filter(c -> "진토닉".equals(c.getCocktailNameKo())).findFirst().orElse(null);
Cocktail c3 = cocktails.stream().filter(c -> "올드패션드".equals(c.getCocktailNameKo())).findFirst().orElse(null);
Cocktail c4 = cocktails.stream().filter(c -> "모히또".equals(c.getCocktailNameKo())).findFirst().orElse(null);

// 방어: 칵테일 누락 시 스킵
if (c1 == null || c2 == null || c3 == null || c4 == null) return;

// A: c1(now-2d), c2(now-1d)
myBarService.keep(userA.getId(), c1.getId());
myBarService.keep(userA.getId(), c2.getId());
myBarRepository.findByUser_IdAndCocktail_Id(userA.getId(), c1.getId()).ifPresent(m -> m.setKeptAt(java.time.LocalDateTime.now().minusDays(2)));
myBarRepository.findByUser_IdAndCocktail_Id(userA.getId(), c2.getId()).ifPresent(m -> m.setKeptAt(java.time.LocalDateTime.now().minusDays(1)));

// B: c3 keep 후 unkeep -> DELETED
myBarService.keep(userB.getId(), c3.getId());
myBarService.unkeep(userB.getId(), c3.getId());

// C: c2(now-3d), c3(now-2d), c4(now-1h)
myBarService.keep(userC.getId(), c2.getId());
myBarService.keep(userC.getId(), c3.getId());
myBarService.keep(userC.getId(), c4.getId());
myBarRepository.findByUser_IdAndCocktail_Id(userC.getId(), c2.getId()).ifPresent(m -> m.setKeptAt(java.time.LocalDateTime.now().minusDays(3)));
myBarRepository.findByUser_IdAndCocktail_Id(userC.getId(), c3.getId()).ifPresent(m -> m.setKeptAt(java.time.LocalDateTime.now().minusDays(2)));
myBarRepository.findByUser_IdAndCocktail_Id(userC.getId(), c4.getId()).ifPresent(m -> m.setKeptAt(java.time.LocalDateTime.now().minusHours(1)));
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/back/global/security/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import static org.springframework.http.HttpMethod.DELETE;

@Configuration
@EnableWebSecurity
Expand Down Expand Up @@ -51,6 +52,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
) // OAuth 인증시 필요할때만 세션 사용

.authorizeHttpRequests(auth -> auth
.requestMatchers(DELETE, "/me/account").authenticated()
// 개발 편의성을 위해 모든 요청 허용
.anyRequest().permitAll()

Expand Down Expand Up @@ -123,4 +125,4 @@ public CorsConfigurationSource corsConfigurationSource() {
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
}
Binary file added src/main/resources/static/img/cocktail/1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/static/img/cocktail/2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/static/img/cocktail/3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/main/resources/static/img/cocktail/4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.