Skip to content

Commit

Permalink
Merge pull request #1623 from innovationacademy-kr/common/dev/feat_co…
Browse files Browse the repository at this point in the history
…in/admin/hyowchoi#1604

Common/dev/feat coin/admin/hyowchoi#1604
  • Loading branch information
Z1Park authored Jun 3, 2024
2 parents 59c00ff + 45ad553 commit 3cb4a48
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.ftclub.cabinet.admin.statistics.controller;

import lombok.RequiredArgsConstructor;
import org.ftclub.cabinet.admin.statistics.service.AdminStatisticsFacadeService;
import org.ftclub.cabinet.auth.domain.AuthGuard;
import org.ftclub.cabinet.auth.domain.AuthLevel;
import org.ftclub.cabinet.dto.CoinCollectStatisticsDto;
import org.ftclub.cabinet.dto.TotalCoinAmountDto;
import org.ftclub.cabinet.log.Logging;
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;

@RestController
@RequestMapping("/v5/admin/statistics")
@RequiredArgsConstructor
@Logging
public class AdminStatisticsControllerV5 {

private final AdminStatisticsFacadeService adminStatisticsFacadeService;

/**
* 특정 연도, 월의 동전 줍기 횟수를 횟수 별로 통계를 내서 반환
*
* @param year
* @param month 조회를 원하는 기간
* @return
*/
@GetMapping("/coins/collect")
@AuthGuard(level = AuthLevel.ADMIN_ONLY)
public CoinCollectStatisticsDto getCoinCollectCountByMonth(
@RequestParam("year") Integer year,
@RequestParam("month") Integer month) {
return adminStatisticsFacadeService.getCoinCollectCountByMonth(year, month);
}

/**
* 전체 기간동안 동전의 발행량 및 사용량 반환
*
* @return
*/
@GetMapping("/coins")
@AuthGuard(level = AuthLevel.ADMIN_ONLY)
public TotalCoinAmountDto getTotalCoinAmount() {
return adminStatisticsFacadeService.getTotalCoinAmount();
}

}
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
package org.ftclub.cabinet.admin.statistics.service;

import static java.util.stream.Collectors.groupingBy;
import static org.ftclub.cabinet.cabinet.domain.CabinetStatus.AVAILABLE;
import static org.ftclub.cabinet.cabinet.domain.CabinetStatus.BROKEN;
import static org.ftclub.cabinet.cabinet.domain.CabinetStatus.FULL;
import static org.ftclub.cabinet.cabinet.domain.CabinetStatus.OVERDUE;
import static org.ftclub.cabinet.item.domain.Sku.COIN_COLLECT;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.RequiredArgsConstructor;
import org.ftclub.cabinet.cabinet.service.CabinetQueryService;
import org.ftclub.cabinet.dto.BlockedUserPaginationDto;
import org.ftclub.cabinet.dto.CabinetFloorStatisticsResponseDto;
import org.ftclub.cabinet.dto.CoinCollectStatisticsDto;
import org.ftclub.cabinet.dto.CoinCollectedCountDto;
import org.ftclub.cabinet.dto.LentsStatisticsResponseDto;
import org.ftclub.cabinet.dto.OverdueUserCabinetDto;
import org.ftclub.cabinet.dto.OverdueUserCabinetPaginationDto;
import org.ftclub.cabinet.dto.TotalCoinAmountDto;
import org.ftclub.cabinet.dto.UserBlockedInfoDto;
import org.ftclub.cabinet.exception.ExceptionStatus;
import org.ftclub.cabinet.exception.ServiceException;
import org.ftclub.cabinet.item.domain.ItemHistory;
import org.ftclub.cabinet.item.service.ItemHistoryQueryService;
import org.ftclub.cabinet.item.service.ItemQueryService;
import org.ftclub.cabinet.item.service.ItemRedisService;
import org.ftclub.cabinet.lent.domain.LentHistory;
import org.ftclub.cabinet.lent.service.LentQueryService;
import org.ftclub.cabinet.log.LogLevel;
import org.ftclub.cabinet.log.Logging;
import org.ftclub.cabinet.mapper.CabinetMapper;
import org.ftclub.cabinet.mapper.ItemMapper;
import org.ftclub.cabinet.mapper.UserMapper;
import org.ftclub.cabinet.user.domain.BanHistory;
import org.ftclub.cabinet.user.service.BanHistoryQueryService;
Expand All @@ -48,6 +60,10 @@ public class AdminStatisticsFacadeService {

private final CabinetMapper cabinetMapper;
private final UserMapper userMapper;
private final ItemHistoryQueryService itemHistoryQueryService;
private final ItemQueryService itemQueryService;
private final ItemMapper itemMapper;
private final ItemRedisService itemRedisService;

/**
* 현재 가용중인 모든 사물함의 현황을 반환합니다.
Expand Down Expand Up @@ -114,4 +130,43 @@ public OverdueUserCabinetPaginationDto getOverdueUsers(Pageable pageable) {
).collect(Collectors.toList());
return cabinetMapper.toOverdueUserCabinetPaginationDto(result, (long) lentHistories.size());
}

/**
* 특정 연도, 월의 동전 줍기 횟수를 횟수 별로 통계를 내서 반환
*
* @param year
* @param month 조회를 원하는 기간
* @return
*/
public CoinCollectStatisticsDto getCoinCollectCountByMonth(Integer year, Integer month) {
Long itemId = itemQueryService.getBySku(COIN_COLLECT).getId();
List<ItemHistory> coinCollectedInfoByMonth =
itemHistoryQueryService.getCoinCollectedInfoByMonth(itemId, year, month);
Map<Long, Long> coinCollectCountByUser = coinCollectedInfoByMonth.stream()
.collect(groupingBy(ItemHistory::getUserId, Collectors.counting()));

int[] coinCollectArray = new int[31];
coinCollectCountByUser.forEach((userId, coinCount) ->
coinCollectArray[coinCount.intValue() - 1]++);

List<CoinCollectedCountDto> coinCollectedCountDto = IntStream.rangeClosed(0,
30) // 1부터 30까지의 범위로 스트림 생성
.mapToObj(i -> new CoinCollectedCountDto(i + 1,
coinCollectArray[i])) // 각 인덱스와 해당하는 배열 값으로 CoinCollectedCountDto 생성
.collect(Collectors.toList()); // 리스트로 변환하여 반환

return new CoinCollectStatisticsDto(coinCollectedCountDto);
}

/**
* 전체 기간동안 동전의 발행량 및 사용량 반환
*
* @return
*/
public TotalCoinAmountDto getTotalCoinAmount() {
long totalCoinSupply = itemRedisService.getTotalCoinSupply();
long totalCoinUsage = itemRedisService.getTotalCoinUsage();

return new TotalCoinAmountDto(-1 * totalCoinUsage, totalCoinSupply);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.ftclub.cabinet.dto;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
public class CoinCollectStatisticsDto {

private List<CoinCollectedCountDto> coinCollectStatistics;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.ftclub.cabinet.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
public class CoinCollectedCountDto {

private Integer coinCount;
private Integer userCount;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.ftclub.cabinet.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class TotalCoinAmountDto {

private Long used;
private Long unused;
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,64 @@ public class ItemController {

private final ItemFacadeService itemFacadeService;

/**
* 전체 아이템 목록 조회
*
* @return
*/
@GetMapping("")
@AuthGuard(level = AuthLevel.USER_OR_ADMIN)
public ItemStoreResponseDto getAllItems() {
return itemFacadeService.getAllItems();
}

/**
* 특정 아이템 구매 요청
*
* @param user
* @param sku
*/
@PostMapping("/{sku}/purchase")
@AuthGuard(level = AuthLevel.USER_ONLY)
public void purchaseItem(@UserSession UserSessionDto user,
@PathVariable Sku sku) {
itemFacadeService.purchaseItem(user.getUserId(), sku);
}

/**
* 유저의 아이템 구매, 사용 내역 목록 조회
*
* @param user
* @param pageable
* @return
*/
@GetMapping("/history")
@AuthGuard(level = AuthLevel.USER_ONLY)
public ItemHistoryPaginationDto getItemHistory(@UserSession UserSessionDto user,
Pageable pageable) {
return itemFacadeService.getItemHistory(user.getUserId(), pageable);
}

/**
* 유저가 보유하고 있는 아이템 목록 조회
*
* @param user
* @return
*/
@GetMapping("/me")
@AuthGuard(level = AuthLevel.USER_ONLY)
public MyItemResponseDto getMyItems(@UserSession UserSessionDto user) {
return itemFacadeService.getMyItems(user);
}

/**
* 유저의 동전 줍기 내역 반환
*
* @param user
* @param type ALL, EARN, USE
* @param pageable
* @return
*/
@GetMapping("/coin/history")
@AuthGuard(level = AuthLevel.USER_ONLY)
public CoinHistoryPaginationDto getCoinHistory(@UserSession UserSessionDto user,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,14 @@ Page<ItemHistory> findAllByUserIdOnMinusPriceItemsWithSubQuery(
List<ItemHistory> getAllUnusedItemHistoryByUser(@Param("userId") Long userId);

List<ItemHistory> findAllByUserIdAndItemIdAndUsedAtIsNull(Long userId, Long itemId);


@Query("SELECT ih "
+ "FROM ItemHistory ih "
+ "WHERE ih.itemId = :itemId "
+ "AND YEAR(ih.purchaseAt) = :year "
+ "AND MONTH(ih.purchaseAt) = :month "
)
List<ItemHistory> findCoinCollectInfoByMonth(@Param("itemId") Long itemId,
@Param("year") Integer year, @Param("month") Integer month);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class ItemRedis {
private static final String COIN_COUNT_KEY_SUFFIX = ":coinCount";
private static final String COIN_COLLECT_KEY_SUFFIX = ":coinCollect";
private static final String COIN_COLLECT_COUNT_KEY_SUFFIX = ":coinCollectCount";
private static final String TOTAL_COIN_SUPPLY_KEY_SUFFIX = "totalCoinSupply";
private static final String TOTAL_COIN_USAGE_KEY_SUFFIX = "totalCoinUsage";


private final RedisTemplate<String, String> coinTemplate;
Expand All @@ -37,6 +39,44 @@ public void saveCoinCount(String userId, String coinCount) {
coinTemplate.opsForValue().set(userId + COIN_COUNT_KEY_SUFFIX, coinCount);
}

/**
* 전체 동전 발행량 반환
*
* @return
*/
public String getTotalCoinSupply() {
return coinTemplate.opsForValue().get(TOTAL_COIN_SUPPLY_KEY_SUFFIX);
}

/**
* 전체 동전 사용량 반환
*
* @return
*/
public String getTotalcoinUsage() {
return coinTemplate.opsForValue().get(TOTAL_COIN_USAGE_KEY_SUFFIX);
}

/**
* 전체 동전 발행량 저장
*
* @param coinSupply
*/

public void saveTotalCoinSupply(String coinSupply) {
coinTemplate.opsForValue().set(TOTAL_COIN_SUPPLY_KEY_SUFFIX, coinSupply);
}

/**
* 전체 동전 사용량 저장
*
* @param coinUsage
*/
public void saveTotalCoinUsage(String coinUsage) {
coinTemplate.opsForValue().set(TOTAL_COIN_USAGE_KEY_SUFFIX, coinUsage);
}


/**
* 하루동안 유지되는 redis를 탐색하여 동전줍기를 했는지 검수
*
Expand Down Expand Up @@ -100,8 +140,4 @@ public void addCoinCollectionCount(String userId) {
coinTemplate.expire(key, expireTime, TimeUnit.SECONDS);
}
}

public void saveCoinCollectionCount(String userId, String coinCollectionCount) {
coinTemplate.opsForValue().set(userId + COIN_COLLECT_COUNT_KEY_SUFFIX, coinCollectionCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ public ItemStoreResponseDto getAllItems() {
return new ItemStoreResponseDto(result);
}

/**
* 유저의 보유 아이템 반환
*
* @param user
* @return
*/
@Transactional(readOnly = true)
public MyItemResponseDto getMyItems(UserSessionDto user) {
List<ItemHistory> userItemHistories = itemHistoryQueryService.findAllItemHistoryByUser(
Expand Down Expand Up @@ -205,13 +211,19 @@ public CoinCollectionRewardResponseDto collectCoinAndIssueReward(Long userId) {
// Redis에 리워드 저장
long coins = itemRedisService.getCoinCount(userId);
itemRedisService.saveCoinCount(userId, coins + reward);

// Redis에 전체 코인 발행량 저장
long totalCoinSupply = itemRedisService.getTotalCoinSupply();
itemRedisService.saveTotalCoinSupply(totalCoinSupply + reward);
}
coinLockMap.remove(userId);
return new CoinCollectionRewardResponseDto(reward);
}


/**
* 아이템 사용
*
* @param userId
* @param sku
* @param data
Expand Down Expand Up @@ -287,6 +299,10 @@ public void purchaseItem(Long userId, Sku sku) {

// 코인 차감
itemRedisService.saveCoinCount(userId, userCoin + price);

// 전체 코인 사용량 저장
long totalCoinUsage = itemRedisService.getTotalCoinUsage();
itemRedisService.saveTotalCoinUsage(totalCoinUsage + price);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ public Page<ItemHistory> getCoinHistory(Long userId, Pageable pageable, List<Lon
public List<ItemHistory> getUnusedItemsInUserInventory(Long userId, Long itemId) {
return itemHistoryRepository.findAllByUserIdAndItemIdAndUsedAtIsNull(userId, itemId);
}

public List<ItemHistory> getCoinCollectedInfoByMonth(Long itemId, Integer year,
Integer month) {
return itemHistoryRepository.findCoinCollectInfoByMonth(itemId, year, month);
}
}
Loading

0 comments on commit 3cb4a48

Please sign in to comment.