Skip to content

Commit

Permalink
feat: 타입 별 카드 마지막 업로드 시간 조회 (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
xxoznge authored Sep 23, 2024
1 parent f58a846 commit 0def2b9
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class CardController {
private final CardService cardService;
private final CardQueryService cardQueryService;

/* 카드 작성 */
@PostMapping(value = "", consumes = "multipart/form-data")
public ApiResponse<CardCreateResponse> createCard(
@UserResolver User authUser,
Expand All @@ -47,45 +48,61 @@ public ApiResponse<CardCreateResponse> createCard(
return ApiResponse.onSuccess(cardService.createCard(authUser, request, file));
}

@GetMapping("/{cardId}")
public ApiResponse<CardDetailGetResponse> getCardDetail(
@PathVariable Long cardId
) {
return ApiResponse.onSuccess(cardQueryService.getCardDetail(cardId));
}

/* 오늘의 따봉도치 랭킹 조회 */
@GetMapping("/top")
public ApiResponse<List<CardSummaryGetResponse>> getTopCardToday() {
return ApiResponse.onSuccess(cardQueryService.getTopCardToday());
}

/* 전체 카드 목록 조회 */
@GetMapping("")
public ApiResponse<List<CardSummaryGetResponse>> getCard(
@RequestParam(name = "sort") CardStatus sortStatus
) {
// 최신순 조회
if (sortStatus == CardStatus.RECENT) {
return ApiResponse.onSuccess(cardQueryService.getRecentCard());
}
// 인기순 조회
if (sortStatus == CardStatus.POPULAR) {
return ApiResponse.onSuccess(cardQueryService.getPopularCard());
}
return ApiResponse.onSuccess(Collections.emptyList());
}

/* 테마 별 카드 목록 조회 */
@GetMapping("/type")
public ApiResponse<List<CardSummaryGetResponse>> getTypeCard(
@RequestParam(name = "type") FortuneType type,
@RequestParam(name = "sort") CardStatus sortStatus
) {
// 최신순 조회
if (sortStatus == CardStatus.RECENT) {
return ApiResponse.onSuccess(cardQueryService.getRecentTypeCard(type));
}
// 인기순 조회
if (sortStatus == CardStatus.POPULAR) {
return ApiResponse.onSuccess(cardQueryService.getPopularTypeCard(type));
}
return ApiResponse.onSuccess(Collections.emptyList());
}

/* 카드 상세 조회 */
@GetMapping("/{cardId}")
public ApiResponse<CardDetailGetResponse> getCardDetail(
@PathVariable Long cardId
) {
return ApiResponse.onSuccess(cardQueryService.getCardDetail(cardId));
}

/* 타입 별 카드 마지막 업로드 시간 조회 */
@GetMapping("/last")
public ApiResponse<String> getLastUploadTime(@RequestParam(name = "type") FortuneType type) {
String lastUploadTime = cardQueryService.getLastUploadTime(type);
return ApiResponse.onSuccess(lastUploadTime);
}

/* 카드 삭제 */
@DeleteMapping("/{cardId}")
public ApiResponse<String> deleteCard(
@UserResolver User authUser,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.ddabong.ddabongdotchiBE.domain.card.dto.request;

import java.time.LocalDateTime;

import com.ddabong.ddabongdotchiBE.domain.card.entity.Card;
import com.ddabong.ddabongdotchiBE.domain.card.entity.FortuneType;
import com.ddabong.ddabongdotchiBE.domain.user.entity.User;
Expand Down Expand Up @@ -30,6 +32,7 @@ public Card toEntity(
.content(content)
.type(FortuneType.valueOf(type))
.user(cardUser)
.lastUploadTime(LocalDateTime.now())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ddabong.ddabongdotchiBE.domain.card.entity;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -60,6 +61,9 @@ public class Card extends BaseEntity {
@Column(name = "comment_count", nullable = false)
private long commentCount;

@Column(name = "last_upload_time")
private LocalDateTime lastUploadTime;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private User user;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
public enum CardErrorCode implements BaseErrorCode {

USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USR4000", "존재하지 않는 사용자입니다."),
CARD_NOT_FOUND(HttpStatus.NOT_FOUND, "CARD4040", "해당 카드가 존재하지 않습니다.");
CARD_NOT_FOUND(HttpStatus.NOT_FOUND, "CARD4040", "해당 카드가 존재하지 않습니다."),
UNAUTHORIZED_ACCESS(HttpStatus.FORBIDDEN, "CARD4030", "권한이 없습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,27 @@ public interface CardRepository extends JpaRepository<Card, Long> {

Optional<Card> findById(Long Id);

// 전체 카드 최신순
List<Card> findAllByOrderByCreatedAtDesc();

// 전체 카드 인기순
List<Card> findAllByOrderByCommentCountDescCreatedAtDesc();

// 타입 별 카드 최신순
List<Card> findAllByTypeOrderByCreatedAtDesc(FortuneType type);

// 타입 별 카드 인기순
List<Card> findAllByTypeOrderByCommentCountDescCreatedAtDesc(FortuneType type);

// 오늘의 따봉도치 랭킹
@Query("SELECT c FROM Card c WHERE c.createdAt >= :today ORDER BY c.commentCount DESC LIMIT 3")
List<Card> findTop3CommentedCardsToday(@Param("today") LocalDateTime today);

// 카드 없을 시 오늘의 따봉도치 랜덤 조회
@Query("SELECT c FROM Card c ORDER BY RAND() LIMIT 3")
List<Card> findRandom3Cards();

// 타입 별 카드 마지막 업로드 시간 조회
@Query("SELECT c.lastUploadTime FROM Card c WHERE c.type = :fortuneType ORDER BY c.lastUploadTime DESC")
LocalDateTime findLastUploadTimeByType(@Param("fortuneType") FortuneType fortuneType);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ddabong.ddabongdotchiBE.domain.card.service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

Expand All @@ -25,52 +26,69 @@ public class CardQueryService {

private final CardRepository cardRepository;

/* 카드 상세 조회 */
public CardDetailGetResponse getCardDetail(Long cardId) {
final Card card = cardRepository.findById(cardId)
.orElseThrow(() -> new CardExceptionHandler(CardErrorCode.CARD_NOT_FOUND));

return CardDetailGetResponse.from(card);
}

/* 오늘의 따봉도치 랭킹 조회 */
public List<CardSummaryGetResponse> getTopCardToday() {
LocalDateTime today = LocalDateTime.now().toLocalDate().atStartOfDay();
List<Card> top3CommentedCards = cardRepository.findTop3CommentedCardsToday(today);

// 댓글 많은 카드가 없을 경우 바로 랜덤 3개 카드 반환
return top3CommentedCards.isEmpty()
? cardRepository.findRandom3Cards().stream()
.map(CardSummaryGetResponse::from)
.toList()
: top3CommentedCards.stream()
.map(CardSummaryGetResponse::from)
.toList();
}

/* 전체 카드 최신순 조회 */
public List<CardSummaryGetResponse> getRecentCard() {
return cardRepository.findAllByOrderByCreatedAtDesc()
.stream()
.map(CardSummaryGetResponse::from)
.toList();
}

/* 전체 카드 인기순 조회 */
public List<CardSummaryGetResponse> getPopularCard() {
return cardRepository.findAllByOrderByCommentCountDescCreatedAtDesc()
.stream()
.map(CardSummaryGetResponse::from)
.toList();
}

/* 타입 별 카드 최신순 조회 */
public List<CardSummaryGetResponse> getRecentTypeCard(FortuneType fortuneType) {
return cardRepository.findAllByTypeOrderByCreatedAtDesc(fortuneType)
.stream()
.map(CardSummaryGetResponse::from)
.toList();
}

/* 타입 별 카드 인기순 조회 */
public List<CardSummaryGetResponse> getPopularTypeCard(FortuneType fortuneType) {
return cardRepository.findAllByTypeOrderByCommentCountDescCreatedAtDesc(fortuneType)
.stream()
.map(CardSummaryGetResponse::from)
.toList();
}

public List<CardSummaryGetResponse> getTopCardToday() {
LocalDateTime today = LocalDateTime.now().toLocalDate().atStartOfDay();
List<Card> top3CommentedCards = cardRepository.findTop3CommentedCardsToday(today);

// 댓글 많은 카드가 없을 경우 바로 랜덤 3개 카드 반환
return top3CommentedCards.isEmpty()
? cardRepository.findRandom3Cards().stream()
.map(CardSummaryGetResponse::from)
.toList()
: top3CommentedCards.stream()
.map(CardSummaryGetResponse::from)
.toList();
/* 타입 별 카드 마지막 업로드 시간 조회 */
public String getLastUploadTime(FortuneType type) {
LocalDateTime lastUploadTime = cardRepository.findLastUploadTimeByType(type);
if (lastUploadTime == null) {
return "마지막 업로드 시간이 없습니다.";
}
Duration duration = Duration.between(lastUploadTime, LocalDateTime.now());
long minutes = duration.toMinutes();
return minutes + "분 전";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class CardService {
private final CardRepository cardRepository;
private final S3Service s3Service;

/* 카드 작성 */
public CardCreateResponse createCard(
User authUser,
CardCreateRequest request,
Expand All @@ -37,11 +38,12 @@ public CardCreateResponse createCard(
return CardCreateResponse.from(card);
}

/* 카드 삭제 */
public void deleteCard(User user, Long cardId) {
final Card card = cardRepository.findById(cardId)
.orElseThrow(() -> new CardExceptionHandler(CardErrorCode.CARD_NOT_FOUND));
if (!card.getUser().getUsername().equals(user.getUsername())) {
throw new CardExceptionHandler(CardErrorCode.CARD_NOT_FOUND);
throw new CardExceptionHandler(CardErrorCode.UNAUTHORIZED_ACCESS);
}
cardRepository.delete(card);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public record UserJoinRequest(
@NotBlank(message = "[ERROR] 닉네임 입력은 필수입니다.")
@Pattern(regexp = "^[가-힣]{2,7}$", message = "[ERROR] 닉네임은 한글로 2~7글자여야 합니다.")
String nickname,

String description
) {

Expand Down

0 comments on commit 0def2b9

Please sign in to comment.