Skip to content

Commit

Permalink
Merge pull request #66 from MoneyMakersClub/develop
Browse files Browse the repository at this point in the history
[Deploy] UserBadge, Item API 배포
  • Loading branch information
seohyun-lee authored Nov 10, 2024
2 parents 770073b + e1571e2 commit 0eadacd
Show file tree
Hide file tree
Showing 33 changed files with 504 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@


import com.mmc.bookduck.domain.archive.entity.Archive;
import com.mmc.bookduck.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface ArchiveRepository extends JpaRepository<Archive, Long> {
Optional<Archive> findByExcerpt_ExcerptId(Long excerptId);

Optional<Archive> findByReview_ReviewId(Long reviewId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.mmc.bookduck.domain.badge.controller;

import com.mmc.bookduck.domain.badge.service.UserBadgeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
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;

@Tag(name = "UserBadge", description = "UserBadge 관련 API입니다.")
@RestController
@RequiredArgsConstructor
public class UserBadgeController {
private final UserBadgeService userBadgeService;

@Operation(summary = "유저의 뱃지 목록 조회", description = "유저의 닉네임과 기록 수를 조회합니다.")
@GetMapping("/users/{userId}/badges")
public ResponseEntity<?> getUserBadges(@PathVariable final Long userId) {
return ResponseEntity.ok().body(userBadgeService.getUserBadges(userId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.mmc.bookduck.domain.badge.dto.common;

import com.mmc.bookduck.domain.badge.entity.Badge;
import com.mmc.bookduck.domain.badge.entity.BadgeType;
import com.mmc.bookduck.domain.badge.entity.UserBadge;

import java.time.LocalDate;

public record UserBadgeUnitDto(
BadgeType badgeType,
String badgeName,
String description,
int unlockValue,
LocalDate createdDate,
Boolean isOwned
) {
public static UserBadgeUnitDto from(Badge badge, UserBadge userBadge, int unlockValue) {
LocalDate localDate = userBadge != null ? userBadge.getCreatedTime().toLocalDate() : null;
Boolean isOwned = userBadge != null;
return new UserBadgeUnitDto(
badge.getBadgeType(),
badge.getBadgeName(),
badge.getDescription(),
unlockValue,
localDate,
isOwned
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mmc.bookduck.domain.badge.dto.response;

import com.mmc.bookduck.domain.badge.dto.common.UserBadgeUnitDto;

import java.util.List;

public record UserBadgeListResponseDto(
long currentReadCount,
long currentArchiveCount,
long currentOneLineCount,
long currentLevel,
List<UserBadgeUnitDto> readBadgeList,
List<UserBadgeUnitDto> archiveBadgeList,
List<UserBadgeUnitDto> oneLineBadgeList,
List<UserBadgeUnitDto> levelBadgeList
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public class Badge {
@NotNull
private String unlockCondition; // 추후 수정 필요할 수 있음


@Builder
public Badge(String badgeName, BadgeType badgeType, String description, String unlockCondition) {
this.badgeName = badgeName;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.mmc.bookduck.domain.badge.entity;

public enum BadgeType {
NORMAL,
CATEGORY_COLLECTION
READ,
ARCHIVE,
ONELINE,
LEVEL
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.mmc.bookduck.domain.badge.repository;

import com.mmc.bookduck.domain.badge.entity.Badge;
import com.mmc.bookduck.domain.badge.entity.BadgeType;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface BadgeRepository extends JpaRepository<Badge, Long> {
int countByBadgeType(BadgeType badgeType);

List<Badge> findAllByBadgeType(BadgeType badgeType);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.mmc.bookduck.domain.badge.repository;

import com.mmc.bookduck.domain.badge.entity.UserBadge;
import com.mmc.bookduck.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserBadgeRepository extends JpaRepository<UserBadge, Long> {
List<UserBadge> findAllByUser(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.mmc.bookduck.domain.badge.service;

import com.mmc.bookduck.domain.badge.entity.Badge;
import com.mmc.bookduck.domain.badge.entity.BadgeType;
import com.mmc.bookduck.domain.badge.repository.BadgeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class BadgeService {
private final BadgeRepository badgeRepository;

@Transactional(readOnly = true)
public int countBadgesByType(BadgeType badgeType) {
return badgeRepository.countByBadgeType(badgeType);
}

@Transactional(readOnly = true)
public List<Badge> getAllBadgesByType(BadgeType badgeType) {
return badgeRepository.findAllByBadgeType(badgeType);
}

@Transactional(readOnly = true)
public List<Badge> getAllBadges() {
return badgeRepository.findAll();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.mmc.bookduck.domain.badge.service;

import com.mmc.bookduck.domain.archive.repository.ArchiveRepository;
import com.mmc.bookduck.domain.archive.repository.ExcerptRepository;
import com.mmc.bookduck.domain.archive.repository.ReviewRepository;
import com.mmc.bookduck.domain.archive.service.ArchiveService;
import com.mmc.bookduck.domain.badge.dto.common.UserBadgeUnitDto;
import com.mmc.bookduck.domain.badge.dto.response.UserBadgeListResponseDto;
import com.mmc.bookduck.domain.badge.entity.Badge;
import com.mmc.bookduck.domain.badge.entity.BadgeType;
import com.mmc.bookduck.domain.badge.entity.UserBadge;
import com.mmc.bookduck.domain.badge.repository.UserBadgeRepository;
import com.mmc.bookduck.domain.book.service.UserBookService;
import com.mmc.bookduck.domain.onelinerating.entity.OneLineRating;
import com.mmc.bookduck.domain.onelinerating.repository.OneLineRatingRepository;
import com.mmc.bookduck.domain.user.entity.User;
import com.mmc.bookduck.domain.user.service.UserGrowthService;
import com.mmc.bookduck.domain.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserBadgeService {
private final UserBadgeRepository userBadgeRepository;
private final OneLineRatingRepository oneLineRatingRepository;
private final ReviewRepository reviewRepository;
private final ExcerptRepository excerptRepository;
private final UserService userService;
private final BadgeService badgeService;
private final UserBookService userBookService;
private final UserGrowthService userGrowthService;

@Transactional(readOnly = true)
public UserBadgeListResponseDto getUserBadges(Long userId) {
User user = userService.getUserByUserId(userId);
List<UserBadge> uniqueUserBadges = deleteDuplicateUserBadges(userBadgeRepository.findAllByUser(user));

// 전체 뱃지
List<Badge> allBadges = badgeService.getAllBadges();

// 사용자가 가진 뱃지를 badgeId로 맵핑
Map<Long, UserBadge> userBadgeMap = uniqueUserBadges.stream()
.collect(Collectors.toMap(badge -> badge.getBadge().getBadgeId(), badge -> badge));

// 모든 뱃지와 isOwned를 결합한 리스트 생성
List<UserBadgeUnitDto> allBadgesWithOwnership = allBadges.stream()
.map(badge -> UserBadgeUnitDto.from(badge, userBadgeMap.get(badge.getBadgeId()), getBadgeUnlockValue(badge)))
.collect(Collectors.toList());

// BadgeType별로 뱃지 리스트 나누기
List<UserBadgeUnitDto> readBadgeList = filterByBadgeType(allBadgesWithOwnership, BadgeType.READ);
List<UserBadgeUnitDto> archiveBadgeList = filterByBadgeType(allBadgesWithOwnership, BadgeType.ARCHIVE);
List<UserBadgeUnitDto> oneLineBadgeList = filterByBadgeType(allBadgesWithOwnership, BadgeType.ONELINE);
List<UserBadgeUnitDto> levelBadgeList = filterByBadgeType(allBadgesWithOwnership, BadgeType.LEVEL);

// 각 분야별 사용자 상태 가져오기
long currentReadCount = userBookService.countFinishedUserBooksByUser(user);
long currentArchiveCount = reviewRepository.countByUser(user) + excerptRepository.countByUser(user);
long currentOneLineCount = oneLineRatingRepository.countAllByUser(user);
long currentLevel = userGrowthService.getUserGrowthByUserId(user.getUserId()).getLevel();

return new UserBadgeListResponseDto(
currentReadCount,
currentArchiveCount,
currentOneLineCount,
currentLevel,
readBadgeList,
archiveBadgeList,
oneLineBadgeList,
levelBadgeList
);
}

private int getBadgeUnlockValue(Badge badge) {
try {
return Integer.parseInt(badge.getUnlockCondition());
} catch (NumberFormatException e) {
return 0;
}
}

private List<UserBadgeUnitDto> filterByBadgeType(List<UserBadgeUnitDto> allBadgesWithOwnership, BadgeType badgeType) {
return allBadgesWithOwnership.stream()
.filter(dto -> dto.badgeType().equals(badgeType))
.collect(Collectors.toList());
}

@Transactional
public List<UserBadge> deleteDuplicateUserBadges(List<UserBadge> userBadges) {
// 중복 제거: 동일한 badgeId를 가진 UserBadge가 여러 개 있으면 하나만 남기기
Map<Long, UserBadge> badgeIdToUniqueUserBadgeMap = userBadges.stream()
.collect(Collectors.toMap(
userBadge -> userBadge.getBadge().getBadgeId(), // 중복 제거 기준: badgeId
userBadge -> userBadge,
(existing, duplicate) -> existing // 중복 시 기존 항목 유지
));

// distinctUserBadges에 포함되지 않는 중복 UserBadge 식별
List<UserBadge> duplicateUserBadges = userBadges.stream()
.filter(userBadge -> !badgeIdToUniqueUserBadgeMap.containsValue(userBadge))
.collect(Collectors.toList());

// 중복된 UserBadge 삭제
if (!duplicateUserBadges.isEmpty()) {
userBadgeRepository.deleteAll(duplicateUserBadges);
}

return new ArrayList<>(badgeIdToUniqueUserBadgeMap.values());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class UserBook extends BaseTimeEntity {
private boolean isArchiveExpGiven;

@ColumnDefault("false")
private boolean isRatingExpGiven;
private boolean isOneLineExpGiven;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", updatable = false)
Expand All @@ -50,7 +50,7 @@ public UserBook(ReadStatus readStatus, User user, BookInfo bookInfo) {
this.bookInfo = bookInfo;
this.isFinishedExpGiven = false;
this.isArchiveExpGiven = false;
this.isRatingExpGiven = false;
this.isOneLineExpGiven = false;
}

public void changeReadStatus(ReadStatus readStatus) {
Expand All @@ -68,7 +68,7 @@ public void markArchiveExpGiven() {
}

// 한줄평 경험치 획득 표시
public void markRatingExpGiven() {
this.isRatingExpGiven = true;
public void markOneLineExpGiven() {
this.isOneLineExpGiven = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ public interface UserBookRepository extends JpaRepository<UserBook, Long> {

List<UserBook> findByUserAndReadStatus(User user, ReadStatus readStatus);

long countByUserAndReadStatus(User user, ReadStatus readStatus);

// userbook 테이블과 bookinfo 테이블 조인해서 userbook의 user에 해당하는 bookinfo 정보 검색
@Query("SELECT ub FROM UserBook ub JOIN ub.bookInfo b WHERE ub.user = :userId AND (" +
"b.title LIKE %:keyword% OR b.author LIKE %:keyword% OR b.description LIKE %:keyword%)")
List<UserBook> searchByUserIdAndKeyword(@Param("userId") User user, @Param("keyword") String keyword);

Optional<UserBook> findByUserAndBookInfo(User user, BookInfo bookInfo);

List<UserBook> findByBookInfo(BookInfo bookInfo);

//최신순
List<UserBook> findAllByUserOrderByCreatedTimeDesc(User user);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,9 @@ public CustomBookResponseDto createCustomBook(CustomBookRequestDto requestDto) {

return CustomBookResponseDto.from(savedUserBook, null, null);
}

@Transactional(readOnly = true)
public long countFinishedUserBooksByUser(User user) {
return userBookRepository.countByUserAndReadStatus(user, ReadStatus.FINISHED);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.mmc.bookduck.domain.friend.dto.common;

import com.mmc.bookduck.domain.friend.entity.FriendRequest;
import com.mmc.bookduck.domain.item.dto.common.UserItemEquippedDto;
import com.mmc.bookduck.domain.item.dto.common.ItemEquippedUnitDto;

import java.util.List;

public record FriendRequestUnitDto(
Long requestId,
Long userId,
String userNickname,
UserItemEquippedDto userItemEquipped
List<ItemEquippedUnitDto> userItemEquipped
) {
public static FriendRequestUnitDto from(FriendRequest friendRequest, Long userId, String userNickname, UserItemEquippedDto userItemEquipped) {
public static FriendRequestUnitDto from(FriendRequest friendRequest, Long userId, String userNickname, List<ItemEquippedUnitDto> userItemEquipped) {
return new FriendRequestUnitDto(
friendRequest.getRequestId(),
userId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.mmc.bookduck.domain.friend.dto.common;

import com.mmc.bookduck.domain.friend.entity.Friend;
import com.mmc.bookduck.domain.item.dto.common.UserItemEquippedDto;
import com.mmc.bookduck.domain.item.dto.common.ItemEquippedUnitDto;

import java.util.List;

public record FriendUnitDto(
Long friendId, // 친구 삭제 기능
Long userId,
String nickname,
UserItemEquippedDto userItemEquipped
List<ItemEquippedUnitDto> userItemEquipped
) {
public static FriendUnitDto from(Friend friend, UserItemEquippedDto userItemEquipped) {
public static FriendUnitDto from(Friend friend, List<ItemEquippedUnitDto> userItemEquipped) {
return new FriendUnitDto(
friend.getFriendId(),
friend.getUser2().getUserId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public FriendRequestListResponseDto getReceivedFriendRequests() {
friendRequest,
friendRequest.getSender().getUserId(),
friendRequest.getSender().getNickname(),
userItemService.getEquippedItemOrDefault(friendRequest.getSender().getUserId())
userItemService.getUserItemEquippedListOfUser(friendRequest.getSender())
))
.collect(Collectors.toList());
return FriendRequestListResponseDto.from(receivedList);
Expand All @@ -90,7 +90,7 @@ public FriendRequestListResponseDto getSentFriendRequests() {
friendRequest,
friendRequest.getReceiver().getUserId(),
friendRequest.getReceiver().getNickname(),
userItemService.getEquippedItemOrDefault(friendRequest.getReceiver().getUserId())
userItemService.getUserItemEquippedListOfUser(friendRequest.getReceiver())
))
.collect(Collectors.toList());
return FriendRequestListResponseDto.from(sentList);
Expand Down
Loading

0 comments on commit 0eadacd

Please sign in to comment.