diff --git a/src/main/java/com/back/domain/mybar/controller/MyBarController.java b/src/main/java/com/back/domain/mybar/controller/MyBarController.java index f6226240..57b246e1 100644 --- a/src/main/java/com/back/domain/mybar/controller/MyBarController.java +++ b/src/main/java/com/back/domain/mybar/controller/MyBarController.java @@ -8,10 +8,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/me/bar") @@ -30,4 +27,14 @@ public RsData getMyBarList( MyBarListResponseDto body = myBarService.getMyBar(userId, page, pageSize); return RsData.successOf(body); // code=200, message="success" } + + /** 킵 추가(생성/복원/재킵) */ + @PostMapping("/{cocktailId}/keep") + public RsData keep( + @AuthenticationPrincipal(expression = "id") Long userId, + @PathVariable Long cocktailId + ) { + myBarService.keep(userId, cocktailId); + return RsData.of(201, "kept"); // Aspect가 HTTP 201로 설정 + } } diff --git a/src/main/java/com/back/domain/mybar/dto/MyBarItemResponseDto.java b/src/main/java/com/back/domain/mybar/dto/MyBarItemResponseDto.java index ab8dc85c..2309deb0 100644 --- a/src/main/java/com/back/domain/mybar/dto/MyBarItemResponseDto.java +++ b/src/main/java/com/back/domain/mybar/dto/MyBarItemResponseDto.java @@ -14,6 +14,7 @@ public class MyBarItemResponseDto { private String cocktailName; private String imageUrl; private LocalDateTime createdAt; + private LocalDateTime keptAt; public static MyBarItemResponseDto from(MyBar m) { return MyBarItemResponseDto.builder() @@ -22,6 +23,7 @@ public static MyBarItemResponseDto from(MyBar m) { .cocktailName(m.getCocktail().getCocktailName()) .imageUrl(m.getCocktail().getCocktailImgUrl()) .createdAt(m.getCreatedAt()) + .keptAt(m.getKeptAt()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/back/domain/mybar/entity/MyBar.java b/src/main/java/com/back/domain/mybar/entity/MyBar.java index 376b9cf2..a194c93d 100644 --- a/src/main/java/com/back/domain/mybar/entity/MyBar.java +++ b/src/main/java/com/back/domain/mybar/entity/MyBar.java @@ -27,6 +27,10 @@ public class MyBar { @CreatedDate private LocalDateTime createdAt; + /** 최근에 '킵'된 시각(생성/복원/재킵 시 갱신) — 목록 정렬에 사용 */ + @Column(name = "kept_at", nullable = false) + private LocalDateTime keptAt; + /** 킵 해제 시각 (ACTIVE일 때는 null) */ private LocalDateTime deletedAt; diff --git a/src/main/java/com/back/domain/mybar/repository/MyBarRepository.java b/src/main/java/com/back/domain/mybar/repository/MyBarRepository.java index 97e8ed91..34cd2ade 100644 --- a/src/main/java/com/back/domain/mybar/repository/MyBarRepository.java +++ b/src/main/java/com/back/domain/mybar/repository/MyBarRepository.java @@ -7,11 +7,19 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface MyBarRepository extends JpaRepository { /** 나만의 bar(킵) 목록: ACTIVE만, id desc */ - Page findByUserIdAndStatusOrderByIdDesc(Long userId, KeepStatus status, Pageable pageable); + Page findByUser_IdAndStatusOrderByKeptAtDescIdDesc(Long userId, KeepStatus status, Pageable pageable); /** 프로필/요약용: ACTIVE 개수 */ - long countByUserIdAndStatus(Long userId, KeepStatus status); + long countByUser_IdAndStatus(Long userId, KeepStatus status); + + /** 현재 킵 상태 확인(아이콘 등): ACTIVE 존재 여부 */ + boolean existsByUser_IdAndCocktail_CocktailIdAndStatus(Long userId, Long cocktailId, KeepStatus status); + + /** 복원/재킵을 위해 status 무시하고 한 건 찾기 (없으면 Optional.empty) */ + Optional findByUser_IdAndCocktail_CocktailId(Long userId, Long cocktailId); } diff --git a/src/main/java/com/back/domain/mybar/service/MyBarService.java b/src/main/java/com/back/domain/mybar/service/MyBarService.java index b49c46df..e99330fa 100644 --- a/src/main/java/com/back/domain/mybar/service/MyBarService.java +++ b/src/main/java/com/back/domain/mybar/service/MyBarService.java @@ -1,28 +1,34 @@ package com.back.domain.mybar.service; +import com.back.domain.cocktail.repository.CocktailRepository; import com.back.domain.mybar.dto.MyBarItemResponseDto; import com.back.domain.mybar.dto.MyBarListResponseDto; import com.back.domain.mybar.entity.MyBar; import com.back.domain.mybar.enums.KeepStatus; import com.back.domain.mybar.repository.MyBarRepository; +import com.back.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor public class MyBarService { private final MyBarRepository myBarRepository; + private final UserRepository userRepository; + private final CocktailRepository cocktailRepository; @Transactional(readOnly = true) public MyBarListResponseDto getMyBar(Long userId, int page, int pageSize) { - Page myBarPage = myBarRepository.findByUserIdAndStatusOrderByIdDesc(userId, KeepStatus.ACTIVE, PageRequest.of(page, pageSize)); + Page myBarPage = myBarRepository.findByUser_IdAndStatusOrderByKeptAtDescIdDesc(userId, KeepStatus.ACTIVE, PageRequest.of(page, pageSize)); List myBars = myBarPage.getContent(); List items = new ArrayList<>(); @@ -33,4 +39,33 @@ public MyBarListResponseDto getMyBar(Long userId, int page, int pageSize) { return new MyBarListResponseDto(items, hasNext, nextPage); } + + @Transactional + public void keep(Long userId, Long cocktailId) { + Optional existingMyBar = + myBarRepository.findByUser_IdAndCocktail_CocktailId(userId, cocktailId); + + LocalDateTime now = LocalDateTime.now(); + + if (existingMyBar.isPresent()) { + // 이미 행이 있으면: 최근에 다시 킵했다고 보고 keptAt만 갱신 + MyBar myBar = existingMyBar.get(); + myBar.setKeptAt(now); + if (myBar.getStatus() == KeepStatus.DELETED) { + // 해제돼 있던 건 복원 + myBar.setStatus(KeepStatus.ACTIVE); + myBar.setDeletedAt(null); + } + return; // 이미 ACTIVE여도 keptAt 갱신으로 충분 + } + + // 없으면 새로 생성 + MyBar myBar = new MyBar(); + myBar.setUser(userRepository.getReferenceById(userId)); + myBar.setCocktail(cocktailRepository.getReferenceById(cocktailId)); + myBar.setStatus(KeepStatus.ACTIVE); + myBar.setKeptAt(now); + + myBarRepository.save(myBar); + } }