diff --git a/createView.sql b/createView.sql index 7e024f5b7..af14bee05 100644 --- a/createView.sql +++ b/createView.sql @@ -3,9 +3,7 @@ create or replace view v_teamuser as from team, team_user tu, user u, game g where team.id=tu.team_id and u.id=tu.user_id and g.id=team.game_id; -create or replace view v_rank_game_detail as -select team.id teamId, team.score, team.win, g.id gameId, g.season_id seasonId, g.start_time startTime, g.status, g.mode, - tu.user_id userId, u.intra_id intraId, u.image_uri image, u.total_exp, - r.wins, r.losses -from team, team_user tu, user u, game g, ranks r -where team.id=tu.team_id and u.id=tu.user_id and g.id=team.game_id and r.user_id = u.id and r.season_id = g.season_id; \ No newline at end of file +create or replace VIEW `v_rank_game_detail` AS +select `team`.`id` AS `teamId`,`team`.`score` AS `score`,`team`.`win` AS `win`,`g`.`id` AS `gameId`,`g`.`season_id` AS `seasonId`,`g`.`start_time` AS `startTime`,`g`.`end_time` AS `endTime`,`g`.`status` AS `status`,`g`.`mode` AS `mode`,`tu`.`user_id` AS `userId`,`u`.`intra_id` AS `intraId`,`u`.`image_uri` AS `image`,`u`.`total_exp` AS `total_exp`,`r`.`wins` AS `wins`,`r`.`losses` AS `losses` +from ((((`team` join `team_user` `tu`) join `user` `u`) join `game` `g`) join `ranks` `r`) +where ((`team`.`id` = `tu`.`team_id`) and (`u`.`id` = `tu`.`user_id`) and (`g`.`id` = `team`.`game_id`) and (`r`.`user_id` = `u`.`id`) and (`r`.`season_id` = `g`.`season_id`)); \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java b/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java new file mode 100644 index 000000000..581766615 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java @@ -0,0 +1,21 @@ +package com.gg.server.admin.coin.controller; + +import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; +import com.gg.server.admin.coin.service.CoinAdminService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("pingpong/admin/coin") +public class CoinAdminController { + private final CoinAdminService coinAdminService; + + @PutMapping() + public ResponseEntity updateUserCoin(@RequestBody CoinUpdateRequestDto coinUpdateRequestDto) { + coinAdminService.updateUserCoin(coinUpdateRequestDto); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java b/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java new file mode 100644 index 000000000..b67d1537a --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java @@ -0,0 +1,44 @@ +package com.gg.server.admin.coin.controller; + +import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; +import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; +import com.gg.server.admin.coin.service.CoinPolicyAdminService; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.dto.PageRequestDto; +import com.gg.server.global.utils.argumentresolver.Login; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("pingpong/admin") +@Validated +public class CoinPolicyAdminController { + private final CoinPolicyAdminService coinPolicyAdminService; + + @GetMapping("/coinpolicy") + public ResponseEntity getCoinPolicyList(@ModelAttribute @Valid PageRequestDto coReq){ + Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); + + return ResponseEntity.ok() + .body(coinPolicyAdminService.findAllCoinPolicy(pageable)); + } + + @PostMapping("/coinpolicy") + public ResponseEntity addCoinPolicy(@Parameter(hidden = true) @Login UserDto userDto, @Valid @RequestBody CoinPolicyAdminAddDto addDto){ + + coinPolicyAdminService.addCoinPolicy(userDto, addDto); + return new ResponseEntity(HttpStatus.CREATED); + } + +} diff --git a/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java b/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java new file mode 100644 index 000000000..87e8f5412 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.admin.coin.data; + +import com.gg.server.domain.coin.data.CoinPolicy; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface CoinPolicyAdminRepository extends JpaRepository { + Optional findFirstByOrderByIdDesc(); +} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java new file mode 100644 index 000000000..1420c2ea3 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java @@ -0,0 +1,29 @@ +package com.gg.server.admin.coin.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CoinPolicyAdminAddDto { + @NotNull(message = "plz. not null attendance") + @PositiveOrZero(message = "plz. attendance PositiveOrZero") + private int attendance; + + @NotNull(message = "plz. not null normal") + @PositiveOrZero(message = "plz. normal PositiveOrZero") + private int normal; + + @NotNull(message = "plz. not null rankWin") + @PositiveOrZero(message = "plz. rankWin PositiveOrZero") + private int rankWin; + + @NotNull(message = "plz. not null rankLose") + @PositiveOrZero(message = "plz. rankLose PositiveOrZero") + private int rankLose; +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java new file mode 100644 index 000000000..b5014b54e --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java @@ -0,0 +1,16 @@ +package com.gg.server.admin.coin.dto; + +import com.gg.server.admin.announcement.dto.AnnouncementAdminResponseDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class CoinPolicyAdminListResponseDto { + private List coinPolicyList; + private int totalPage; +} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java new file mode 100644 index 000000000..08110e751 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java @@ -0,0 +1,31 @@ +package com.gg.server.admin.coin.dto; + +import com.gg.server.domain.announcement.data.Announcement; +import com.gg.server.domain.coin.data.CoinPolicy; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +public class CoinPolicyAdminResponseDto { + private Long coinPolicyId; + private String createUserId; + private int attendance; + private int normal; + private int rankWin; + private int rankLose; + private LocalDateTime createdAt; + + public CoinPolicyAdminResponseDto(CoinPolicy coinPolicyAdmin) + { + this.coinPolicyId = coinPolicyAdmin.getId(); + this.createUserId = coinPolicyAdmin.getUser().getIntraId(); + this.attendance = coinPolicyAdmin.getAttendance(); + this.normal = coinPolicyAdmin.getNormal(); + this.rankWin = coinPolicyAdmin.getRankWin(); + this.rankLose = coinPolicyAdmin.getRankLose(); + this.createdAt = coinPolicyAdmin.getCreatedAt(); + } +} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java new file mode 100644 index 000000000..85349c464 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java @@ -0,0 +1,19 @@ +package com.gg.server.admin.coin.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class CoinUpdateRequestDto { + @NotNull(message = "intraId는 null이 될 수 없습니다.") + private String intraId; + @NotNull(message = "change는 null이 될 수 없습니다.") + private int change; + @NotNull(message = "content는 null이 될 수 없습니다.") + private String content; +} diff --git a/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java b/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java new file mode 100644 index 000000000..2c2237f26 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java @@ -0,0 +1,25 @@ +package com.gg.server.admin.coin.service; + +import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; +import com.gg.server.domain.coin.data.CoinHistory; +import com.gg.server.domain.coin.service.CoinHistoryService; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class CoinAdminService { + private final UserRepository userRepository; + private final CoinHistoryService coinHistoryService; + + @Transactional + public void updateUserCoin(CoinUpdateRequestDto coinUpdateRequestDto) { + User user = userRepository.findByIntraId(coinUpdateRequestDto.getIntraId()).orElseThrow(UserNotFoundException::new); + user.addGgCoin(coinUpdateRequestDto.getChange()); + coinHistoryService.addCoinHistory(new CoinHistory(user, coinUpdateRequestDto.getContent(), coinUpdateRequestDto.getChange())); + } +} diff --git a/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java b/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java new file mode 100644 index 000000000..8311b72e7 --- /dev/null +++ b/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java @@ -0,0 +1,43 @@ +package com.gg.server.admin.coin.service; + +import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; +import com.gg.server.admin.announcement.dto.AnnouncementAdminResponseDto; +import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; +import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; +import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; +import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.domain.announcement.data.Announcement; +import com.gg.server.domain.coin.data.CoinPolicy; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@AllArgsConstructor +public class CoinPolicyAdminService { + private final CoinPolicyAdminRepository coinPolicyAdminRepository; + private final UserAdminRepository userAdminRepository; + + @Transactional(readOnly = true) + public CoinPolicyAdminListResponseDto findAllCoinPolicy(Pageable pageable) { + Page allCoinPolicy = coinPolicyAdminRepository.findAll(pageable); + Page responseDtos = allCoinPolicy.map(CoinPolicyAdminResponseDto::new); + + return new CoinPolicyAdminListResponseDto(responseDtos.getContent(), + responseDtos.getTotalPages()); + } + + @Transactional + public void addCoinPolicy(UserDto userDto, CoinPolicyAdminAddDto addDto){ + User user = userAdminRepository.findByIntraId(userDto.getIntraId()).orElseThrow(UserNotFoundException::new); + + CoinPolicy coinPolicy = CoinPolicy.from(user, addDto); + coinPolicyAdminRepository.save(coinPolicy); + } +} diff --git a/src/main/java/com/gg/server/admin/game/service/GameAdminService.java b/src/main/java/com/gg/server/admin/game/service/GameAdminService.java index ec7b5862d..0e2d55e54 100644 --- a/src/main/java/com/gg/server/admin/game/service/GameAdminService.java +++ b/src/main/java/com/gg/server/admin/game/service/GameAdminService.java @@ -1,166 +1,152 @@ -package com.gg.server.admin.game.service; - -import com.gg.server.admin.game.dto.GameLogAdminDto; -import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; -import com.gg.server.admin.game.data.GameAdminRepository; -import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; -import com.gg.server.admin.game.exception.NotRecentlyGameException; -import com.gg.server.admin.pchange.data.PChangeAdminRepository; -import com.gg.server.admin.pchange.exception.PChangeNotExistException; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.team.data.TeamUserAdminRepository; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import java.util.Arrays; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Caching; -import org.springframework.data.domain.*; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -@Slf4j -public class GameAdminService { - - private final GameAdminRepository gameAdminRepository; - private final SeasonAdminRepository seasonAdminRepository; - private final UserAdminRepository userAdminRepository; - private final PChangeRepository pChangeRepository; - private final PChangeAdminRepository pChangeAdminRepository; - private final RankRedisService rankRedisService; - private final TeamUserAdminRepository teamUserAdminRepository; - private final RedisMatchUserRepository redisMatchUserRepository; - - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findAllGamesByAdmin(Pageable pageable) { - Page gamePage = gameAdminRepository.findAll(pageable); //모든 게임 정보 가져오기 - return new GameLogListAdminResponseDto(getGameLogList(gamePage.getContent().stream().map(Game::getId).collect(Collectors.toList())), gamePage.getTotalPages()); - } - - - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findGamesBySeasonId(Long seasonId, Pageable pageable){ - Season season = seasonAdminRepository.findById(seasonId).orElseThrow(()-> new SeasonNotFoundException()); - Page games = gameAdminRepository.findBySeason(pageable, season); //시즌 id로 게임들 찾아오기 - return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); - } - - @Transactional(readOnly = true) - public List getGameLogList(List gameIdList){ - List teamViews = gameAdminRepository.findTeamsByGameIsIn(gameIdList); - return teamViews.stream().map(GameLogAdminDto::new).collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findGamesByIntraId(String intraId, Pageable pageable){ - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()); - List pChangeList = pChangeRepository.findAllByUserId(user.getId()); - List gameList = new ArrayList<>(); - - for(PChange pChange : pChangeList) - gameList.add(pChange.getGame()); - - int start = (int)pageable.getOffset(); - int end = Math.min((start + pageable.getPageSize()), gameList.size()); - Page games = new PageImpl<>(gameList.subList(start, end), pageable, gameList.size()); - return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); - } - - @Transactional - @Caching(evict = { - @CacheEvict(value = "rankGameListByIntra", allEntries = true), - @CacheEvict(value = "rankGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true) - }) - public void rankResultEdit(RankGamePPPModifyReqDto reqDto, Long gameId) { - // 게임이 두명 다 가장 마지막 게임인지 확인 (그 game에 해당하는 팀이 맞는지 확인) - List teamUsers = teamUserAdminRepository.findUsersByTeamIdIn(List.of(reqDto.getTeam1Id(), reqDto.getTeam2Id())); - Game game = gameAdminRepository.findById(gameId) - .orElseThrow(GameNotExistException::new); - Season season = seasonAdminRepository.findById(game.getSeason().getId()) - .orElseThrow(SeasonNotFoundException::new); - if (!isRecentlyGame(teamUsers, gameId) || EnrollSlots(teamUsers)) { - throw new NotRecentlyGameException(); - } - // pchange 가져와서 rank ppp 이전 값을 가지고 새 점수를 바탕으로 다시 계산 - for (TeamUser teamUser : - teamUsers) { - List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); - if (!pChanges.get(0).getGame().getId().equals(gameId)) { - throw new PChangeNotExistException(); - } - rollbackGameResult(reqDto, season, teamUser, pChanges); - pChangeAdminRepository.delete(pChanges.get(0)); - } - rankRedisService.updateRankRedis(teamUsers.get(0), teamUsers.get(1), game); - } - - private void rollbackGameResult(RankGamePPPModifyReqDto reqDto, Season season, TeamUser teamUser, List pChanges) { - // pchange ppp도 update - // rankredis 에 ppp 다시 반영 - // rank zset 도 update - // 이전 ppp, exp 되돌리기 - // rank data 에 있는 ppp 되돌리기 - if (pChanges.size() == 1) { - rankRedisService.rollbackRank(teamUser, season.getStartPpp(), season.getId()); - teamUser.getUser().updateExp(0); - } else { - rankRedisService.rollbackRank(teamUser, pChanges.get(1).getPppResult(), season.getId()); - teamUser.getUser().updateExp(pChanges.get(1).getExp()); - } - if (teamUser.getTeam().getId().equals(reqDto.getTeam1Id())) { - teamUser.getTeam().updateScore(reqDto.getTeam1Score(), reqDto.getTeam1Score() > reqDto.getTeam2Score()); - } else if (teamUser.getTeam().getId().equals(reqDto.getTeam2Id())) { - teamUser.getTeam().updateScore(reqDto.getTeam2Score(), reqDto.getTeam2Score() > reqDto.getTeam1Score()); - } - } - - private Boolean isRecentlyGame(List teamUsers, Long gameId) { - for (TeamUser teamUser : teamUsers) { - List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); - if (!pChanges.get(0).getGame().getId().equals(gameId)) - return false; - } - return true; - } - - private Boolean EnrollSlots(List teamUsers) { - for (TeamUser teamUser : teamUsers) { - Long userId = teamUser.getUser().getId(); - if (redisMatchUserRepository.countMatchTime(userId) > 0) { - return true; - } - if (gameAdminRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userId).isPresent()) { - return true; - } - } - return false; - } -} +package com.gg.server.admin.game.service; + +import com.gg.server.admin.game.dto.GameLogAdminDto; +import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; +import com.gg.server.admin.game.data.GameAdminRepository; +import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; +import com.gg.server.admin.game.exception.NotRecentlyGameException; +import com.gg.server.admin.pchange.data.PChangeAdminRepository; +import com.gg.server.admin.season.data.SeasonAdminRepository; +import com.gg.server.admin.team.data.TeamUserAdminRepository; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.dto.GameTeamUser; +import com.gg.server.domain.game.exception.GameNotExistException; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.match.data.RedisMatchUserRepository; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; + +import com.gg.server.domain.rank.redis.RankRedisService; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.exception.SeasonNotFoundException; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.data.domain.*; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class GameAdminService { + + private final GameAdminRepository gameAdminRepository; + private final SeasonAdminRepository seasonAdminRepository; + private final UserAdminRepository userAdminRepository; + private final PChangeRepository pChangeRepository; + private final PChangeAdminRepository pChangeAdminRepository; + private final RankRedisService rankRedisService; + private final TeamUserAdminRepository teamUserAdminRepository; + private final RedisMatchUserRepository redisMatchUserRepository; + + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findAllGamesByAdmin(Pageable pageable) { + Page gamePage = gameAdminRepository.findAll(pageable); //모든 게임 정보 가져오기 + return new GameLogListAdminResponseDto(getGameLogList(gamePage.getContent().stream().map(Game::getId).collect(Collectors.toList())), gamePage.getTotalPages()); + } + + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findGamesBySeasonId(Long seasonId, Pageable pageable){ + Season season = seasonAdminRepository.findById(seasonId).orElseThrow(()-> new SeasonNotFoundException()); + Page games = gameAdminRepository.findBySeason(pageable, season); //시즌 id로 게임들 찾아오기 + return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); + } + + @Transactional(readOnly = true) + public List getGameLogList(List gameIdList){ + List teamViews = gameAdminRepository.findTeamsByGameIsIn(gameIdList); + return teamViews.stream().map(GameLogAdminDto::new).collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findGamesByIntraId(String intraId, Pageable pageable){ + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()); + List pChangeList = pChangeRepository.findAllByUserId(user.getId()); + List gameList = new ArrayList<>(); + + for(PChange pChange : pChangeList) + gameList.add(pChange.getGame()); + + int start = (int)pageable.getOffset(); + int end = Math.min((start + pageable.getPageSize()), gameList.size()); + Page games = new PageImpl<>(gameList.subList(start, end), pageable, gameList.size()); + return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); + } + + @Transactional + @Caching(evict = { + @CacheEvict(value = "rankGameListByIntra", allEntries = true), + @CacheEvict(value = "rankGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true) + }) + public void rankResultEdit(RankGamePPPModifyReqDto reqDto, Long gameId) { + // 게임이 두명 다 가장 마지막 게임인지 확인 (그 game에 해당하는 팀이 맞는지 확인) + List teamUsers = teamUserAdminRepository.findUsersByTeamIdIn(List.of(reqDto.getTeam1Id(), reqDto.getTeam2Id())); + Game game = gameAdminRepository.findById(gameId) + .orElseThrow(GameNotExistException::new); + Season season = seasonAdminRepository.findById(game.getSeason().getId()) + .orElseThrow(SeasonNotFoundException::new); + if (!isRecentlyGame(teamUsers, gameId) || EnrollSlots(teamUsers)) { + throw new NotRecentlyGameException(); + } + // pchange 가져와서 rank ppp 이전 값을 가지고 새 점수를 바탕으로 다시 계산 + for (TeamUser teamUser : + teamUsers) { + List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); + rollbackGameResult(reqDto, season, teamUser, pChanges); + pChangeAdminRepository.delete(pChanges.get(0)); + } + rankRedisService.updateRankRedis(teamUsers.get(0), teamUsers.get(1), game); + } + + private void rollbackGameResult(RankGamePPPModifyReqDto reqDto, Season season, TeamUser teamUser, List pChanges) { + // pchange ppp도 update + // rankredis 에 ppp 다시 반영 + // rank zset 도 update + // 이전 ppp, exp 되돌리기 + // rank data 에 있는 ppp 되돌리기 + if (pChanges.size() == 1) { + rankRedisService.rollbackRank(teamUser, season.getStartPpp(), season.getId()); + teamUser.getUser().updateExp(0); + } else { + rankRedisService.rollbackRank(teamUser, pChanges.get(1).getPppResult(), season.getId()); + teamUser.getUser().updateExp(pChanges.get(1).getExp()); + } + if (teamUser.getTeam().getId().equals(reqDto.getTeam1Id())) { + teamUser.getTeam().updateScore(reqDto.getTeam1Score(), reqDto.getTeam1Score() > reqDto.getTeam2Score()); + } else if (teamUser.getTeam().getId().equals(reqDto.getTeam2Id())) { + teamUser.getTeam().updateScore(reqDto.getTeam2Score(), reqDto.getTeam2Score() > reqDto.getTeam1Score()); + } + } + + private Boolean isRecentlyGame(List teamUsers, Long gameId) { + for (TeamUser teamUser : teamUsers) { + List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); + if (!pChanges.get(0).getGame().getId().equals(gameId)) + return false; + } + return true; + } + + private Boolean EnrollSlots(List teamUsers) { + for (TeamUser teamUser : teamUsers) { + Long userId = teamUser.getUser().getId(); + if (redisMatchUserRepository.countMatchTime(userId) > 0) { + return true; + } + if (gameAdminRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userId).isPresent()) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java b/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java new file mode 100644 index 000000000..ab76b429e --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java @@ -0,0 +1,61 @@ +package com.gg.server.admin.item.controller; + +import com.gg.server.admin.item.dto.ItemListResponseDto; +import com.gg.server.admin.item.dto.ItemUpdateRequestDto; +import com.gg.server.admin.item.service.ItemAdminService; +import com.gg.server.domain.item.exception.ItemImageLargeException; +import com.gg.server.domain.item.exception.ItemImageTypeException; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.dto.PageRequestDto; +import com.gg.server.global.utils.argumentresolver.Login; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.Valid; +import java.io.IOException; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/items") +public class ItemAdminController { + private final ItemAdminService itemAdminService; + + @GetMapping("/history") + public ItemListResponseDto getItemHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("createdAt").descending()); + return itemAdminService.getAllItemHistory(pageable); + } + + @PostMapping(path="/{itemId}", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) + public ResponseEntity updateItem(@PathVariable("itemId") Long itemId, + @RequestPart @Valid ItemUpdateRequestDto updateItemInfo, + @RequestPart(required = false) MultipartFile imgData, + @Parameter(hidden = true) @Login UserDto user) throws IOException { + if (imgData != null) { + if (imgData.getSize() > 50000) { + throw new ItemImageLargeException(); + } else if (imgData.getContentType() == null || !imgData.getContentType().equals("image/jpeg")) { + throw new ItemImageTypeException(); + } + itemAdminService.updateItem(itemId, updateItemInfo, imgData, user); + } else { + itemAdminService.updateItem(itemId, updateItemInfo, user); + } + return new ResponseEntity(HttpStatus.NO_CONTENT); + } + + @DeleteMapping("/{itemId}") + public ResponseEntity deleteItem(@PathVariable("itemId") Long itemId, @Parameter(hidden = true) @Login UserDto user) { + itemAdminService.deleteItem(itemId, user); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java b/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java new file mode 100644 index 000000000..7525bc053 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.admin.item.data; + +import com.gg.server.domain.item.data.Item; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ItemAdminRepository extends JpaRepository { + Page findAll(Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java new file mode 100644 index 000000000..5e8acf572 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java @@ -0,0 +1,56 @@ +package com.gg.server.admin.item.dto; + +import com.gg.server.domain.item.data.Item; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemHistoryResponseDto { + private Long itemId; + private String name; + private String mainContent; + private String subContent; + private String imageUri; + private Integer price; + private Integer discount; + private boolean isVisible; + private LocalDateTime createdAt; + private String creatorIntraId; + private String deleterIntraId; + + public ItemHistoryResponseDto(Item item) { + this.itemId = item.getId(); + this.name = item.getName(); + this.mainContent = item.getMainContent(); + this.subContent = item.getSubContent(); + this.imageUri = item.getImageUri(); + this.price = item.getPrice(); + this.discount = item.getDiscount(); + this.isVisible = item.getIsVisible(); + this.createdAt = item.getCreatedAt(); + this.creatorIntraId = item.getCreatorIntraId(); + this.deleterIntraId = item.getDeleterIntraId(); + } + + @Override + public String toString() { + return "ItemHistoryResponseDto{" + + "itemId=" + itemId + + ", name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", imageUri='" + imageUri + '\'' + + ", price=" + price + + ", discount=" + discount + + ", isVisible=" + isVisible + + ", createdAt=" + createdAt + + ", creatorIntraId='" + creatorIntraId + '\'' + + ", deleterIntraId='" + deleterIntraId + '\'' + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java new file mode 100644 index 000000000..c56e7f1a1 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java @@ -0,0 +1,15 @@ +package com.gg.server.admin.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemListResponseDto { + private List historyList; + private Integer totalPage; +} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java new file mode 100644 index 000000000..4c454ebe7 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java @@ -0,0 +1,43 @@ +package com.gg.server.admin.item.dto; + +import com.gg.server.domain.item.type.ItemType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemUpdateRequestDto { + @NotNull(message = "[Request] 아이템 이름은 Null 일 수 없습니다.") + private String name; + + @NotNull(message = "[Request] 주 설명은 Null 일 수 없습니다.") + private String mainContent; + + @NotNull(message = "[Request] 부 설명은 Null 일 수 없습니다.") + private String subContent; + + @NotNull(message = "[Request] 가격은 Null 일 수 없습니다.") + private Integer price; + + @NotNull(message = "[Request] 할인율은 Null 일 수 없습니다.") + private Integer discount; + + @NotNull(message = "[Request] 아이템 타입은 Null 일 수 없습니다.") + private ItemType itemType; + + @Override + public String toString() { + return "ItemUpdateRequestDto{" + + "name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", price=" + price + + ", discount=" + discount + + ", itemType='" + itemType + '\'' + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java b/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java new file mode 100644 index 000000000..1334c1909 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java @@ -0,0 +1,10 @@ +package com.gg.server.admin.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; + +public class ItemNotFoundException extends NotExistException { + public ItemNotFoundException() { + super("아이템이 없습니다.", ErrorCode.ITEM_NOT_FOUND); + } +} diff --git a/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java b/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java new file mode 100644 index 000000000..7fb4a6f49 --- /dev/null +++ b/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java @@ -0,0 +1,68 @@ +package com.gg.server.admin.item.service; + +import com.gg.server.admin.item.data.ItemAdminRepository; +import com.gg.server.admin.item.dto.ItemHistoryResponseDto; +import com.gg.server.admin.item.dto.ItemListResponseDto; +import com.gg.server.admin.item.dto.ItemUpdateRequestDto; +import com.gg.server.admin.item.exception.ItemNotFoundException; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.exception.ItemNotAvailableException; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.utils.aws.AsyncNewItemImageUploader; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + + +@Service +@RequiredArgsConstructor +public class ItemAdminService { + + private final ItemAdminRepository itemAdminRepository; + private final AsyncNewItemImageUploader asyncNewItemImageUploader; + + @Transactional(readOnly = true) + public ItemListResponseDto getAllItemHistory(Pageable pageable) { + Page responseDtos = itemAdminRepository.findAll(pageable).map(ItemHistoryResponseDto::new); + return new ItemListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + // 아이템 수정 시 신규 이미지가 존재하는 경우 + @Transactional + public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, + MultipartFile itemImageFile, UserDto user) throws IOException { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotAvailableException(); + } + item.setVisibility(user.getIntraId()); + Item newItem = new Item(itemUpdateRequestDto, user.getIntraId(), null); + if (itemImageFile != null) + asyncNewItemImageUploader.upload(newItem, itemImageFile); + itemAdminRepository.save(newItem); + } + + // 아이템 수정 시 신규 이미지가 존재하지 않는 경우 + @Transactional + public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, + UserDto user) { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotAvailableException(); + } + item.setVisibility(user.getIntraId()); + Item newItem = new Item(itemUpdateRequestDto, user.getIntraId(), item.getImageUri()); + itemAdminRepository.save(newItem); + } + + @Transactional + public void deleteItem(Long itemId, UserDto user) { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + item.setVisibility(user.getIntraId()); + } +} diff --git a/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java b/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java new file mode 100644 index 000000000..2986447f9 --- /dev/null +++ b/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java @@ -0,0 +1,30 @@ +package com.gg.server.admin.megaphone.controller; + +import com.gg.server.admin.megaphone.dto.MegaphoneHistoryResponseDto; +import com.gg.server.admin.megaphone.service.MegaphoneAdminService; +import com.gg.server.global.dto.PageRequestDto; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/megaphones") +public class MegaphoneAdminController { + private final MegaphoneAdminService megaphoneAdminService; + + @GetMapping("/history") + public MegaphoneHistoryResponseDto getMegaphoneHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto, + @RequestParam(required = false) String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("id").descending()); + if (intraId == null) + return megaphoneAdminService.getMegaphoneHistory(pageable); + return megaphoneAdminService.getMegaphoneHistoryByIntraId(intraId, pageable); + + } +} diff --git a/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java b/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java new file mode 100644 index 000000000..18e964254 --- /dev/null +++ b/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.admin.megaphone.data; + +import com.gg.server.domain.megaphone.data.Megaphone; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MegaphoneAdminRepository extends JpaRepository { + Page findMegaphonesByUserIntraId(String intraId, Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java new file mode 100644 index 000000000..9984a0351 --- /dev/null +++ b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java @@ -0,0 +1,23 @@ +package com.gg.server.admin.megaphone.dto; + +import com.gg.server.domain.megaphone.data.Megaphone; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneAdminResponseDto { + private Long megaphoneId; + private String content; + private String usedAt; + private String status; + private String intraId; + + public MegaphoneAdminResponseDto(Megaphone megaphone){ + this.megaphoneId = megaphone.getId(); + this.content = megaphone.getContent(); + this.usedAt = megaphone.getUsedAt().toString(); + this.status = megaphone.getReceipt().getStatus().getDescription(); + this.intraId = megaphone.getUser().getIntraId(); + } +} diff --git a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java new file mode 100644 index 000000000..9337d047e --- /dev/null +++ b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java @@ -0,0 +1,18 @@ +package com.gg.server.admin.megaphone.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +public class MegaphoneHistoryResponseDto { + private List megaphoneList; + private int totalPage; + + public MegaphoneHistoryResponseDto(List newDtos, int totalPage){ + this.megaphoneList = newDtos; + this.totalPage= totalPage; + } +} diff --git a/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java b/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java new file mode 100644 index 000000000..b91076db5 --- /dev/null +++ b/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java @@ -0,0 +1,27 @@ +package com.gg.server.admin.megaphone.service; + +import com.gg.server.admin.megaphone.data.MegaphoneAdminRepository; + +import com.gg.server.admin.megaphone.dto.MegaphoneAdminResponseDto; +import com.gg.server.admin.megaphone.dto.MegaphoneHistoryResponseDto; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + + +@Service +@RequiredArgsConstructor +public class MegaphoneAdminService { + private final MegaphoneAdminRepository megaphoneAdminRepository; + + public MegaphoneHistoryResponseDto getMegaphoneHistory(Pageable pageable) { + Page megaphoneHistory = megaphoneAdminRepository.findAll(pageable).map(MegaphoneAdminResponseDto::new); + return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); + } + + public MegaphoneHistoryResponseDto getMegaphoneHistoryByIntraId(String intraId, Pageable pageable) { + Page megaphoneHistory = megaphoneAdminRepository.findMegaphonesByUserIntraId(intraId, pageable).map(MegaphoneAdminResponseDto::new); + return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); + } +} diff --git a/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java b/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java index 4ab186da5..82b1e6d5b 100644 --- a/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java +++ b/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java @@ -1,48 +1,47 @@ -package com.gg.server.admin.noti.service; - -import com.gg.server.admin.noti.data.NotiAdminRepository; -import com.gg.server.admin.noti.dto.NotiAdminDto; -import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@AllArgsConstructor -public class NotiAdminService { - private final NotiAdminRepository notiAdminRepository; - private final UserAdminRepository userAdminRepository; - - @Transactional - public void sendAnnounceNotiToUser(SendNotiAdminRequestDto sendNotiAdminRequestDto) { - String message = sendNotiAdminRequestDto.getMessage(); - String intraId = sendNotiAdminRequestDto.getIntraId(); - - User user = userAdminRepository.findByIntraId(intraId) - .orElseThrow(() -> new UserNotFoundException()); - notiAdminRepository.save(new Noti(user, NotiType.ANNOUNCE, message, false)); - } - - @Transactional(readOnly = true) - public NotiListAdminResponseDto getAllNoti(Pageable pageable) { - Page allNotiPage = notiAdminRepository.findAll(pageable); - Page notiAdminDtoPage = allNotiPage.map(NotiAdminDto::new); - return new NotiListAdminResponseDto(notiAdminDtoPage.getContent(), notiAdminDtoPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public NotiListAdminResponseDto getFilteredNotifications(Pageable pageable, String intraId) { - Page findNotis = notiAdminRepository.findNotisByUserIntraId(pageable, intraId); - Page notiResponseDtoPage = findNotis.map(NotiAdminDto::new); - return new NotiListAdminResponseDto(notiResponseDtoPage.getContent(), notiResponseDtoPage.getTotalPages()); - } -} +package com.gg.server.admin.noti.service; + +import com.gg.server.admin.noti.data.NotiAdminRepository; +import com.gg.server.admin.noti.dto.NotiAdminDto; +import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; +import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@AllArgsConstructor +public class NotiAdminService { + private final NotiAdminRepository notiAdminRepository; + private final UserAdminRepository userAdminRepository; + + @Transactional + public void sendAnnounceNotiToUser(SendNotiAdminRequestDto sendNotiAdminRequestDto) { + String message = sendNotiAdminRequestDto.getMessage(); + String intraId = sendNotiAdminRequestDto.getIntraId(); + + User user = userAdminRepository.findByIntraId(intraId) + .orElseThrow(UserNotFoundException::new); + notiAdminRepository.save(new Noti(user, NotiType.ANNOUNCE, message, false)); + } + + @Transactional(readOnly = true) + public NotiListAdminResponseDto getAllNoti(Pageable pageable) { + Page allNotiPage = notiAdminRepository.findAll(pageable); + Page notiAdminDtoPage = allNotiPage.map(NotiAdminDto::new); + return new NotiListAdminResponseDto(notiAdminDtoPage.getContent(), notiAdminDtoPage.getTotalPages()); + } + + @Transactional(readOnly = true) + public NotiListAdminResponseDto getFilteredNotifications(Pageable pageable, String intraId) { + Page findNotis = notiAdminRepository.findNotisByUserIntraId(pageable, intraId); + Page notiResponseDtoPage = findNotis.map(NotiAdminDto::new); + return new NotiListAdminResponseDto(notiResponseDtoPage.getContent(), notiResponseDtoPage.getTotalPages()); + } +} diff --git a/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java b/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java index 2d8d807f0..dcff03b48 100644 --- a/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java +++ b/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java @@ -1,110 +1,110 @@ -package com.gg.server.admin.penalty.service; - -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; -import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; -import com.gg.server.admin.penalty.dto.PenaltyUserResponseDto; -import com.gg.server.domain.penalty.exception.PenaltyExpiredException; -import com.gg.server.domain.penalty.exception.PenaltyNotFoundException; -import com.gg.server.domain.penalty.exception.RedisPenaltyUserNotFoundException; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.service.UserFindService; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class PenaltyAdminService { - private final PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; - private final UserFindService userFindService; - private final PenaltyAdminRepository penaltyRepository; - - @Transactional - public void givePenalty(String intraId, Integer penaltyTime, String reason) { - User user = userFindService.findByIntraId(intraId); - Optional redisPenaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - LocalDateTime releaseTime; - RedisPenaltyUser penaltyUser; - Penalty penalty; - LocalDateTime now = LocalDateTime.now(); - if (redisPenaltyUser.isPresent()) { - releaseTime = redisPenaltyUser.get().getReleaseTime().plusHours(penaltyTime); - penaltyUser = new RedisPenaltyUser(intraId, redisPenaltyUser.get().getPenaltyTime() + penaltyTime * 60, - releaseTime, redisPenaltyUser.get().getStartTime(), reason); - penalty = new Penalty(user, PenaltyType.NOSHOW, reason, redisPenaltyUser.get().getReleaseTime(), penaltyTime * 60); - } else { - releaseTime = now.plusHours(penaltyTime); - penaltyUser = new RedisPenaltyUser(intraId, penaltyTime * 60, releaseTime, now, reason); - penalty = new Penalty(user, PenaltyType.NOSHOW, reason, now, penaltyTime * 60); - } - penaltyRepository.save(penalty); - penaltyUserAdminRedisRepository.addPenaltyUser(penaltyUser, releaseTime); - } - - - @Transactional(readOnly = true) - public PenaltyListResponseDto getAllPenalties(Pageable pageable, Boolean current) { - Page allPenalties; - if (current) { - allPenalties = penaltyRepository.findAllCurrent(pageable, LocalDateTime.now()); - } else { - allPenalties = penaltyRepository.findAll(pageable); - } - Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); - return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - - @Transactional - public void deletePenalty(Long penaltyId) { - Penalty penalty = penaltyRepository.findById(penaltyId).orElseThrow(() - -> new PenaltyNotFoundException()); - if (penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()).isBefore(LocalDateTime.now())) { - throw new PenaltyExpiredException(); - } - RedisPenaltyUser penaltyUser = penaltyUserAdminRedisRepository - .findByIntraId(penalty.getUser().getIntraId()).orElseThrow(() - -> new RedisPenaltyUserNotFoundException()); - penaltyUserAdminRedisRepository.deletePenaltyInUser(penaltyUser, - penalty.getPenaltyTime());//redis 시간 줄여주기 - //뒤에 있는 penalty 시간 당겨주기 - modifyStartTimeOfAfterPenalties(penalty); - penaltyRepository.delete(penalty); - } - - @Transactional(readOnly = true) - public PenaltyListResponseDto getAllPenaltiesByIntraId(Pageable pageable, String intraId, Boolean current) { - Page allPenalties; - if (current) { - allPenalties = penaltyRepository.findAllCurrentByIntraId(pageable, LocalDateTime.now(), intraId); - } else { - allPenalties = penaltyRepository.findAllByIntraId(pageable, intraId); - } - Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); - return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - private void modifyStartTimeOfAfterPenalties(Penalty penalty) { - List afterPenalties = penaltyRepository.findAfterPenaltiesByUser(penalty.getUser().getId(), - penalty.getStartTime()); - LocalDateTime newStartTime; - if (penalty.getStartTime().isAfter(LocalDateTime.now())) { - newStartTime = penalty.getStartTime(); - } else { - newStartTime = LocalDateTime.now(); - } - for (Penalty afterPenalty : afterPenalties) { - afterPenalty.updateStartTime(newStartTime); - newStartTime = newStartTime.plusMinutes(afterPenalty.getPenaltyTime()); - } - } -} +package com.gg.server.admin.penalty.service; + +import com.gg.server.admin.penalty.data.PenaltyAdminRepository; +import com.gg.server.domain.penalty.data.Penalty; +import com.gg.server.domain.penalty.redis.RedisPenaltyUser; +import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; +import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; +import com.gg.server.admin.penalty.dto.PenaltyUserResponseDto; +import com.gg.server.domain.penalty.exception.PenaltyExpiredException; +import com.gg.server.domain.penalty.exception.PenaltyNotFoundException; +import com.gg.server.domain.penalty.exception.RedisPenaltyUserNotFoundException; +import com.gg.server.domain.penalty.type.PenaltyType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.service.UserFindService; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class PenaltyAdminService { + private final PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; + private final UserFindService userFindService; + private final PenaltyAdminRepository penaltyRepository; + + @Transactional + public void givePenalty(String intraId, Integer penaltyTime, String reason) { + User user = userFindService.findByIntraId(intraId); + Optional redisPenaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + LocalDateTime releaseTime; + RedisPenaltyUser penaltyUser; + Penalty penalty; + LocalDateTime now = LocalDateTime.now(); + if (redisPenaltyUser.isPresent()) { + releaseTime = redisPenaltyUser.get().getReleaseTime().plusHours(penaltyTime); + penaltyUser = new RedisPenaltyUser(intraId, redisPenaltyUser.get().getPenaltyTime() + penaltyTime * 60, + releaseTime, redisPenaltyUser.get().getStartTime(), reason); + penalty = new Penalty(user, PenaltyType.NOSHOW, reason, redisPenaltyUser.get().getReleaseTime(), penaltyTime * 60); + } else { + releaseTime = now.plusHours(penaltyTime); + penaltyUser = new RedisPenaltyUser(intraId, penaltyTime * 60, releaseTime, now, reason); + penalty = new Penalty(user, PenaltyType.NOSHOW, reason, now, penaltyTime * 60); + } + penaltyRepository.save(penalty); + penaltyUserAdminRedisRepository.addPenaltyUser(penaltyUser, releaseTime); + } + + + @Transactional(readOnly = true) + public PenaltyListResponseDto getAllPenalties(Pageable pageable, Boolean current) { + Page allPenalties; + if (current) { + allPenalties = penaltyRepository.findAllCurrent(pageable, LocalDateTime.now()); + } else { + allPenalties = penaltyRepository.findAll(pageable); + } + Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); + return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + + @Transactional + public void deletePenalty(Long penaltyId) { + Penalty penalty = penaltyRepository.findById(penaltyId).orElseThrow(() + -> new PenaltyNotFoundException()); + if (penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()).isBefore(LocalDateTime.now())) { + throw new PenaltyExpiredException(); + } + RedisPenaltyUser penaltyUser = penaltyUserAdminRedisRepository + .findByIntraId(penalty.getUser().getIntraId()).orElseThrow(() + -> new RedisPenaltyUserNotFoundException()); + penaltyUserAdminRedisRepository.deletePenaltyInUser(penaltyUser, + penalty.getPenaltyTime());//redis 시간 줄여주기 + //뒤에 있는 penalty 시간 당겨주기 + modifyStartTimeOfAfterPenalties(penalty); + penaltyRepository.delete(penalty); + } + + @Transactional(readOnly = true) + public PenaltyListResponseDto getAllPenaltiesByIntraId(Pageable pageable, String intraId, Boolean current) { + Page allPenalties; + if (current) { + allPenalties = penaltyRepository.findAllCurrentByIntraId(pageable, LocalDateTime.now(), intraId); + } else { + allPenalties = penaltyRepository.findAllByIntraId(pageable, intraId); + } + Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); + return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + private void modifyStartTimeOfAfterPenalties(Penalty penalty) { + List afterPenalties = penaltyRepository.findAfterPenaltiesByUser(penalty.getUser().getId(), + penalty.getStartTime()); + LocalDateTime newStartTime; + if (penalty.getStartTime().isAfter(LocalDateTime.now())) { + newStartTime = penalty.getStartTime(); + } else { + newStartTime = LocalDateTime.now(); + } + for (Penalty afterPenalty : afterPenalties) { + afterPenalty.updateStartTime(newStartTime); + newStartTime = newStartTime.plusMinutes(afterPenalty.getPenaltyTime()); + } + } +} diff --git a/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java b/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java index 3d5838c24..ceed91df3 100644 --- a/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java +++ b/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java @@ -1,53 +1,58 @@ -package com.gg.server.admin.rank.service; - -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.season.exception.SeasonForbiddenException; -import com.gg.server.domain.season.exception.SeasonTimeBeforeException; -import com.gg.server.domain.user.User; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static com.gg.server.domain.user.type.RoleType.GUEST; - -@Service -@AllArgsConstructor -public class RankAdminService { - private final RankRepository rankRepository; - private final UserAdminRepository userAdminRepository; - private final SeasonRepository seasonRepository; - - @Transactional - public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { - if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) - throw new SeasonTimeBeforeException(); - List users = userAdminRepository.findAll(); - - List ranks = new ArrayList<>(); - Season season = seasonRepository.findById(seasonAdminDto.getSeasonId()).get(); - users.forEach(user -> { - if (user.getRoleType() != GUEST) { - Rank userRank = Rank.from(user, season, seasonAdminDto.getStartPpp()); - ranks.add(userRank); - } - }); - rankRepository.saveAll(ranks); - } - - @Transactional - public void deleteAllUserRankBySeason(SeasonAdminDto seasonAdminDto) { - if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) - throw new SeasonForbiddenException(); - - rankRepository.deleteAllBySeasonId(seasonAdminDto.getSeasonId()); - } -} +package com.gg.server.admin.rank.service; + +import com.gg.server.admin.season.dto.SeasonAdminDto; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.season.exception.SeasonForbiddenException; +import com.gg.server.domain.season.exception.SeasonTimeBeforeException; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static com.gg.server.domain.user.type.RoleType.GUEST; + +@Service +@AllArgsConstructor +public class RankAdminService { + private final RankRepository rankRepository; + private final UserAdminRepository userAdminRepository; + private final SeasonRepository seasonRepository; + private final TierRepository tierRepository; + + @Transactional + public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { + if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) + throw new SeasonTimeBeforeException(); + List users = userAdminRepository.findAll(); + + List ranks = new ArrayList<>(); + Season season = seasonRepository.findById(seasonAdminDto.getSeasonId()).get(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + users.forEach(user -> { + if (user.getRoleType() != GUEST) { + Rank userRank = Rank.from(user, season, seasonAdminDto.getStartPpp(), tier); + ranks.add(userRank); + } + }); + rankRepository.saveAll(ranks); + } + + @Transactional + public void deleteAllUserRankBySeason(SeasonAdminDto seasonAdminDto) { + if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) + throw new SeasonForbiddenException(); + + rankRepository.deleteAllBySeasonId(seasonAdminDto.getSeasonId()); + } +} diff --git a/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java b/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java index c16d362a2..c8c6a1cca 100644 --- a/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java +++ b/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java @@ -1,58 +1,63 @@ -package com.gg.server.admin.rank.service; - -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static com.gg.server.domain.user.type.RoleType.GUEST; - -@Service -@AllArgsConstructor -public class RankRedisAdminService { - private final UserRepository userRepository; - private final RankRedisRepository rankRedisRepository; - - @Transactional - public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { - List users = userRepository.findAll(); - - String redisHashKey = RedisKeyManager.getHashKey(seasonAdminDto.getSeasonId()); - - users.forEach(user -> { - if (user.getRoleType() != GUEST) { - UserDto userDto = UserDto.from(user); - RankRedis userRank = RankRedis.from(userDto, seasonAdminDto.getStartPpp()); - - rankRedisRepository.addRankData(redisHashKey, user.getId(), userRank); - } - }); - } - - @Transactional - public void deleteSeasonRankBySeasonId(Long seasonId) { - String redisHashKey = RedisKeyManager.getHashKey(seasonId); - - rankRedisRepository.deleteHashKey(redisHashKey); - } - - public void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { - rankRedisRepository.updateRankData(hashKey, userId, userRank); - if (userPlayedRank(userRank)){ - rankRedisRepository.deleteFromZSet(zsetKey, userId); - rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); - } - } - - private boolean userPlayedRank(RankRedis userRank) { - return (userRank.getWins() + userRank.getLosses()) != 0; - } -} +package com.gg.server.admin.rank.service; + +import com.gg.server.admin.season.dto.SeasonAdminDto; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static com.gg.server.domain.user.type.RoleType.GUEST; + +@Service +@AllArgsConstructor +public class RankRedisAdminService { + private final UserRepository userRepository; + private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; + + @Transactional + public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { + List users = userRepository.findAll(); + + String redisHashKey = RedisKeyManager.getHashKey(seasonAdminDto.getSeasonId()); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + + users.forEach(user -> { + if (user.getRoleType() != GUEST) { + UserDto userDto = UserDto.from(user); + RankRedis userRank = RankRedis.from(userDto, seasonAdminDto.getStartPpp(), tier.getImageUri()); + + rankRedisRepository.addRankData(redisHashKey, user.getId(), userRank); + } + }); + } + + @Transactional + public void deleteSeasonRankBySeasonId(Long seasonId) { + String redisHashKey = RedisKeyManager.getHashKey(seasonId); + + rankRedisRepository.deleteHashKey(redisHashKey); + } + + public void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { + rankRedisRepository.updateRankData(hashKey, userId, userRank); + if (userPlayedRank(userRank)){ + rankRedisRepository.deleteFromZSet(zsetKey, userId); + rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); + } + } + + private boolean userPlayedRank(RankRedis userRank) { + return (userRank.getWins() + userRank.getLosses()) != 0; + } +} diff --git a/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java b/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java new file mode 100644 index 000000000..5f67a94e0 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java @@ -0,0 +1,35 @@ +package com.gg.server.admin.receipt.controller; + +import com.gg.server.admin.receipt.dto.ReceiptAdminPageRequestDto; +import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; +import com.gg.server.admin.receipt.service.ReceiptAdminService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/receipt") +public class ReceiptAdminController { + private final ReceiptAdminService receiptAdminService; + + @GetMapping + public ReceiptListResponseDto getReceiptList(@ModelAttribute @Valid ReceiptAdminPageRequestDto req) { + + if (req.getIntraId() == null) { + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return receiptAdminService.getAllReceipt(pageable); + } + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return receiptAdminService.findByIntraId(req.getIntraId(), pageable); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java new file mode 100644 index 000000000..69f387d11 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.admin.receipt.data; + +import com.gg.server.domain.receipt.data.Receipt; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReceiptAdminRepository extends JpaRepository, ReceiptAdminRepositorySearch{ + Page findAll(Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java new file mode 100644 index 000000000..4065857a5 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java @@ -0,0 +1,12 @@ +package com.gg.server.admin.receipt.data; + +import com.gg.server.domain.receipt.data.Receipt; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ReceiptAdminRepositorySearch { + @Query(value = "select re from Receipt re where re.purchaserIntraId = :intraId or re.ownerIntraId = :intraId") + Page findReceiptByIntraId(@Param("intraId") String intraId, Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java new file mode 100644 index 000000000..5fcd0db68 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java @@ -0,0 +1,14 @@ +package com.gg.server.admin.receipt.dto; + +import com.gg.server.global.dto.PageRequestDto; +import lombok.Getter; + +@Getter +public class ReceiptAdminPageRequestDto extends PageRequestDto { + private String intraId; + + public ReceiptAdminPageRequestDto(String intraId, Integer page, Integer size) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java new file mode 100644 index 000000000..e994ac244 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java @@ -0,0 +1,15 @@ +package com.gg.server.admin.receipt.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ReceiptListResponseDto { + private List receiptList; + private Integer totalPage; +} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java new file mode 100644 index 000000000..41c9e1b44 --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java @@ -0,0 +1,47 @@ +package com.gg.server.admin.receipt.dto; + +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.type.ItemStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ReceiptResponseDto { + private Long receiptId; + private LocalDateTime createdAt; + private String itemName; + private Integer itemPrice; + private String purchaserIntraId; + private String ownerIntraId; + private ItemStatus itemStatusType; + + public ReceiptResponseDto(Receipt receipt) { + Item item = receipt.getItem(); + this.itemName = item.getName(); + this.itemPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); + this.receiptId = receipt.getId(); + this.createdAt = receipt.getCreatedAt(); + this.purchaserIntraId = receipt.getPurchaserIntraId(); + this.ownerIntraId = receipt.getOwnerIntraId(); + this.itemStatusType = receipt.getStatus(); + } + + @Override + public String toString() { + return "ReceiptResponseDto{" + + "receiptId=" + receiptId + + ", createdAt=" + createdAt + + ", itemName='" + itemName + '\'' + + ", itemPrice=" + itemPrice + + ", purchaserIntraId='" + purchaserIntraId + '\'' + + ", ownerIntraId='" + ownerIntraId + '\'' + + ", itemStatusType=" + itemStatusType + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java b/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java new file mode 100644 index 000000000..9462acbbf --- /dev/null +++ b/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java @@ -0,0 +1,30 @@ +package com.gg.server.admin.receipt.service; + +import com.gg.server.admin.receipt.data.ReceiptAdminRepository; +import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; +import com.gg.server.admin.receipt.dto.ReceiptResponseDto; +import com.gg.server.domain.receipt.data.Receipt; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class ReceiptAdminService { + private final ReceiptAdminRepository receiptAdminRepository; + + @Transactional(readOnly = true) + public ReceiptListResponseDto getAllReceipt(Pageable pageable) { + Page responseDtos = receiptAdminRepository.findAll(pageable).map(ReceiptResponseDto::new); + return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + @Transactional(readOnly = true) + public ReceiptListResponseDto findByIntraId(String intraId, Pageable pageable) { + Page receipts = receiptAdminRepository.findReceiptByIntraId(intraId, pageable); + Page responseDtos = receipts.map(ReceiptResponseDto::new); + return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } +} diff --git a/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java b/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java index f6218d2c1..aeee8b46d 100644 --- a/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java +++ b/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java @@ -83,6 +83,9 @@ public void updateSeason(Long seasonId, SeasonUpdateRequestDto updateDto) { Season season = seasonAdminRepository.findById(seasonId) .orElseThrow(() -> new SeasonNotFoundException()); + if (LocalDateTime.now().isAfter(season.getStartTime())) + throw new SeasonForbiddenException(); + if (LocalDateTime.now().isBefore(season.getStartTime())) { detach(season); season.setSeasonName(updateDto.getSeasonName()); diff --git a/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java b/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java index d6434b496..07974e80d 100644 --- a/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java +++ b/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java @@ -1,18 +1,17 @@ -package com.gg.server.admin.team.data; - -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; - -public interface TeamUserAdminRepository extends JpaRepository { - @Query("SELECT tu.user FROM TeamUser tu WHERE tu.team.id = :teamId") - List findUsersByTeamId(@Param("teamId") Long teamId); - - @Query("SELECT tu FROM TeamUser tu, Team t WHERE tu.team.id IN (:teamId) AND t.id = tu.team.id") - List findUsersByTeamIdIn(@Param("teamId") List teamId); -} +package com.gg.server.admin.team.data; + +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.user.data.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface TeamUserAdminRepository extends JpaRepository { + @Query("SELECT tu.user FROM TeamUser tu WHERE tu.team.id = :teamId") + List findUsersByTeamId(@Param("teamId") Long teamId); + + @Query("SELECT tu FROM TeamUser tu, Team t WHERE tu.team.id IN (:teamId) AND t.id = tu.team.id") + List findUsersByTeamIdIn(@Param("teamId") List teamId); +} diff --git a/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java b/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java index 76e63da38..69a870aff 100644 --- a/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java +++ b/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java @@ -1,20 +1,14 @@ package com.gg.server.admin.user.controller; -import com.gg.server.admin.user.dto.UserDetailAdminResponseDto; -import com.gg.server.admin.user.dto.UserSearchAdminRequestDto; -import com.gg.server.admin.user.dto.UserSearchAdminResponseDto; -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; +import com.gg.server.admin.user.dto.*; import com.gg.server.admin.user.service.UserAdminService; -import com.gg.server.domain.rank.exception.RankUpdateException; import com.gg.server.domain.user.exception.UserImageLargeException; import com.gg.server.domain.user.exception.UserImageTypeException; import com.gg.server.global.dto.PageRequestDto; import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -25,7 +19,6 @@ @RestController @AllArgsConstructor @RequestMapping(value = "/pingpong/admin/users") -@Slf4j public class UserAdminController { private final UserAdminService userAdminService; @@ -61,6 +54,55 @@ public ResponseEntity userUpdateDetail(@PathVariable String intraId, } userAdminService.updateUserDetail(intraId, updateUserInfo, imgData); - return new ResponseEntity(HttpStatus.NO_CONTENT); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/images/{intraId}") + public ResponseEntity deleteUserProfileImage(@PathVariable String intraId) { + userAdminService.deleteUserProfileImage(intraId); + return ResponseEntity.noContent().build(); + } + + @GetMapping("/delete-list") + public UserImageListAdminResponseDto getUserImageDeleteList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize(), + Sort.by("id").descending()); + return userAdminService.getUserImageDeleteList(pageable); + } + + @GetMapping("/delete-list/{intraId}") + public UserImageListAdminResponseDto getUserImageDeleteListByIntraId(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageDeleteListByIntraId(pageable, intraId); + } + + @GetMapping("/images") + public UserImageListAdminResponseDto getUserImageList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageList(pageable); + } + + @GetMapping("/images/{intraId}") + public UserImageListAdminResponseDto getUserImage(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageListByIntraId(pageable, intraId); + } + + @GetMapping("/images/current") + public UserImageListAdminResponseDto getUserImageCurrent(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageCurrent(pageable); + } + + @GetMapping("/images/current/{intraId}") + public UserImageListAdminResponseDto getUserImageCurrentByIntraId(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageCurrentByIntraId(pageable, intraId); } } diff --git a/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java b/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java index 44a2245a7..3eb4712ea 100644 --- a/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java +++ b/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java @@ -1,15 +1,15 @@ -package com.gg.server.admin.user.data; - -import com.gg.server.domain.user.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserAdminRepository extends JpaRepository { - Optional findByIntraId(String intraId); - Page findByIntraIdContains(Pageable pageable, String intraId); - Page findByIntraId(Pageable pageable, String intraId); - Page findAll(Pageable pageable); -} +package com.gg.server.admin.user.data; + +import com.gg.server.domain.user.data.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserAdminRepository extends JpaRepository { + Optional findByIntraId(String intraId); + Page findByIntraIdContains(Pageable pageable, String intraId); + Page findByIntraId(Pageable pageable, String intraId); + Page findAll(Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java b/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java new file mode 100644 index 000000000..c18eb09dd --- /dev/null +++ b/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java @@ -0,0 +1,42 @@ +package com.gg.server.admin.user.data; + +import com.gg.server.domain.user.data.User; +import org.springframework.data.repository.query.Param; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import com.gg.server.domain.user.data.UserImage; +import org.springframework.data.jpa.repository.Query; + + +import java.util.Optional; + +public interface UserImageAdminRepository extends JpaRepository{ + Optional findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(User user); + + Optional findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(User user); + + Page findAllByDeletedAtNotNullOrderByDeletedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.user.id = :user_id " + + "AND ui.deletedAt != NULL ORDER BY ui.deletedAt DESC") + Page findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc(@Param("user_id") Long userId, Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + + "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + + ") ORDER BY ui.createdAt DESC") + Page findAllChangedOrderByCreatedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + + "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + + ") AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") + Page findAllByUserOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS TRUE" + + " ORDER BY ui.createdAt DESC") + Page findAllByIsCurrentTrueOrderByCreatedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS True" + + " AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") + Page findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java index b1f47ca24..521f0c36e 100644 --- a/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java +++ b/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java @@ -1,53 +1,54 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class UserAdminDto { - private Long id; - private String intraId; - private String eMail; - private String imageUri; - private RacketType racketType; - private RoleType roleType; - private Integer totalExp; - private SnsType snsNotiOpt; - - static public UserAdminDto from (User user) { - UserAdminDto userDto; - if (user == null) { - userDto = null; - } else { - userDto = UserAdminDto.builder() - .id(user.getId()) - .intraId(user.getIntraId()) - .eMail(user.getEMail()) - .imageUri(user.getImageUri()) - .racketType(user.getRacketType()) - .roleType(user.getRoleType()) - .totalExp(user.getTotalExp()) - .snsNotiOpt(user.getSnsNotiOpt()) - .build(); - } - return userDto; - } - - @Override - public String toString() { - return "UserDto{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", eMail='" + eMail + '\'' + - ", imageUri='" + imageUri + '\'' + - ", racketType=" + racketType + '\'' + - ", roleType=" + roleType + '\'' + - ", totalExp=" + totalExp + - '}'; - } -} +package com.gg.server.admin.user.dto; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserAdminDto { + private Long id; + private String intraId; + private String eMail; + private String imageUri; + private RacketType racketType; + private RoleType roleType; + private Integer totalExp; + private SnsType snsNotiOpt; + + static public UserAdminDto from (User user, UserImage userImage) { + UserAdminDto userDto; + if (user == null) { + userDto = null; + } else { + userDto = UserAdminDto.builder() + .id(user.getId()) + .intraId(user.getIntraId()) + .eMail(user.getEMail()) + .imageUri(userImage.getImageUri()) + .racketType(user.getRacketType()) + .roleType(user.getRoleType()) + .totalExp(user.getTotalExp()) + .snsNotiOpt(user.getSnsNotiOpt()) + .build(); + } + return userDto; + } + + @Override + public String toString() { + return "UserDto{" + + "id=" + id + + ", intraId='" + intraId + '\'' + + ", eMail='" + eMail + '\'' + + ", imageUri='" + imageUri + '\'' + + ", racketType=" + racketType + '\'' + + ", roleType=" + roleType + '\'' + + ", totalExp=" + totalExp + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java index d34e2ba8c..819134d75 100644 --- a/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java +++ b/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java @@ -1,68 +1,71 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.user.User; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserDetailAdminResponseDto { - private Long userId; - private String intraId; - private String userImageUri; - private String racketType; - private String statusMessage; - private Integer wins; - private Integer losses; - private Integer ppp; - private String email; - private String roleType; - private Integer exp; - - public UserDetailAdminResponseDto(User user, RankRedis rank) { - this.userId = user.getId(); - this.intraId = user.getIntraId(); - this.userImageUri = user.getImageUri(); - this.racketType = user.getRacketType().getCode(); - this.statusMessage = rank.getStatusMessage(); - this.wins = rank.getWins(); - this.losses = rank.getLosses(); - this.ppp = rank.getPpp(); - this.email = user.getEMail(); - this.roleType = user.getRoleType().getKey(); - this.exp = user.getTotalExp(); - } - - public UserDetailAdminResponseDto(User user) { - this.userId = user.getId(); - this.intraId = user.getIntraId(); - this.userImageUri = user.getImageUri(); - this.racketType = user.getRacketType().getCode(); - this.statusMessage = ""; - this.wins = 0; - this.losses = 0; - this.ppp = 0; - this.email = user.getEMail() == null ? "" : user.getEMail(); - this.roleType = user.getRoleType().getKey(); - this.exp = user.getTotalExp(); - } - - @Override - public String toString() { - return "UserDetailResponseDto{" + - "intraId='" + intraId + '\'' + - ", userImageUri='" + userImageUri + '\'' + - ", racketType='" + racketType + '\'' + - ", statusMessage='" + statusMessage + '\'' + - ", wins='" + wins.toString() + '\'' + - ", losses='" + losses.toString() + '\'' + - ", ppp='" + ppp.toString() + '\'' + - ", email='" + email + '\'' + - ", roleType='" + roleType + '\'' + - '}'; - } -} +package com.gg.server.admin.user.dto; + +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.user.data.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserDetailAdminResponseDto { + private Long userId; + private String intraId; + private String userImageUri; + private String racketType; + private String statusMessage; + private Integer wins; + private Integer losses; + private Integer ppp; + private String email; + private String roleType; + private Integer exp; + private Integer coin; + + public UserDetailAdminResponseDto(User user, RankRedis rank) { + this.userId = user.getId(); + this.intraId = user.getIntraId(); + this.userImageUri = user.getImageUri(); + this.racketType = user.getRacketType().getCode(); + this.statusMessage = rank.getStatusMessage(); + this.wins = rank.getWins(); + this.losses = rank.getLosses(); + this.ppp = rank.getPpp(); + this.email = user.getEMail(); + this.roleType = user.getRoleType().getKey(); + this.exp = user.getTotalExp(); + this.coin = user.getGgCoin(); + } + + public UserDetailAdminResponseDto(User user) { + this.userId = user.getId(); + this.intraId = user.getIntraId(); + this.userImageUri = user.getImageUri(); + this.racketType = user.getRacketType().getCode(); + this.statusMessage = ""; + this.wins = 0; + this.losses = 0; + this.ppp = 0; + this.email = user.getEMail() == null ? "" : user.getEMail(); + this.roleType = user.getRoleType().getKey(); + this.exp = user.getTotalExp(); + this.coin = user.getGgCoin(); + } + + @Override + public String toString() { + return "UserDetailResponseDto{" + + "intraId='" + intraId + '\'' + + ", userImageUri='" + userImageUri + '\'' + + ", racketType='" + racketType + '\'' + + ", statusMessage='" + statusMessage + '\'' + + ", wins='" + wins.toString() + '\'' + + ", losses='" + losses.toString() + '\'' + + ", ppp='" + ppp.toString() + '\'' + + ", email='" + email + '\'' + + ", roleType='" + roleType + '\'' + + ", coin='" + coin + '\'' + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java new file mode 100644 index 000000000..a0a90fda1 --- /dev/null +++ b/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java @@ -0,0 +1,29 @@ +package com.gg.server.admin.user.dto; + +import com.gg.server.domain.user.data.UserImage; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserImageAdminDto { + Long id; + String userIntraId; + String imageUri; + LocalDateTime createdAt; + LocalDateTime deletedAt; + Boolean isCurrent; + + public UserImageAdminDto(UserImage userImage) { + this.id = userImage.getId(); + this.userIntraId = userImage.getUser().getIntraId(); + this.imageUri = userImage.getImageUri(); + this.createdAt = userImage.getCreatedAt(); + this.deletedAt = userImage.getDeletedAt(); + this.isCurrent = userImage.getIsCurrent(); + } +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java new file mode 100644 index 000000000..1c07d01a2 --- /dev/null +++ b/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java @@ -0,0 +1,16 @@ +package com.gg.server.admin.user.dto; + +import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserImageListAdminResponseDto { + private List userImageList; + private int totalPage; +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java index 3bc7cd6e4..7acb80653 100644 --- a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java +++ b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java @@ -1,33 +1,32 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.RoleType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UserSearchAdminDto { - private Long id; - private String intraId; - private String statusMessage; - private RoleType roleType; - - public UserSearchAdminDto (User user, String statusMessage) { - this.id = user.getId(); - this.intraId = user.getIntraId(); - this.statusMessage = statusMessage; - this.roleType = user.getRoleType(); - } - - @Override - public String toString() { - return "UserAdminDto{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", statusMessage='" + statusMessage + '\'' + - ", roleType=" + roleType + - '}'; - } -} +package com.gg.server.admin.user.dto; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.RoleType; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserSearchAdminDto { + private Long id; + private String intraId; + private String statusMessage; + private RoleType roleType; + + public UserSearchAdminDto (User user, String statusMessage) { + this.id = user.getId(); + this.intraId = user.getIntraId(); + this.statusMessage = statusMessage; + this.roleType = user.getRoleType(); + } + + @Override + public String toString() { + return "{" + + "id=" + id + + ", intraId='" + intraId + '\'' + + ", statusMessage='" + statusMessage + '\'' + + ", roleType=" + roleType + + '}'; + } +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java index 6329da76b..9fe6df5ec 100644 --- a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java +++ b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java @@ -1,25 +1,22 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.User; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import org.springframework.data.domain.Page; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@AllArgsConstructor -public class UserSearchAdminResponseDto { - private List userSearchAdminDtos; - private Integer totalPage; - - public void filterUser(String filterString) { - if (filterString == null) - return ; - this.userSearchAdminDtos = this.userSearchAdminDtos.stream() - .filter(userSearchAdminDto -> userSearchAdminDto.getIntraId().equals(filterString)) - .collect(Collectors.toList()); - } -} +package com.gg.server.admin.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@AllArgsConstructor +public class UserSearchAdminResponseDto { + private List userSearchAdminDtos; + private Integer totalPage; + + public void filterUser(String filterString) { + if (filterString == null) + return ; + this.userSearchAdminDtos = this.userSearchAdminDtos.stream() + .filter(userSearchAdminDto -> userSearchAdminDto.getIntraId().equals(filterString)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java b/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java index c98b55de0..7175be106 100644 --- a/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java +++ b/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java @@ -15,6 +15,7 @@ public class UserUpdateAdminRequestDto { private Integer ppp; private String email; private String roleType; + private Integer coin; @Override public String toString() { @@ -23,9 +24,10 @@ public String toString() { ", statusMessage='" + statusMessage + '\'' + ", wins='" + wins + '\'' + ", losses'" + losses + '\'' + - ", ppp=" + ppp + '\'' + - ", email=" + email + '\'' + - ", roleType=" + roleType + + ", ppp='" + ppp + '\'' + + ", email='" + email + '\'' + + ", roleType='" + roleType + '\'' + + ", coin='" + coin + '\'' + '}'; } } diff --git a/src/main/java/com/gg/server/admin/user/service/UserAdminService.java b/src/main/java/com/gg/server/admin/user/service/UserAdminService.java index d89380bb7..65ce4f42d 100644 --- a/src/main/java/com/gg/server/admin/user/service/UserAdminService.java +++ b/src/main/java/com/gg/server/admin/user/service/UserAdminService.java @@ -1,128 +1,185 @@ -package com.gg.server.admin.user.service; -import com.gg.server.admin.rank.service.RankRedisAdminService; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.admin.user.dto.UserDetailAdminResponseDto; -import com.gg.server.admin.user.dto.UserSearchAdminDto; -import com.gg.server.admin.user.dto.UserSearchAdminRequestDto; -import com.gg.server.admin.user.dto.UserSearchAdminResponseDto; -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.exception.RankUpdateException; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.service.UserFindService; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; -import lombok.AllArgsConstructor; -import org.apache.tomcat.jni.Local; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.redis.core.convert.RedisData; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; -import org.webjars.NotFoundException; - -import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; - -@Service -@AllArgsConstructor -public class UserAdminService { - - private final UserAdminRepository userAdminRepository; - private final SeasonAdminRepository seasonAdminRepository; - private final RankRepository rankRepository; - private final RankRedisRepository rankRedisRepository; - private final RankRedisAdminService rankRedisAdminService; - private final AsyncNewUserImageUploader asyncNewUserImageUploader; - private final UserFindService userFindService; - - @Transactional(readOnly = true) - public UserSearchAdminResponseDto searchAll(Pageable pageable) { - Page userPage = userAdminRepository.findAll(pageable); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserSearchAdminResponseDto searchByIntraId(Pageable pageable, String intraId) { - Page userPage = userAdminRepository.findByIntraId(pageable, intraId); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - /* 문자열을 포함하는 intraId를 가진 유저 찾기 */ - @Transactional(readOnly = true) - public UserSearchAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { - Page userPage = userAdminRepository.findByIntraIdContains(pageable, intraId); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserDetailAdminResponseDto getUserDetailByIntraId(String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()); - Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); - try { - RankRedis userCurrRank = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeason.getId()), - user.getId()); - return new UserDetailAdminResponseDto(user, userCurrRank); - } catch (RedisDataNotFoundException e){ - return new UserDetailAdminResponseDto(user); - } - } - - @Transactional - public void updateUserDetail(String intraId, - UserUpdateAdminRequestDto userUpdateAdminRequestDto, - MultipartFile userImageFile) throws IOException{ - Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()); - - user.modifyUserDetail(userUpdateAdminRequestDto); - if (userImageFile != null) - asyncNewUserImageUploader.update(intraId, userImageFile); - updateUserRank(user.getId(), currSeason.getId(), userUpdateAdminRequestDto); - } - - private void updateUserRank(Long userId, Long currSeasonId, UserUpdateAdminRequestDto updateReq) { - Rank userCurrRank = rankRepository.findByUserIdAndSeasonId(userId, currSeasonId).orElseThrow(() -> new RankNotFoundException()); - RankRedis userCurrRankRedis = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeasonId), - userId); - - userCurrRank.modifyUserRank(updateReq); - userCurrRank.setStatusMessage(updateReq.getStatusMessage()); - - userCurrRankRedis.changedRank(updateReq.getPpp(), - updateReq.getWins(), - updateReq.getLosses()); - userCurrRankRedis.setStatusMessage(updateReq.getStatusMessage()); - rankRedisAdminService.updateRankUser(RedisKeyManager.getHashKey(currSeasonId), - RedisKeyManager.getZSetKey(currSeasonId), - userId, userCurrRankRedis); - } -} +package com.gg.server.admin.user.service; +import com.gg.server.admin.rank.service.RankRedisAdminService; +import com.gg.server.admin.season.data.SeasonAdminRepository; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.admin.user.data.UserImageAdminRepository; +import com.gg.server.admin.user.dto.*; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.exception.RankNotFoundException; +import com.gg.server.domain.rank.exception.RedisDataNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.exception.SeasonNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.domain.user.service.UserFindService; +import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@AllArgsConstructor +public class UserAdminService { + + private final UserAdminRepository userAdminRepository; + private final SeasonAdminRepository seasonAdminRepository; + private final RankRepository rankRepository; + private final RankRedisRepository rankRedisRepository; + private final RankRedisAdminService rankRedisAdminService; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final UserFindService userFindService; + private final UserImageAdminRepository userImageAdminRepository; + + @Transactional(readOnly = true) + public UserSearchAdminResponseDto searchAll(Pageable pageable) { + Page userPage = userAdminRepository.findAll(pageable); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserSearchAdminResponseDto searchByIntraId(Pageable pageable, String intraId) { + Page userPage = userAdminRepository.findByIntraId(pageable, intraId); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + /* 문자열을 포함하는 intraId를 가진 유저 찾기 */ + @Transactional(readOnly = true) + public UserSearchAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { + Page userPage = userAdminRepository.findByIntraIdContains(pageable, intraId); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserDetailAdminResponseDto getUserDetailByIntraId(String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); + try { + RankRedis userCurrRank = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeason.getId()), + user.getId()); + return new UserDetailAdminResponseDto(user, userCurrRank); + } catch (RedisDataNotFoundException e){ + return new UserDetailAdminResponseDto(user); + } + } + + @Transactional + public void updateUserDetail(String intraId, + UserUpdateAdminRequestDto userUpdateAdminRequestDto, + MultipartFile userImageFile) throws IOException{ + Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + + user.modifyUserDetail(userUpdateAdminRequestDto); + if (userImageFile != null) + asyncNewUserImageUploader.update(intraId, userImageFile); + updateUserRank(user.getId(), currSeason.getId(), userUpdateAdminRequestDto); + } + + private void updateUserRank(Long userId, Long currSeasonId, UserUpdateAdminRequestDto updateReq) { + Rank userCurrRank = rankRepository.findByUserIdAndSeasonId(userId, currSeasonId).orElseThrow(() -> new RankNotFoundException()); + RankRedis userCurrRankRedis = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeasonId), + userId); + + userCurrRank.modifyUserRank(updateReq); + userCurrRank.setStatusMessage(updateReq.getStatusMessage()); + + userCurrRankRedis.changedRank(updateReq.getPpp(), + updateReq.getWins(), + updateReq.getLosses()); + userCurrRankRedis.setStatusMessage(updateReq.getStatusMessage()); + rankRedisAdminService.updateRankUser(RedisKeyManager.getHashKey(currSeasonId), + RedisKeyManager.getZSetKey(currSeasonId), + userId, userCurrRankRedis); + } + + public String getUserImageToString(User user) { + UserImage userImage = userImageAdminRepository.findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(user).orElse(null); + if (userImage == null) + return "null"; + else { + userImage.updateIsCurrent(); + return userImage.getImageUri(); + } + } + + @Transactional + public void deleteUserProfileImage(String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + UserImage userImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); + userImage.updateDeletedAt(LocalDateTime.now()); + String userImageUri = getUserImageToString(user); + user.updateImageUri(userImageUri); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageDeleteList(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllByDeletedAtNotNullOrderByDeletedAtDesc(pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageDeleteListByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc(user.getId(), pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageList(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllChangedOrderByCreatedAtDesc(pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageListByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserOrderByCreatedAtDesc(user.getId(), pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageCurrent(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllByIsCurrentTrueOrderByCreatedAtDesc(pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageCurrentByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc(user.getId(), pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } +} diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java b/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java new file mode 100644 index 000000000..96f746de4 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java @@ -0,0 +1,41 @@ +package com.gg.server.domain.coin.data; + +import com.gg.server.domain.user.data.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class CoinHistory { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "history", length = 30) + private String history; + + @Column(name = "amount") + private int amount; + + @CreatedDate + @Column(name = "createdAt", updatable = false, nullable = false) + private LocalDateTime createdAt; + + public CoinHistory(User user, String history, int amount) { + this.user = user; + this.history = history; + this.amount = amount; + this.createdAt = LocalDateTime.now(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java b/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java new file mode 100644 index 000000000..358b6c162 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java @@ -0,0 +1,24 @@ +package com.gg.server.domain.coin.data; + +import com.gg.server.domain.feedback.data.Feedback; +import com.gg.server.domain.user.data.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +public interface CoinHistoryRepository extends JpaRepository { + @Query("SELECT CASE WHEN COUNT(ch) > 0 THEN true ELSE false END FROM CoinHistory ch WHERE ch.user = :user AND ch.history = :history AND ch.createdAt >= :startOfDay AND ch.createdAt < :endOfDay") + boolean existsUserAttendedCheckToday(@Param("user") User user, @Param("history") String history, @Param("startOfDay") LocalDateTime startOfDay, @Param("endOfDay") LocalDateTime endOfDay); + + Optional findFirstByOrderByIdDesc(); + + List findAllByUserOrderByIdDesc(User user); + + Page findAllByUserOrderByIdDesc(User user, Pageable pageable); +} diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java b/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java new file mode 100644 index 000000000..28c884afd --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java @@ -0,0 +1,62 @@ +package com.gg.server.domain.coin.data; + +import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; +import com.gg.server.domain.user.data.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class CoinPolicy { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "attendance") + private int attendance; + + @Column(name = "normal") + private int normal; + + @Column(name = "rankWin") + private int rankWin; + + @Column(name = "rankLose") + private int rankLose; + + @CreatedDate + @Column(name = "createdAt", updatable = false, nullable = false) + private LocalDateTime createdAt; + + @Builder + public CoinPolicy(User user, int attendance, int normal, int rankWin, int rankLose) { + this.user = user; + this.attendance = attendance; + this.normal = normal; + this.rankWin = rankWin; + this.rankLose = rankLose; + this.createdAt = LocalDateTime.now(); + } + + static public CoinPolicy from(User user, CoinPolicyAdminAddDto addDto) { + return CoinPolicy.builder() + .user(user) + .attendance(addDto.getAttendance()) + .normal(addDto.getNormal()) + .rankWin(addDto.getRankWin()) + .rankLose(addDto.getRankLose()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java b/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java new file mode 100644 index 000000000..6e3eb8a77 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.coin.data; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface CoinPolicyRepository extends JpaRepository { + Optional findTopByOrderByCreatedAtDesc(); + +} diff --git a/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java b/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java new file mode 100644 index 000000000..4030c370b --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java @@ -0,0 +1,18 @@ +package com.gg.server.domain.coin.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserGameCoinResultDto { + private int beforeCoin; + private int afterCoin; + private int coinIncrement; + + public UserGameCoinResultDto(int afterCoin, int coinIncrement) { + this.beforeCoin = afterCoin - coinIncrement; + this.afterCoin = afterCoin; + this.coinIncrement = coinIncrement; + } +} diff --git a/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java b/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java new file mode 100644 index 000000000..c8e0710c5 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.coin.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.CustomRuntimeException; + +public class CoinHistoryNotFoundException extends CustomRuntimeException { + public CoinHistoryNotFoundException() { + super(ErrorCode.COIN_HISTORY_NOT_FOUND.getMessage(), ErrorCode.COIN_HISTORY_NOT_FOUND); + } +} diff --git a/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java b/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java new file mode 100644 index 000000000..5e857eeab --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.coin.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.CustomRuntimeException; + +public class CoinPolicyNotFoundException extends CustomRuntimeException { + public CoinPolicyNotFoundException() { + super(ErrorCode.CoinPolicy_NOT_FOUND.getMessage(), ErrorCode.CoinPolicy_NOT_FOUND); + } +} diff --git a/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java b/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java new file mode 100644 index 000000000..36962a1f9 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java @@ -0,0 +1,76 @@ +package com.gg.server.domain.coin.service; + +import com.gg.server.domain.coin.data.CoinHistory; +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import com.gg.server.domain.coin.data.CoinPolicyRepository; +import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; +import com.gg.server.domain.coin.type.HistoryType; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.user.data.User; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Service +@RequiredArgsConstructor +public class CoinHistoryService { + private final CoinHistoryRepository coinHistoryRepository; + private final CoinPolicyRepository coinPolicyRepository; + + @Transactional + public void addAttendanceCoinHistory(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getAttendance(); + addCoinHistory(new CoinHistory(user, HistoryType.ATTENDANCECOIN.getHistory(), amount)); + } + + @Transactional + public void addPurchaseItemCoinHistory(User user, Item item, Integer price) { + addCoinHistory(new CoinHistory(user, item.getName() + " 구매", price * (-1))); + } + + @Transactional + public void addGiftItemCoinHistory(User user, User giftTarget, Item item, Integer price) { + addCoinHistory(new CoinHistory(user, giftTarget.getIntraId() + "에게 " + item.getName() + " 선물", price * (-1))); + } + + @Transactional + public void addNormalCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal(); + addCoinHistory(new CoinHistory(user, HistoryType.NORMAL.getHistory(), amount)); + } + + @Transactional + public int addRankWinCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankWin(); + addCoinHistory(new CoinHistory(user, HistoryType.RANKWIN.getHistory(), amount)); + return amount; + } + + @Transactional + public int addRankLoseCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankLose(); + if (amount == 0) + return amount; + addCoinHistory(new CoinHistory(user, HistoryType.RANKLOSE.getHistory(), amount)); + return amount; + } + + @Transactional(readOnly = true) + public boolean hasAttendedToday(User user) { + LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); + LocalDateTime endOfDay = startOfDay.plusDays(1); + return coinHistoryRepository.existsUserAttendedCheckToday( + user, HistoryType.ATTENDANCECOIN.getHistory(), startOfDay, endOfDay); + } + + public void addCoinHistory(CoinHistory coinHistory) { + coinHistoryRepository.save(coinHistory); + } + +} diff --git a/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java b/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java new file mode 100644 index 000000000..b30dbc385 --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java @@ -0,0 +1,97 @@ +package com.gg.server.domain.coin.service; + +import com.gg.server.domain.coin.data.CoinPolicyRepository; +import com.gg.server.domain.coin.dto.UserGameCoinResultDto; +import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; +import com.gg.server.domain.game.service.GameFindService; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.team.data.Team; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserAlreadyAttendanceException; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class UserCoinChangeService { + private final CoinPolicyRepository coinPolicyRepository; + private final CoinHistoryService coinHistoryService; + private final UserRepository userRepository; + private final GameFindService gameFindService; + + @Transactional + public int addAttendanceCoin(User user){ + if (coinHistoryService.hasAttendedToday(user)) + throw new UserAlreadyAttendanceException(); + int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getAttendance(); + user.addGgCoin(coinIncrement); + coinHistoryService.addAttendanceCoinHistory(user); + return coinIncrement; + } + + @Transactional + public void purchaseItemCoin(Item item, Integer price, Long userId){ + + User user = userRepository.findById(userId) + .orElseThrow(UserNotFoundException::new); + + user.payGgCoin(price); + + coinHistoryService.addPurchaseItemCoinHistory(user, item, price); + } + + @Transactional + public void giftItemCoin(Item item, Integer price, User user, User giftTarget){ + user.payGgCoin(price); + + coinHistoryService.addGiftItemCoinHistory(user, giftTarget, item, price); + } + + + @Transactional + public UserGameCoinResultDto addNormalGameCoin(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getNormal(); + + user.addGgCoin(coinIncrement); + coinHistoryService.addNormalCoin(user); + return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); + } + + @Transactional + public UserGameCoinResultDto addRankGameCoin(Long gameId, Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + int coinIncrement; + + if (userIsWinner(gameId, user)) + coinIncrement = coinHistoryService.addRankWinCoin(user); + else + coinIncrement = coinHistoryService.addRankLoseCoin(user); + + user.addGgCoin(coinIncrement); + return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); + } + + private boolean userIsWinner(Long gameId, User user) { + List teams = gameFindService.findByGameId(gameId).getTeams(); + + for(Team team: teams) { + for (TeamUser teamUser : team.getTeamUsers()){ + if (teamUser.getUser().getId() == user.getId() && team.getWin()) + return true; + else if (teamUser.getUser().getId() == user.getId() && !team.getWin()) + return false; + } + } + + return false; + } +} diff --git a/src/main/java/com/gg/server/domain/coin/type/HistoryType.java b/src/main/java/com/gg/server/domain/coin/type/HistoryType.java new file mode 100644 index 000000000..8144c712a --- /dev/null +++ b/src/main/java/com/gg/server/domain/coin/type/HistoryType.java @@ -0,0 +1,16 @@ +package com.gg.server.domain.coin.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum HistoryType { + + ATTENDANCECOIN("출석"), + NORMAL("일반전 참가"), + RANKWIN("랭크전 승리"), + RANKLOSE("랭크전 패배"); + + private final String history; +} diff --git a/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java b/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java index 4a6a54716..b18bd2edd 100644 --- a/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java +++ b/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java @@ -1,33 +1,33 @@ -package com.gg.server.domain.feedback.controller; - - -import com.gg.server.domain.feedback.dto.FeedbackRequestDto; -import com.gg.server.domain.feedback.service.FeedbackService; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping(value = "/pingpong") -public class FeedbackController { - private final FeedbackService feedbackService; - private final UserRepository userRepository; - - @PostMapping(value = "/feedback") - public ResponseEntity feedbackSave(@Valid @RequestBody FeedbackRequestDto feedbackRequestDto, - @Parameter(hidden = true) @Login UserDto user) { - feedbackService.addFeedback(feedbackRequestDto, user.getId()); - return new ResponseEntity(HttpStatus.CREATED); - } -} +package com.gg.server.domain.feedback.controller; + + +import com.gg.server.domain.feedback.dto.FeedbackRequestDto; +import com.gg.server.domain.feedback.service.FeedbackService; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.utils.argumentresolver.Login; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/pingpong") +public class FeedbackController { + private final FeedbackService feedbackService; + private final UserRepository userRepository; + + @PostMapping(value = "/feedback") + public ResponseEntity feedbackSave(@Valid @RequestBody FeedbackRequestDto feedbackRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + feedbackService.addFeedback(feedbackRequestDto, user.getId()); + return new ResponseEntity(HttpStatus.CREATED); + } +} diff --git a/src/main/java/com/gg/server/domain/feedback/data/Feedback.java b/src/main/java/com/gg/server/domain/feedback/data/Feedback.java index 76fc60e16..f70d61947 100644 --- a/src/main/java/com/gg/server/domain/feedback/data/Feedback.java +++ b/src/main/java/com/gg/server/domain/feedback/data/Feedback.java @@ -1,44 +1,44 @@ -package com.gg.server.domain.feedback.data; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@Entity -@Getter -public class Feedback extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "category", length = 15) - private FeedbackType category; - - @NotNull - @Column(name = "content", length = 600) - private String content; - - @Setter - @NotNull - @Column(name = "is_solved") - private Boolean isSolved; - - @Builder - public Feedback(User user, FeedbackType category, String content) { - this.user = user; - this.category = category; - this.content = content; - this.isSolved = false; - } -} +package com.gg.server.domain.feedback.data; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.feedback.type.FeedbackType; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@NoArgsConstructor +@Entity +@Getter +public class Feedback extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "category", length = 15) + private FeedbackType category; + + @NotNull + @Column(name = "content", length = 600) + private String content; + + @Setter + @NotNull + @Column(name = "is_solved") + private Boolean isSolved; + + @Builder + public Feedback(User user, FeedbackType category, String content) { + this.user = user; + this.category = category; + this.content = content; + this.isSolved = false; + } +} diff --git a/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java b/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java index 2441dc784..3bccca5d5 100644 --- a/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java +++ b/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java @@ -1,26 +1,25 @@ -package com.gg.server.domain.feedback.dto; - -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.domain.user.User; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -public class FeedbackRequestDto { - @NotNull(message = "plz. content") - private FeedbackType category; - @NotNull(message = "plz. content") - @Length(max = 600, message = "plz. maxSizeMessage 600") - private String content; - - @Builder - public FeedbackRequestDto(FeedbackType category, String content) { - this.category = category; - this.content = content; - } -} +package com.gg.server.domain.feedback.dto; + +import com.gg.server.domain.feedback.type.FeedbackType; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +public class FeedbackRequestDto { + @NotNull(message = "plz. not null FeedbackType") + private FeedbackType category; + @NotNull(message = "plz. not null content") + @Length(max = 600, message = "plz. maxSizeMessage 600") + private String content; + + @Builder + public FeedbackRequestDto(FeedbackType category, String content) { + this.category = category; + this.content = content; + } +} diff --git a/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java b/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java index 3279ef5c7..22df6d097 100644 --- a/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java +++ b/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java @@ -1,30 +1,26 @@ -package com.gg.server.domain.feedback.service; - -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.data.FeedbackRepository; -import com.gg.server.domain.feedback.dto.FeedbackRequestDto; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class FeedbackService { - private final FeedbackRepository feedbackRepository; - private final UserRepository userRepository; - - @Transactional - public void addFeedback(FeedbackRequestDto feedbackRequestDto, Long userId) { - User user = userRepository.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User" + userId)); - - Feedback feedback = Feedback.builder() - .user(user) - .category(feedbackRequestDto.getCategory()) - .content(feedbackRequestDto.getContent()) - .build(); - feedbackRepository.save(feedback); - } -} +package com.gg.server.domain.feedback.service; + +import com.gg.server.domain.feedback.data.Feedback; +import com.gg.server.domain.feedback.data.FeedbackRepository; +import com.gg.server.domain.feedback.dto.FeedbackRequestDto; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class FeedbackService { + private final FeedbackRepository feedbackRepository; + private final UserRepository userRepository; + + @Transactional + public void addFeedback(FeedbackRequestDto feedbackRequestDto, Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + Feedback feedback = new Feedback(user, feedbackRequestDto.getCategory(), feedbackRequestDto.getContent()); + feedbackRepository.save(feedback); + } +} diff --git a/src/main/java/com/gg/server/domain/game/GameController.java b/src/main/java/com/gg/server/domain/game/GameController.java index 9ea9ec2cc..3ab466208 100644 --- a/src/main/java/com/gg/server/domain/game/GameController.java +++ b/src/main/java/com/gg/server/domain/game/GameController.java @@ -8,6 +8,7 @@ import com.gg.server.domain.game.exception.ScoreNotMatchedException; import com.gg.server.domain.game.service.GameFindService; import com.gg.server.domain.game.service.GameService; +import com.gg.server.domain.rank.redis.RankRedisService; import com.gg.server.domain.user.dto.UserDto; import com.gg.server.global.exception.ErrorCode; import com.gg.server.global.exception.custom.InvalidParameterException; @@ -29,6 +30,7 @@ public class GameController { private final GameService gameService; private final GameFindService gameFindService; + private final RankRedisService rankRedisService; @GetMapping GameListResDto allGameList(@Valid GameListReqDto gameReq) { @@ -73,6 +75,7 @@ synchronized ResponseEntity createRankResult(@Valid @RequestBody RankResultReqDt if (!gameService.createRankResult(reqDto, user.getId())) { throw new ScoreNotMatchedException(); } + rankRedisService.updateAllTier(reqDto.getGameId()); return new ResponseEntity(HttpStatus.CREATED); } diff --git a/src/main/java/com/gg/server/domain/game/data/GameRepository.java b/src/main/java/com/gg/server/domain/game/data/GameRepository.java index 7e311a167..21a1ec5ff 100644 --- a/src/main/java/com/gg/server/domain/game/data/GameRepository.java +++ b/src/main/java/com/gg/server/domain/game/data/GameRepository.java @@ -3,12 +3,14 @@ import com.gg.server.domain.game.dto.GameTeamUserInfo; import com.gg.server.domain.game.type.Mode; import com.gg.server.domain.game.type.StatusType; + import java.time.LocalDateTime; import java.util.Optional; import com.gg.server.domain.team.dto.GameUser; import javax.persistence.LockModeType; -import org.springframework.cache.annotation.Cacheable; + +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import com.gg.server.domain.game.dto.GameTeamUser; import org.springframework.data.domain.Pageable; @@ -19,17 +21,22 @@ import java.util.List; -public interface GameRepository extends JpaRepository, GameRepositoryCustom{ +public interface GameRepository extends JpaRepository, GameRepositoryCustom { Slice findAllByModeAndStatus(Mode mode, StatusType status, Pageable pageable); + Slice findAllByAndStatus(StatusType status, Pageable pageable); + Slice findAllByAndStatusIn(List statusList, Pageable pageable); + Slice findAllByModeAndStatusAndSeasonId(Mode mode, StatusType status, Long season, Pageable pageable); + @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + "from v_rank_game_detail t1, v_rank_game_detail t2 " + "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsIn(@Param("games") List games); + @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, " + "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.image t2Image, t2.total_exp t2Exp " + @@ -39,30 +46,38 @@ public interface GameRepository extends JpaRepository, GameRepositor @Query(value = "SELECT teamId, gameId, score, startTime, status, mode, userId, intraId, image, total_exp exp" + " FROM v_teamuser where gameId = :gameId", nativeQuery = true) - List findTeamGameUser(Long gameId); + List findTeamGameUser(@Param("gameId") Long gameId); + Optional findByStartTime(LocalDateTime startTime); + @Query(value = "select g from Game g where g.startTime > :startTime and g.startTime < :endTime") - List findAllBetween(@Param("startTime")LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); + List findAllBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); + @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.startTime > :startTime AND g.startTime < :endTime " + "AND g.id = t.game.id AND t.id = tu.team.id AND tu.user.id = :userId") - Optional findByUserInSlots(@Param("startTime")LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("userId") Long userId); + Optional findByUserInSlots(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("userId") Long userId); + @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.status = :status AND g.id = t.game.id" + " AND t.id = tu.team.id AND tu.user.id = :userId") Optional findByStatusTypeAndUserId(@Param("status") StatusType status, @Param("userId") Long userId); + @Query(value = "select gameId " + "from v_teamuser " + "where intraId = :intra and status in (:status)", nativeQuery = true) Slice findGamesByUser(@Param("intra") String intra, @Param("status") List status, Pageable pageable); + @Query(value = "select gameId " + "from v_teamuser " + "where intraId = :intra and mode in (:mode) and status=:status", nativeQuery = true) Slice findGamesByUserAndMode(@Param("intra") String intra, @Param("mode") String mode, @Param("status") String status, Pageable pageable); + @Query(value = "select gameId " + "from v_teamuser " + "where intraId = :intra and mode in (:mode) and seasonId = :seasonId and status=:status", nativeQuery = true) Slice findGamesByUserAndModeAndSeason(@Param("intra") String intra, @Param("mode") String mode, @Param("seasonId") Long seasonId, @Param("status") String status, Pageable pageable); List findAllByStatusAndStartTimeLessThanEqual(StatusType status, LocalDateTime startTime); + List findAllByStatusAndEndTimeLessThanEqual(StatusType status, LocalDateTime endTime); @Query(value = "SELECT u.id userId, u.e_mail email, u.intra_id intraId, u.sns_noti_opt snsNotiOpt, g.id gameId " + @@ -71,6 +86,11 @@ public interface GameRepository extends JpaRepository, GameRepositor "team t, team_user tu, user u " + "WHERE g.id=t.game_id AND t.id = tu.team_id AND tu.user_id=u.id AND g.status = 'BEFORE'", nativeQuery = true) List findAllByStartTimeLessThanEqual(@Param("time") LocalDateTime time); + @Lock(LockModeType.PESSIMISTIC_WRITE) Optional findWithPessimisticLockById(Long gameId); + + @Override + @EntityGraph(attributePaths = {"season"}) + Optional findById(Long gameId); } diff --git a/src/main/java/com/gg/server/domain/game/dto/ExpChangeResultResDto.java b/src/main/java/com/gg/server/domain/game/dto/ExpChangeResultResDto.java index 9afe3842e..d8303f3fb 100644 --- a/src/main/java/com/gg/server/domain/game/dto/ExpChangeResultResDto.java +++ b/src/main/java/com/gg/server/domain/game/dto/ExpChangeResultResDto.java @@ -1,5 +1,6 @@ package com.gg.server.domain.game.dto; +import com.gg.server.domain.coin.dto.UserGameCoinResultDto; import com.gg.server.global.utils.ExpLevelCalculator; import lombok.Getter; import lombok.NoArgsConstructor; @@ -13,14 +14,20 @@ public class ExpChangeResultResDto { private Integer increasedExp; private Integer increasedLevel; private Integer afterMaxExp; + private int beforeCoin; + private int afterCoin; + private int coinIncrement; - public ExpChangeResultResDto(Integer beforeExp, Integer currentExp) { + public ExpChangeResultResDto(Integer beforeExp, Integer currentExp, UserGameCoinResultDto userGameCoinResultDto) { this.beforeExp = ExpLevelCalculator.getCurrentLevelMyExp(beforeExp); this.beforeLevel = ExpLevelCalculator.getLevel(beforeExp); this.beforeMaxExp = ExpLevelCalculator.getLevelMaxExp(beforeLevel); this.increasedExp = currentExp - beforeExp; this.increasedLevel = ExpLevelCalculator.getLevel(currentExp) - this.beforeLevel; this.afterMaxExp = ExpLevelCalculator.getLevelMaxExp(this.beforeLevel + this.increasedLevel); + this.beforeCoin = userGameCoinResultDto.getBeforeCoin(); + this.afterCoin = userGameCoinResultDto.getAfterCoin(); + this.coinIncrement = userGameCoinResultDto.getCoinIncrement(); } @Override diff --git a/src/main/java/com/gg/server/domain/game/dto/PPPChangeResultResDto.java b/src/main/java/com/gg/server/domain/game/dto/PPPChangeResultResDto.java index 92c0ababe..0faed8f19 100644 --- a/src/main/java/com/gg/server/domain/game/dto/PPPChangeResultResDto.java +++ b/src/main/java/com/gg/server/domain/game/dto/PPPChangeResultResDto.java @@ -1,5 +1,6 @@ package com.gg.server.domain.game.dto; +import com.gg.server.domain.coin.dto.UserGameCoinResultDto; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,8 +11,8 @@ public class PPPChangeResultResDto extends ExpChangeResultResDto { private Integer changedPpp; private Integer beforePpp; - public PPPChangeResultResDto(Integer beforeExp, Integer currentExp, Integer beforePpp, Integer afterPpp) { - super(beforeExp, currentExp); + public PPPChangeResultResDto(Integer beforeExp, Integer currentExp, Integer beforePpp, Integer afterPpp, UserGameCoinResultDto userGameCoinResultDto) { + super(beforeExp, currentExp, userGameCoinResultDto); this.changedPpp = afterPpp - beforePpp; this.beforePpp = beforePpp; } diff --git a/src/main/java/com/gg/server/domain/game/dto/req/RankResultReqDto.java b/src/main/java/com/gg/server/domain/game/dto/req/RankResultReqDto.java index 8b5aa31d7..779cc7cbc 100644 --- a/src/main/java/com/gg/server/domain/game/dto/req/RankResultReqDto.java +++ b/src/main/java/com/gg/server/domain/game/dto/req/RankResultReqDto.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import javax.validation.constraints.Max; import javax.validation.constraints.NotNull; @@ -9,6 +10,7 @@ import javax.validation.constraints.PositiveOrZero; @Getter +@NoArgsConstructor @AllArgsConstructor public class RankResultReqDto { diff --git a/src/main/java/com/gg/server/domain/game/service/GameFindService.java b/src/main/java/com/gg/server/domain/game/service/GameFindService.java index 94db942ad..1b4e047dd 100644 --- a/src/main/java/com/gg/server/domain/game/service/GameFindService.java +++ b/src/main/java/com/gg/server/domain/game/service/GameFindService.java @@ -86,4 +86,8 @@ public Game findByGameId(Long gameId) { return gameRepository.findById(gameId) .orElseThrow(GameNotExistException::new); } + public Game findGameWithPessimisticLockById(Long id) { + return gameRepository.findWithPessimisticLockById(id) + .orElseThrow(GameNotExistException::new); + } } diff --git a/src/main/java/com/gg/server/domain/game/service/GameService.java b/src/main/java/com/gg/server/domain/game/service/GameService.java index f6434fe5d..b81a6c3ad 100644 --- a/src/main/java/com/gg/server/domain/game/service/GameService.java +++ b/src/main/java/com/gg/server/domain/game/service/GameService.java @@ -1,190 +1,195 @@ -package com.gg.server.domain.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.*; -import com.gg.server.domain.game.dto.req.NormalResultReqDto; -import com.gg.server.domain.game.dto.req.RankResultReqDto; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import com.gg.server.domain.pchange.service.PChangeService; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.team.exception.TeamIdNotMatchException; -import com.gg.server.domain.user.User; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Caching; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.*; - -@Service -@RequiredArgsConstructor -@Slf4j -public class GameService { - private final GameRepository gameRepository; - private final TeamUserRepository teamUserRepository; - private final RankRedisService rankRedisService; - private final PChangeService pChangeService; - private final PChangeRepository pChangeRepository; - - private final GameFindService gameFindService; - - @Transactional(readOnly = true) - public GameTeamInfo getUserGameInfo(Long gameId, Long userId) { - List infos = gameRepository.findTeamGameUser(gameId); - if (infos.size() == 0) { - throw new GameNotExistException(); - } - return new GameTeamInfo(infos, userId); - } - - @Transactional - @Caching(evict = { - @CacheEvict(value = "rankGameListByIntra", allEntries = true), - @CacheEvict(value = "rankGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true) - }) - public Boolean createRankResult(RankResultReqDto scoreDto, Long userId) { - // 현재 게임 id - Game game = gameRepository.findWithPessimisticLockById(scoreDto.getGameId()) - .orElseThrow(GameNotExistException::new); - if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { - return false; - } - return updateScore(game, scoreDto, userId); - } - - @Transactional - @Caching(evict = { - @CacheEvict(value = "normalGameListByIntra", allEntries = true), - @CacheEvict(value = "normalGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true) - }) - public synchronized Boolean normalExpResult(NormalResultReqDto normalResultReqDto, Long loginUserId) { - Game game = gameFindService.findByGameId(normalResultReqDto.getGameId()); - List teamUsers = teamUserRepository.findAllByGameId(game.getId()); - if (teamUsers.size() == 2 && - (game.getStatus() == StatusType.WAIT || game.getStatus() == StatusType.LIVE)) { - expUpdates(game, teamUsers); - savePChange(game, teamUsers, loginUserId); - return true; - } else if (teamUsers.size() == 2 && game.getStatus() == StatusType.END) { - updatePchangeIsChecked(game, loginUserId); - return true; - } else if (teamUsers.size() != 2) { - throw new InvalidParameterException("team 이 잘못되었습니다.", ErrorCode.VALID_FAILED); - } - return false; - } - - private void updatePchangeIsChecked(Game game, Long loginUserId) { - pChangeRepository.findPChangeByUserIdAndGameId(loginUserId, game.getId()) - .ifPresentOrElse(pChange -> { - pChange.userCheckResult(); - pChangeRepository.save(pChange); - }, () -> { - throw new PChangeNotExistException(); - }); - } - - private void savePChange(Game game, List teamUsers, Long loginUserId) { - Long team1UserId = teamUsers.get(0).getUser().getId(); - Long team2UserId = teamUsers.get(1).getUser().getId(); - pChangeService.addPChange(game, teamUsers.get(0).getUser(), - rankRedisService.getUserPpp(team1UserId, game.getSeason().getId()), team1UserId.equals(loginUserId)); - pChangeService.addPChange(game, teamUsers.get(1).getUser(), - rankRedisService.getUserPpp(team2UserId, game.getSeason().getId()), team2UserId.equals(loginUserId)); - } - - @Transactional(readOnly = true) - public ExpChangeResultResDto expChangeResult(Long gameId, Long userId) { - List pChanges = pChangeService.findExpChangeHistory(gameId, userId); - if (pChanges.size() == 1) { - return new ExpChangeResultResDto(0, pChanges.get(0).getExp()); - } else { - log.info("before:", pChanges.get(1).getExp(), ", after: ", pChanges.get(0).getExp()); - return new ExpChangeResultResDto(pChanges.get(1).getExp(), pChanges.get(0).getExp()); - } - } - - @Transactional(readOnly = true) - public PPPChangeResultResDto pppChangeResult(Long gameId, Long userId) throws PChangeNotExistException { - Season season = gameFindService.findByGameId(gameId).getSeason(); - List pppHistory = pChangeService.findPPPChangeHistory(gameId, userId, season.getId()); - List expHistory = pChangeService.findExpChangeHistory(gameId, userId); - return new PPPChangeResultResDto(expHistory.size() <= 1 ? 0 : expHistory.get(1).getExp(), - pppHistory.get(0).getExp(), - pppHistory.size() <= 1 ? season.getStartPpp() : pppHistory.get(1).getPppResult(), - pppHistory.get(0).getPppResult()); - } - - public void expUpdates(Game game, List teamUsers) { - LocalDateTime time = getToday(game.getStartTime()); - for (TeamUser tu : - teamUsers) { - expUpdate(tu, time); - } - if (game.getStatus() == StatusType.LIVE) { - game.updateStatus(); - } - game.updateStatus(); - } - - private void expUpdate(TeamUser teamUser, LocalDateTime time) { - Integer gamePerDay = teamUserRepository.findByDateAndUser(time, teamUser.getUser().getId()); - teamUser.getUser().addExp(ExpLevelCalculator.getExpPerGame() + (ExpLevelCalculator.getExpBonus() * gamePerDay)); - } - - private static LocalDateTime getToday(LocalDateTime gameTime) { - return LocalDateTime.of(gameTime.getYear(), gameTime.getMonthValue(), gameTime.getDayOfMonth(), 0, 0); - } - - private void setTeamScore(TeamUser tu, int teamScore, Boolean isWin) { - tu.getTeam().updateScore(teamScore, isWin); - } - - private TeamUser findTeamId(Long teamId, List teamUsers) { - for (TeamUser tu : - teamUsers) { - if (tu.getTeam().getId().equals(teamId)) { - return tu; - } - } - throw new TeamIdNotMatchException(); - } - - private Boolean updateScore(Game game, RankResultReqDto scoreDto, Long userId) { - List teams = teamUserRepository.findAllByGameId(game.getId()); - TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); - TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); - if (!myTeam.getUser().getId().equals(userId)) { - throw new InvalidParameterException("team user 정보 불일치.", ErrorCode.VALID_FAILED); - } else { - if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)){ - setTeamScore(myTeam, scoreDto.getMyTeamScore(), scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); - setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); - expUpdates(game, teams); - rankRedisService.updateRankRedis(myTeam, enemyTeam, game); - } else { - // score 가 이미 입력됨 - return false; - } - return true; - } - } +package com.gg.server.domain.game.service; + +import com.gg.server.domain.coin.dto.UserGameCoinResultDto; +import com.gg.server.domain.coin.service.UserCoinChangeService; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.*; +import com.gg.server.domain.game.dto.req.NormalResultReqDto; +import com.gg.server.domain.game.dto.req.RankResultReqDto; +import com.gg.server.domain.game.exception.GameNotExistException; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; +import com.gg.server.domain.pchange.exception.PChangeNotExistException; +import com.gg.server.domain.pchange.service.PChangeService; +import com.gg.server.domain.rank.redis.RankRedisService; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.rank.service.RedisUploadService; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.team.data.TeamUserRepository; +import com.gg.server.domain.team.exception.TeamIdNotMatchException; +import com.gg.server.domain.tier.service.TierService; +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.InvalidParameterException; +import com.gg.server.global.utils.ExpLevelCalculator; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.*; + +@Service +@RequiredArgsConstructor +public class GameService { + private final GameRepository gameRepository; + private final TeamUserRepository teamUserRepository; + private final RankRedisService rankRedisService; + private final PChangeService pChangeService; + private final PChangeRepository pChangeRepository; + private final GameFindService gameFindService; + private final UserCoinChangeService userCoinChangeService; + private final TierService tierService; + private final RedisUploadService redisUploadService; + + @Transactional(readOnly = true) + public GameTeamInfo getUserGameInfo(Long gameId, Long userId) { + List infos = gameRepository.findTeamGameUser(gameId); + if (infos.size() == 0) { + throw new GameNotExistException(); + } + return new GameTeamInfo(infos, userId); + } + + @Transactional + @Caching(evict = { + @CacheEvict(value = "rankGameListByIntra", allEntries = true), + @CacheEvict(value = "rankGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true) + }) + public Boolean createRankResult(RankResultReqDto scoreDto, Long userId) { + // 현재 게임 id + Game game = gameFindService.findGameWithPessimisticLockById(scoreDto.getGameId()); + if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { + return false; + } + return updateScore(game, scoreDto, userId); + } + + @Transactional + @Caching(evict = { + @CacheEvict(value = "normalGameListByIntra", allEntries = true), + @CacheEvict(value = "normalGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true) + }) + public Boolean normalExpResult(NormalResultReqDto normalResultReqDto, Long loginUserId) { + Game game = gameFindService.findGameWithPessimisticLockById(normalResultReqDto.getGameId()); + List teamUsers = teamUserRepository.findAllByGameId(game.getId()); + if (teamUsers.size() == 2 && + (game.getStatus() == StatusType.WAIT || game.getStatus() == StatusType.LIVE)) { + expUpdates(game, teamUsers); + savePChange(game, teamUsers, loginUserId); + return true; + } else if (teamUsers.size() == 2 && game.getStatus() == StatusType.END) { + updatePchangeIsChecked(game, loginUserId); + return true; + } else if (teamUsers.size() != 2) { + throw new InvalidParameterException("team 이 잘못되었습니다.", ErrorCode.VALID_FAILED); + } + return false; + } + + private void updatePchangeIsChecked(Game game, Long loginUserId) { + pChangeRepository.findPChangeByUserIdAndGameId(loginUserId, game.getId()) + .ifPresentOrElse(pChange -> { + pChange.userCheckResult(); + pChangeRepository.save(pChange); + }, () -> { + throw new PChangeNotExistException(); + }); + } + + private void savePChange(Game game, List teamUsers, Long loginUserId) { + Long team1UserId = teamUsers.get(0).getUser().getId(); + Long team2UserId = teamUsers.get(1).getUser().getId(); + pChangeService.addPChange(game, teamUsers.get(0).getUser(), + rankRedisService.getUserPpp(team1UserId, game.getSeason().getId()), team1UserId.equals(loginUserId)); + pChangeService.addPChange(game, teamUsers.get(1).getUser(), + rankRedisService.getUserPpp(team2UserId, game.getSeason().getId()), team2UserId.equals(loginUserId)); + } + + @Transactional + public ExpChangeResultResDto expChangeResult(Long gameId, Long userId) { + List pChanges = pChangeService.findExpChangeHistory(gameId, userId); + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); + + if (pChanges.size() == 1) { + return new ExpChangeResultResDto(0, pChanges.get(0).getExp(), userGameCoinResultDto); + } else { + return new ExpChangeResultResDto(pChanges.get(1).getExp(), pChanges.get(0).getExp(), userGameCoinResultDto); + } + } + + @Transactional + public PPPChangeResultResDto pppChangeResult(Long gameId, Long userId) throws PChangeNotExistException { + Season season = gameFindService.findByGameId(gameId).getSeason(); + List pppHistory = pChangeService.findPPPChangeHistory(gameId, userId, season.getId()); + List expHistory = pChangeService.findExpChangeHistory(gameId, userId); + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addRankGameCoin(gameId, userId); + return new PPPChangeResultResDto(expHistory.size() <= 1 ? 0 : expHistory.get(1).getExp(), + pppHistory.get(0).getExp(), + pppHistory.size() <= 1 ? season.getStartPpp() : pppHistory.get(1).getPppResult(), + pppHistory.get(0).getPppResult(), userGameCoinResultDto); + } + + public void expUpdates(Game game, List teamUsers) { + LocalDateTime time = getToday(game.getStartTime()); + for (TeamUser tu : + teamUsers) { + expUpdate(tu, time); + } + if (game.getStatus() == StatusType.LIVE) { + game.updateStatus(); + } + game.updateStatus(); + } + + private void expUpdate(TeamUser teamUser, LocalDateTime time) { + Integer gamePerDay = teamUserRepository.findByDateAndUser(time, teamUser.getUser().getId()); + teamUser.getUser().addExp(ExpLevelCalculator.getExpPerGame() + (ExpLevelCalculator.getExpBonus() * gamePerDay)); + } + + private static LocalDateTime getToday(LocalDateTime gameTime) { + return LocalDateTime.of(gameTime.getYear(), gameTime.getMonthValue(), gameTime.getDayOfMonth(), 0, 0); + } + + private void setTeamScore(TeamUser tu, int teamScore, Boolean isWin) { + tu.getTeam().updateScore(teamScore, isWin); + } + + private TeamUser findTeamId(Long teamId, List teamUsers) { + for (TeamUser tu : + teamUsers) { + if (tu.getTeam().getId().equals(teamId)) { + return tu; + } + } + throw new TeamIdNotMatchException(); + } + + public Boolean updateScore(Game game, RankResultReqDto scoreDto, Long userId) { + List teams = teamUserRepository.findAllByGameId(game.getId()); + TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); + TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); + if (!myTeam.getUser().getId().equals(userId)) { + throw new InvalidParameterException("team user 정보 불일치.", ErrorCode.VALID_FAILED); + } else { + if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)){ + setTeamScore(myTeam, scoreDto.getMyTeamScore(), scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); + setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); + expUpdates(game, teams); + rankRedisService.updateRankRedis(myTeam, enemyTeam, game); + tierService.updateAllTier(game.getSeason()); + } else { + // score 가 이미 입력됨 + return false; + } + return true; + } + } } \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/controller/ItemController.java b/src/main/java/com/gg/server/domain/item/controller/ItemController.java new file mode 100644 index 000000000..9b3d7df3a --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/controller/ItemController.java @@ -0,0 +1,56 @@ +package com.gg.server.domain.item.controller; + +import com.gg.server.domain.item.dto.ItemGiftRequestDto; +import com.gg.server.domain.item.dto.ItemStoreListResponseDto; +import com.gg.server.domain.item.dto.UserItemListResponseDto; +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.dto.PageRequestDto; +import com.gg.server.global.utils.argumentresolver.Login; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/items") +public class ItemController { + + private final ItemService itemService; + + @GetMapping("/store") + public ItemStoreListResponseDto getAllItems() { + return itemService.getAllItems(); + } + + @PostMapping("/purchases/{itemId}") + public ResponseEntity purchaseItem(@PathVariable Long itemId, + @Parameter(hidden = true) @Login UserDto userDto) { + itemService.purchaseItem(itemId, userDto); + return new ResponseEntity(HttpStatus.CREATED); + } + + @PostMapping("/gift/{itemId}") + public ResponseEntity giftItem(@PathVariable Long itemId, + @RequestBody ItemGiftRequestDto recipient, + @Parameter(hidden = true) @Login UserDto userDto) { + itemService.giftItem(itemId, recipient.getOwnerId(), userDto); + return new ResponseEntity(HttpStatus.CREATED); + } + + @GetMapping + public UserItemListResponseDto getItemByUser(@ModelAttribute @Valid PageRequestDto req, + @Parameter(hidden = true) @Login UserDto userDto) { + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return itemService.getItemByUser(userDto, pageable); + } + +} diff --git a/src/main/java/com/gg/server/domain/item/data/Item.java b/src/main/java/com/gg/server/domain/item/data/Item.java new file mode 100644 index 000000000..651de5fb6 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/data/Item.java @@ -0,0 +1,111 @@ +package com.gg.server.domain.item.data; + +import com.gg.server.admin.item.dto.ItemUpdateRequestDto; +import com.gg.server.domain.item.type.ItemType; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Entity +@Getter +@NoArgsConstructor +public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name", length = 30) + private String name; + + @Column(name = "main_content", length = 255) + private String mainContent; + + @Column(name = "sub_content", length = 255) + private String subContent; + + @Column(name = "image_uri", length = 255) + private String imageUri; + + @NotNull + @Column(name = "price") + private Integer price; + + @NotNull + @Column(name = "is_visible") + private Boolean isVisible; + + @Column(name = "discount") + private Integer discount; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "type") + private ItemType type; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + @NotNull + @Column(name = "creator_intra_id", length = 10) + private String creatorIntraId; + + @Column(name = "deleter_intra_id", length = 10) + private String deleterIntraId; + + public Item(String name, String mainContent, String subContent, String imageUri, Integer price, + Boolean isVisible, Integer discount, ItemType type, LocalDateTime createdAt, String creatorIntraId) { + this.name = name; + this.mainContent = mainContent; + this.subContent = subContent; + this.imageUri = imageUri; + this.price = price; + this.isVisible = isVisible; + this.discount = discount; + this.type = type; + this.createdAt = createdAt; + this.creatorIntraId = creatorIntraId; + } + + @Builder + public Item(ItemUpdateRequestDto updateRequestDto, String creatorIntraId, String itemImageUri) { + this.name = updateRequestDto.getName(); + this.mainContent = updateRequestDto.getMainContent(); + this.subContent = updateRequestDto.getSubContent(); + this.imageUri = itemImageUri; + this.price = updateRequestDto.getPrice(); + this.discount = updateRequestDto.getDiscount(); + this.isVisible = true; + this.creatorIntraId = creatorIntraId; + this.createdAt = LocalDateTime.now(); + this.type = updateRequestDto.getItemType(); + } + + public void imageUpdate(String imageUri) { + this.imageUri = imageUri; + } + + public void setVisibility(String intraId) { + this.isVisible = false; + this.deleterIntraId = intraId; + } + + @Override + public String toString() { + return "Item{" + + "id=" + id + + ", name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", imageUri='" + imageUri + '\'' + + ", price=" + price + + ", isVisible=" + isVisible + + ", discount=" + discount + + ", createdAt=" + createdAt + + ", creatorIntraId='" + creatorIntraId + '\'' + + ", deleterIntraId='" + deleterIntraId + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/data/ItemRepository.java b/src/main/java/com/gg/server/domain/item/data/ItemRepository.java new file mode 100644 index 000000000..ef6f26fd8 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/data/ItemRepository.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.data; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import java.util.List; + +public interface ItemRepository extends JpaRepository { + @Query("SELECT i FROM Item i WHERE i.isVisible = true ORDER BY i.createdAt DESC") + List findAllByCreatedAtDesc(); +} diff --git a/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java b/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java new file mode 100644 index 000000000..6fcab5174 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java @@ -0,0 +1,15 @@ +package com.gg.server.domain.item.data; + +import com.gg.server.domain.receipt.data.Receipt; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface UserItemRepository extends JpaRepository { + + @Query("select r from Receipt r where r.ownerIntraId = :intraId " + + "and (r.status = 'BEFORE' or r.status = 'USING' or r.status = 'WAITING') order by r.createdAt desc") + Page findByOwnerIntraId(@Param("intraId") String intraId, Pageable pageable); +} diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java new file mode 100644 index 000000000..4085b5eac --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java @@ -0,0 +1,12 @@ +package com.gg.server.domain.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ItemGiftRequestDto { + private String ownerId; +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java new file mode 100644 index 000000000..702ac6950 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java @@ -0,0 +1,16 @@ +package com.gg.server.domain.item.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor +@Getter +public class ItemStoreListResponseDto { + private List itemList; + + public ItemStoreListResponseDto(List itemList){ + this.itemList = itemList; + } +} diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java new file mode 100644 index 000000000..4ecc4bb46 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java @@ -0,0 +1,34 @@ +package com.gg.server.domain.item.dto; + +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.type.ItemType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ItemStoreResponseDto { + private Long itemId; + private String itemName; + private String mainContent; + private String subContent; + private ItemType itemType; + private String imageUri; + private Integer originalPrice; + private Integer discount; + private Integer salePrice; + + public ItemStoreResponseDto(Item item) { + this.itemId = item.getId(); + this.itemName = item.getName(); + this.mainContent = item.getMainContent(); + this.subContent = item.getSubContent(); + this.itemType = item.getType(); + this.imageUri = item.getImageUri(); + this.originalPrice = item.getPrice(); + this.discount = item.getDiscount(); + this.salePrice = this.originalPrice - (this.originalPrice * this.discount / 100); + } +} diff --git a/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java new file mode 100644 index 000000000..230d00524 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java @@ -0,0 +1,19 @@ +package com.gg.server.domain.item.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +public class UserItemListResponseDto { + private List storageItemList; + private Integer totalPage; + + public UserItemListResponseDto(List storageItemList, Integer totalPage){ + this.storageItemList = storageItemList; + this.totalPage = totalPage; + } + +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java new file mode 100644 index 000000000..a2e5d49bd --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java @@ -0,0 +1,32 @@ +package com.gg.server.domain.item.dto; + +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.type.ItemStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserItemResponseDto { + private Long receiptId; + private String itemName; + private String imageUri; + private String purchaserIntra; + private ItemStatus itemStatus; + private ItemType itemType; + + public UserItemResponseDto(Receipt receipt) { + Item item = receipt.getItem(); + this.receiptId = receipt.getId(); + this.itemName = item.getName(); + this.imageUri = item.getImageUri(); + this.purchaserIntra = receipt.getPurchaserIntraId(); + this.itemStatus = receipt.getStatus(); + this.itemType = item.getType(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java b/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java new file mode 100644 index 000000000..aefb4d198 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class InsufficientGgcoinException extends BusinessException { + public InsufficientGgcoinException() { + super("GGcoin이 부족합니다.", ErrorCode.INSUFFICIENT_GGCOIN); + } +} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java new file mode 100644 index 000000000..8c8dd7561 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.FileException; + +public class ItemImageLargeException extends FileException { + public ItemImageLargeException() { + super("이미지 파일 50KB 초과", ErrorCode.USER_IMAGE_TOO_LARGE); + } +} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java new file mode 100644 index 000000000..34955934f --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.FileException; + +public class ItemImageTypeException extends FileException { + public ItemImageTypeException() { + super("이미지 타입이 올바르지 않습니다", ErrorCode.ITEM_IMAGE_WRONG_TYPE); + } +} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java new file mode 100644 index 000000000..ab807ed84 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.FileException; + +public class ItemNotAvailableException extends FileException { + public ItemNotAvailableException() { + super("아이템 접근이 불가합니다", ErrorCode.ITEM_NOT_AVAILABLE); + } +} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java new file mode 100644 index 000000000..88e74d13f --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; + +public class ItemNotFoundException extends NotExistException { + public ItemNotFoundException() { + super("해당 아이템이 없습니다.", ErrorCode.ITEM_NOT_FOUND); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java new file mode 100644 index 000000000..170bfc7b5 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class ItemNotPurchasableException extends BusinessException { + public ItemNotPurchasableException() { + super("지금은 구매할 수 없는 아이템 입니다.", ErrorCode.ITEM_NOT_PURCHASABLE); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java new file mode 100644 index 000000000..4e39acfe5 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java @@ -0,0 +1,8 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class ItemTypeException extends BusinessException { + public ItemTypeException() {super("아이템 타입 오류입니다.", ErrorCode.ITEM_TYPE_NOT_MATCHED);} +} diff --git a/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java b/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java new file mode 100644 index 000000000..e85c4190e --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class KakaoGiftException extends BusinessException { + public KakaoGiftException() { + super("카카오 게스트는 선물할 수 없습니다.", ErrorCode.GUEST_ROLE_GIFT_FORBIDDEN); + } +} diff --git a/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java b/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java new file mode 100644 index 000000000..2164fb165 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java @@ -0,0 +1,11 @@ +package com.gg.server.domain.item.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class KakaoPurchaseException extends BusinessException { + public KakaoPurchaseException() { + super("카카오 게스트는 구매할 수 없습니다.", ErrorCode.GUEST_ROLE_PURCHASE_FORBIDDEN); + } +} + diff --git a/src/main/java/com/gg/server/domain/item/service/ItemService.java b/src/main/java/com/gg/server/domain/item/service/ItemService.java new file mode 100644 index 000000000..71268b568 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/service/ItemService.java @@ -0,0 +1,149 @@ +package com.gg.server.domain.item.service; + +import com.gg.server.domain.coin.service.UserCoinChangeService; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.data.ItemRepository; +import com.gg.server.domain.item.data.UserItemRepository; +import com.gg.server.domain.item.dto.ItemStoreListResponseDto; +import com.gg.server.domain.item.dto.ItemStoreResponseDto; +import com.gg.server.domain.item.dto.UserItemListResponseDto; +import com.gg.server.domain.item.dto.UserItemResponseDto; +import com.gg.server.domain.item.exception.*; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.noti.service.NotiService; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.data.ReceiptRepository; +import com.gg.server.domain.receipt.exception.ItemStatusException; +import com.gg.server.domain.receipt.exception.ReceiptNotOwnerException; +import com.gg.server.domain.receipt.type.ItemStatus; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.domain.user.type.RoleType; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class ItemService { + + private final ItemRepository itemRepository; + private final ReceiptRepository receiptRepository; + private final UserRepository userRepository; + private final UserItemRepository userItemRepository; + private final NotiService notiService; + private final UserCoinChangeService userCoinChangeService; + + @Transactional(readOnly = true) + public ItemStoreListResponseDto getAllItems() { + + List itemStoreListResponseDto = itemRepository.findAllByCreatedAtDesc() + .stream().map(ItemStoreResponseDto::new).collect(Collectors.toList()); + return new ItemStoreListResponseDto(itemStoreListResponseDto); + } + + @Transactional + public void purchaseItem(Long itemId, UserDto userDto) { + Item item = itemRepository.findById(itemId) + .orElseThrow(() -> { + throw new ItemNotFoundException(); + }); + if (!item.getIsVisible()) { + throw new ItemNotPurchasableException(); + } + + //세일가격 존재할때 세일가로 결정 + Integer finalPrice; + if (item.getDiscount() != null && item.getDiscount() > 0) { + finalPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); + } else { + finalPrice = item.getPrice(); + } + + User payUser = userRepository.findById(userDto.getId()) + .orElseThrow(() -> new UserNotFoundException()); + + if (payUser.getRoleType() == RoleType.GUEST) { + throw new KakaoPurchaseException(); + } + + userCoinChangeService.purchaseItemCoin(item, finalPrice, userDto.getId()); + + Receipt receipt = new Receipt(item, userDto.getIntraId(), userDto.getIntraId(), + ItemStatus.BEFORE, LocalDateTime.now()); + receiptRepository.save(receipt); + } + + @Transactional + public void giftItem(Long itemId, String ownerId, UserDto userDto) { + Item item = itemRepository.findById(itemId) + .orElseThrow(() -> { + throw new ItemNotFoundException(); + }); + if (!item.getIsVisible()) { + throw new ItemNotPurchasableException(); + } + + //세일가격 존재할때 세일가로 결정 + Integer finalPrice; + if (item.getDiscount() != null && item.getDiscount() > 0) { + finalPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); + } else { + finalPrice = item.getPrice(); + } + + User payUser = userRepository.findById(userDto.getId()) + .orElseThrow(UserNotFoundException::new); + + if (payUser.getRoleType() == RoleType.GUEST) { + throw new KakaoPurchaseException(); + } + + User owner = userRepository.findByIntraId(ownerId) + .orElseThrow(UserNotFoundException::new); + + if (owner.getRoleType() == RoleType.GUEST) { + throw new KakaoGiftException(); + } + + userCoinChangeService.giftItemCoin(item, finalPrice, payUser, owner); + + Receipt receipt = new Receipt(item, userDto.getIntraId(), ownerId, + ItemStatus.BEFORE, LocalDateTime.now()); + receiptRepository.save(receipt); + notiService.createGiftNoti(owner, payUser, item.getName()); + } + + @Transactional(readOnly = true) + public UserItemListResponseDto getItemByUser(UserDto userDto, Pageable pageable) { + Page receipts = userItemRepository.findByOwnerIntraId(userDto.getIntraId(), pageable); + Page responseDtos = receipts.map(UserItemResponseDto::new); + return new UserItemListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + public void checkItemOwner(User loginUser, Receipt receipt) { + if (!receipt.getOwnerIntraId().equals(loginUser.getIntraId())) + throw new ReceiptNotOwnerException(); + } + + public void checkItemType(Receipt receipt, ItemType itemType) { + if (!receipt.getItem().getType().equals(itemType)) + throw new ItemTypeException(); + } + + public void checkItemStatus(Receipt receipt) { + if (receipt.getItem().getType().equals(ItemType.MEGAPHONE)) { + if (!(receipt.getStatus().equals(ItemStatus.WAITING) || receipt.getStatus().equals(ItemStatus.USING))) throw new ItemStatusException(); + } else { + if (!receipt.getStatus().equals(ItemStatus.BEFORE)) throw new ItemStatusException(); + } + } +} diff --git a/src/main/java/com/gg/server/domain/item/type/ItemType.java b/src/main/java/com/gg/server/domain/item/type/ItemType.java new file mode 100644 index 000000000..1bfafaae1 --- /dev/null +++ b/src/main/java/com/gg/server/domain/item/type/ItemType.java @@ -0,0 +1,9 @@ +package com.gg.server.domain.item.type; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ItemType { + MEGAPHONE, BACKGROUND, EDGE, TEXT_COLOR, PROFILE_IMAGE + +} diff --git a/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java b/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java index 780e7e721..0deaadf91 100644 --- a/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java +++ b/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java @@ -1,59 +1,57 @@ -package com.gg.server.domain.match.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.match.data.RedisMatchTime; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class MatchStatusDto { - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime startTime; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime endTime; - private Boolean isMatched; - private Boolean isImminent; - private List myTeam; - private List enemyTeam; - - public MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement) { - this.startTime = game.getStartTime(); - this.endTime = game.getEndTime(); - this.isMatched = true; - this.isImminent = game.getStartTime().minusMinutes(slotManagement.getOpenMinute()) - .isBefore(LocalDateTime.now()); - this.myTeam = List.of(userIntraId); - this.enemyTeam = List.of(enemyIntraId); - - } - - public MatchStatusDto(RedisMatchTime redisMatchTime, Integer interval) { - this.startTime = redisMatchTime.getStartTime(); - this.endTime = redisMatchTime.getStartTime().plusMinutes(interval); - this.isMatched = false; - this.isImminent = false; - this.myTeam = List.of(); - this.enemyTeam = List.of(); - } - - @Override - public String toString() { - return "CurrentMatchResponseDto{" + - "startTime=" + startTime + - "endTIme=" + endTime + - ", myTeam=" + myTeam + - ", enemyTeam=" + enemyTeam + - ", isMatched=" + isMatched + - '}'; - } -} +package com.gg.server.domain.match.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.match.data.RedisMatchTime; +import com.gg.server.domain.slotmanagement.SlotManagement; + +import java.time.LocalDateTime; +import java.util.List; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MatchStatusDto { + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime startTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime endTime; + private Boolean isMatched; + private Boolean isImminent; + private List myTeam; + private List enemyTeam; + + public MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement) { + this.startTime = game.getStartTime(); + this.endTime = game.getEndTime(); + this.isMatched = true; + this.isImminent = game.getStartTime().minusMinutes(slotManagement.getOpenMinute()) + .isBefore(LocalDateTime.now()); + this.myTeam = List.of(userIntraId); + this.enemyTeam = List.of(enemyIntraId); + + } + + public MatchStatusDto(RedisMatchTime redisMatchTime, Integer interval) { + this.startTime = redisMatchTime.getStartTime(); + this.endTime = redisMatchTime.getStartTime().plusMinutes(interval); + this.isMatched = false; + this.isImminent = false; + this.myTeam = List.of(); + this.enemyTeam = List.of(); + } + + @Override + public String toString() { + return "CurrentMatchResponseDto{" + + "startTime=" + startTime + + "endTIme=" + endTime + + ", myTeam=" + myTeam + + ", enemyTeam=" + enemyTeam + + ", isMatched=" + isMatched + + '}'; + } +} diff --git a/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java b/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java index a10c696e3..ede5a87cd 100644 --- a/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java +++ b/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java @@ -2,10 +2,7 @@ import com.gg.server.domain.game.data.Game; import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.GameAlreadyExistException; -import com.gg.server.domain.game.type.StatusType; import com.gg.server.domain.match.dto.GameAddDto; -import com.gg.server.domain.match.exception.EnrolledSlotException; import com.gg.server.domain.match.exception.SlotNotFoundException; import com.gg.server.domain.noti.data.Noti; import com.gg.server.domain.noti.service.NotiService; @@ -16,8 +13,8 @@ import com.gg.server.domain.team.data.TeamRepository; import com.gg.server.domain.team.data.TeamUser; import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; import com.gg.server.domain.user.dto.UserDto; import com.gg.server.domain.user.exception.UserNotFoundException; import java.time.LocalDateTime; diff --git a/src/main/java/com/gg/server/domain/match/service/MatchFindService.java b/src/main/java/com/gg/server/domain/match/service/MatchFindService.java index bdccfa613..6fcad5a76 100644 --- a/src/main/java/com/gg/server/domain/match/service/MatchFindService.java +++ b/src/main/java/com/gg/server/domain/match/service/MatchFindService.java @@ -20,8 +20,11 @@ import com.gg.server.domain.season.service.SeasonFindService; import com.gg.server.domain.slotmanagement.SlotManagement; import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; import com.gg.server.domain.user.dto.UserDto; import com.gg.server.domain.user.type.RoleType; import java.time.LocalDateTime; @@ -44,6 +47,7 @@ public class MatchFindService { private final SeasonFindService seasonFindService; private final RankRedisRepository rankRedisRepository; private final RedisMatchTimeRepository redisMatchTimeRepository; + private final TierRepository tierRepository; @Transactional(readOnly = true) @@ -70,9 +74,10 @@ public SlotStatusResponseListDto getAllMatchStatus(UserDto userDto, Option optio SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) .orElseThrow(SlotNotFoundException::new); Season season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); RankRedis user; if (userDto.getRoleType().equals(RoleType.GUEST)) { - user = RankRedis.from(userDto, season.getStartPpp()); + user = RankRedis.from(userDto, season.getStartPpp(), tier.getImageUri()); } else { user = rankRedisRepository. findRankByUserId(RedisKeyManager.getHashKey(season.getId()), userDto.getId()); diff --git a/src/main/java/com/gg/server/domain/match/service/MatchService.java b/src/main/java/com/gg/server/domain/match/service/MatchService.java index c2f49ab56..52be369c7 100644 --- a/src/main/java/com/gg/server/domain/match/service/MatchService.java +++ b/src/main/java/com/gg/server/domain/match/service/MatchService.java @@ -21,8 +21,8 @@ import com.gg.server.domain.rank.redis.RedisKeyManager; import com.gg.server.domain.season.data.Season; import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; import com.gg.server.domain.user.dto.UserDto; import com.gg.server.domain.user.exception.UserNotFoundException; import java.time.LocalDateTime; diff --git a/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java b/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java new file mode 100644 index 000000000..e088b9946 --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java @@ -0,0 +1,47 @@ +package com.gg.server.domain.megaphone.controller; + +import com.gg.server.domain.megaphone.dto.MegaphoneDetailResponseDto; +import com.gg.server.domain.megaphone.dto.MegaphoneTodayListResponseDto; +import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; +import com.gg.server.domain.megaphone.service.MegaphoneService; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.utils.argumentresolver.Login; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/megaphones") +public class MegaphoneController { + private final MegaphoneService megaphoneService; + + @PostMapping() + public ResponseEntity useMegaphone(@RequestBody @Valid MegaphoneUseRequestDto megaphoneUseRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + megaphoneService.useMegaphone(megaphoneUseRequestDto, user); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping("/{megaphoneId}") + public ResponseEntity deleteMegaphone(@PathVariable Long megaphoneId, + @Parameter(hidden = true) @Login UserDto user) { + megaphoneService.deleteMegaphone(megaphoneId, user); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + @GetMapping("/receipt/{receiptId}") + public ResponseEntity getMegaphoneDetail(@PathVariable Long receiptId, @Parameter(hidden = true) @Login UserDto user) { + return ResponseEntity.ok(megaphoneService.getMegaphoneDetail(receiptId, user)); + } + + @GetMapping() + public ResponseEntity> getMegaphoneTodayList(@Parameter(hidden = true) @Login UserDto user) { + return ResponseEntity.ok(megaphoneService.getMegaphoneTodayList()); + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java b/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java new file mode 100644 index 000000000..a5715c44d --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java @@ -0,0 +1,44 @@ +package com.gg.server.domain.megaphone.data; + +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.user.data.User; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDate; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Megaphone { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "receipt_id") + private Receipt receipt; + + @Column(name = "content", length = 30) + private String content; + + @NotNull + @Column(name = "used_at") + private LocalDate usedAt; + + public Megaphone(User user, Receipt receipt, String content, LocalDate usedAt) { + this.user = user; + this.receipt = receipt; + this.content = content; + this.usedAt = usedAt; + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java b/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java new file mode 100644 index 000000000..3c3f33087 --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java @@ -0,0 +1,17 @@ +package com.gg.server.domain.megaphone.data; + +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.type.ItemStatus; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +public interface MegaphoneRepository extends JpaRepository { + List findAllByUsedAtAndReceiptStatus(LocalDate date, ItemStatus itemStatus); + + Megaphone findFirstByOrderByIdDesc(); + + Optional findByReceipt(Receipt receipt); +} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java new file mode 100644 index 000000000..25237287b --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java @@ -0,0 +1,19 @@ +package com.gg.server.domain.megaphone.dto; + +import com.gg.server.domain.megaphone.data.Megaphone; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneDetailResponseDto { + private Long megaphoneId; + private String content; + private String usedAt; + + public MegaphoneDetailResponseDto(Megaphone megaphone) { + this.megaphoneId = megaphone.getId(); + this.content = megaphone.getContent(); + this.usedAt = megaphone.getUsedAt().toString(); + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java new file mode 100644 index 000000000..67e0c33fa --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java @@ -0,0 +1,19 @@ +package com.gg.server.domain.megaphone.dto; + +import com.gg.server.domain.megaphone.redis.MegaphoneRedis; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneTodayListResponseDto { + private Long megaphoneId; + private String content; + private String intraId; + + public MegaphoneTodayListResponseDto(MegaphoneRedis megaphoneRedis) { + this.megaphoneId = megaphoneRedis.getId(); + this.content = megaphoneRedis.getContent(); + this.intraId = megaphoneRedis.getIntraId(); + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java new file mode 100644 index 000000000..8b44b6175 --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java @@ -0,0 +1,18 @@ +package com.gg.server.domain.megaphone.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MegaphoneUseRequestDto { + @NotNull(message = "receiptId는 null이 될 수 없습니다.") + private Long receiptId; + @NotNull(message = "content는 null이 될 수 없습니다.") @Size(max = 30) + private String content; +} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java new file mode 100644 index 000000000..8022d7bef --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.megaphone.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class MegaphoneContentException extends BusinessException { + public MegaphoneContentException() { + super("확성기 내용이 없습니다.", ErrorCode.MEGAPHONE_CONTENT); + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java new file mode 100644 index 000000000..accd2759d --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java @@ -0,0 +1,8 @@ +package com.gg.server.domain.megaphone.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; + +public class MegaphoneNotFoundException extends NotExistException { + public MegaphoneNotFoundException() {super("확성기를 찾을 수 없습니다.", ErrorCode.MEGAPHONE_TIME);} +} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java new file mode 100644 index 000000000..f11bd29f3 --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.megaphone.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class MegaphoneTimeException extends BusinessException { + public MegaphoneTimeException() { + super("확성기 사용이 불가능한 시간입니다.", ErrorCode.MEGAPHONE_TIME); + } +} diff --git a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java new file mode 100644 index 000000000..bd560df0b --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java @@ -0,0 +1,30 @@ +package com.gg.server.domain.megaphone.redis; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.redis.core.RedisHash; + +import javax.persistence.Id; +import java.time.LocalDateTime; + +@RedisHash("megaphone") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MegaphoneRedis { + @Id + private Long id; + private String intraId; + private String content; + + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime usedAt; +} diff --git a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java new file mode 100644 index 000000000..d1fd99ed3 --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java @@ -0,0 +1,33 @@ +package com.gg.server.domain.megaphone.redis; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; +import java.util.List; + + +@Repository +@RequiredArgsConstructor +public class MegaphoneRedisRepository { + private final RedisTemplate redisTemplate; + + public void addMegaphone(MegaphoneRedis megaphoneRedis) { + Duration duration = Duration.between(megaphoneRedis.getUsedAt(), megaphoneRedis.getUsedAt().plusDays(1)); + redisTemplate.opsForValue().set("megaphone" + megaphoneRedis.getId(), megaphoneRedis, duration); + } + + public List getAllMegaphone() { + return redisTemplate.opsForValue().multiGet(redisTemplate.keys("megaphone*")); + } + + public void deleteAllMegaphone() { + redisTemplate.delete(redisTemplate.keys("megaphone*")); + } + + public void deleteMegaphoneById(Long id) { + redisTemplate.delete("megaphone" + id); + } + +} diff --git a/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java b/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java new file mode 100644 index 000000000..d3f258dde --- /dev/null +++ b/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java @@ -0,0 +1,104 @@ +package com.gg.server.domain.megaphone.service; + +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.megaphone.data.Megaphone; +import com.gg.server.domain.megaphone.data.MegaphoneRepository; +import com.gg.server.domain.megaphone.dto.MegaphoneDetailResponseDto; +import com.gg.server.domain.megaphone.dto.MegaphoneTodayListResponseDto; +import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; +import com.gg.server.domain.megaphone.exception.MegaphoneContentException; +import com.gg.server.domain.megaphone.exception.MegaphoneNotFoundException; +import com.gg.server.domain.megaphone.exception.MegaphoneTimeException; +import com.gg.server.domain.megaphone.redis.MegaphoneRedis; +import com.gg.server.domain.megaphone.redis.MegaphoneRedisRepository; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.data.ReceiptRepository; +import com.gg.server.domain.receipt.exception.ItemStatusException; +import com.gg.server.domain.receipt.exception.ReceiptNotFoundException; +import com.gg.server.domain.receipt.type.ItemStatus; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.domain.user.type.RoleType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class MegaphoneService { + private final UserRepository userRepository; + private final ReceiptRepository receiptRepository; + private final MegaphoneRepository megaphoneRepository; + private final MegaphoneRedisRepository megaphoneRedisRepository; + private final ItemService itemService; + + @Transactional + public void useMegaphone(MegaphoneUseRequestDto megaphoneUseRequestDto, UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + if (LocalTime.now().isAfter(LocalTime.of(23, 55)) || LocalTime.now().isBefore(LocalTime.of(0, 5))) { + throw new MegaphoneTimeException(); + } + Receipt receipt = receiptRepository.findById(megaphoneUseRequestDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); + itemService.checkItemType(receipt, ItemType.MEGAPHONE); + itemService.checkItemOwner(loginUser, receipt); + if (!receipt.getStatus().equals(ItemStatus.BEFORE)) { + throw new ItemStatusException(); + } + if (megaphoneUseRequestDto.getContent().length() == 0) { + throw new MegaphoneContentException(); + } + receipt.updateStatus(ItemStatus.WAITING); + Megaphone megaphone = new Megaphone(loginUser, receipt, megaphoneUseRequestDto.getContent(), LocalDate.now().plusDays(1)); + megaphoneRepository.save(megaphone); + } + + @Transactional + public void setMegaphoneList(LocalDate today) { + megaphoneRepository.findAllByUsedAtAndReceiptStatus(today, ItemStatus.USING).forEach(megaphone -> megaphone.getReceipt().updateStatus(ItemStatus.USED)); + megaphoneRedisRepository.deleteAllMegaphone(); + List megaphones = megaphoneRepository.findAllByUsedAtAndReceiptStatus(today.plusDays(1), ItemStatus.WAITING); + for (Megaphone megaphone : megaphones) { + megaphone.getReceipt().updateStatus(ItemStatus.USING); + megaphoneRedisRepository.addMegaphone(new MegaphoneRedis(megaphone.getId(), megaphone.getUser().getIntraId(), megaphone.getContent(), + LocalDateTime.of(megaphone.getUsedAt(), LocalTime.of(0, 0)))); + } + } + + @Transactional + public void deleteMegaphone(Long megaphoneId, UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Megaphone megaphone = megaphoneRepository.findById(megaphoneId).orElseThrow(MegaphoneNotFoundException::new); + Receipt receipt = megaphone.getReceipt(); + if (!user.getRoleType().equals(RoleType.ADMIN)) { + itemService.checkItemOwner(loginUser, receipt); + } + itemService.checkItemStatus(receipt); + if (receipt.getStatus().equals(ItemStatus.USING)) { + megaphoneRedisRepository.deleteMegaphoneById(megaphone.getId()); + } + receipt.updateStatus(ItemStatus.DELETED); + } + + public MegaphoneDetailResponseDto getMegaphoneDetail(Long receiptId, UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Receipt receipt = receiptRepository.findById(receiptId).orElseThrow(ReceiptNotFoundException::new); + itemService.checkItemType(receipt, ItemType.MEGAPHONE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + Megaphone megaphone = megaphoneRepository.findByReceipt(receipt).orElseThrow(MegaphoneNotFoundException::new); + return new MegaphoneDetailResponseDto(megaphone); + } + + public List getMegaphoneTodayList() { + return megaphoneRedisRepository.getAllMegaphone().stream().map(MegaphoneTodayListResponseDto::new).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/gg/server/domain/noti/data/Noti.java b/src/main/java/com/gg/server/domain/noti/data/Noti.java index fb425e0d6..404d00d3b 100644 --- a/src/main/java/com/gg/server/domain/noti/data/Noti.java +++ b/src/main/java/com/gg/server/domain/noti/data/Noti.java @@ -1,53 +1,53 @@ -package com.gg.server.domain.noti.data; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class Noti extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "noti_type", length = 15) - @Enumerated(EnumType.STRING) - private NotiType type; - - @Column(name = "message", length = 255) - private String message; - - @NotNull - @Column(name = "is_checked") - private Boolean isChecked; - - public Noti(User user, NotiType type, String message, Boolean isChecked) { - this.user = user; - this.type = type; - this.message = message; - this.isChecked = isChecked; - } - - public void update(User user, NotiType type, String message, Boolean isChecked) { - this.user = user; - this.type = type; - this.message = message; - this.isChecked = isChecked; - } - - public void modifyIsChecked(Boolean isChecked) { - this.isChecked = isChecked; - } -} +package com.gg.server.domain.noti.data; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class Noti extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "noti_type", length = 15) + @Enumerated(EnumType.STRING) + private NotiType type; + + @Column(name = "message", length = 255) + private String message; + + @NotNull + @Column(name = "is_checked") + private Boolean isChecked; + + public Noti(User user, NotiType type, String message, Boolean isChecked) { + this.user = user; + this.type = type; + this.message = message; + this.isChecked = isChecked; + } + + public void update(User user, NotiType type, String message, Boolean isChecked) { + this.user = user; + this.type = type; + this.message = message; + this.isChecked = isChecked; + } + + public void modifyIsChecked(Boolean isChecked) { + this.isChecked = isChecked; + } +} diff --git a/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java b/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java index ff7d99be0..fb291af76 100644 --- a/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java +++ b/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java @@ -1,14 +1,14 @@ -package com.gg.server.domain.noti.data; - -import com.gg.server.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; -import java.util.Optional; - -public interface NotiRepository extends JpaRepository, NotiRepositoryCustom { - List findByUser(User user); - Optional findByIdAndUser(Long notiId, User user); - List findAllByUser(User user); - List findAllByUserOrderByIdDesc(User user); - void deleteAllByUser(User user); -} +package com.gg.server.domain.noti.data; + +import com.gg.server.domain.user.data.User; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; +import java.util.Optional; + +public interface NotiRepository extends JpaRepository, NotiRepositoryCustom { + List findByUser(User user); + Optional findByIdAndUser(Long notiId, User user); + List findAllByUser(User user); + List findAllByUserOrderByIdDesc(User user); + void deleteAllByUser(User user); +} diff --git a/src/main/java/com/gg/server/domain/noti/service/NotiService.java b/src/main/java/com/gg/server/domain/noti/service/NotiService.java index 114c705d8..f1a019265 100644 --- a/src/main/java/com/gg/server/domain/noti/service/NotiService.java +++ b/src/main/java/com/gg/server/domain/noti/service/NotiService.java @@ -1,99 +1,106 @@ -package com.gg.server.domain.noti.service; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.dto.NotiDto; -import com.gg.server.domain.noti.dto.NotiResponseDto; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; -import lombok.AllArgsConstructor; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@AllArgsConstructor -public class NotiService { - private final NotiRepository notiRepository; - private final UserRepository userRepository; - private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); - - @Transactional(readOnly = true) - public List findNotiByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(() -> new UsernameNotFoundException("User" + userDto.getId())); - List notiList = notiRepository.findAllByUserOrderByIdDesc(user); - List notiResponseDtoList = notiList.stream().map(NotiResponseDto::from).collect(Collectors.toList()); - return notiResponseDtoList; - } - - @Transactional - public NotiDto findNotiByIdAndUser(UserDto userDto, Long notiId) { - User user = userRepository.findById(userDto.getId()).orElseThrow(() -> new UsernameNotFoundException("User" + userDto.getId())); - Noti noti = notiRepository.findByIdAndUser(notiId, user).orElseThrow(() -> new NotExistException("요청한 알림을 찾을 수 없습니다.", ErrorCode.NOT_FOUND)); - return NotiDto.from(noti); - } - - @Transactional - public void modifyNotiCheckedByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(() -> new UsernameNotFoundException("User" + userDto.getId())); - List notis = notiRepository.findAllByUser(user); - notis.forEach(noti -> {noti.modifyIsChecked(true);}); - } - - @Transactional - public void removeNotiById(Long notiId) { - notiRepository.deleteById(notiId); - } - - @Transactional - public void removeAllNotisByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(() -> new UsernameNotFoundException("User" + userDto.getId())); - notiRepository.deleteAllByUser(user); - } - - @Transactional - public Noti createMatched(User user, LocalDateTime startTime) { - String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 성사되었습니다."; - Noti noti = new Noti(user, NotiType.MATCHED, notiMessage, false); - notiRepository.save(noti); - return noti; - } - - @Transactional - public Noti createMatchCancel(User user, LocalDateTime startTime) { - String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 상대에 의해 취소되었습니다."; - Noti noti = new Noti(user, NotiType.CANCELEDBYMAN, notiMessage, false); - notiRepository.save(noti); - return noti; - } - - public Noti createImminentNoti(User user, String enemyIntra, NotiType notiType, Integer gameOpenMinute) { - String msg = "님과 경기 " + gameOpenMinute + "분 전 입니다. 서두르세요!"; - return notiRepository.save(new Noti(user, notiType, msg, false)); - } - - public String getMessage(Noti noti) { - String message; - if (noti.getType() != NotiType.ANNOUNCE) { - message = notiMsg(noti.getType()); - } else { - message = "🧚: \"새로운 알림이 도착했핑.\"\n" + "🧚: \"" + noti.getType().getMessage() + "\"\n\n공지사항: " - + noti.getMessage() + "\n\n 🏓42GG와 함께하는 행복한 탁구생활🏓" + "\n$$지금 즉시 접속$$ ----> https://42gg.kr"; - } - return message; - } - public String notiMsg(NotiType notiType) { - return "🧚: \"새로운 알림이 도착했핑.\"\n" + "🧚: \"" + notiType.getMessage() + "\"\n\n 🏓42GG와 함께하는 행복한 탁구생활🏓" + - "\n$$지금 즉시 접속$$ ----> https://42gg.kr"; - } -} +package com.gg.server.domain.noti.service; + +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.noti.dto.NotiDto; +import com.gg.server.domain.noti.dto.NotiResponseDto; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class NotiService { + private final NotiRepository notiRepository; + private final UserRepository userRepository; + private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); + + @Transactional(readOnly = true) + public List findNotiByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + List notiList = notiRepository.findAllByUserOrderByIdDesc(user); + List notiResponseDtoList = notiList.stream().map(NotiResponseDto::from).collect(Collectors.toList()); + return notiResponseDtoList; + } + + @Transactional + public NotiDto findNotiByIdAndUser(UserDto userDto, Long notiId) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + Noti noti = notiRepository.findByIdAndUser(notiId, user).orElseThrow(() -> new NotExistException("요청한 알림을 찾을 수 없습니다.", ErrorCode.NOT_FOUND)); + return NotiDto.from(noti); + } + + @Transactional + public void modifyNotiCheckedByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + List notis = notiRepository.findAllByUser(user); + notis.forEach(noti -> {noti.modifyIsChecked(true);}); + } + + @Transactional + public void removeNotiById(Long notiId) { + notiRepository.deleteById(notiId); + } + + @Transactional + public void removeAllNotisByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + notiRepository.deleteAllByUser(user); + } + + @Transactional + public Noti createMatched(User user, LocalDateTime startTime) { + String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 성사되었습니다."; + Noti noti = new Noti(user, NotiType.MATCHED, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + @Transactional + public Noti createMatchCancel(User user, LocalDateTime startTime) { + String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 상대에 의해 취소되었습니다."; + Noti noti = new Noti(user, NotiType.CANCELEDBYMAN, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + @Transactional + public Noti createGiftNoti(User ownerUser, User payUser, String itemName) { + String notiMessage = "ଘ(੭ˊᵕˋ)੭* ੈ✩ " + payUser.getIntraId() + "님에게 " + itemName + " 아이템을 선물받았어요!"; + Noti noti = new Noti(ownerUser, NotiType.GIFT, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + public Noti createImminentNoti(User user, String enemyIntra, NotiType notiType, Integer gameOpenMinute) { + String msg = "님과 경기 " + gameOpenMinute + "분 전 입니다. 서두르세요!"; + return notiRepository.save(new Noti(user, notiType, msg, false)); + } + + public String getMessage(Noti noti) { + String message; + if (noti.getType() != NotiType.ANNOUNCE) { + message = notiMsg(noti.getType()); + } else { + message = "🧚: \"새로운 알림이 도착했핑.\"\n" + "🧚: \"" + noti.getType().getMessage() + "\"\n\n공지사항: " + + noti.getMessage() + "\n\n 🏓42GG와 함께하는 행복한 탁구생활🏓" + "\n$$지금 즉시 접속$$ ----> https://42gg.kr"; + } + return message; + } + public String notiMsg(NotiType notiType) { + return "🧚: \"새로운 알림이 도착했핑.\"\n" + "🧚: \"" + notiType.getMessage() + "\"\n\n 🏓42GG와 함께하는 행복한 탁구생활🏓" + + "\n$$지금 즉시 접속$$ ----> https://42gg.kr"; + } +} diff --git a/src/main/java/com/gg/server/domain/noti/type/NotiType.java b/src/main/java/com/gg/server/domain/noti/type/NotiType.java index 331d86d1b..55fce1253 100644 --- a/src/main/java/com/gg/server/domain/noti/type/NotiType.java +++ b/src/main/java/com/gg/server/domain/noti/type/NotiType.java @@ -14,7 +14,8 @@ public enum NotiType { CANCELEDBYMAN("canceledbyman", "매칭이 취소되었퐁."), CANCELEDBYTIME("canceledbytime", "매칭이 상대 없음으로 취소되었퐁."), IMMINENT("imminent", "매치가 곧 시작될퐁."), - ANNOUNCE("announce", "공지사항이 도착했퐁."); + ANNOUNCE("announce", "공지사항이 도착했퐁."), + GIFT("gift", "새로운 선물이 도착했퐁."); private final String code; private final String message; diff --git a/src/main/java/com/gg/server/domain/pchange/data/PChange.java b/src/main/java/com/gg/server/domain/pchange/data/PChange.java index 9eb657115..d75e1644f 100644 --- a/src/main/java/com/gg/server/domain/pchange/data/PChange.java +++ b/src/main/java/com/gg/server/domain/pchange/data/PChange.java @@ -1,72 +1,72 @@ -package com.gg.server.domain.pchange.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.user.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Getter -public class PChange extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "game_id") - private Game game; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "ppp_result") - private Integer pppResult; - - @NotNull - @Column(name = "exp") - private Integer exp; - - @NotNull - @Column(name = "is_checked") - private Boolean isChecked; - - public PChange(Game game, User user, Integer pppResult, Boolean isChecked) { - this.game = game; - this.user = user; - this.pppResult = pppResult; - this.exp = user.getTotalExp(); - this.isChecked = isChecked; - } - - public void userCheckResult() { - this.isChecked = true; - } - - public void checkPChange() { - this.isChecked = true; - } - public void updatePPP(Integer ppp) { - this.pppResult = ppp; - } - - @Override - public String toString() { - return "PChange{" + - "id=" + id + - ", game=" + game + - ", user=" + user + - ", pppResult=" + pppResult + - ", exp=" + exp + - ", isChecked=" + isChecked + - '}'; - } -} +package com.gg.server.domain.pchange.data; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.user.data.User; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +public class PChange extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "game_id") + private Game game; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "ppp_result") + private Integer pppResult; + + @NotNull + @Column(name = "exp") + private Integer exp; + + @NotNull + @Column(name = "is_checked") + private Boolean isChecked; + + public PChange(Game game, User user, Integer pppResult, Boolean isChecked) { + this.game = game; + this.user = user; + this.pppResult = pppResult; + this.exp = user.getTotalExp(); + this.isChecked = isChecked; + } + + public void userCheckResult() { + this.isChecked = true; + } + + public void checkPChange() { + this.isChecked = true; + } + public void updatePPP(Integer ppp) { + this.pppResult = ppp; + } + + @Override + public String toString() { + return "PChange{" + + "id=" + id + + ", game=" + game + + ", user=" + user + + ", pppResult=" + pppResult + + ", exp=" + exp + + ", isChecked=" + isChecked + + '}'; + } +} diff --git a/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java b/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java index 465d88453..968f2755a 100644 --- a/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java +++ b/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java @@ -1,44 +1,39 @@ -package com.gg.server.domain.pchange.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.dto.ExpChangeResultResDto; -import com.gg.server.domain.game.dto.PPPChangeResultResDto; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.User; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Slf4j -public class PChangeService { - private final PChangeRepository pChangeRepository; - - @Transactional - public void addPChange(Game game, User user, Integer pppResult, Boolean isChecked) { - pChangeRepository.save(new PChange(game, user, pppResult, isChecked)); - } - - public List findExpChangeHistory(Long gameId, Long userId) { - List pChanges = pChangeRepository.findExpHistory(userId, gameId); - if (pChanges.isEmpty()) { - throw new PChangeNotExistException(); - } - return pChanges; - } - - public List findPPPChangeHistory(Long gameId, Long userId, Long seasonId) { - List pChanges = pChangeRepository.findPPPHistory(userId, gameId, seasonId); - if (pChanges.isEmpty()) { - throw new PChangeNotExistException(); - } - return pChanges; - } -} +package com.gg.server.domain.pchange.service; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; +import com.gg.server.domain.user.data.User; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.gg.server.domain.pchange.exception.PChangeNotExistException; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PChangeService { + private final PChangeRepository pChangeRepository; + + @Transactional + public void addPChange(Game game, User user, Integer pppResult, Boolean isChecked) { + pChangeRepository.save(new PChange(game, user, pppResult, isChecked)); + } + + public List findExpChangeHistory(Long gameId, Long userId) { + List pChanges = pChangeRepository.findExpHistory(userId, gameId); + if (pChanges.isEmpty()) { + throw new PChangeNotExistException(); + } + return pChanges; + } + + public List findPPPChangeHistory(Long gameId, Long userId, Long seasonId) { + List pChanges = pChangeRepository.findPPPHistory(userId, gameId, seasonId); + if (pChanges.isEmpty()) { + throw new PChangeNotExistException(); + } + return pChanges; + } +} diff --git a/src/main/java/com/gg/server/domain/penalty/data/Penalty.java b/src/main/java/com/gg/server/domain/penalty/data/Penalty.java index 689939a0d..f187edfb4 100644 --- a/src/main/java/com/gg/server/domain/penalty/data/Penalty.java +++ b/src/main/java/com/gg/server/domain/penalty/data/Penalty.java @@ -1,55 +1,54 @@ -package com.gg.server.domain.penalty.data; - -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Penalty extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "penalty_type", length = 20) - @Enumerated(EnumType.STRING) - private PenaltyType type; - - @Column(name = "message", length = 100) - private String message; - - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @NotNull - @Column(name = "penalty_time") - private Integer penaltyTime; - - public Penalty(User user, PenaltyType type, String message, LocalDateTime startTime, Integer penaltyTime) { - this.user = user; - this.type = type; - this.message = message; - this.startTime = startTime; - this.penaltyTime = penaltyTime; - } - - public void updateStartTime(LocalDateTime startTime) { - this.startTime = startTime; - } -} +package com.gg.server.domain.penalty.data; + +import com.gg.server.domain.penalty.type.PenaltyType; +import com.gg.server.domain.user.data.User; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Penalty extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "penalty_type", length = 20) + @Enumerated(EnumType.STRING) + private PenaltyType type; + + @Column(name = "message", length = 100) + private String message; + + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @NotNull + @Column(name = "penalty_time") + private Integer penaltyTime; + + public Penalty(User user, PenaltyType type, String message, LocalDateTime startTime, Integer penaltyTime) { + this.user = user; + this.type = type; + this.message = message; + this.startTime = startTime; + this.penaltyTime = penaltyTime; + } + + public void updateStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } +} diff --git a/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java b/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java index c1aaef2d4..ed680721d 100644 --- a/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java +++ b/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java @@ -1,53 +1,53 @@ -package com.gg.server.domain.penalty.service; - -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.data.PenaltyRepository; -import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.service.UserFindService; -import com.gg.server.domain.user.service.UserService; -import java.time.LocalDateTime; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class PenaltyService { - private final PenaltyRepository penaltyRepository; - private final PenaltyUserRedisRepository penaltyUserRedisRepository; - private final UserFindService userFindService; - - /** - * penalty 1분 부여 - * **/ - public void givePenalty(UserDto userDto, Integer penaltyMinutes) { - - User user = userFindService.findUserById(userDto.getId()); - Optional redisPenaltyUser = penaltyUserRedisRepository - .findByIntraId(userDto.getIntraId()); - LocalDateTime releaseTime; - RedisPenaltyUser penaltyUser; - Penalty penalty; - LocalDateTime now = LocalDateTime.now(); - if (redisPenaltyUser.isPresent()) { - releaseTime = redisPenaltyUser.get().getReleaseTime().plusMinutes(penaltyMinutes); - penaltyUser = new RedisPenaltyUser(userDto.getIntraId(), redisPenaltyUser.get().getPenaltyTime() + penaltyMinutes, - releaseTime, redisPenaltyUser.get().getStartTime(), "[AUTO] 매칭 취소"); - penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] 매칭 취소", redisPenaltyUser.get().getReleaseTime(), penaltyMinutes); - } else { - releaseTime = now.plusMinutes(penaltyMinutes); - penaltyUser = new RedisPenaltyUser(user.getIntraId(), penaltyMinutes, releaseTime, now, "[AUTO] 매칭 취소"); - penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] 매칭 취소", now, penaltyMinutes); - } - penaltyRepository.save(penalty); - penaltyUserRedisRepository.addPenaltyUser(penaltyUser, releaseTime); - } - - public Boolean isPenaltyUser(String intraId) { - return penaltyUserRedisRepository.findByIntraId(intraId).isPresent(); - } -} +package com.gg.server.domain.penalty.service; + +import com.gg.server.domain.penalty.data.Penalty; +import com.gg.server.domain.penalty.data.PenaltyRepository; +import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; +import com.gg.server.domain.penalty.redis.RedisPenaltyUser; +import com.gg.server.domain.penalty.type.PenaltyType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.service.UserFindService; + +import java.time.LocalDateTime; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PenaltyService { + private final PenaltyRepository penaltyRepository; + private final PenaltyUserRedisRepository penaltyUserRedisRepository; + private final UserFindService userFindService; + + /** + * penalty 1분 부여 + * **/ + public void givePenalty(UserDto userDto, Integer penaltyMinutes) { + + User user = userFindService.findUserById(userDto.getId()); + Optional redisPenaltyUser = penaltyUserRedisRepository + .findByIntraId(userDto.getIntraId()); + LocalDateTime releaseTime; + RedisPenaltyUser penaltyUser; + Penalty penalty; + LocalDateTime now = LocalDateTime.now(); + if (redisPenaltyUser.isPresent()) { + releaseTime = redisPenaltyUser.get().getReleaseTime().plusMinutes(penaltyMinutes); + penaltyUser = new RedisPenaltyUser(userDto.getIntraId(), redisPenaltyUser.get().getPenaltyTime() + penaltyMinutes, + releaseTime, redisPenaltyUser.get().getStartTime(), "[AUTO] 매칭 취소"); + penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] 매칭 취소", redisPenaltyUser.get().getReleaseTime(), penaltyMinutes); + } else { + releaseTime = now.plusMinutes(penaltyMinutes); + penaltyUser = new RedisPenaltyUser(user.getIntraId(), penaltyMinutes, releaseTime, now, "[AUTO] 매칭 취소"); + penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] 매칭 취소", now, penaltyMinutes); + } + penaltyRepository.save(penalty); + penaltyUserRedisRepository.addPenaltyUser(penaltyUser, releaseTime); + } + + public Boolean isPenaltyUser(String intraId) { + return penaltyUserRedisRepository.findByIntraId(intraId).isPresent(); + } +} diff --git a/src/main/java/com/gg/server/domain/rank/data/Rank.java b/src/main/java/com/gg/server/domain/rank/data/Rank.java index a6c68f1c4..275f21646 100644 --- a/src/main/java/com/gg/server/domain/rank/data/Rank.java +++ b/src/main/java/com/gg/server/domain/rank/data/Rank.java @@ -1,89 +1,100 @@ -package com.gg.server.domain.rank.data; - -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -@Entity -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Table(name="ranks") -public class Rank extends BaseTimeEntity implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "season_id") - private Season season; - - @NotNull - @Column(name = "ppp") - private Integer ppp; - - @NotNull - @Column(name = "wins") - private Integer wins; - - @NotNull - @Column(name = "losses") - private Integer losses; - - @Column(name = "status_message", length = 30) - private String statusMessage; - - - public static Rank from (User user, Season season, Integer ppp) { - return Rank.builder() - .user(user) - .ppp(ppp) - .season(season) - .wins(0) - .losses(0) - .statusMessage("") - .build(); - } - - @Builder - public Rank(User user, Season season, Integer ppp, Integer wins, - Integer losses, String statusMessage) { - this.user = user; - this.season = season; - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - this.statusMessage = statusMessage; - } - - public void setStatusMessage(String statusMessage) { - this.statusMessage = statusMessage; - } - - public void modifyUserRank(UserUpdateAdminRequestDto userUpdateAdminRequestDto) { - this.ppp = userUpdateAdminRequestDto.getPpp(); - this.wins = userUpdateAdminRequestDto.getWins(); - this.losses = userUpdateAdminRequestDto.getLosses(); - } - - public void modifyUserRank(Integer ppp, int wins, int losses) { - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - } -} +package com.gg.server.domain.rank.data; + +import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.user.data.User; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name="ranks") +public class Rank extends BaseTimeEntity implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "season_id") + private Season season; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tier_id") + private Tier tier; + + @NotNull + @Column(name = "ppp") + private Integer ppp; + + @NotNull + @Column(name = "wins") + private Integer wins; + + @NotNull + @Column(name = "losses") + private Integer losses; + + @Column(name = "status_message", length = 30) + private String statusMessage; + + + public static Rank from (User user, Season season, Integer ppp, Tier tier) { + return Rank.builder() + .user(user) + .ppp(ppp) + .season(season) + .wins(0) + .losses(0) + .statusMessage("") + .tier(tier) + .build(); + } + + @Builder + public Rank(User user, Season season, Integer ppp, Integer wins, + Integer losses, String statusMessage, Tier tier) { + this.user = user; + this.season = season; + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + this.statusMessage = statusMessage; + this.tier = tier; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + public void modifyUserRank(UserUpdateAdminRequestDto userUpdateAdminRequestDto) { + this.ppp = userUpdateAdminRequestDto.getPpp(); + this.wins = userUpdateAdminRequestDto.getWins(); + this.losses = userUpdateAdminRequestDto.getLosses(); + } + + public void modifyUserRank(Integer ppp, int wins, int losses) { + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + } + + public void updateTier(Tier tier) { + this.tier = tier; + } +} diff --git a/src/main/java/com/gg/server/domain/rank/data/RankRepository.java b/src/main/java/com/gg/server/domain/rank/data/RankRepository.java index 4c9bc6ca3..67726c8e2 100644 --- a/src/main/java/com/gg/server/domain/rank/data/RankRepository.java +++ b/src/main/java/com/gg/server/domain/rank/data/RankRepository.java @@ -20,6 +20,11 @@ public interface RankRepository extends JpaRepository { Optional findFirstByOrderByCreatedAtDesc(); - @EntityGraph(attributePaths = {"user"}) + @EntityGraph(attributePaths = {"user", "tier"}) List findAllBySeasonId(Long seasonId); + + List findAllBySeasonIdOrderByPppDesc(Long seasonId); + + @Query(value = "select count(r) from Rank r where r.season.id=:seasonId and not (r.wins = 0 and r.losses = 0)") + Long countRealRankPlayers(@Param("seasonId") Long seasonId); } diff --git a/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java b/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java index a8267a2d5..6d3f86756 100644 --- a/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java +++ b/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java @@ -1,27 +1,32 @@ -package com.gg.server.domain.rank.dto; - -import com.gg.server.domain.user.User; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class ExpRankDto { - private String intraId; - private Integer rank; - private String statusMessage; - private Integer level; - private Integer exp; - - public static ExpRankDto from (User user, Integer rank, String statusMessage){ - ExpRankDto dto = ExpRankDto.builder() - .intraId(user.getIntraId()) - .rank(user.getTotalExp() == 0 ? -1 : rank) - .statusMessage(statusMessage) - .level(ExpLevelCalculator.getLevel(user.getTotalExp())) - .exp(user.getTotalExp()) - .build(); - return dto; - } -} +package com.gg.server.domain.rank.dto; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.global.utils.ExpLevelCalculator; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ExpRankDto { + private String intraId; + private Integer rank; + private String statusMessage; + private Integer level; + private Integer exp; + private String userImageUri; + private String textColor; + + public static ExpRankDto from (User user, Integer rank, String statusMessage){ + ExpRankDto dto = ExpRankDto.builder() + .intraId(user.getIntraId()) + .rank(user.getTotalExp() == 0 ? -1 : rank) + .statusMessage(statusMessage) + .level(ExpLevelCalculator.getLevel(user.getTotalExp())) + .exp(user.getTotalExp()) + .userImageUri(user.getImageUri()) + .textColor(user.getTextColor()) + .build(); + return dto; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/rank/dto/RankDto.java b/src/main/java/com/gg/server/domain/rank/dto/RankDto.java index 78d88f66d..15fb4b42c 100644 --- a/src/main/java/com/gg/server/domain/rank/dto/RankDto.java +++ b/src/main/java/com/gg/server/domain/rank/dto/RankDto.java @@ -4,15 +4,19 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @AllArgsConstructor +@NoArgsConstructor @Builder public class RankDto { private String intraId; private int rank; private int ppp; private String statusMessage; + private String tierImageUri; + private String textColor; public static RankDto from(RankRedis rankRedis, int rank) { @@ -21,6 +25,8 @@ public static RankDto from(RankRedis rankRedis, int rank) { .rank(rank) .ppp(rankRedis.getPpp()) .statusMessage(rankRedis.getStatusMessage()) + .tierImageUri(rankRedis.getTierImageUri()) + .textColor(rankRedis.getTextColor()) .build(); return dto; } diff --git a/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java b/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java index ad7c1860d..3bd4a4dee 100644 --- a/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java +++ b/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java @@ -2,11 +2,13 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.List; @Getter @AllArgsConstructor +@NoArgsConstructor public class RankPageResponseDto { private int myRank; private int currentPage; diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java index bef626f96..eb0590c35 100644 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java +++ b/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java @@ -1,76 +1,86 @@ -package com.gg.server.domain.rank.redis; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import lombok.*; -import org.springframework.data.redis.core.RedisHash; - -import java.io.Serializable; - -@RedisHash("rank") -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RankRedis implements Serializable { - - private Long userId; - private String intraId; - private int ppp; - private int wins; - private int losses; - private String statusMessage; - - public void updateRank(int changePpp, int wins, int losses) { - this.ppp += changePpp; - this.wins = wins; - this.losses = losses; - } - - public void changedRank(int ppp, int wins, int losses) { - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - } - - public void setStatusMessage(String msg) { - this.statusMessage = msg; - } - - public static RankRedis from(UserDto user, Integer ppp) { - RankRedis rankRedis = RankRedis.builder() - .userId(user.getId()) - .intraId(user.getIntraId()) - .ppp(ppp) - .wins(0) - .losses(0) - .statusMessage("") - .build(); - return rankRedis; - } - - public static RankRedis from(Rank rank){ - RankRedis rankRedis = RankRedis.builder() - .userId(rank.getUser().getId()) - .intraId(rank.getUser().getIntraId()) - .ppp(rank.getPpp()) - .wins(rank.getWins()) - .losses(rank.getLosses()) - .statusMessage(rank.getStatusMessage()) - .build(); - return rankRedis; - } - - @Override - public String toString() { - return "RankRedis{" + - "userId=" + userId + - ", intraId='" + intraId + '\'' + - ", ppp=" + ppp + - ", wins=" + wins + - ", losses=" + losses + - ", statusMessage='" + statusMessage + '\'' + - '}'; - } -} +package com.gg.server.domain.rank.redis; + +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.user.dto.UserDto; +import lombok.*; +import org.springframework.data.redis.core.RedisHash; + +import java.io.Serializable; + +@RedisHash("rank") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class RankRedis implements Serializable { + private Long userId; + private String intraId; + private int ppp; + private int wins; + private int losses; + private String statusMessage; + private String tierImageUri; + private String textColor; + + public void updateRank(int changePpp, int wins, int losses) { + this.ppp += changePpp; + this.wins = wins; + this.losses = losses; + } + + public void updateTierImage(String tierImageUri) { + this.tierImageUri = tierImageUri; + } + + public void changedRank(int ppp, int wins, int losses) { + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + } + + public void setStatusMessage(String msg) { + this.statusMessage = msg; + } + + public static RankRedis from(UserDto user, Integer ppp, String tierImageUri) { + RankRedis rankRedis = RankRedis.builder() + .userId(user.getId()) + .intraId(user.getIntraId()) + .ppp(ppp) + .wins(0) + .losses(0) + .statusMessage("") + .tierImageUri(tierImageUri) + .textColor(user.getTextColor()) + .build(); + return rankRedis; + } + + public static RankRedis from(Rank rank) { + RankRedis rankRedis = RankRedis.builder() + .userId(rank.getUser().getId()) + .intraId(rank.getUser().getIntraId()) + .ppp(rank.getPpp()) + .wins(rank.getWins()) + .losses(rank.getLosses()) + .statusMessage(rank.getStatusMessage()) + .tierImageUri(rank.getTier().getImageUri()) + .textColor(rank.getUser().getTextColor()) + .build(); + return rankRedis; + } + + @Override + public String toString() { + return "RankRedis{" + + "userId=" + userId + + ", intraId='" + intraId + '\'' + + ", ppp=" + ppp + + ", wins=" + wins + + ", losses=" + losses + + ", statusMessage='" + statusMessage + '\'' + + ", tierImageUri='" + tierImageUri + '\'' + + ", textColor='" + textColor + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java index 23ea2b2a6..a64fce40f 100644 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java +++ b/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; +import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -186,6 +187,13 @@ public List findRanksByUserIds(String key, List userIds) { return objects.stream().map(RankRedis.class::cast).collect(Collectors.toList()); } + public List findAllRanksOrderByPppDesc(String key) { + List objects = hashOps.values(key); + if(objects == null) + throw new RedisDataNotFoundException(); + return objects.stream().map(RankRedis.class::cast).sorted(Comparator.comparing(RankRedis::getPpp).reversed()).collect(Collectors.toList()); + } + public Long countTotalRank(String zSetKey) { Long result = zSetOps.size(zSetKey); if(result == null) diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java index 18a0c353f..e79bc3c11 100644 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java +++ b/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java @@ -1,20 +1,25 @@ package com.gg.server.domain.rank.redis; import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.service.GameService; import com.gg.server.domain.pchange.service.PChangeService; import com.gg.server.domain.rank.data.Rank; import com.gg.server.domain.rank.data.RankRepository; import com.gg.server.domain.rank.exception.RankNotFoundException; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.service.SeasonFindService; import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; import com.gg.server.global.exception.ErrorCode; import com.gg.server.global.exception.custom.NotExistException; import com.gg.server.global.utils.EloRating; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.List; @Service @@ -22,8 +27,10 @@ @Slf4j public class RankRedisService { private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; private final PChangeService pChangeService; private final RankRepository rankRepository; + private final SeasonFindService seasonFindService; public Integer getUserPpp(Long userId, Long seasonId) { String hashKey = RedisKeyManager.getHashKey(seasonId); @@ -61,8 +68,59 @@ public void updatePPP(TeamUser teamuser, RankRedis myTeam, int enemyScore, Integ Integer changedPpp = EloRating.pppChange(myPPP, enemyPPP, teamuser.getTeam().getWin(), Math.abs(teamuser.getTeam().getScore() - enemyScore) == 2); rank.modifyUserRank(rank.getPpp() + changedPpp, win, losses); + myTeam.updateRank(changedPpp, win, losses); + + } + + @Transactional + public void updateAllTier(Long gameId) { + // 전체 레디스 랭크 티어 새로고침하는 로직 + Season targetSeason = seasonFindService.findSeasonByGameId(gameId); + String key = RedisKeyManager.getHashKey(targetSeason.getId()); + String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); + List rankRedisList = rankRedisRepository.findAllRanksOrderByPppDesc(key); + Long totalRankPlayers = rankRepository.countRealRankPlayers(targetSeason.getId()); + List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); + + int top30percentPpp = rankRedisList.get((int) (totalRankPlayers * 0.3)).getPpp(); + int top10percentPpp = rankRedisList.get((int) (totalRankPlayers * 0.1)).getPpp(); + + for (int i = 0; i < rankRedisList.size(); i++) { + RankRedis rankRedis = rankRedisList.get(i); + if (rankRedis.getWins() == 0 && rankRedis.getLosses() == 0) { + rankRedis.updateTierImage(tierList.get(0).getImageUri()); + } else { + if (i < 3) { + rankRedis.updateTierImage(tierList.get(6).getImageUri()); + updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); + continue; + } + if (rankRedis.getPpp() < 970) { + // 970 미만 + rankRedis.updateTierImage(tierList.get(1).getImageUri()); + } else if (rankRedis.getPpp() < 1010) { + // 970 ~ 1009 + rankRedis.updateTierImage(tierList.get(2).getImageUri()); + } else if (rankRedis.getPpp() < 1050) { + // 1010 ~ 1049 + rankRedis.updateTierImage(tierList.get(3).getImageUri()); + } else { + if ((rankRedis.getPpp() >= top30percentPpp) && (rankRedis.getPpp() < top10percentPpp)) { + // 1050 이상, 30% 이상, 10% 미만 + rankRedis.updateTierImage(tierList.get(4).getImageUri()); + } else if (rankRedis.getPpp() >= top10percentPpp) { + // 1050 이상, 10% 이상 + rankRedis.updateTierImage(tierList.get(5).getImageUri()); + } else { + // 1050 이상, 30% 미만 + rankRedis.updateTierImage(tierList.get(3).getImageUri()); + } + } + updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); + } + } } public void rollbackRank(TeamUser teamUser, int ppp, Long seasonId) { diff --git a/src/main/java/com/gg/server/domain/rank/service/RankFindService.java b/src/main/java/com/gg/server/domain/rank/service/RankFindService.java index a19b90655..f6e7e1f87 100644 --- a/src/main/java/com/gg/server/domain/rank/service/RankFindService.java +++ b/src/main/java/com/gg/server/domain/rank/service/RankFindService.java @@ -13,7 +13,6 @@ public class RankFindService { private final RankRepository rankRepository; - @Transactional(readOnly = true) public Rank findByUserIdAndSeasonId(Long userId, Long seasonId){ return rankRepository.findByUserIdAndSeasonId(userId, seasonId).orElseThrow(() -> new RankNotFoundException()); } diff --git a/src/main/java/com/gg/server/domain/rank/service/RankService.java b/src/main/java/com/gg/server/domain/rank/service/RankService.java index 622b4a58e..1abd82f1a 100644 --- a/src/main/java/com/gg/server/domain/rank/service/RankService.java +++ b/src/main/java/com/gg/server/domain/rank/service/RankService.java @@ -1,121 +1,126 @@ -package com.gg.server.domain.rank.service; - -import com.gg.server.domain.rank.dto.ExpRankDto; -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.PageNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Configuration; -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.stream.Collectors; - -@Service -@Configuration -@RequiredArgsConstructor -public class RankService { - private final UserRepository userRepository; - private final RankRedisRepository redisRepository; - private final SeasonFindService seasonFindService; - - @Transactional(readOnly = true) - public ExpRankPageResponseDto getExpRankPage(PageRequest pageRequest, UserDto curUser) { - - Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); - Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); - if(pageRequest.getPageNumber() + 1 > users.getTotalPages()) - throw new PageNotFoundException("페이지가 존재하지 않습니다.", ErrorCode.PAGE_NOT_FOUND); - - List userIds = users.getContent().stream().map(user -> user.getId()).collect(Collectors.toList()); - Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - - String hashKey = RedisKeyManager.getHashKey(curSeason.getId()); - List ranks = redisRepository.findRanksByUserIds(hashKey, userIds); - - Integer startRank = pageRequest.getPageSize() * pageRequest.getPageNumber() + 1; - List expRankDtos = new ArrayList<>(); - for(int i = 0; i < ranks.size(); i++) { - RankRedis rank = ranks.get(i); - User user = users.getContent().get(i); - expRankDtos.add(ExpRankDto.from(user, startRank + i, rank.getStatusMessage())); - } - - return new ExpRankPageResponseDto(myRank.intValue(), pageRequest.getPageNumber() + 1, users.getTotalPages(), expRankDtos); - } - - @Transactional(readOnly = true) - public RankPageResponseDto getRankPage(PageRequest pageRequest, UserDto curUser, Long seasonId) { - Season season; - if (seasonId == null || seasonId == 0) { - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - } else { - season = seasonFindService.findSeasonById(seasonId); - } - int totalPage = calcTotalPage(season, pageRequest.getPageSize()); - if (totalPage == 0) - return returnEmptyRankPage(); - if (pageRequest.getPageNumber() + 1 > totalPage) - throw new PageNotFoundException("페이지가 존재하지 않습니다.", ErrorCode.PAGE_NOT_FOUND); - - int myRank = findMyRank(curUser, season); - int startRank = pageRequest.getPageNumber() * pageRequest.getPageSize(); - int endRank = startRank + pageRequest.getPageSize() - 1; - List rankList = createRankList(startRank, endRank, season); - return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); - } - - private RankPageResponseDto returnEmptyRankPage() { - return new RankPageResponseDto(-1, 1, 1, new ArrayList<>()); - } - - private int findMyRank(UserDto curUser, Season season) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - try { - Long myRank = redisRepository.getRankInZSet(zSetKey, curUser.getId()); - return myRank.intValue() + 1; - } catch (RedisDataNotFoundException e) { - return -1; - } - } - - private int calcTotalPage(Season season, int pageSize) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - try{ - Long totalUserCount = redisRepository.countTotalRank(zSetKey); - return (int) Math.ceil((double) totalUserCount / pageSize); - } catch (RedisDataNotFoundException e) { - return 0; - } - } - - private List createRankList(int startRank, int endRank, Season season) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - - List userIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, startRank, endRank); - List userRanks = redisRepository.findRanksByUserIds(hashKey, userIds); - List rankList = new ArrayList<>(); - - for (int i = 0; i < userRanks.size(); i++) { - rankList.add(RankDto.from(userRanks.get(i), ++startRank)); - } - return rankList; - } -} +package com.gg.server.domain.rank.service; + +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.dto.ExpRankDto; +import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; +import com.gg.server.domain.rank.dto.RankDto; +import com.gg.server.domain.rank.dto.RankPageResponseDto; +import com.gg.server.domain.rank.exception.RedisDataNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.service.SeasonFindService; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserImageRepository; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.PageNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +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.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Configuration +@RequiredArgsConstructor +public class RankService { + private final UserRepository userRepository; + private final RankRedisRepository redisRepository; + private final SeasonFindService seasonFindService; + + @Transactional(readOnly = true) + public ExpRankPageResponseDto getExpRankPage(PageRequest pageRequest, UserDto curUser) { + + Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); + Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); + if(pageRequest.getPageNumber() + 1 > users.getTotalPages()) + throw new PageNotFoundException("페이지가 존재하지 않습니다.", ErrorCode.PAGE_NOT_FOUND); + + List userIds = users.getContent().stream().map(user -> user.getId()).collect(Collectors.toList()); + Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + + String hashKey = RedisKeyManager.getHashKey(curSeason.getId()); + List ranks = redisRepository.findRanksByUserIds(hashKey, userIds); + + Integer startRank = pageRequest.getPageSize() * pageRequest.getPageNumber() + 1; + List expRankDtos = new ArrayList<>(); + for(int i = 0; i < ranks.size(); i++) { + RankRedis rank = ranks.get(i); + User user = users.getContent().get(i); + expRankDtos.add(ExpRankDto.from(user, startRank + i, rank.getStatusMessage())); + } + + return new ExpRankPageResponseDto(myRank.intValue(), pageRequest.getPageNumber() + 1, users.getTotalPages(), expRankDtos); + } + + @Transactional(readOnly = true) + public RankPageResponseDto getRankPage(PageRequest pageRequest, UserDto curUser, Long seasonId) { + Season season; + if (seasonId == null || seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + int totalPage = calcTotalPage(season, pageRequest.getPageSize()); + if (totalPage == 0) + return returnEmptyRankPage(); + if (pageRequest.getPageNumber() + 1 > totalPage) + throw new PageNotFoundException("페이지가 존재하지 않습니다.", ErrorCode.PAGE_NOT_FOUND); + + int myRank = findMyRank(curUser, season); + int startRank = pageRequest.getPageNumber() * pageRequest.getPageSize(); + int endRank = startRank + pageRequest.getPageSize() - 1; + List rankList = createRankList(startRank, endRank, season); + return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); + } + + private RankPageResponseDto returnEmptyRankPage() { + return new RankPageResponseDto(-1, 1, 1, new ArrayList<>()); + } + + private int findMyRank(UserDto curUser, Season season) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + try { + Long myRank = redisRepository.getRankInZSet(zSetKey, curUser.getId()); + return myRank.intValue() + 1; + } catch (RedisDataNotFoundException e) { + return -1; + } + } + + private int calcTotalPage(Season season, int pageSize) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + try{ + Long totalUserCount = redisRepository.countTotalRank(zSetKey); + return (int) Math.ceil((double) totalUserCount / pageSize); + } catch (RedisDataNotFoundException e) { + return 0; + } + } + + private List createRankList(int startRank, int endRank, Season season) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + + List userIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, startRank, endRank); + List userRanks = redisRepository.findRanksByUserIds(hashKey, userIds); + List rankList = new ArrayList<>(); + + for (RankRedis userRank : userRanks) { + rankList.add(RankDto.from(userRank, ++startRank)); + } + return rankList; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/receipt/data/Receipt.java b/src/main/java/com/gg/server/domain/receipt/data/Receipt.java new file mode 100644 index 000000000..33df458ca --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/data/Receipt.java @@ -0,0 +1,67 @@ +package com.gg.server.domain.receipt.data; + +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.receipt.type.ItemStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class Receipt { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + + @NotNull + @Column(name = "purchaser_intra_id") + private String purchaserIntraId; + + @NotNull + @Column(name = "owner_intra_id") + private String ownerIntraId; + + @NotNull + @Enumerated(EnumType.STRING) + private ItemStatus status; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + public Receipt(Item item, String purchaserIntraId, String ownerIntraId, + ItemStatus status, LocalDateTime purchasedAt) { + this.item = item; + this.purchaserIntraId = purchaserIntraId; + this.ownerIntraId = ownerIntraId; + this.status = status; + this.createdAt = purchasedAt; + } + + @Override + public String toString() { + return "Receipt{" + + "id=" + id + + ", item=" + item + + ", purchaserIntraId='" + purchaserIntraId + '\'' + + ", ownerIntraId='" + ownerIntraId + '\'' + + ", status=" + status + + ", purchasedAt=" + createdAt + + '}'; + } + + public void updateStatus(ItemStatus status) { + this.status = status; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java b/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java new file mode 100644 index 000000000..22463618d --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java @@ -0,0 +1,6 @@ +package com.gg.server.domain.receipt.data; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReceiptRepository extends JpaRepository { +} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java b/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java new file mode 100644 index 000000000..102c8f46f --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java @@ -0,0 +1,8 @@ +package com.gg.server.domain.receipt.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.BusinessException; + +public class ItemStatusException extends BusinessException { + public ItemStatusException() {super("아이템 상태 오류입니다.", ErrorCode.RECEIPT_STATUS_NOT_MATCHED);} +} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java new file mode 100644 index 000000000..711812ea4 --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java @@ -0,0 +1,8 @@ +package com.gg.server.domain.receipt.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; + +public class ReceiptNotFoundException extends NotExistException { + public ReceiptNotFoundException() {super("해당 거래내역이 없습니다.", ErrorCode.RECEIPT_NOT_FOUND);} +} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java new file mode 100644 index 000000000..6441cd4ef --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java @@ -0,0 +1,8 @@ +package com.gg.server.domain.receipt.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.ForbiddenException; + +public class ReceiptNotOwnerException extends ForbiddenException { + public ReceiptNotOwnerException() {super("아이템의 소유자가 아닙니다.", ErrorCode.RECEIPT_NOT_OWNER);} +} diff --git a/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java b/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java new file mode 100644 index 000000000..de03b6551 --- /dev/null +++ b/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java @@ -0,0 +1,16 @@ +package com.gg.server.domain.receipt.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ItemStatus { + BEFORE("사용 전"), + WAITING("사용 대기"), + USING("사용 중"), + USED("사용 완료"), + DELETED("삭제"); + + private final String description; +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java b/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java index 625176255..d20216078 100644 --- a/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java +++ b/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java @@ -1,5 +1,8 @@ package com.gg.server.domain.season.service; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.exception.GameNotExistException; import com.gg.server.domain.season.data.Season; import com.gg.server.domain.season.data.SeasonRepository; import com.gg.server.domain.season.exception.SeasonNotFoundException; @@ -15,6 +18,7 @@ public class SeasonFindService { private final SeasonRepository seasonRepository; + private final GameRepository gameRepository; @Transactional(readOnly = true) public Season findCurrentSeason(LocalDateTime now){ @@ -25,4 +29,10 @@ public Season findCurrentSeason(LocalDateTime now){ public Season findSeasonById(Long seasonId){ return seasonRepository.findById(seasonId).orElseThrow(() -> new SeasonNotFoundException()); } + + @Transactional(readOnly = true) + public Season findSeasonByGameId(Long gameId){ + Game game = gameRepository.findById(gameId).orElseThrow(() -> new GameNotExistException()); + return game.getSeason(); + } } diff --git a/src/main/java/com/gg/server/domain/team/data/TeamUser.java b/src/main/java/com/gg/server/domain/team/data/TeamUser.java index 405d31e18..e59b40ff2 100644 --- a/src/main/java/com/gg/server/domain/team/data/TeamUser.java +++ b/src/main/java/com/gg/server/domain/team/data/TeamUser.java @@ -1,34 +1,33 @@ -package com.gg.server.domain.team.data; - -import com.gg.server.domain.user.User; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.util.List; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Entity -@Getter -@ToString -public class TeamUser { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "team_id") - private Team team; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - public TeamUser(Team team, User user) { - this.team = team; - this.user = user; - } +package com.gg.server.domain.team.data; + +import com.gg.server.domain.user.data.User; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Entity +@Getter +@ToString +public class TeamUser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id") + private Team team; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + public TeamUser(Team team, User user) { + this.team = team; + this.user = user; + } } \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java b/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java index a34e99c4f..e5ef8f7a4 100644 --- a/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java +++ b/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java @@ -1,21 +1,20 @@ -package com.gg.server.domain.team.data; - -import com.gg.server.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; - -public interface TeamUserRepository extends JpaRepository { - @Query(value = "select team_user.id, team_user.team_id, team_user.user_id from team, team_user " + - "where team.game_id =:gid and team.id = team_user.team_id", nativeQuery = true) - List findAllByGameId(Long gid); - - @Query(value = "select count(*) from game, team, team_user " + - "where game.start_time >= :today and team_user.team_id = team.id and team_user.user_id = :userId " + - "and team.game_id = game.id and game.status = 'END'", nativeQuery = true) - Integer findByDateAndUser(LocalDateTime today, Long userId); - -} +package com.gg.server.domain.team.data; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDateTime; +import java.util.List; + +public interface TeamUserRepository extends JpaRepository { + @Query(value = "select team_user.id, team_user.team_id, team_user.user_id from team, team_user " + + "where team.game_id =:gid and team.id = team_user.team_id", nativeQuery = true) + List findAllByGameId(@Param("gid")Long gid); + + @Query(value = "select count(*) from game, team, team_user " + + "where game.start_time >= :today and team_user.team_id = team.id and team_user.user_id = :userId " + + "and team.game_id = game.id and game.status = 'END'", nativeQuery = true) + Integer findByDateAndUser(@Param("today")LocalDateTime today, @Param("userId") Long userId); + +} diff --git a/src/main/java/com/gg/server/domain/tier/data/Tier.java b/src/main/java/com/gg/server/domain/tier/data/Tier.java new file mode 100644 index 000000000..f367e7071 --- /dev/null +++ b/src/main/java/com/gg/server/domain/tier/data/Tier.java @@ -0,0 +1,28 @@ +package com.gg.server.domain.tier.data; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class Tier implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "image_uri") + private String imageUri; + + @Column(name = "name") + private String name; + + public Tier(String imageUri) { + this.imageUri = imageUri; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/tier/data/TierRepository.java b/src/main/java/com/gg/server/domain/tier/data/TierRepository.java new file mode 100644 index 000000000..0aec19207 --- /dev/null +++ b/src/main/java/com/gg/server/domain/tier/data/TierRepository.java @@ -0,0 +1,14 @@ +package com.gg.server.domain.tier.data; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface TierRepository extends JpaRepository { + + @Query("SELECT t FROM Tier t WHERE t.id = 1L") + Optional findStartTier(); + + Optional findByName(String name); +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java b/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java new file mode 100644 index 000000000..fe13c392b --- /dev/null +++ b/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java @@ -0,0 +1,11 @@ +package com.gg.server.domain.tier.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.NotExistException; + +public class TierNotFoundException extends NotExistException { + public TierNotFoundException() { + super("해당 티어가 존재하지 않습니다.", ErrorCode.TIER_NOT_FOUND); + } + +} diff --git a/src/main/java/com/gg/server/domain/tier/service/TierService.java b/src/main/java/com/gg/server/domain/tier/service/TierService.java new file mode 100644 index 000000000..8821003d7 --- /dev/null +++ b/src/main/java/com/gg/server/domain/tier/service/TierService.java @@ -0,0 +1,63 @@ +package com.gg.server.domain.tier.service; + +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class TierService { + private final TierRepository tierRepository; + private final RankRepository rankRepository; + + @Transactional + public void updateAllTier(Season season) { + List rankList = rankRepository.findAllBySeasonIdOrderByPppDesc(season.getId()); + Long totalRankPlayers = rankRepository.countRealRankPlayers(season.getId()); + List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); + + int top30percentPpp = rankList.get((int) (totalRankPlayers * 0.3)).getPpp(); + int top10percentPpp = rankList.get((int) (totalRankPlayers * 0.1)).getPpp(); + + for (int i = 0; i < rankList.size(); i++) { + Rank rank = rankList.get(i); + if (rank.getWins() == 0 && rank.getLosses() == 0) { + rank.updateTier(tierList.get(0)); + } else { + if (i < 3) { + rank.updateTier(tierList.get(6)); + continue; + } + if (rank.getPpp() < 970) { + // 970 미만 + rank.updateTier(tierList.get(1)); + } else if (rank.getPpp() < 1010) { + // 970 - 1009 + rank.updateTier(tierList.get(2)); + } else if (rank.getPpp() < 1050) { + // 1010 - 1049 + rank.updateTier(tierList.get(3)); + } else if (rank.getPpp() >= 1050) { + if (rank.getPpp() >= top30percentPpp && rank.getPpp() < top10percentPpp) { + // 1050 이상, 30% 이상, 10% 미만 + rank.updateTier(tierList.get(4)); + } else if (rank.getPpp() >= top10percentPpp) { + // 1050 이상, 10% 이상 + rank.updateTier(tierList.get(5)); + } else { + // 1050 이상, 30% 미만 + rank.updateTier(tierList.get(3)); + } + } + } + } + } +} diff --git a/src/main/java/com/gg/server/domain/user/controller/UserController.java b/src/main/java/com/gg/server/domain/user/controller/UserController.java index 1aade54bd..b22eb73f7 100644 --- a/src/main/java/com/gg/server/domain/user/controller/UserController.java +++ b/src/main/java/com/gg/server/domain/user/controller/UserController.java @@ -3,31 +3,28 @@ import com.gg.server.domain.game.type.Mode; import com.gg.server.domain.user.dto.*; import com.gg.server.domain.user.exception.KakaoOauth2AlreadyExistException; -import com.gg.server.domain.user.exception.KakaoOauth2NotFoundException; -import com.gg.server.domain.user.service.UserAuthenticationService; -import com.gg.server.domain.user.service.UserService; +import com.gg.server.domain.user.service.*; import com.gg.server.domain.user.type.OauthType; import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.security.config.properties.AppProperties; +import com.gg.server.global.dto.PageRequestDto; import com.gg.server.global.security.cookie.CookieUtil; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; import com.gg.server.global.security.jwt.utils.TokenHeaders; -import com.gg.server.global.utils.ApplicationYmlRead; -import com.gg.server.global.utils.HeaderUtil; import com.gg.server.global.utils.argumentresolver.Login; import io.swagger.v3.oas.annotations.Parameter; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.io.IOException; import java.util.List; @RestController @@ -37,6 +34,7 @@ public class UserController { private final UserService userService; private final UserAuthenticationService userAuthenticationService; private final CookieUtil cookieUtil; + private final UserCoinService userCoinService; @PostMapping("/accesstoken") public ResponseEntity generateAccessToken(@RequestParam String refreshToken) { @@ -46,8 +44,7 @@ public ResponseEntity generateAccessToken(@RequestParam Stri @GetMapping UserNormalDetailResponseDto getUserNormalDetail(@Parameter(hidden = true) @Login UserDto user){ - Boolean isAdmin = user.getRoleType() == RoleType.ADMIN; - return new UserNormalDetailResponseDto(user.getIntraId(), user.getImageUri(), isAdmin); + return userService.getUserNormalDetail(user); } @GetMapping("/live") @@ -80,11 +77,11 @@ public UserHistoryResponseDto getUserHistory(@PathVariable String intraId, @Requ public ResponseEntity doModifyUser (@Valid @RequestBody UserModifyRequestDto userModifyRequestDto, @PathVariable String intraId, @Parameter(hidden = true) @Login UserDto loginUser) { if (!loginUser.getIntraId().equals(intraId)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } userService.updateUser(userModifyRequestDto.getRacketType(), userModifyRequestDto.getStatusMessage(), userModifyRequestDto.getSnsNotiOpt(), intraId); - return new ResponseEntity(HttpStatus.NO_CONTENT); + return ResponseEntity.noContent().build(); } @PostMapping("/logout") @@ -108,7 +105,7 @@ public UserOauthDto getUserOauth2Information(@Parameter(hidden = true) @Login Us return new UserOauthDto(OauthType.of(user.getRoleType(), user.getKakaoId()).getCode()); } - @GetMapping("/images") + @GetMapping("/top3") public UserImageResponseDto getUserImage(@RequestParam(required = false) Long seasonId, Mode mode) { if (mode == Mode.RANK) return userService.getRankedUserImagesByPPP(seasonId); @@ -117,4 +114,47 @@ public UserImageResponseDto getUserImage(@RequestParam(required = false) Long se return userService.getRankedUserImagesByExp(pageRequest); } } + + @PatchMapping("/text-color") + public ResponseEntity updateTextColor(@RequestBody @Valid UserTextColorDto textColorDto, @Parameter(hidden = true) @Login UserDto user) { + userService.updateTextColor(user.getId() ,textColorDto); + return ResponseEntity.noContent().build(); + } + + @PostMapping("/attendance") + public UserAttendanceResponseDto attendUser(@Parameter(hidden = true) @Login UserDto user) { + return userService.attendUser(user.getId()); + } + + @PatchMapping("/edge") + public String updateEdge(@RequestBody @Valid UserEdgeDto userEdgeDto, @Parameter(hidden = true) @Login UserDto user) { + String edge = userService.updateEdge(user, userEdgeDto); + return "{\"edge\": " + "\"" + edge + "\"" +"}"; + } + + @GetMapping("/coin") + public UserCoinResponseDto getUserCoin(@Parameter(hidden = true) @Login UserDto user) { + return userCoinService.getUserCoin(user.getIntraId()); + } + + @PatchMapping("/background") + public String updateBackground(@RequestBody @Valid UserBackgroundDto userBackgroundDto, @Parameter(hidden = true) @Login UserDto user) { + String background = userService.updateBackground(user, userBackgroundDto); + return "{\"background\": " + "\"" + background + "\"" +"}"; + } + + @GetMapping("/coinhistory") + public UserCoinHistoryListResponseDto getUserCoinHistory(@ModelAttribute @Valid PageRequestDto coReq, @Parameter(hidden = true) @Login UserDto user) { + Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); + + return userCoinService.getUserCoinHistory(pageable ,user.getIntraId()); + } + + @PostMapping(path = "/profile-image", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity updateUserProfileImage(@RequestPart(required = false) MultipartFile profileImage, + @RequestPart @Valid UserProfileImageRequestDto userProfileImageRequestDto, + @Parameter(hidden = true) @Login UserDto user) throws IOException { + userService.updateUserProfileImage(user, userProfileImageRequestDto, profileImage); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/gg/server/domain/user/User.java b/src/main/java/com/gg/server/domain/user/data/User.java similarity index 60% rename from src/main/java/com/gg/server/domain/user/User.java rename to src/main/java/com/gg/server/domain/user/data/User.java index 2ff650d27..1a9b58b21 100644 --- a/src/main/java/com/gg/server/domain/user/User.java +++ b/src/main/java/com/gg/server/domain/user/data/User.java @@ -1,90 +1,132 @@ -package com.gg.server.domain.user; - -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class User extends BaseTimeEntity implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @Column(name = "intra_id", length = 30) - private String intraId; - - @Column(name = "e_mail", length = 60) - private String eMail; - - @Column(name = "image_uri") - private String imageUri; - - @Enumerated(EnumType.STRING) - @Column(name = "racket_type", length = 10) - private RacketType racketType; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "role_type", length = 10) - private RoleType roleType; - - @Column(name = "total_exp") - private Integer totalExp; - - @Column(name = "sns_noti_opt", length = 10) - @Enumerated(EnumType.STRING) - private SnsType snsNotiOpt; - - @Column(name = "kakao_id") - private Long kakaoId; - - @Builder - public User(String intraId, String eMail, String imageUri, RacketType racketType, - RoleType roleType, Integer totalExp, SnsType snsNotiOpt, Long kakaoId) { - this.intraId = intraId; - this.eMail = eMail; - this.imageUri = imageUri; - this.racketType = racketType; - this.roleType = roleType; - this.totalExp = totalExp; - this.snsNotiOpt = snsNotiOpt; - this.kakaoId = kakaoId; - } - - public void modifyUserDetail(UserUpdateAdminRequestDto updateReq) { - this.eMail = updateReq.getEmail(); - this.racketType = updateReq.getRacketType(); - this.roleType = RoleType.of(updateReq.getRoleType()); - } - - public void imageUpdate(String imageUri) { - this.imageUri = imageUri; - } - - public void updateTypes(RacketType racketType, SnsType snsType) { - this.racketType = racketType; - this.snsNotiOpt = snsType; - } - - public void addExp(int plus) { - this.totalExp += plus; - } - - public void updateExp(int beforeExp) { - this.totalExp = beforeExp; - } - - public void updateKakaoId(Long kakaoId) { - this.kakaoId = kakaoId; - } -} +package com.gg.server.domain.user.data; + +import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; +import com.gg.server.domain.item.exception.InsufficientGgcoinException; +import com.gg.server.domain.user.type.*; +import com.gg.server.global.utils.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class User extends BaseTimeEntity implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "intra_id", length = 30) + private String intraId; + + @Column(name = "e_mail", length = 60) + private String eMail; + + @Column(name = "image_uri") + private String imageUri; + + @Enumerated(EnumType.STRING) + @Column(name = "racket_type", length = 10) + private RacketType racketType; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "role_type", length = 10) + private RoleType roleType; + + @Column(name = "total_exp") + private Integer totalExp; + + @Column(name = "sns_noti_opt", length = 10) + @Enumerated(EnumType.STRING) + private SnsType snsNotiOpt; + + @Column(name = "kakao_id") + private Long kakaoId; + + @Column(name = "gg_coin") + private Integer ggCoin; + + @Column(name = "background") + @Enumerated(EnumType.STRING) + private BackgroundType background; + + @Column(name = "text_color", length = 10) + private String textColor; + + @Column(name = "edge") + @Enumerated(EnumType.STRING) + private EdgeType edge; + + @Builder + public User(String intraId, String eMail, String imageUri, RacketType racketType, + RoleType roleType, Integer totalExp, SnsType snsNotiOpt, Long kakaoId) { + this.intraId = intraId; + this.eMail = eMail; + this.imageUri = imageUri; + this.racketType = racketType; + this.roleType = roleType; + this.totalExp = totalExp; + this.snsNotiOpt = snsNotiOpt; + this.kakaoId = kakaoId; + this.background = BackgroundType.BASIC; + this.textColor = "#000000"; + this.edge = EdgeType.BASIC; + this.ggCoin = 0; + } + + public void modifyUserDetail(UserUpdateAdminRequestDto updateReq) { + this.eMail = updateReq.getEmail(); + this.racketType = updateReq.getRacketType(); + this.roleType = RoleType.of(updateReq.getRoleType()); + this.ggCoin = updateReq.getCoin(); + } + + public void updateImageUri(String imageUri) { + this.imageUri = imageUri; + } + + public void updateTypes(RacketType racketType, SnsType snsType) { + this.racketType = racketType; + this.snsNotiOpt = snsType; + } + + public void addExp(int plus) { + this.totalExp += plus; + } + + public void updateExp(int beforeExp) { + this.totalExp = beforeExp; + } + + public void updateKakaoId(Long kakaoId) { + this.kakaoId = kakaoId; + } + + public void updateTextColor(String textColor) { + this.textColor = textColor; + } + + public void updateEdge(EdgeType edge) { + this.edge = edge; + } + + public int addGgCoin(int plus) { + this.ggCoin += plus; + return this.ggCoin; + } + + public void payGgCoin(int amount) { + if (this.ggCoin < amount) { + throw new InsufficientGgcoinException(); // 사용자의 ggCoin이 필요한 금액보다 적을 경우 예외를 발생 + } + this.ggCoin = this.ggCoin - amount; + } + + public void updateBackground(BackgroundType background) { + this.background = background; + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/data/UserImage.java b/src/main/java/com/gg/server/domain/user/data/UserImage.java new file mode 100644 index 000000000..8cd0bf920 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/data/UserImage.java @@ -0,0 +1,56 @@ +package com.gg.server.domain.user.data; + +import com.sun.istack.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +public class UserImage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "image_uri") + private String imageUri; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @NotNull + @Column(name = "is_current") + private Boolean isCurrent; + + public UserImage(User user, String imageUri, LocalDateTime createdAt, LocalDateTime deletedAt, Boolean isCurrent) { + this.user = user; + this.imageUri = imageUri; + this.createdAt = createdAt; + this.deletedAt = deletedAt; + this.isCurrent = isCurrent; + } + + public void updateIsCurrent() { + this.isCurrent = !this.isCurrent; + } + + public void updateDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + updateIsCurrent(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java b/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java new file mode 100644 index 000000000..660805a63 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java @@ -0,0 +1,9 @@ +package com.gg.server.domain.user.data; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserImageRepository extends JpaRepository { + Optional findTopByUserAndIsCurrentIsTrueOrderByIdDesc(User user); +} diff --git a/src/main/java/com/gg/server/domain/user/UserRepository.java b/src/main/java/com/gg/server/domain/user/data/UserRepository.java similarity index 90% rename from src/main/java/com/gg/server/domain/user/UserRepository.java rename to src/main/java/com/gg/server/domain/user/data/UserRepository.java index be0fc843e..ffc3f96c1 100644 --- a/src/main/java/com/gg/server/domain/user/UserRepository.java +++ b/src/main/java/com/gg/server/domain/user/data/UserRepository.java @@ -1,31 +1,36 @@ -package com.gg.server.domain.user; - -import java.util.List; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.Optional; - -public interface UserRepository extends JpaRepository { - Optional findByIntraId(String intraId); - User getUserByIntraId(String IntraId); - Page findByIntraIdContains(Pageable pageable, String intraId); - - Page findAllByTotalExpGreaterThan(Pageable pageable, Integer exp); - Optional findByKakaoId(Long kakaoId); - @Query(nativeQuery = true, value = "select ranking from " + - "(select intra_id, row_number() over (order by total_exp desc, intra_id asc) as ranking from user) ranked where intra_id=:intraId") - Long findExpRankingByIntraId(@Param("intraId") String intraId); - - Page findAll(Pageable pageable); - - @Query("select tu.user from User u, TeamUser tu, Team t, Game g" + - " where g.id=:gameId and t.game.id =g.id and tu.team.id = t.id " - + "and u.id = tu.user.id and u.id !=:userId") - List findEnemyByGameAndUser(@Param("gameId") Long gameId, @Param("userId") Long userId); - - List findUsersByIdIn(List userIds); -} +package com.gg.server.domain.user.data; + +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByIntraId(String intraId); + + Optional getUserByIntraId(String IntraId); + + Page findByIntraIdContains(Pageable pageable, String intraId); + + Page findAllByTotalExpGreaterThan(Pageable pageable, Integer exp); + + Optional findByKakaoId(Long kakaoId); + + @Query(nativeQuery = true, value = "select ranking from " + + "(select intra_id, row_number() over (order by total_exp desc, intra_id asc) as ranking from user) ranked where intra_id=:intraId") + Long findExpRankingByIntraId(@Param("intraId") String intraId); + + Page findAll(Pageable pageable); + + @Query("select tu.user from User u, TeamUser tu, Team t, Game g" + + " where g.id=:gameId and t.game.id =g.id and tu.team.id = t.id " + + "and u.id = tu.user.id and u.id !=:userId") + List findEnemyByGameAndUser(@Param("gameId") Long gameId, @Param("userId") Long userId); + + List findUsersByIdIn(List userIds); +} diff --git a/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java new file mode 100644 index 000000000..74066fb9f --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java @@ -0,0 +1,22 @@ +package com.gg.server.domain.user.dto; + +import com.gg.server.domain.coin.data.CoinHistory; +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +public class CoinHistoryResponseDto { + private String history; + private int amount; + private LocalDateTime createdAt; + + public CoinHistoryResponseDto(CoinHistory coinHistory) { + this.history = coinHistory.getHistory(); + this.amount = coinHistory.getAmount(); + this.createdAt = coinHistory.getCreatedAt(); + } +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java new file mode 100644 index 000000000..c9f7b2ea6 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java @@ -0,0 +1,14 @@ +package com.gg.server.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserAttendanceResponseDto { + private int beforeCoin; + private int afterCoin; + private int coinIncrement; +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java b/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java new file mode 100644 index 000000000..38065e6d8 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java @@ -0,0 +1,15 @@ +package com.gg.server.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserBackgroundDto { + @NotNull + private Long receiptId; +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java new file mode 100644 index 000000000..0c80b4a71 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java @@ -0,0 +1,17 @@ +package com.gg.server.domain.user.dto; + +import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; +import com.gg.server.domain.coin.data.CoinHistory; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class UserCoinHistoryListResponseDto { + private List useCoinList; + private int totalPage; +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java new file mode 100644 index 000000000..fa5e130ad --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java @@ -0,0 +1,14 @@ +package com.gg.server.domain.user.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class UserCoinResponseDto { + private int coin; + + public UserCoinResponseDto(int userCoin) { + this.coin = userCoin; + } +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java index 842f7497d..1fb6b72ec 100644 --- a/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java +++ b/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java @@ -1,37 +1,50 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.*; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class UserDetailResponseDto { - private String intraId; - private String userImageUri; - private String racketType; - private String statusMessage; - private Integer level; - private Integer currentExp; - private Integer maxExp; - private Double expRate; - private SnsType snsNotiOpt; - - public UserDetailResponseDto(User user, String statusMessage) { - this.intraId = user.getIntraId(); - this.userImageUri = user.getImageUri(); - this.racketType = user.getRacketType().getCode(); - this.statusMessage = statusMessage; - this.snsNotiOpt = user.getSnsNotiOpt(); - calculateExpAndLevel(user); - } - - private void calculateExpAndLevel(User user) { - this.currentExp = ExpLevelCalculator.getCurrentLevelMyExp(user.getTotalExp()); - this.maxExp = ExpLevelCalculator.getLevelMaxExp(ExpLevelCalculator.getLevel(user.getTotalExp())); - this.level = ExpLevelCalculator.getLevel(user.getTotalExp()); - this.expRate = (double)(currentExp * 10000 / maxExp) / 100; - } - -} +package com.gg.server.domain.user.dto; + +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.BackgroundType; +import com.gg.server.domain.user.type.EdgeType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.utils.ExpLevelCalculator; +import lombok.*; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserDetailResponseDto { + private String intraId; + private String userImageUri; + private String racketType; + private String statusMessage; + private Integer level; + private Integer currentExp; + private Integer maxExp; + private Double expRate; + private SnsType snsNotiOpt; + private BackgroundType background; + private String textColor; + private EdgeType edge; + private String tierName; + private String tierImageUri; + + public UserDetailResponseDto(User user, String statusMessage, Tier tier) { + this.intraId = user.getIntraId(); + this.racketType = user.getRacketType().getCode(); + this.userImageUri = user.getImageUri(); + this.statusMessage = statusMessage; + this.snsNotiOpt = user.getSnsNotiOpt(); + this.background= user.getBackground(); + this.textColor = user.getTextColor(); + this.edge = user.getEdge(); + this.tierName = tier.getName(); + this.tierImageUri = tier.getImageUri(); + calculateExpAndLevel(user); + } + + private void calculateExpAndLevel(User user) { + this.currentExp = ExpLevelCalculator.getCurrentLevelMyExp(user.getTotalExp()); + this.maxExp = ExpLevelCalculator.getLevelMaxExp(ExpLevelCalculator.getLevel(user.getTotalExp())); + this.level = ExpLevelCalculator.getLevel(user.getTotalExp()); + this.expRate = (double)(currentExp * 10000 / maxExp) / 100; + } + +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserDto.java b/src/main/java/com/gg/server/domain/user/dto/UserDto.java index 13382c45d..393aeaa6a 100644 --- a/src/main/java/com/gg/server/domain/user/dto/UserDto.java +++ b/src/main/java/com/gg/server/domain/user/dto/UserDto.java @@ -1,57 +1,57 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class UserDto { - private Long id; - private String intraId; - private String eMail; - private String imageUri; - private RacketType racketType; - private RoleType roleType; - private Integer totalExp; - private SnsType snsNotiOpt; - private Long kakaoId; - - static public UserDto from (User user) { - UserDto userDto; - if (user == null) { - userDto = null; - } else { - userDto = UserDto.builder() - .id(user.getId()) - .intraId(user.getIntraId()) - .eMail(user.getEMail()) - .imageUri(user.getImageUri()) - .racketType(user.getRacketType()) - .roleType(user.getRoleType()) - .totalExp(user.getTotalExp()) - .snsNotiOpt(user.getSnsNotiOpt()) - .kakaoId(user.getKakaoId()) - .build(); - } - return userDto; - } - - @Override - public String toString() { - return "UserDto{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", eMail='" + eMail + '\'' + - ", imageUri='" + imageUri + '\'' + - ", racketType=" + racketType + - ", roleType=" + roleType + - ", totalExp=" + totalExp + - ", snsNotiOpt=" + snsNotiOpt + - ", kakaoId=" + kakaoId + - '}'; - } -} +package com.gg.server.domain.user.dto; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserDto { + private Long id; + private String intraId; + private String eMail; + private RacketType racketType; + private RoleType roleType; + private Integer totalExp; + private SnsType snsNotiOpt; + private Long kakaoId; + private String textColor; + private Integer ggCoin; + + static public UserDto from (User user) { + UserDto userDto; + if (user == null) { + userDto = null; + } else { + userDto = UserDto.builder() + .id(user.getId()) + .intraId(user.getIntraId()) + .eMail(user.getEMail()) + .racketType(user.getRacketType()) + .roleType(user.getRoleType()) + .totalExp(user.getTotalExp()) + .snsNotiOpt(user.getSnsNotiOpt()) + .kakaoId(user.getKakaoId()) + .ggCoin(user.getGgCoin()) + .build(); + } + return userDto; + } + + @Override + public String toString() { + return "UserDto{" + + "id=" + id + + ", intraId='" + intraId + '\'' + + ", eMail='" + eMail + '\'' + + ", racketType=" + racketType + + ", roleType=" + roleType + + ", totalExp=" + totalExp + + ", snsNotiOpt=" + snsNotiOpt + + ", kakaoId=" + kakaoId + + '}'; + } +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java b/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java new file mode 100644 index 000000000..e333aed27 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java @@ -0,0 +1,15 @@ +package com.gg.server.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserEdgeDto { + @NotNull + private Long receiptId; +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java b/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java index 33c02c46d..b4e0f4fd1 100644 --- a/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java +++ b/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java @@ -1,14 +1,26 @@ package com.gg.server.domain.user.dto; +import com.gg.server.domain.user.type.EdgeType; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.time.LocalDateTime; + @Getter @NoArgsConstructor -@AllArgsConstructor public class UserImageDto { String intraId; - String userImageUri; + String imageUri; + EdgeType edge; + String tierImage; + public UserImageDto(String intraId, String imageUri, EdgeType edge, String tierImage) { + this.intraId = intraId; + this.imageUri = imageUri; + this.edge = edge; + this.tierImage = tierImage; + } } diff --git a/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java index 709aad937..259c3db39 100644 --- a/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java +++ b/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java @@ -1,12 +1,20 @@ package com.gg.server.domain.user.dto; +import com.gg.server.domain.user.type.EdgeType; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; -@AllArgsConstructor @Getter +@AllArgsConstructor +@NoArgsConstructor public class UserNormalDetailResponseDto { private String intraId; private String userImageUri; private Boolean isAdmin; + private Boolean isAttended; + private EdgeType edgeType; + private String tierName; + private String tierImageUri; + private Integer level; } diff --git a/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java b/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java new file mode 100644 index 000000000..7666b2afe --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java @@ -0,0 +1,15 @@ +package com.gg.server.domain.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserProfileImageRequestDto { + @NotNull + private Long receiptId; +} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java b/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java new file mode 100644 index 000000000..3629792c2 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java @@ -0,0 +1,16 @@ +package com.gg.server.domain.user.dto; + +import com.sun.istack.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserTextColorDto { + @NotNull + private Long receiptId; + @NotNull + private String textColor; +} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java b/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java new file mode 100644 index 000000000..3e3ce132e --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.user.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.DuplicationException; + +public class UserAlreadyAttendanceException extends DuplicationException { + public UserAlreadyAttendanceException() { + super("이미 출석한 유저입니다.", ErrorCode.USER_ALREADY_ATTENDANCE); + } +} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java b/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java new file mode 100644 index 000000000..b7e8b8598 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.user.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.FileException; + +public class UserImageNullException extends FileException { + public UserImageNullException() { + super("이미지 파일이 없습니다.", ErrorCode.USER_IMAGE_NOT_FOUND); + } +} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java b/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java new file mode 100644 index 000000000..c1c40abea --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java @@ -0,0 +1,10 @@ +package com.gg.server.domain.user.exception; + +import com.gg.server.global.exception.ErrorCode; +import com.gg.server.global.exception.custom.CustomRuntimeException; + +public class UserTextColorException extends CustomRuntimeException { + public UserTextColorException() { + super("user text color code is not valid", ErrorCode.USER_TEXT_COLOR_WRONG_TYPE); + } +} diff --git a/src/main/java/com/gg/server/domain/user/service/UserCoinService.java b/src/main/java/com/gg/server/domain/user/service/UserCoinService.java new file mode 100644 index 000000000..58fcf7407 --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/service/UserCoinService.java @@ -0,0 +1,45 @@ +package com.gg.server.domain.user.service; + +import com.gg.server.admin.feedback.dto.FeedbackAdminResponseDto; +import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; +import com.gg.server.domain.coin.data.CoinHistory; +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import com.gg.server.domain.feedback.data.Feedback; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.CoinHistoryResponseDto; +import com.gg.server.domain.user.dto.UserCoinHistoryListResponseDto; +import com.gg.server.domain.user.dto.UserCoinResponseDto; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +public class UserCoinService { + private final UserRepository userRepository; + private final CoinHistoryRepository coinHistoryRepository; + + @Transactional(readOnly = true) + public UserCoinResponseDto getUserCoin(String intraId) { + int userCoin = userRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()).getGgCoin(); + + return new UserCoinResponseDto(userCoin); + } + + @Transactional(readOnly = true) + public UserCoinHistoryListResponseDto getUserCoinHistory(Pageable pageable, String intraId) { + User user = userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + + Page coinHistories = coinHistoryRepository.findAllByUserOrderByIdDesc(user, pageable); + Page coinHistoryResponseDtos = coinHistories.map(CoinHistoryResponseDto::new); + UserCoinHistoryListResponseDto responseDto = new UserCoinHistoryListResponseDto(coinHistoryResponseDtos.getContent(), + coinHistoryResponseDtos.getTotalPages()); + + return responseDto; + } +} diff --git a/src/main/java/com/gg/server/domain/user/service/UserFindService.java b/src/main/java/com/gg/server/domain/user/service/UserFindService.java index 16479021a..59515de0f 100644 --- a/src/main/java/com/gg/server/domain/user/service/UserFindService.java +++ b/src/main/java/com/gg/server/domain/user/service/UserFindService.java @@ -1,47 +1,46 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -public class UserFindService { - private final UserRepository userRepository; - private final SeasonFindService seasonFindService; - private final RankRedisRepository rankRedisRepository; - - @Transactional(readOnly = true) - public User findUserById(Long userId) { - return userRepository.findById(userId).orElseThrow(() -> new UserNotFoundException()); - } - - @Transactional(readOnly = true) - public User findByIntraId(String intraId){ - return userRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()); - } - - @Transactional(readOnly = true) - public String getUserStatusMessage(User targetUser) { - Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); - try{ - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, targetUser.getId()); - return userRank.getStatusMessage(); - }catch (RedisDataNotFoundException e){ - return ""; - } - } -} +package com.gg.server.domain.user.service; + +import com.gg.server.domain.rank.exception.RedisDataNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.service.SeasonFindService; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Service +@RequiredArgsConstructor +public class UserFindService { + private final UserRepository userRepository; + private final SeasonFindService seasonFindService; + private final RankRedisRepository rankRedisRepository; + + @Transactional(readOnly = true) + public User findUserById(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + } + + @Transactional(readOnly = true) + public User findByIntraId(String intraId){ + return userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + } + + @Transactional(readOnly = true) + public String getUserStatusMessage(User targetUser) { + Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); + try{ + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, targetUser.getId()); + return userRank.getStatusMessage(); + }catch (RedisDataNotFoundException e){ + return ""; + } + } +} diff --git a/src/main/java/com/gg/server/domain/user/service/UserService.java b/src/main/java/com/gg/server/domain/user/service/UserService.java index 29a985ed3..cf2fad59b 100644 --- a/src/main/java/com/gg/server/domain/user/service/UserService.java +++ b/src/main/java/com/gg/server/domain/user/service/UserService.java @@ -1,241 +1,356 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.rank.service.RankFindService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.*; -import com.gg.server.domain.user.exception.TokenNotValidException; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.config.properties.AppProperties; -import com.gg.server.global.security.jwt.repository.JwtRedisRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import jdk.jshell.Snippet; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class UserService { - - private final UserFindService userFindService; - private final UserRepository userRepository; - private final NotiRepository notiRepository; - private final GameRepository gameRepository; - private final RankRedisRepository rankRedisRepository; - private final SeasonFindService seasonFindService; - private final PChangeRepository pChangeRepository; - private final RankFindService rankFindService; - private final RedisMatchUserRepository redisMatchUserRepository; - - - - /** - * @param intraId - * @return intraId가 포함된 유저들의 intraId를 페이징 관계없이 최대 5개까지 검색하여 List로 return - */ - @Transactional(readOnly = true) - public List findByPartOfIntraId(String intraId) { - Pageable pageable = PageRequest.of(0, 5, Sort.by("intraId").ascending()); - Page pageUsers = userRepository.findByIntraIdContains(pageable, intraId); - return pageUsers.getContent().stream().map(user -> user.getIntraId()) - .collect(Collectors.toList()); - } - - /** - * - * @param user - * - event: - * - null → 로그인 유저가 잡힌 매칭이 하나도 없을 때 - * - match → 매칭은 되었으나 게임시작 전일 때 or 매칭중인 경우 - * - game → 유저가 게임이 잡혔고 현재 게임중인 경우 - * - * - currentMatchMode - * - normal - * - rank - * - null -> 매칭이 안잡혔을 때 or 게임 전 - */ - @Transactional() - public UserLiveResponseDto getUserLiveDetail(UserDto user) { - int notiCnt = notiRepository.countNotCheckedNotiByUser(user.getId()); - Optional optionalGame = gameRepository.getLatestGameByUser(user.getId()); - int userMatchCnt = redisMatchUserRepository.countMatchTime(user.getId()); - if (optionalGame.isPresent()) { - Game game = optionalGame.get(); - if (game.getStatus() == StatusType.LIVE || game.getStatus() == StatusType.WAIT) - return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); - else if (game.getStatus() == StatusType.END) { - PChange userPChange = pChangeRepository.findPChangeByUserIdAndGameId(user.getId(), game.getId()).orElseThrow(() -> new PChangeNotExistException()); - if (userPChange.getIsChecked() == false) { - userPChange.checkPChange(); - return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); - } - } - - if (game.getStatus() == StatusType.BEFORE) - return new UserLiveResponseDto(notiCnt, "match", null, null); - } - if (userMatchCnt > 0){ - return new UserLiveResponseDto(notiCnt, "match", null, null); - } - return new UserLiveResponseDto(notiCnt, null, null, null); - } - - @Transactional(readOnly = true) - public UserDetailResponseDto getUserDetail(String targetUserIntraId) { - User targetUser = userFindService.findByIntraId(targetUserIntraId); - String statusMessage = userFindService.getUserStatusMessage(targetUser); - return new UserDetailResponseDto(targetUser, statusMessage); - } - - @Transactional - public void updateUser(RacketType racketType, String statusMessage, SnsType snsNotiOpt, String intraId) { - User user = userFindService.findByIntraId(intraId); - Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - updateRedisRankStatusMessage(statusMessage, user, currentSeason); - updateRankTableStatusMessage(user.getId(), statusMessage, currentSeason.getId()); - user.updateTypes(racketType, snsNotiOpt); - } - - private void updateRankTableStatusMessage(Long userId, String statusMessage, Long seasonId) { - Rank rank = rankFindService.findByUserIdAndSeasonId(userId, seasonId); - rank.setStatusMessage(statusMessage); - } - - private void updateRedisRankStatusMessage(String statusMessage, User user, Season currentSeason) { - String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); - - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); - userRank.setStatusMessage(statusMessage); - rankRedisRepository.updateRankData(hashKey, user.getId(), userRank); - } - - /** - * - * @param intraId - * @param seasonId - * seasonId == 0 -> current season, else -> 해당 Id를 가진 season의 데이터 - * - * 기존 쿼리 - * @Query(nativeQuery = true, value = "SELECT * FROM pchange " + - * "where game_id in (SELECT id FROM game where season = :season and mode = :mode ) " + - * "AND user_id = :intraId ORDER BY id Desc limit :limit") - * -> Limit에는 10이 기본으로 들어감 - * - * @return 유저의 최근 10개의 랭크 경기 기록 - */ - @Transactional(readOnly = true) - public UserHistoryResponseDto getUserHistory(String intraId, Long seasonId) { - Season season; - if (seasonId == 0){ - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - }else{ - season = seasonFindService.findSeasonById(seasonId); - } - List pChanges = pChangeRepository.findPChangesHistory(intraId, season.getId()); - List historyData = pChanges.stream().map(UserHistoryData::new).collect(Collectors.toList()); - Collections.reverse(historyData); - return new UserHistoryResponseDto(historyData); - } - - /** - * - * @param targetUserIntraId - * @param seasonId - * seasonId == 0 -> current season, else -> 해당 Id를 가진 season의 데이터 - * @return - */ - @Transactional(readOnly = true) - public UserRankResponseDto getUserRankDetail(String targetUserIntraId, Long seasonId) { - Season season; - if (seasonId == 0){ - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - }else{ - season = seasonFindService.findSeasonById(seasonId); - } - String ZSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - User user = userFindService.findByIntraId(targetUserIntraId); - try { - Long userRanking = rankRedisRepository.getRankInZSet(ZSetKey, user.getId()); - userRanking += 1; - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); - double winRate = (double)(userRank.getWins() * 10000 / (userRank.getWins() + userRank.getLosses())) / 100; - return new UserRankResponseDto(userRanking.intValue(), userRank.getPpp(), userRank.getWins(), userRank.getLosses(), winRate); - } catch (RedisDataNotFoundException ex){ - return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); - } catch (ArithmeticException ex2){ - return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); - } - } - - public User getUser(Long userId) { - return userRepository.findById(userId).orElseThrow(() -> new UsernameNotFoundException("User" + userId)); - } - - @Transactional - public void deleteKakaoId(Long userId) { - User user = userRepository.findById(userId).orElseThrow(() -> new UserNotFoundException()); - user.updateKakaoId(null); - } - - @Transactional(readOnly = true) - public UserImageResponseDto getRankedUserImagesByPPP(Long seasonId) { - Season targetSeason; - if (seasonId == 0) - targetSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - else - targetSeason = seasonFindService.findSeasonById(seasonId); - try { - String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); - List userIds = rankRedisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 2); - List users = userRepository.findUsersByIdIn(userIds); - List userImages = new ArrayList<>(); - userIds.forEach(userId -> { - User user = users.stream().filter(u -> u.getId().equals(userId)).findFirst().orElseThrow(UserNotFoundException::new); - userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri())); - }); - return new UserImageResponseDto(userImages); - } catch (RedisDataNotFoundException ex){ - return new UserImageResponseDto(new ArrayList<>()); - } - } - - public UserImageResponseDto getRankedUserImagesByExp(PageRequest pageRequest) { - List users = userRepository.findAll(pageRequest).getContent(); - List userImages = new ArrayList<>(); - for (User user : users) { - userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri())); - } - return new UserImageResponseDto(userImages); - } -} +package com.gg.server.domain.user.service; + +import com.gg.server.domain.coin.service.CoinHistoryService; +import com.gg.server.domain.coin.service.UserCoinChangeService; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.match.data.RedisMatchUserRepository; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; +import com.gg.server.domain.pchange.exception.PChangeNotExistException; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.exception.RankNotFoundException; +import com.gg.server.domain.rank.exception.RedisDataNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.rank.service.RankFindService; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.data.ReceiptRepository; +import com.gg.server.domain.receipt.exception.ReceiptNotFoundException; +import com.gg.server.domain.receipt.type.ItemStatus; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.service.SeasonFindService; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserImageRepository; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.*; +import com.gg.server.domain.user.exception.*; +import com.gg.server.domain.user.type.*; +import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; +import com.gg.server.global.utils.ExpLevelCalculator; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserFindService userFindService; + private final UserRepository userRepository; + private final NotiRepository notiRepository; + private final GameRepository gameRepository; + private final RankRedisRepository rankRedisRepository; + private final SeasonFindService seasonFindService; + private final PChangeRepository pChangeRepository; + private final RankFindService rankFindService; + private final RedisMatchUserRepository redisMatchUserRepository; + private final UserCoinChangeService userCoinChangeService; + private final CoinHistoryService coinHistoryService; + private final ReceiptRepository receiptRepository; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final UserImageRepository userImageRepository; + private final ItemService itemService; + private final TierRepository tierRepository; + + /** + * @param intraId + * @return intraId가 포함된 유저들의 intraId를 페이징 관계없이 최대 5개까지 검색하여 List로 return + */ + @Transactional(readOnly = true) + public List findByPartOfIntraId(String intraId) { + Pageable pageable = PageRequest.of(0, 5, Sort.by("intraId").ascending()); + Page pageUsers = userRepository.findByIntraIdContains(pageable, intraId); + return pageUsers.getContent().stream().map(user -> user.getIntraId()) + .collect(Collectors.toList()); + } + + /** + * @param user - event: + * - null → 로그인 유저가 잡힌 매칭이 하나도 없을 때 + * - match → 매칭은 되었으나 게임시작 전일 때 or 매칭중인 경우 + * - game → 유저가 게임이 잡혔고 현재 게임중인 경우 + *

+ * - currentMatchMode + * - normal + * - rank + * - null -> 매칭이 안잡혔을 때 or 게임 전 + */ + @Transactional() + public UserLiveResponseDto getUserLiveDetail(UserDto user) { + int notiCnt = notiRepository.countNotCheckedNotiByUser(user.getId()); + Optional optionalGame = gameRepository.getLatestGameByUser(user.getId()); + int userMatchCnt = redisMatchUserRepository.countMatchTime(user.getId()); + if (optionalGame.isPresent()) { + Game game = optionalGame.get(); + if (game.getStatus() == StatusType.LIVE || game.getStatus() == StatusType.WAIT) + return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); + else if (game.getStatus() == StatusType.END) { + PChange userPChange = pChangeRepository.findPChangeByUserIdAndGameId(user.getId(), game.getId()).orElseThrow(() -> new PChangeNotExistException()); + if (userPChange.getIsChecked() == false) { + userPChange.checkPChange(); + return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); + } + } + + if (game.getStatus() == StatusType.BEFORE) + return new UserLiveResponseDto(notiCnt, "match", null, null); + } + if (userMatchCnt > 0) { + return new UserLiveResponseDto(notiCnt, "match", null, null); + } + return new UserLiveResponseDto(notiCnt, null, null, null); + } + + @Transactional(readOnly = true) + public UserDetailResponseDto getUserDetail(String targetUserIntraId) { + User targetUser = userFindService.findByIntraId(targetUserIntraId); + String statusMessage = userFindService.getUserStatusMessage(targetUser); + Tier tier; + try{ + tier = rankFindService.findByUserIdAndSeasonId(targetUser.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + } catch (RankNotFoundException e) { + tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + } + return new UserDetailResponseDto(targetUser, statusMessage, tier); + } + + @Transactional + public void updateUser(RacketType racketType, String statusMessage, SnsType snsNotiOpt, String intraId) { + User user = userFindService.findByIntraId(intraId); + Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + updateRedisRankStatusMessage(statusMessage, user, currentSeason); + updateRankTableStatusMessage(user.getId(), statusMessage, currentSeason.getId()); + user.updateTypes(racketType, snsNotiOpt); + } + + private void updateRankTableStatusMessage(Long userId, String statusMessage, Long seasonId) { + Rank rank = rankFindService.findByUserIdAndSeasonId(userId, seasonId); + rank.setStatusMessage(statusMessage); + } + + private void updateRedisRankStatusMessage(String statusMessage, User user, Season currentSeason) { + String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); + + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); + userRank.setStatusMessage(statusMessage); + rankRedisRepository.updateRankData(hashKey, user.getId(), userRank); + } + + /** + * @param intraId + * @param seasonId seasonId == 0 -> current season, else -> 해당 Id를 가진 season의 데이터 + *

+ * 기존 쿼리 + * @return 유저의 최근 10개의 랭크 경기 기록 + * @Query(nativeQuery = true, value = "SELECT * FROM pchange " + + * "where game_id in (SELECT id FROM game where season = :season and mode = :mode ) " + + * "AND user_id = :intraId ORDER BY id Desc limit :limit") + * -> Limit에는 10이 기본으로 들어감 + */ + @Transactional(readOnly = true) + public UserHistoryResponseDto getUserHistory(String intraId, Long seasonId) { + Season season; + if (seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + List pChanges = pChangeRepository.findPChangesHistory(intraId, season.getId()); + List historyData = pChanges.stream().map(UserHistoryData::new).collect(Collectors.toList()); + Collections.reverse(historyData); + return new UserHistoryResponseDto(historyData); + } + + /** + * @param targetUserIntraId + * @param seasonId seasonId == 0 -> current season, else -> 해당 Id를 가진 season의 데이터 + * @return + */ + @Transactional(readOnly = true) + public UserRankResponseDto getUserRankDetail(String targetUserIntraId, Long seasonId) { + Season season; + if (seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + String ZSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + User user = userFindService.findByIntraId(targetUserIntraId); + try { + Long userRanking = rankRedisRepository.getRankInZSet(ZSetKey, user.getId()); + userRanking += 1; + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); + double winRate = (double) (userRank.getWins() * 10000 / (userRank.getWins() + userRank.getLosses())) / 100; + return new UserRankResponseDto(userRanking.intValue(), userRank.getPpp(), userRank.getWins(), userRank.getLosses(), winRate); + } catch (RedisDataNotFoundException ex) { + return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); + } catch (ArithmeticException ex2) { + return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); + } + } + + public User getUser(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + } + + @Transactional + public void deleteKakaoId(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + user.updateKakaoId(null); + } + + @Transactional(readOnly = true) + public UserImageResponseDto getRankedUserImagesByPPP(Long seasonId) { + Season targetSeason; + + if (seasonId == 0) + targetSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + else + targetSeason = seasonFindService.findSeasonById(seasonId); + try { + String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); + List userIds = rankRedisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 2); + List users = userRepository.findUsersByIdIn(userIds); + List userImages = new ArrayList<>(); + userIds.forEach(userId -> { + User user = users.stream().filter(u -> u.getId().equals(userId)).findFirst().orElseThrow(UserNotFoundException::new); + Tier tier = rankFindService.findByUserIdAndSeasonId(user.getId(), targetSeason.getId()).getTier(); + userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), user.getEdge(), tier.getImageUri())); + }); + return new UserImageResponseDto(userImages); + } catch (RedisDataNotFoundException ex) { + return new UserImageResponseDto(new ArrayList<>()); + } + } + + public UserImageResponseDto getRankedUserImagesByExp(PageRequest pageRequest) { + List users = userRepository.findAll(pageRequest).getContent(); + List userImages = new ArrayList<>(); + for (User user : users) { + Tier tier = rankFindService.findByUserIdAndSeasonId(user.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), user.getEdge(), tier.getImageUri())); + } + return new UserImageResponseDto(userImages); + } + + @Transactional + public UserAttendanceResponseDto attendUser(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + int plus = userCoinChangeService.addAttendanceCoin(user); + + return new UserAttendanceResponseDto(user.getGgCoin() - plus, user.getGgCoin(), plus); + } + + @Transactional + public UserNormalDetailResponseDto getUserNormalDetail(UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Boolean isAdmin = user.getRoleType() == RoleType.ADMIN; + Boolean isAttended = coinHistoryService.hasAttendedToday(loginUser); + Integer level = ExpLevelCalculator.getLevel(user.getTotalExp()); + Tier tier; + try { + tier = rankFindService.findByUserIdAndSeasonId(user.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + } catch (RankNotFoundException ex) { + // 카카오 유저나 Rank가 없는 유저 + tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + } + return new UserNormalDetailResponseDto(user.getIntraId(), loginUser.getImageUri(), isAdmin, isAttended, loginUser.getEdge(), tier.getName(), tier.getImageUri(), level); + } + + @Transactional() + public void updateTextColor(Long userId, UserTextColorDto textColorDto) { + String textColor = textColorDto.getTextColor(); + Receipt receipt = receiptRepository.findById(textColorDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); + User loginUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + if (!UserTextColorCheckService.check(textColor)) + throw new UserTextColorException(); + + itemService.checkItemType(receipt, ItemType.TEXT_COLOR); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateTextColor(textColor); + receipt.updateStatus(ItemStatus.USED); + } + + @Transactional + public String updateEdge(UserDto user, UserEdgeDto userEdgeDto) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + EdgeType edgeType = EdgeType.getRandomEdgeType(); + Receipt receipt = receiptRepository.findById(userEdgeDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.EDGE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateEdge(edgeType); + receipt.updateStatus(ItemStatus.USED); + + return edgeType.toString(); + } + + @Transactional + public String updateBackground(UserDto user, UserBackgroundDto userBackgroundDto) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + BackgroundType backgroundType = BackgroundType.getRandomBackgroundType(); + Receipt receipt = receiptRepository.findById(userBackgroundDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.BACKGROUND); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateBackground(backgroundType); + receipt.updateStatus(ItemStatus.USED); + + return backgroundType.toString(); + } + + @Transactional + public void updateUserProfileImage(UserDto user, UserProfileImageRequestDto userProfileImageRequestDto, MultipartFile userImageFile) throws IOException { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Receipt receipt = receiptRepository.findById(userProfileImageRequestDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.PROFILE_IMAGE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + if (userImageFile == null) + throw new UserImageNullException(); + if (userImageFile.getSize() > 50000) { + throw new UserImageLargeException(); + } else if (userImageFile.getContentType() == null || !userImageFile.getContentType().equals("image/jpeg")) { + throw new UserImageTypeException(); + } + + UserImage userImage = userImageRepository.findTopByUserAndIsCurrentIsTrueOrderByIdDesc(loginUser).orElseThrow(UserImageNullException::new); + userImage.updateIsCurrent(); + asyncNewUserImageUploader.update(user.getIntraId(), userImageFile); + receipt.updateStatus(ItemStatus.USED); + } +} diff --git a/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java b/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java new file mode 100644 index 000000000..278cc6e5f --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java @@ -0,0 +1,23 @@ +package com.gg.server.domain.user.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserTextColorCheckService { + public static boolean check(String textColor) { + if (textColor == null) + return false; + if (textColor.length() != 7) + return false; + if (textColor.charAt(0) != '#') + return false; + for (int i = 1; i < 7; i++) { + char c = textColor.charAt(i); + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) + return false; + } + return true; + } +} diff --git a/src/main/java/com/gg/server/domain/user/type/BackgroundType.java b/src/main/java/com/gg/server/domain/user/type/BackgroundType.java new file mode 100644 index 000000000..01629e6fc --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/type/BackgroundType.java @@ -0,0 +1,51 @@ +package com.gg.server.domain.user.type; + +import lombok.RequiredArgsConstructor; + +import java.util.Random; + +@RequiredArgsConstructor +public enum BackgroundType { + BASIC(0), + COLOR1(1), + COLOR2(2), + COLOR3(3), + COLOR4(4), + COLOR5(5), + COLOR6(6), + COLOR7(7), + COLOR8(8), + COLOR9(9), + COLOR10(10), + COLOR11(11), + COLOR12(12), + COLOR13(13), + COLOR14(14), + COLOR15(15), + COLOR16(16); + + private final Integer code; + + public static BackgroundType getRandomBackgroundType() { + Random random = new Random(); + int tierInt = random.nextInt(100); + int colorInt; + + if (tierInt <= 50) + colorInt = random.nextInt(100) % 4 + 1; + else if (tierInt <= 70) + colorInt = (random.nextInt(99) % 3) + 5; + else if (tierInt <= 85) + colorInt = (random.nextInt(99) % 3) + 8; + else if (tierInt <= 95) + colorInt = (random.nextInt(99) % 3) + 11; + else + colorInt = (random.nextInt(99) % 3) + 14; + + return BackgroundType.values()[colorInt]; + } + + public static BackgroundType of(String code) { + return BackgroundType.valueOf(code); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/type/EdgeType.java b/src/main/java/com/gg/server/domain/user/type/EdgeType.java new file mode 100644 index 000000000..e6446216f --- /dev/null +++ b/src/main/java/com/gg/server/domain/user/type/EdgeType.java @@ -0,0 +1,51 @@ +package com.gg.server.domain.user.type; + +import lombok.RequiredArgsConstructor; + +import java.util.Random; + +@RequiredArgsConstructor +public enum EdgeType { + BASIC(0), + COLOR1(1), + COLOR2(2), + COLOR3(3), + COLOR4(4), + COLOR5(5), + COLOR6(6), + COLOR7(7), + COLOR8(8), + COLOR9(9), + COLOR10(10), + COLOR11(11), + COLOR12(12), + COLOR13(13), + COLOR14(14), + COLOR15(15), + COLOR16(16); + + private final Integer code; + + public static EdgeType getRandomEdgeType() { + Random random = new Random(); + int tierInt = random.nextInt(100); + int colorInt; + + if (tierInt <= 50) + colorInt = random.nextInt(100) % 4 + 1; + else if (tierInt <= 70) + colorInt = (random.nextInt(99) % 3) + 5; + else if (tierInt <= 85) + colorInt = (random.nextInt(99) % 3) + 8; + else if (tierInt <= 95) + colorInt = (random.nextInt(99) % 3) + 11; + else + colorInt = (random.nextInt(99) % 3) + 14; + + return EdgeType.values()[colorInt]; + } + + public static EdgeType of(String code) { + return EdgeType.valueOf(code); + } +} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/config/WebConfig.java b/src/main/java/com/gg/server/global/config/WebConfig.java index d914c1642..f7573f428 100644 --- a/src/main/java/com/gg/server/global/config/WebConfig.java +++ b/src/main/java/com/gg/server/global/config/WebConfig.java @@ -1,31 +1,31 @@ -package com.gg.server.global.config; - -import com.gg.server.domain.user.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.argumentresolver.LoginMemberArgumentResolver; -import com.gg.server.global.utils.querytracker.LoggingInterceptor; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import java.util.List; - -@Configuration -@RequiredArgsConstructor -public class WebConfig implements WebMvcConfigurer { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - private final LoggingInterceptor loggingInterceptor; - - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(new LoginMemberArgumentResolver(userRepository, tokenProvider)); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(loggingInterceptor); - } -} +package com.gg.server.global.config; + +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.global.utils.argumentresolver.LoginMemberArgumentResolver; +import com.gg.server.global.utils.querytracker.LoggingInterceptor; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +@RequiredArgsConstructor +public class WebConfig implements WebMvcConfigurer { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + private final LoggingInterceptor loggingInterceptor; + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new LoginMemberArgumentResolver(userRepository, tokenProvider)); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loggingInterceptor); + } +} diff --git a/src/main/java/com/gg/server/global/exception/ErrorCode.java b/src/main/java/com/gg/server/global/exception/ErrorCode.java index 8e8cae278..39beafda3 100644 --- a/src/main/java/com/gg/server/global/exception/ErrorCode.java +++ b/src/main/java/com/gg/server/global/exception/ErrorCode.java @@ -9,16 +9,24 @@ public enum ErrorCode { //user USER_NOT_FOUND(404, "UR100", "USER NOT FOUND"), + USER_IMAGE_NOT_FOUND(404, "UR200", "USER IMAGE NOT FOUND"), USER_IMAGE_TOO_LARGE(413, "UR401", "USER IMAGE IS TOO LARGE"), USER_IMAGE_WRONG_TYPE(415, "UR402", "USER IMAGE TYPE IS WRONG"), KAKAO_OAUTH2_NOT_FOUND(404, "UR101", "KAKAO OAUTH2 NOT FOUND"), KAKAO_OAUTH2_DUPLICATE(409, "UR300", "KAKAO OAUTH2 ALREADY EXIST"), - + USER_TEXT_COLOR_WRONG_TYPE(401, "UR403", "USER TEXT COLOR CODE IS WRONG"), + USER_ALREADY_ATTENDANCE(409, "UR301", "USER ALREADY ATTENDANCE"), //announcement ANNOUNCE_NOT_FOUND(404, "AN100", "ANNOUNCEMENT NOT FOUND"), ANNOUNCE_DUPLICATE(409, "AN300", "ANNOUNCEMENT DUPLICATION"), + //coinPolicy + CoinPolicy_NOT_FOUND(404, "CP100", "COINPOLICY NOT FOUND"), + + //coinHistory + COIN_HISTORY_NOT_FOUND(404, "CH100", "COIN HISTORY NOT FOUND"), + //season SEASON_NOT_FOUND(404, "SE100", "SEASON NOT FOUND"), SEASON_FORBIDDEN(400, "SE500", "SEASON FORBIDDEN ERROR"), @@ -33,6 +41,30 @@ public enum ErrorCode { REDIS_RANK_NOT_FOUND(404, "RK101", "REDIS RANK NOT FOUND"), RANK_UPDATE_FAIL(400, "RK200", "RANK UPDATE FAIL"), + //tier + TIER_NOT_FOUND(404, "TR100", "TIER NOT FOUND"), + + //item + ITEM_NOT_FOUND(404, "IT100", "ITEM NOT FOUND"), + ITEM_TYPE_NOT_MATCHED(400, "IT200", "ITEM TYPE NOT MATCHED"), + ITEM_NOT_PURCHASABLE(400, "IT201", "ITEM NOT PURCHASABLE"), + INSUFFICIENT_GGCOIN(400,"IT202","INSUFFICIENT GGCOIN"), + GUEST_ROLE_PURCHASE_FORBIDDEN(403, "IT203", "GUEST ROLE USERS CANNOT PURCHASE ITEMS."), + GUEST_ROLE_GIFT_FORBIDDEN(403, "IT204", "GUEST ROLE USERS CANNOT GIFT ITEMS."), + ITEM_NOT_AVAILABLE(400, "IT205", "ITEM NOT AVAILABLE"), + ITEM_IMAGE_TOO_LARGE(413, "IT401", "ITEM IMAGE IS TOO LARGE"), + ITEM_IMAGE_WRONG_TYPE(415, "IT402", "ITEM IMAGE TYPE IS WRONG"), + + //receipt + RECEIPT_NOT_FOUND(404, "RC100", "RECEIPT NOT FOUND"), + RECEIPT_NOT_OWNER(403, "RC500", "RECEIPT NOT OWNER"), + RECEIPT_STATUS_NOT_MATCHED(400, "RC200", "RECEIPT STATUS NOT MATCHED"), + + //megaphone + MEGAPHONE_NOT_FOUND(404, "ME100", "MEGAPHONE NOT FOUND"), + MEGAPHONE_TIME(400, "ME200", "MEGAPHONE TIME"), + MEGAPHONE_CONTENT(400, "ME201", "MEGAPHONE CONTENT IS EMPTY"), + /** Penalty **/ PENALTY_NOT_FOUND(404, "PE100", "PENALTY NOT FOUND"), REDIS_PENALTY_USER_NOT_FOUND(404, "PE101", "REDIS PENALTY USER NOT FOUND"), diff --git a/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java b/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java new file mode 100644 index 000000000..e814d0981 --- /dev/null +++ b/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java @@ -0,0 +1,26 @@ +package com.gg.server.global.scheduler; + +import com.gg.server.domain.megaphone.service.MegaphoneService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; + +@Component +@Slf4j +public class MegaphoneScheduler extends AbstractScheduler { + private final MegaphoneService megaphoneService; + + public MegaphoneScheduler(MegaphoneService megaphoneService) { + this.megaphoneService = megaphoneService; + this.setCron("0 59 23 * * *"); + } + + @Override + public Runnable runnable() { + return () -> { + log.info("Set Megaphone List "); + megaphoneService.setMegaphoneList(LocalDate.now()); + }; + } +} diff --git a/src/main/java/com/gg/server/global/security/UserPrincipal.java b/src/main/java/com/gg/server/global/security/UserPrincipal.java index 1428d76b1..30eb2236e 100644 --- a/src/main/java/com/gg/server/global/security/UserPrincipal.java +++ b/src/main/java/com/gg/server/global/security/UserPrincipal.java @@ -1,83 +1,81 @@ -package com.gg.server.global.security; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.RoleType; -import lombok.Getter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.*; - -@Getter -public class UserPrincipal implements OAuth2User, UserDetails { - private final Long id; - private final String nickname; - private final String profileImg; - private final Collection authorities; - private Map attributes; - - public UserPrincipal(Long id, String nickname, String profileImg, Collection authorities) { - this.id = id; - this.nickname = nickname; - this.profileImg = profileImg; - this.authorities = authorities; - } - - public static UserPrincipal create(User user) { - List authorities = new ArrayList<>(); - if (user.getRoleType().getKey().equals("ROLE_USER")) { - authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); - } else if (user.getRoleType().getKey().equals("ROLE_ADMIN")) { - authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); - authorities.add(new SimpleGrantedAuthority(RoleType.ADMIN.getKey())); - } - return new UserPrincipal(user.getId(), user.getIntraId(), user.getImageUri(), authorities); - } - - public static UserPrincipal create(User user, Map attributes) { - UserPrincipal userPrincipal = UserPrincipal.create(user); - userPrincipal.setAttributes(attributes); - return userPrincipal; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - @Override - public String getPassword() { - return null; - } - - @Override - public String getUsername() { - return nickname; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public String getName() { - return String.valueOf(id); - } +package com.gg.server.global.security; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.RoleType; +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import java.util.*; + +@Getter +public class UserPrincipal implements OAuth2User, UserDetails { + private final Long id; + private final String nickname; + private final Collection authorities; + private Map attributes; + + public UserPrincipal(Long id, String nickname, Collection authorities) { + this.id = id; + this.nickname = nickname; + this.authorities = authorities; + } + + public static UserPrincipal create(User user) { + List authorities = new ArrayList<>(); + if (user.getRoleType().getKey().equals("ROLE_USER")) { + authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); + } else if (user.getRoleType().getKey().equals("ROLE_ADMIN")) { + authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); + authorities.add(new SimpleGrantedAuthority(RoleType.ADMIN.getKey())); + } + return new UserPrincipal(user.getId(), user.getIntraId(), authorities); + } + + public static UserPrincipal create(User user, Map attributes) { + UserPrincipal userPrincipal = UserPrincipal.create(user); + userPrincipal.setAttributes(attributes); + return userPrincipal; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return nickname; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public String getName() { + return String.valueOf(id); + } } \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java b/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java index 37f63ca4d..752d21292 100644 --- a/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java +++ b/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java @@ -1,8 +1,7 @@ package com.gg.server.global.security.handler; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; import com.gg.server.domain.user.exception.UserNotFoundException; import com.gg.server.domain.user.type.RoleType; import com.gg.server.global.security.UserPrincipal; @@ -129,5 +128,3 @@ private void clearAuthenticationAttributes(HttpServletRequest request, HttpServl } - - diff --git a/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java b/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java index ac78b1ee0..a7442973c 100644 --- a/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java +++ b/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java @@ -1,109 +1,110 @@ -package com.gg.server.global.security.service; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.UserPrincipal; -import com.gg.server.global.security.info.OAuthUserInfo; -import com.gg.server.global.security.info.OAuthUserInfoFactory; -import com.gg.server.global.security.info.ProviderType; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.NoSuchElementException; - -@Service -@RequiredArgsConstructor -@Transactional -public class CustomOAuth2UserService extends DefaultOAuth2UserService { - private final UserRepository userRepository; - private final AsyncNewUserImageUploader asyncNewUserImageUploader; - private final RankRepository rankRepository; - private final SeasonRepository seasonRepository; - private final RankRedisRepository rankRedisRepository; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - @Override - public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - OAuth2User user = super.loadUser(userRequest); - - try { - return this.process(userRequest, user); - } catch (AuthenticationException ex) { - throw ex; - } catch (Exception ex) { - ex.printStackTrace(); - throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause()); - } - } - - private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) { - ProviderType providerType = ProviderType.keyOf(userRequest.getClientRegistration().getRegistrationId().toUpperCase()); - User savedUser; - OAuthUserInfo userInfo = OAuthUserInfoFactory.getOAuth2UserInfo(providerType, user.getAttributes()); - if (providerType.equals(ProviderType.FORTYTWO)) { - savedUser = userRepository.findByIntraId(userInfo.getIntraId()) - .orElse(null); - } else { - savedUser = userRepository.findByKakaoId(userInfo.getKakaoId()) - .orElse(null); - } - if (savedUser == null) { - savedUser = createUser(userInfo); - if (providerType.equals(ProviderType.FORTYTWO)) - createUserRank(savedUser); - if (userInfo.getImageUrl().startsWith("https://cdn.intra.42.fr/")) { - asyncNewUserImageUploader.upload(userInfo.getIntraId(), userInfo.getImageUrl()); - } - } - return UserPrincipal.create(savedUser, user.getAttributes()); - } - - private void createUserRank(User savedUser) { - seasonRepository.findCurrentAndNewSeason(LocalDateTime.now()).forEach( - season -> { - Rank userRank = Rank.from(savedUser, season, season.getStartPpp()); - rankRepository.save(userRank); - RankRedis rankRedis = RankRedis.from(UserDto.from(savedUser), season.getStartPpp()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(hashKey, savedUser.getId(), rankRedis); - } - ); - } - - private User createUser(OAuthUserInfo userInfo) { - User user = User.builder() - .intraId(userInfo.getIntraId()) - .roleType(userInfo.getRoleType()) - .imageUri(userInfo.getImageUrl()) - .kakaoId(userInfo.getKakaoId()) - .snsNotiOpt(SnsType.EMAIL) - .racketType(RacketType.NONE) - .totalExp(0) - .eMail(userInfo.getEmail()) - .build(); - return userRepository.saveAndFlush(user); - } -} +package com.gg.server.global.security.service; + +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.UserPrincipal; +import com.gg.server.global.security.info.OAuthUserInfo; +import com.gg.server.global.security.info.OAuthUserInfoFactory; +import com.gg.server.global.security.info.ProviderType; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Service +@RequiredArgsConstructor +@Transactional +public class CustomOAuth2UserService extends DefaultOAuth2UserService { + private final UserRepository userRepository; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final RankRepository rankRepository; + private final SeasonRepository seasonRepository; + private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + OAuth2User user = super.loadUser(userRequest); + + try { + return this.process(userRequest, user); + } catch (AuthenticationException ex) { + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause()); + } + } + + private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) { + ProviderType providerType = ProviderType.keyOf(userRequest.getClientRegistration().getRegistrationId().toUpperCase()); + User savedUser; + OAuthUserInfo userInfo = OAuthUserInfoFactory.getOAuth2UserInfo(providerType, user.getAttributes()); + if (providerType.equals(ProviderType.FORTYTWO)) { + savedUser = userRepository.findByIntraId(userInfo.getIntraId()) + .orElse(null); + } else { + savedUser = userRepository.findByKakaoId(userInfo.getKakaoId()) + .orElse(null); + } + if (savedUser == null) { + savedUser = createUser(userInfo); + if (providerType.equals(ProviderType.FORTYTWO)) + createUserRank(savedUser); + if (userInfo.getImageUrl().startsWith("https://cdn.intra.42.fr/")) { + asyncNewUserImageUploader.upload(userInfo.getIntraId(), userInfo.getImageUrl()); + } + } + return UserPrincipal.create(savedUser, user.getAttributes()); + } + + private void createUserRank(User savedUser) { + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + seasonRepository.findCurrentAndNewSeason(LocalDateTime.now()).forEach( + season -> { + Rank userRank = Rank.from(savedUser, season, season.getStartPpp(), tier); + rankRepository.save(userRank); + RankRedis rankRedis = RankRedis.from(UserDto.from(savedUser), season.getStartPpp(), tier.getImageUri()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(hashKey, savedUser.getId(), rankRedis); + } + ); + } + + private User createUser(OAuthUserInfo userInfo) { + User user = User.builder() + .intraId(userInfo.getIntraId()) + .roleType(userInfo.getRoleType()) + .kakaoId(userInfo.getKakaoId()) + .snsNotiOpt(SnsType.EMAIL) + .racketType(RacketType.NONE) + .totalExp(0) + .eMail(userInfo.getEmail()) + .build(); + return userRepository.saveAndFlush(user); + } +} diff --git a/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java b/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java index 3526ca8ee..a27fd87a2 100644 --- a/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java +++ b/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java @@ -1,31 +1,29 @@ -package com.gg.server.global.security.service; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.service.UserFindService; -import com.gg.server.domain.user.service.UserService; -import com.gg.server.global.security.UserPrincipal; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class CustomUserDetailsService implements UserDetailsService { - - private final UserFindService userFindService; - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - User user = userFindService.findByIntraId(username); - return UserPrincipal.create(user); - } - - public UserDetails loadUserById(Long id) { - User user = userFindService.findUserById(id); - return UserPrincipal.create(user); - } -} +package com.gg.server.global.security.service; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.domain.user.service.UserFindService; +import com.gg.server.global.security.UserPrincipal; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class CustomUserDetailsService implements UserDetailsService { + + private final UserFindService userFindService; + @Override + public UserDetails loadUserByUsername(String username) throws UserNotFoundException { + User user = userFindService.findByIntraId(username); + return UserPrincipal.create(user); + } + + public UserDetails loadUserById(Long id) { + User user = userFindService.findUserById(id); + return UserPrincipal.create(user); + } +} diff --git a/src/main/java/com/gg/server/global/utils/ItemImageHandler.java b/src/main/java/com/gg/server/global/utils/ItemImageHandler.java new file mode 100644 index 000000000..dfcd319c9 --- /dev/null +++ b/src/main/java/com/gg/server/global/utils/ItemImageHandler.java @@ -0,0 +1,51 @@ +package com.gg.server.global.utils; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.gg.server.domain.item.data.Item; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +@Component +public class ItemImageHandler { + private final AmazonS3 amazonS3; + + public ItemImageHandler(AmazonS3 amazonS3) { + this.amazonS3 = amazonS3; + } + + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${cloud.aws.s3.dir}") + private String dir; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + + public String updateAndGetS3ImageUri(MultipartFile multipartFile, Item item) throws IOException { + String itemFileName = item.getName() + "-" + UUID.randomUUID() + ".jpeg"; + if (itemFileName.equals("small_default.jpeg")) + return defaultImageUrl; + else { + String s3ImageUrl = uploadToS3(multipartFile, itemFileName); + return s3ImageUrl; + } + } + + public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException { + String s3FileName = dir + fileName; + InputStream inputStream = multipartFile.getInputStream(); + ObjectMetadata objMeta = new ObjectMetadata(); + objMeta.setContentLength(multipartFile.getSize()); + amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl(CannedAccessControlList.PublicRead)); + return amazonS3.getUrl(bucketName, s3FileName).toString(); + } +} diff --git a/src/main/java/com/gg/server/global/utils/UserImageHandler.java b/src/main/java/com/gg/server/global/utils/UserImageHandler.java index aa9312011..a29e0037d 100644 --- a/src/main/java/com/gg/server/global/utils/UserImageHandler.java +++ b/src/main/java/com/gg/server/global/utils/UserImageHandler.java @@ -1,76 +1,78 @@ -package com.gg.server.global.utils; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.gg.server.domain.user.User; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - -@Component -public class UserImageHandler { - private final AmazonS3 amazonS3; - private final FileDownloader fileDownloader; - - public UserImageHandler(AmazonS3 amazonS3, FileDownloader fileDownloader) { - this.amazonS3 = amazonS3; - this.fileDownloader = fileDownloader; - } - - @Value("${cloud.aws.s3.bucket}") - private String bucketName; - - @Value("${cloud.aws.s3.dir}") - private String dir; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - public String uploadAndGetS3ImageUri(String intraId, String imageUrl) { - if (!isStringValid(intraId) || !isStringValid(imageUrl)) { - return defaultImageUrl; - } - byte[] downloadedImageBytes = fileDownloader.downloadFromUrl(imageUrl); - try { - byte[] resizedImageBytes = ImageResizingUtil.resizeImageBytes(downloadedImageBytes, 0.5); - MultipartFile multipartFile = new JpegMultipartFile(resizedImageBytes, intraId); - return uploadToS3(multipartFile, multipartFile.getOriginalFilename()); - } catch (IOException e) { - return defaultImageUrl; - } - } - - public String updateAndGetS3ImageUri(MultipartFile multipartFile, User user) throws IOException - { - String imageUrl = user.getImageUri(); - String userFileName = imageUrl.split("/")[imageUrl.split("/").length - 1]; - String updateFileName = user.getIntraId() + "-" + UUID.randomUUID().toString() + ".jpeg"; - if (updateFileName.equals("small_default.jpeg")) - return defaultImageUrl; - else { - String s3ImageUrl = uploadToS3(multipartFile, updateFileName);; - if (!imageUrl.equals(defaultImageUrl)) - amazonS3.deleteObject(new DeleteObjectRequest(bucketName, dir + userFileName)); - return s3ImageUrl; - } - } - private Boolean isStringValid(String intraId) { - return intraId != null && intraId.length() != 0; - } - - public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException{ - String s3FileName = dir + fileName; - InputStream inputStream = multipartFile.getInputStream(); - ObjectMetadata objMeta = new ObjectMetadata(); - objMeta.setContentLength(multipartFile.getSize()); - amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl(CannedAccessControlList.PublicRead)); - return amazonS3.getUrl(bucketName, s3FileName).toString(); - } -} +package com.gg.server.global.utils; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserImageRepository; +import com.gg.server.domain.user.exception.UserImageNullException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +@Component +public class UserImageHandler { + private final AmazonS3 amazonS3; + private final FileDownloader fileDownloader; + + public UserImageHandler(AmazonS3 amazonS3, FileDownloader fileDownloader, + UserImageRepository userImageRepository) { + this.amazonS3 = amazonS3; + this.fileDownloader = fileDownloader; + this.userImageRepository = userImageRepository; + } + + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${cloud.aws.s3.dir}") + private String dir; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + private final UserImageRepository userImageRepository; + + public String uploadAndGetS3ImageUri(String intraId, String imageUrl) { + if (!isStringValid(intraId) || !isStringValid(imageUrl)) { + return defaultImageUrl; + } + byte[] downloadedImageBytes = fileDownloader.downloadFromUrl(imageUrl); + try { + byte[] resizedImageBytes = ImageResizingUtil.resizeImageBytes(downloadedImageBytes, 0.5); + MultipartFile multipartFile = new JpegMultipartFile(resizedImageBytes, intraId); + return uploadToS3(multipartFile, multipartFile.getOriginalFilename()); + } catch (IOException e) { + return defaultImageUrl; + } + } + + public String updateAndGetS3ImageUri(MultipartFile multipartFile, User user) throws IOException + { + String updateFileName = user.getIntraId() + "-" + UUID.randomUUID().toString() + ".jpeg"; + if (updateFileName.equals("small_default.jpeg")) + return defaultImageUrl; + else { + String s3ImageUrl = uploadToS3(multipartFile, updateFileName);; + return s3ImageUrl; + } + } + + private Boolean isStringValid(String intraId) { + return intraId != null && intraId.length() != 0; + } + + public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException{ + String s3FileName = dir + fileName; + InputStream inputStream = multipartFile.getInputStream(); + ObjectMetadata objMeta = new ObjectMetadata(); + objMeta.setContentLength(multipartFile.getSize()); + amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl(CannedAccessControlList.PublicRead)); + return amazonS3.getUrl(bucketName, s3FileName).toString(); + } +} diff --git a/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java b/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java index b4f2e8051..36fabe80f 100644 --- a/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java +++ b/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java @@ -1,39 +1,39 @@ -package com.gg.server.global.utils.argumentresolver; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.HeaderUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -import javax.servlet.http.HttpServletRequest; - -@RequiredArgsConstructor -public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - - @Override - public boolean supportsParameter(MethodParameter parameter) { - boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class); - boolean hasUserType = UserDto.class.isAssignableFrom(parameter.getParameterType()); - return hasLoginAnnotation && hasUserType; - } - - @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { - HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); - String accessToken = HeaderUtil.getAccessToken(request); - Long loginUserId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(loginUserId).orElseThrow(); - UserDto userDto = UserDto.from(user); - return userDto; - } -} +package com.gg.server.global.utils.argumentresolver; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.global.utils.HeaderUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.servlet.http.HttpServletRequest; + +@RequiredArgsConstructor +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class); + boolean hasUserType = UserDto.class.isAssignableFrom(parameter.getParameterType()); + return hasLoginAnnotation && hasUserType; + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); + String accessToken = HeaderUtil.getAccessToken(request); + Long loginUserId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(loginUserId).orElseThrow(); + UserDto userDto = UserDto.from(user); + return userDto; + } +} diff --git a/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java b/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java new file mode 100644 index 000000000..5dcce6806 --- /dev/null +++ b/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java @@ -0,0 +1,33 @@ +package com.gg.server.global.utils.aws; + +import com.gg.server.domain.item.data.Item; +import com.gg.server.global.utils.ItemImageHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@Component +public class AsyncNewItemImageUploader { + private final ItemImageHandler itemImageHandler; + + @Value("${info.image.itemNotFoundUrl}") + private String defaultImageUrl; + + public AsyncNewItemImageUploader(ItemImageHandler itemImageHandler) { + this.itemImageHandler = itemImageHandler; + } + + @Transactional + public void upload(Item item, + MultipartFile multipartFile) throws IOException { + String s3ImageUrl = itemImageHandler.updateAndGetS3ImageUri(multipartFile, item); + if (s3ImageUrl == null) { + item.imageUpdate(defaultImageUrl); + } else { + item.imageUpdate(s3ImageUrl); + } + } +} diff --git a/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java b/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java index 90e5cd866..802e8ccc9 100644 --- a/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java +++ b/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java @@ -1,57 +1,62 @@ -package com.gg.server.global.utils.aws; - -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.global.utils.UserImageHandler; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import java.io.IOException; - -@Component -public class AsyncNewUserImageUploader { - private final UserImageHandler userImageHandler; - private final UserRepository userRepository; - @PersistenceContext - private EntityManager entityManager; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - public AsyncNewUserImageUploader(UserImageHandler userImageHandler, UserRepository userRepository) { - this.userImageHandler = userImageHandler; - this.userRepository = userRepository; - } - - @Async("asyncExecutor") - public void upload(String intraId, String imageUrl) { - String s3ImageUrl = userImageHandler.uploadAndGetS3ImageUri(intraId, imageUrl); - if (defaultImageUrl.equals(s3ImageUrl)) { - return ; - } - userRepository.findByIntraId(intraId).ifPresent(user -> { - if (s3ImageUrl == null) { - user.imageUpdate(defaultImageUrl); - } else { - user.imageUpdate(s3ImageUrl); - } - userRepository.save(user); - }); - } - - @Transactional - public void update(String intraId, MultipartFile multipartFile) throws IOException { - User user = userRepository.getUserByIntraId(intraId); - String s3ImageUrl = userImageHandler.updateAndGetS3ImageUri(multipartFile, user); - if (s3ImageUrl == null) { - user.imageUpdate(defaultImageUrl); - } else { - user.imageUpdate(s3ImageUrl); - } - } -} +package com.gg.server.global.utils.aws; + +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserImageRepository; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.utils.UserImageHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.io.IOException; +import java.time.LocalDateTime; + +@Slf4j +@Component +public class AsyncNewUserImageUploader { + private final UserImageHandler userImageHandler; + private final UserRepository userRepository; + @PersistenceContext + private EntityManager entityManager; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + private final UserImageRepository userImageRepository; + + public AsyncNewUserImageUploader(UserImageHandler userImageHandler, UserRepository userRepository, + UserImageRepository userImageRepository) { + this.userImageHandler = userImageHandler; + this.userRepository = userRepository; + this.userImageRepository = userImageRepository; + } + + @Async("asyncExecutor") + public void upload(String intraId, String imageUrl) { + String s3ImageUrl = userImageHandler.uploadAndGetS3ImageUri(intraId, imageUrl); + if (defaultImageUrl.equals(s3ImageUrl)) { + return ; + } + userRepository.findByIntraId(intraId).ifPresent(user -> { + UserImage userImage = new UserImage(user, (s3ImageUrl != null) ? s3ImageUrl : defaultImageUrl, + LocalDateTime.now(), null, true); + userImageRepository.save(userImage); + user.updateImageUri(userImage.getImageUri()); + }); + } + + @Transactional + public void update(String intraId, MultipartFile multipartFile) throws IOException { + User user = userRepository.findByIntraId(intraId).get(); + String s3ImageUrl = userImageHandler.updateAndGetS3ImageUri(multipartFile, user); + s3ImageUrl = s3ImageUrl == null ? defaultImageUrl : s3ImageUrl; + UserImage userImage = new UserImage(user, s3ImageUrl, LocalDateTime.now(), null, true); + userImageRepository.saveAndFlush(userImage); + user.updateImageUri(s3ImageUrl); + } +} diff --git a/src/main/resources/db/migration/V2.1__add_item_creator.sql b/src/main/resources/db/migration/V2.1__add_item_creator.sql new file mode 100644 index 000000000..0d0c75c10 --- /dev/null +++ b/src/main/resources/db/migration/V2.1__add_item_creator.sql @@ -0,0 +1,5 @@ +alter table item + add column creator_intra_id varchar(10) NOT NULL; + +alter table item + add column deleter_intra_id varchar(10); diff --git a/src/main/resources/db/migration/V2.2__add_item_type.sql b/src/main/resources/db/migration/V2.2__add_item_type.sql new file mode 100644 index 000000000..d1a0ed5ca --- /dev/null +++ b/src/main/resources/db/migration/V2.2__add_item_type.sql @@ -0,0 +1,2 @@ +alter table item + add column type varchar(255) NOT NULL; \ No newline at end of file diff --git a/src/main/resources/db/migration/V2.3__add_megaphone_receiptId.sql b/src/main/resources/db/migration/V2.3__add_megaphone_receiptId.sql new file mode 100644 index 000000000..e740d7362 --- /dev/null +++ b/src/main/resources/db/migration/V2.3__add_megaphone_receiptId.sql @@ -0,0 +1,7 @@ +alter table megaphone + add column receipt_id bigint; + +alter table megaphone + add constraint fk_megaphone_receipt_receipt_id + foreign key (receipt_id) + references receipt (id); \ No newline at end of file diff --git a/src/main/resources/db/migration/V2.4__modify_item_content_columns.sql b/src/main/resources/db/migration/V2.4__modify_item_content_columns.sql new file mode 100644 index 000000000..06d2baae0 --- /dev/null +++ b/src/main/resources/db/migration/V2.4__modify_item_content_columns.sql @@ -0,0 +1,10 @@ +alter table item + add column main_content varchar(255); + +alter table item + add column sub_content varchar(255); + +UPDATE item SET main_content = content, sub_content = content; + +alter table item +drop column content; \ No newline at end of file diff --git a/src/main/resources/db/migration/V2.5__add_userImage_and_user_image_uri.sql b/src/main/resources/db/migration/V2.5__add_userImage_and_user_image_uri.sql new file mode 100644 index 000000000..c67b74395 --- /dev/null +++ b/src/main/resources/db/migration/V2.5__add_userImage_and_user_image_uri.sql @@ -0,0 +1,18 @@ +create table user_image +( + id bigint not null auto_increment, + user_id bigint, + image_uri varchar(255), + created_at datetime(6) not null, + deleted_at datetime(6) default null, + is_current bit default 1 not null, + + primary key (id) +); + +alter table user_image + add constraint fk_user_image_user_user_id + foreign key (user_id) + references `user` (id); + +INSERT INTO user_image (user_id, image_uri, created_at) SELECT id, image_uri, created_at FROM user; \ No newline at end of file diff --git a/src/main/resources/db/migration/V2__migration_42gg_4th.sql b/src/main/resources/db/migration/V2__migration_42gg_4th.sql new file mode 100644 index 000000000..04c56121c --- /dev/null +++ b/src/main/resources/db/migration/V2__migration_42gg_4th.sql @@ -0,0 +1,102 @@ +create table coin_history +( + id bigint not null auto_increment, + amount integer, + created_at datetime(6) not null, + history varchar(30), + user_id bigint, + primary key (id) +); + +create table coin_policy +( + id bigint not null auto_increment, + user_id bigint, + attendance integer, + created_at datetime(6) not null, + normal integer, + rank_lose integer, + rank_win integer, + primary key (id) +); + +create table item +( + id bigint not null auto_increment, + content varchar(255), + created_at datetime(6) not null, + discount integer, + image_uri varchar(255), + is_visible bit not null, + name varchar(30), + price integer not null, + primary key (id) +); + +create table megaphone +( + id bigint not null auto_increment, + content varchar(30), + used_at date not null, + user_id bigint not null, + primary key (id) +); + +alter table ranks + add column tier_id bigint; + +create table receipt +( + id bigint not null auto_increment, + owner_intra_id varchar(255) not null, + created_at datetime(6) not null, + purchaser_intra_id varchar(255) not null, + status varchar(255) not null, + item_id bigint not null, + primary key (id) +); + +create table tier +( + id bigint not null auto_increment, + image_uri varchar(255), + name varchar(255), + primary key (id) +); + +alter table user + add column background varchar(255) default "BASIC"; + +alter table user + add column edge varchar(255) default "BASIC"; + +alter table user + add column gg_coin integer default 0; + +alter table user + add column text_color varchar(10); + +alter table coin_history + add constraint fk_coin_history_user_user_id + foreign key (user_id) + references user (id); + +alter table coin_policy + add constraint fk_coin_policy_user_user_id + foreign key (user_id) + references user (id); + +alter table megaphone + add constraint fk_megaphone_user_user_id + foreign key (user_id) + references user (id); + +alter table ranks + add constraint fk_ranks_tier_tier_id + foreign key (tier_id) + references tier (id); + +alter table receipt + add constraint fk_receipt_item_item_id + foreign key (item_id) + references item (id); \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java new file mode 100644 index 000000000..bcc4734e8 --- /dev/null +++ b/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java @@ -0,0 +1,58 @@ +package com.gg.server.admin.coin.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class CoinAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("PUT /pingpong/admin/coin") + public void updateCoinTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String creatorId = userRepository.getById(userId).getIntraId(); + int beforeCoin = userRepository.getById(userId).getGgCoin(); + int changeCoin = 10; + CoinUpdateRequestDto coinUpdateRequestDto = new CoinUpdateRequestDto(creatorId, changeCoin, "관리자 코인 지급 테스트"); + mockMvc.perform(put("/pingpong/admin/coin").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(coinUpdateRequestDto))) + .andExpect(status().isNoContent()); + Assertions.assertThat(userRepository.getById(userId).getGgCoin()).isEqualTo(beforeCoin + changeCoin); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java new file mode 100644 index 000000000..5aa2cc706 --- /dev/null +++ b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java @@ -0,0 +1,60 @@ +package com.gg.server.admin.coin.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; +import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +public class CoinPolicyAdminControllerFailTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinPolicyAdminRepository coinPolicyAdminRepository; + + @Test + @DisplayName("[Post FAIL]/pingpong/admin/coinpolicy") + void addAnnouncement() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1,2,5,-1); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/coinpolicy"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java new file mode 100644 index 000000000..cce47e6b4 --- /dev/null +++ b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java @@ -0,0 +1,100 @@ +package com.gg.server.admin.coin.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; +import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; +import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; +import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; +import com.gg.server.domain.coin.data.CoinPolicy; +import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class CoinPolicyAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinPolicyAdminRepository coinPolicyAdminRepository; + + @Test + @DisplayName("[Get]/pingpong/admin/coinpolicy") + void getCoinPolicy() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 1; + Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 + + String url = "/pingpong/admin/coinpolicy?page=" + currentPage + "&size=" + pageSize; + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + CoinPolicyAdminListResponseDto result = objectMapper.readValue(contentAsString, CoinPolicyAdminListResponseDto.class); + assertThat(result.getCoinPolicyList().size()).isEqualTo(3); + System.out.println(result.getCoinPolicyList().get(0).getCoinPolicyId()); + System.out.println(result.getCoinPolicyList().get(0).getCreateUserId()); + System.out.println(result.getCoinPolicyList().get(0).getAttendance()); + System.out.println(result.getCoinPolicyList().get(0).getNormal()); + System.out.println(result.getCoinPolicyList().get(0).getRankWin()); + System.out.println(result.getCoinPolicyList().get(0).getRankLose()); + + } + + @Test + @DisplayName("[Post]/pingpong/admin/coinpolicy") + void addCoinPolicy() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1,2,5,0); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/coinpolicy"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + CoinPolicy result = coinPolicyAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new CoinPolicyNotFoundException()); + + assertThat(result.getAttendance()).isEqualTo(addDto.getAttendance()); + assertThat(result.getNormal()).isEqualTo(addDto.getNormal()); + assertThat(result.getRankWin()).isEqualTo(addDto.getRankWin()); + assertThat(result.getRankLose()).isEqualTo(addDto.getRankLose()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java b/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java index 571eb24ae..da6b005ef 100644 --- a/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java @@ -1,128 +1,128 @@ -package com.gg.server.admin.feedback.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.feedback.data.FeedbackAdminRepository; -import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@SpringBootTest -@AutoConfigureMockMvc -@Transactional -class FeedbackAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - FeedbackAdminRepository feedbackAdminRepository; - @Autowired - UserRepository userRepository; - - @Test - @DisplayName("[Get]/pingpong/admin/feedback") - void getFeedback() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 1; - Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 - - String url = "/pingpong/admin/feedback?page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - - FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); - assertThat(result.getFeedbackList().size()).isEqualTo(5); - System.out.println(result.getFeedbackList().get(0).getId()); - System.out.println(result.getFeedbackList().get(0).getContent()); - - } - - @Test - @DisplayName("[Patch]pingpong/admin/feedback/{id}") - void patchFeedback() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Feedback feedback = Feedback.builder() - .category(FeedbackType.ETC) - .content("test1234") - .user(userRepository.findById(userId).get()) - .build(); - feedbackAdminRepository.save(feedback); - - String url = "/pingpong/admin/feedback/" + feedback.getId().toString(); - Boolean status = feedback.getIsSolved(); - - String contentAsString = mockMvc.perform(patch(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - - } - - @Test - @DisplayName("[get]pingpong/admin/feedback?intraId=${intraId}&page=${pageNumber}&size={size}") - void findFeedbackByIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - User user = userRepository.findById(userId).get(); - - Feedback feedback = Feedback.builder() - .category(FeedbackType.ETC) - .content("test1234") - .user(user) - .build(); - feedbackAdminRepository.save(feedback); - - Integer currentPage = 1; - Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 - - String url = "/pingpong/admin/feedback?intraId=" + user.getIntraId() + "&page=" + currentPage + "&size=" + pageSize; - Boolean status = feedback.getIsSolved(); - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); - assertThat(result.getFeedbackList().size()).isBetween(0, 5); - assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); - assertThat(result.getFeedbackList().get(0).getContent()).isEqualTo("test1234"); - assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); - } +package com.gg.server.admin.feedback.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.feedback.data.FeedbackAdminRepository; +import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; +import com.gg.server.domain.feedback.data.Feedback; +import com.gg.server.domain.feedback.type.FeedbackType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class FeedbackAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + FeedbackAdminRepository feedbackAdminRepository; + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("[Get]/pingpong/admin/feedback") + void getFeedback() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 1; + Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 + + String url = "/pingpong/admin/feedback?page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + + FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); + assertThat(result.getFeedbackList().size()).isEqualTo(5); + System.out.println(result.getFeedbackList().get(0).getId()); + System.out.println(result.getFeedbackList().get(0).getContent()); + + } + + @Test + @DisplayName("[Patch]pingpong/admin/feedback/{id}") + void patchFeedback() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Feedback feedback = Feedback.builder() + .category(FeedbackType.ETC) + .content("test1234") + .user(userRepository.findById(userId).get()) + .build(); + feedbackAdminRepository.save(feedback); + + String url = "/pingpong/admin/feedback/" + feedback.getId().toString(); + Boolean status = feedback.getIsSolved(); + + String contentAsString = mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + + } + + @Test + @DisplayName("[get]pingpong/admin/feedback?intraId=${intraId}&page=${pageNumber}&size={size}") + void findFeedbackByIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + User user = userRepository.findById(userId).get(); + + Feedback feedback = Feedback.builder() + .category(FeedbackType.ETC) + .content("test1234") + .user(user) + .build(); + feedbackAdminRepository.save(feedback); + + Integer currentPage = 1; + Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 + + String url = "/pingpong/admin/feedback?intraId=" + user.getIntraId() + "&page=" + currentPage + "&size=" + pageSize; + Boolean status = feedback.getIsSolved(); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); + assertThat(result.getFeedbackList().size()).isBetween(0, 5); + assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); + assertThat(result.getFeedbackList().get(0).getContent()).isEqualTo("test1234"); + assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); + } } \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java b/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java index 8c1057d7f..f0c23b2a1 100644 --- a/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java @@ -1,183 +1,177 @@ -package com.gg.server.admin.game.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; -import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.dto.req.RankResultReqDto; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.dto.GameAddDto; -import com.gg.server.domain.match.service.GameUpdateService; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.DoubleStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.InstanceOfAssertFactories.completableFuture; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@SpringBootTest -@AutoConfigureMockMvc -@Transactional -class GameAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - GameRepository gameRepository; - - @Autowired - UserRepository userRepository; - - @Autowired - GameUpdateService gameUpdateService; - - @Autowired - GameService gameService; - - @Autowired - RankRepository rankRepository; - - @Autowired - RankRedisRepository rankRedisRepository; - - - @Test - @DisplayName("[Get]/pingpong/admin/games/users?intraId=${intraId}&page=${pageNumber}&size={sizeNum}") - void getUserGameList() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 2; - Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 - - String url = "/pingpong/admin/games/users?intraId=" - + "nheo" + "&page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - GameLogListAdminResponseDto result = objectMapper.readValue(contentAsString, GameLogListAdminResponseDto.class); - assertThat(result.getGameLogList().size()).isEqualTo(pageSize); - System.out.println(result.getGameLogList().get(0).getGameId()); - System.out.println(result.getGameLogList().get(0).getStartAt()); - System.out.println(result.getGameLogList().get(0).getMode()); - - } - - @Test - @DisplayName("[PUT] /pingpong/admin/games") - @Transactional - public void 관리자게임전적수정테스트() throws Exception { - String url = "/pingpong/admin/games"; - Mode currentMatchMode = Mode.RANK; - Season season = testDataUtils.createSeason(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long adminUserId = tokenProvider.getUserIdFromAccessToken(accessToken); - User adminUser = userRepository.findById(adminUserId).get(); - GameInfoDto game1Info = testDataUtils.createGame(adminUser, LocalDateTime.now().minusMinutes(5), LocalDateTime.now().plusMinutes(5), season, currentMatchMode); - - User enemyUser1 = userRepository.findById(game1Info.getEnemyUserId()).get(); - testDataUtils.createUserRank(adminUser, "adminUserMessage", season); - testDataUtils.createUserRank(enemyUser1, "enemy111UserMessage", season); - - RankResultReqDto rankResultReqDto = new RankResultReqDto(game1Info.getGameId(), - game1Info.getMyTeamId(), - 2, - game1Info.getEnemyTeamId(), - 1); - gameService.createRankResult(rankResultReqDto, adminUserId); - - Rank adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - Rank enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()).get(); - System.out.println("MANGO ADMIN1 before DB PPP : " + adminUserRank.getPpp()); - System.out.println("MANGO ENEMY1 before DB PPP : " + enemyUser1Rank.getPpp()); - - - RankGamePPPModifyReqDto modifyReqDto = new RankGamePPPModifyReqDto(game1Info.getMyTeamId(), 1, game1Info.getEnemyTeamId(), 0); - mockMvc.perform(put("/pingpong/admin/games/" + game1Info.getGameId()) - .content(objectMapper.writeValueAsString(modifyReqDto)) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - GameTeamUser historyGame1 = gameRepository.findTeamsByGameIsIn(List.of(game1Info.getGameId())).get(0); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()).get(); - System.out.println("MANGO ADMIN1 after DB PPP : " + adminUserRank.getPpp()); - System.out.println("MANGO ENEMY1 after DB PPP : " + enemyUser1Rank.getPpp()); - - ////////////////////////////// - Thread.sleep(1000); - ////////////////////////////// - GameInfoDto game2Info = testDataUtils.createGame(adminUser, LocalDateTime.now().minusMinutes(4), LocalDateTime.now().plusMinutes(6), season, currentMatchMode); - User enemyUser2 = userRepository.findById(game2Info.getEnemyUserId()).get(); - testDataUtils.createUserRank(adminUser, "adminUserMessage", season); - testDataUtils.createUserRank(enemyUser2, "enemy222UserMessage", season); - - rankResultReqDto = new RankResultReqDto(game2Info.getGameId(), - game2Info.getMyTeamId(), - 1, - game2Info.getEnemyTeamId(), - 2); - gameService.createRankResult(rankResultReqDto, adminUserId); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - Rank enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); - System.out.println("MANGO ADMIN2 before DB PPP : " + adminUserRank.getPpp()); - System.out.println("MANGO ENEMY2 before DB PPP : " + enemyUser2Rank.getPpp()); - - - modifyReqDto = new RankGamePPPModifyReqDto(game2Info.getMyTeamId(), 0, game2Info.getEnemyTeamId(), 1); - mockMvc.perform(put("/pingpong/admin/games/" + game2Info.getGameId()) - .content(objectMapper.writeValueAsString(modifyReqDto)) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); - System.out.println("MANGO ADMIN2 after DB PPP : " + adminUserRank.getPpp()); - System.out.println("MANGO ENEMY2 after DB PPP : " + enemyUser2Rank.getPpp()); - } +package com.gg.server.admin.game.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; +import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.GameTeamUser; +import com.gg.server.domain.game.dto.req.RankResultReqDto; +import com.gg.server.domain.game.service.GameService; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.match.service.GameUpdateService; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.controller.dto.GameInfoDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class GameAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + GameRepository gameRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + GameUpdateService gameUpdateService; + + @Autowired + GameService gameService; + + @Autowired + RankRepository rankRepository; + + @Autowired + RankRedisRepository rankRedisRepository; + + + @Test + @DisplayName("[Get]/pingpong/admin/games/users?intraId=${intraId}&page=${pageNumber}&size={sizeNum}") + void getUserGameList() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 2; + Integer pageSize = 5;//페이지 사이즈 크기가 실제 디비 정보보다 큰지 확인할 것 + + String url = "/pingpong/admin/games/users?intraId=" + + "nheo" + "&page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + GameLogListAdminResponseDto result = objectMapper.readValue(contentAsString, GameLogListAdminResponseDto.class); + assertThat(result.getGameLogList().size()).isEqualTo(pageSize); + System.out.println(result.getGameLogList().get(0).getGameId()); + System.out.println(result.getGameLogList().get(0).getStartAt()); + System.out.println(result.getGameLogList().get(0).getMode()); + + } + + @Test + @DisplayName("[PUT] /pingpong/admin/games") + @Transactional + public void 관리자게임전적수정테스트() throws Exception { + String url = "/pingpong/admin/games"; + Mode currentMatchMode = Mode.RANK; + Season season = testDataUtils.createSeason(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long adminUserId = tokenProvider.getUserIdFromAccessToken(accessToken); + User adminUser = userRepository.findById(adminUserId).get(); + GameInfoDto game1Info = testDataUtils.createGame(adminUser, LocalDateTime.now().minusMinutes(5), LocalDateTime.now().plusMinutes(5), season, currentMatchMode); + + User enemyUser1 = userRepository.findById(game1Info.getEnemyUserId()).get(); + testDataUtils.createUserRank(adminUser, "adminUserMessage", season); + testDataUtils.createUserRank(enemyUser1, "enemy111UserMessage", season); + + RankResultReqDto rankResultReqDto = new RankResultReqDto(game1Info.getGameId(), + game1Info.getMyTeamId(), + 2, + game1Info.getEnemyTeamId(), + 1); + gameService.createRankResult(rankResultReqDto, adminUserId); + + Rank adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + Rank enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()).get(); + System.out.println("MANGO ADMIN1 before DB PPP : " + adminUserRank.getPpp()); + System.out.println("MANGO ENEMY1 before DB PPP : " + enemyUser1Rank.getPpp()); + + + RankGamePPPModifyReqDto modifyReqDto = new RankGamePPPModifyReqDto(game1Info.getMyTeamId(), 1, game1Info.getEnemyTeamId(), 0); + mockMvc.perform(put("/pingpong/admin/games/" + game1Info.getGameId()) + .content(objectMapper.writeValueAsString(modifyReqDto)) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + GameTeamUser historyGame1 = gameRepository.findTeamsByGameIsIn(List.of(game1Info.getGameId())).get(0); + + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()).get(); + System.out.println("MANGO ADMIN1 after DB PPP : " + adminUserRank.getPpp()); + System.out.println("MANGO ENEMY1 after DB PPP : " + enemyUser1Rank.getPpp()); + + ////////////////////////////// + Thread.sleep(1000); + ////////////////////////////// + GameInfoDto game2Info = testDataUtils.createGame(adminUser, LocalDateTime.now().minusMinutes(4), LocalDateTime.now().plusMinutes(6), season, currentMatchMode); + User enemyUser2 = userRepository.findById(game2Info.getEnemyUserId()).get(); + testDataUtils.createUserRank(adminUser, "adminUserMessage", season); + testDataUtils.createUserRank(enemyUser2, "enemy222UserMessage", season); + + rankResultReqDto = new RankResultReqDto(game2Info.getGameId(), + game2Info.getMyTeamId(), + 1, + game2Info.getEnemyTeamId(), + 2); + gameService.createRankResult(rankResultReqDto, adminUserId); + + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + Rank enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); + System.out.println("MANGO ADMIN2 before DB PPP : " + adminUserRank.getPpp()); + System.out.println("MANGO ENEMY2 before DB PPP : " + enemyUser2Rank.getPpp()); + + + modifyReqDto = new RankGamePPPModifyReqDto(game2Info.getMyTeamId(), 0, game2Info.getEnemyTeamId(), 1); + mockMvc.perform(put("/pingpong/admin/games/" + game2Info.getGameId()) + .content(objectMapper.writeValueAsString(modifyReqDto)) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); + System.out.println("MANGO ADMIN2 after DB PPP : " + adminUserRank.getPpp()); + System.out.println("MANGO ENEMY2 after DB PPP : " + enemyUser2Rank.getPpp()); + } } \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java b/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java new file mode 100644 index 000000000..69e3aa86f --- /dev/null +++ b/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java @@ -0,0 +1,108 @@ +package com.gg.server.admin.item.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.item.data.ItemAdminRepository; +import com.gg.server.admin.item.dto.ItemListResponseDto; +import com.gg.server.admin.item.service.ItemAdminService; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; + + +import javax.transaction.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class ItemAdminControllerTest { + @Autowired + ItemAdminService itemAdminService; + @Autowired + UserRepository userRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + ItemAdminRepository itemAdminRepository; + @Autowired + MockMvc mockMvc; + + @Test + @DisplayName("GET /pingpong/admin/items/history") + public void getAllItemHistoryTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + String url = "/pingpong/admin/items/history?page=" + page + "&size=" + size; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + ItemListResponseDto expect = itemAdminService.getAllItemHistory(pageable); + System.out.println(expect.getHistoryList()); + ItemListResponseDto result = objectMapper.readValue(contentAsString, ItemListResponseDto.class); + System.out.println(expect.getHistoryList().get(0)); + System.out.println(result.getHistoryList().get(0)); + assertThat(result.getHistoryList().get(0).getItemId()); + assertThat(result.getHistoryList().get(0).getName()); + assertThat(result.getHistoryList().get(0).getMainContent()); + assertThat(result.getHistoryList().get(0).getSubContent()); + assertThat(result.getHistoryList().get(0).getPrice()); + } + + @Test + @DisplayName("PUT /pingpong/admin/items/history/{itemId}") + public void updateItemTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String creatorId = userRepository.getById(userId).getIntraId(); + MockMultipartFile image = new MockMultipartFile("file", "imagefile.jpeg", "image/jpeg", "<>".getBytes()); + MockMultipartFile jsonFile = new MockMultipartFile("itemRequestDto", "", "application/json", "{\"name\": \"TEST\", \"content\": \"TESTING\", \"price\": 42, \"discount\": 50, \"itemType\": \"MEGAPHONE\"}".getBytes()); + String contentAsString = mockMvc.perform(multipart("/pingpong/admin/items/{itemId}", 1) + .file(image) + .file(jsonFile) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("DELETE /pingpong/admin/items/{itemId}") + public void deleteItemTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String deleterId = userRepository.getById(userId).getIntraId(); + String contentAsString = mockMvc.perform(delete("/pingpong/admin/items/{itemId}", 1) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + List list = itemAdminRepository.findAll(); + assertThat(list.get(0).getDeleterIntraId()).isEqualTo(deleterId); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java b/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java new file mode 100644 index 000000000..27b671f0a --- /dev/null +++ b/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java @@ -0,0 +1,44 @@ +package com.gg.server.admin.megaphone.controller; + +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +class MegaphoneAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + AuthTokenProvider tokenProvider; + + @Test + @DisplayName("[GET] /pingpong/admin/megaphones/history?page={page}&size={pageSize}&intraId={intraId}") + void getMegaphoneListTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/admin/megaphones/history?page=1&size=30"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java b/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java index d6c5b4e40..2daaec8bf 100644 --- a/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java @@ -1,146 +1,142 @@ -package com.gg.server.admin.noti.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.noti.data.NotiAdminRepository; -import com.gg.server.admin.noti.dto.NotiAdminDto; -import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.dto.NotiListResponseDto; -import com.gg.server.domain.noti.dto.NotiResponseDto; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.web.servlet.MockMvc; - -import javax.transaction.Transactional; - -import java.util.List; -import java.util.UUID; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@SpringBootTest -@AutoConfigureMockMvc -class NotiAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - NotiAdminService notiAdminService; - @Autowired - NotiAdminRepository notiAdminRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - - @Test - @DisplayName("GET /pingpong/admin/notifications") - @Transactional - public void getAllNotiTest() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - String testMessage = "Test notification"; - notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(user.getIntraId(), testMessage)); - String url = "/pingpong/admin/notifications?page=1&size=20"; - String url2 = "/pingpong/admin/notifications?page=1&q=\"" + user.getIntraId() + "\""; - - //when - //200 성공(전체조회) - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); - //200 성공(검색조회) - String contentAsString2 = mockMvc.perform(get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); - Pageable pageable = PageRequest.of(0, 20); - Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending()); - - //then - List notiList1 = notiAdminRepository.findAll(pageable).getContent(); - List expectedNotiAdminDtoList = actureResponse1.getNotiList(); - for (int i = 0; i < notiList1.size(); i++) { - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIntraId()).isEqualTo(expectedNotiAdminDtoList.get(i).getIntraId()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getMessage()).isEqualTo(expectedNotiAdminDtoList.get(i).getMessage()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIsChecked()).isEqualTo(expectedNotiAdminDtoList.get(i).getIsChecked()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getType()).isEqualTo(expectedNotiAdminDtoList.get(i).getType()); - } - - List notiList2 = notiRepository.findByUser(user); - Assertions.assertThat(notiList2.size()).isEqualTo(1); - Noti expectedNoti2 = notiList2.get(0); - NotiAdminDto actureNotiResponseDto2 = actureResponse2.getNotiList().get(0); - Assertions.assertThat(expectedNoti2.getUser().getIntraId()).isEqualTo(actureNotiResponseDto2.getIntraId()); - Assertions.assertThat(expectedNoti2.getMessage()).isEqualTo(testMessage); - Assertions.assertThat(expectedNoti2.getIsChecked()).isFalse(); - Assertions.assertThat(expectedNoti2.getType()).isEqualTo(NotiType.ANNOUNCE); - } - - @Test - @DisplayName("POST /pingpong/admin/notifications") - @Transactional - public void sendNotiToUserTest() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - String url = "/pingpong/admin/notifications"; - String wrongIntraId = UUID.randomUUID().toString().substring(0, 30); - String expectedMessage = "test 알림 message "; - - //when - //201 성공 - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(user.getIntraId(), expectedMessage)))) - .andExpect(status().isCreated()); - - //404 존재하지 않는 intraId - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(wrongIntraId, expectedMessage)))) - .andExpect(status().isNotFound()); - - //then - List notiList = notiRepository.findByUser(user); - Assertions.assertThat(notiList.size()).isEqualTo(1); - Noti actureNoti = notiList.get(0); - Assertions.assertThat(actureNoti.getUser()).isEqualTo(user); - Assertions.assertThat(actureNoti.getMessage()).isEqualTo(expectedMessage); - Assertions.assertThat(actureNoti.getIsChecked()).isFalse(); - Assertions.assertThat(actureNoti.getType()).isEqualTo(NotiType.ANNOUNCE); - } -} +package com.gg.server.admin.noti.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.noti.data.NotiAdminRepository; +import com.gg.server.admin.noti.dto.NotiAdminDto; +import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; +import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; +import com.gg.server.admin.noti.service.NotiAdminService; +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import javax.transaction.Transactional; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +class NotiAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + NotiAdminService notiAdminService; + @Autowired + NotiAdminRepository notiAdminRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + + @Test + @DisplayName("GET /pingpong/admin/notifications") + @Transactional + public void getAllNotiTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + String testMessage = "Test notification"; + notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(user.getIntraId(), testMessage)); + String url = "/pingpong/admin/notifications?page=1&size=20"; + String url2 = "/pingpong/admin/notifications?page=1&q=\"" + user.getIntraId() + "\""; + + //when + //200 성공(전체조회) + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); + //200 성공(검색조회) + String contentAsString2 = mockMvc.perform(get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); + Pageable pageable = PageRequest.of(0, 20); + Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending()); + + //then + List notiList1 = notiAdminRepository.findAll(pageable).getContent(); + List expectedNotiAdminDtoList = actureResponse1.getNotiList(); + for (int i = 0; i < notiList1.size(); i++) { + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIntraId()).isEqualTo(expectedNotiAdminDtoList.get(i).getIntraId()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getMessage()).isEqualTo(expectedNotiAdminDtoList.get(i).getMessage()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIsChecked()).isEqualTo(expectedNotiAdminDtoList.get(i).getIsChecked()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getType()).isEqualTo(expectedNotiAdminDtoList.get(i).getType()); + } + + List notiList2 = notiRepository.findByUser(user); + Assertions.assertThat(notiList2.size()).isEqualTo(1); + Noti expectedNoti2 = notiList2.get(0); + NotiAdminDto actureNotiResponseDto2 = actureResponse2.getNotiList().get(0); + Assertions.assertThat(expectedNoti2.getUser().getIntraId()).isEqualTo(actureNotiResponseDto2.getIntraId()); + Assertions.assertThat(expectedNoti2.getMessage()).isEqualTo(testMessage); + Assertions.assertThat(expectedNoti2.getIsChecked()).isFalse(); + Assertions.assertThat(expectedNoti2.getType()).isEqualTo(NotiType.ANNOUNCE); + } + + @Test + @DisplayName("POST /pingpong/admin/notifications") + @Transactional + public void sendNotiToUserTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + String url = "/pingpong/admin/notifications"; + String wrongIntraId = UUID.randomUUID().toString().substring(0, 30); + String expectedMessage = "test 알림 message "; + + //when + //201 성공 + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(user.getIntraId(), expectedMessage)))) + .andExpect(status().isCreated()); + + //404 존재하지 않는 intraId + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(wrongIntraId, expectedMessage)))) + .andExpect(status().isNotFound()); + + //then + List notiList = notiRepository.findByUser(user); + Assertions.assertThat(notiList.size()).isEqualTo(1); + Noti actureNoti = notiList.get(0); + Assertions.assertThat(actureNoti.getUser()).isEqualTo(user); + Assertions.assertThat(actureNoti.getMessage()).isEqualTo(expectedMessage); + Assertions.assertThat(actureNoti.getIsChecked()).isFalse(); + Assertions.assertThat(actureNoti.getType()).isEqualTo(NotiType.ANNOUNCE); + } +} diff --git a/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java b/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java index 454ed782e..b70cad13b 100644 --- a/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java @@ -1,355 +1,355 @@ -package com.gg.server.admin.penalty.controller; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; -import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; -import com.gg.server.admin.penalty.dto.PenaltyRequestDto; -import com.gg.server.admin.penalty.service.PenaltyAdminService; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.http.MediaType; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@SpringBootTest -@AutoConfigureMockMvc -@ActiveProfiles("local") -@Transactional -class PenaltyAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @Autowired - UserRepository userRepository; - @Autowired - PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; - @Autowired - PenaltyAdminRepository penaltyAdminRepository; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - RedisConnectionFactory redisConnectionFactory; - @Autowired - PenaltyAdminService penaltyAdminService; - - private final String headUrl = "/pingpong/admin/"; - - @AfterEach - void clear() { - RedisConnection connection = redisConnectionFactory.getConnection(); - connection.flushDb(); - connection.close(); - } - - @Test - @DisplayName("POST : penalty를 부여받지 않은 유효한 intraId에 penalty 부여") - public void giveUserPenaltyforFirstTimeWithValidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty"; - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().isCreated()); - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - //redis - Assertions.assertThat(penaltyUser).isPresent(); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(3 * 60); - Assertions.assertThat( - Duration.between(penaltyUser.get().getStartTime(), - penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(3 * 60 * 60); - Assertions.assertThat(penaltyUser.get().getReason()); - //mySQL - List penalties = penaltyAdminRepository.findAll(); - Assertions.assertThat(penalties.stream().anyMatch(ele -> ele.getUser().getIntraId().equals(intraId) - && ele.getPenaltyTime().equals(3 * 60))).isEqualTo(true); - } - - @Test - @DisplayName("POST : penalty를 부여받은 유효한 intraId에 penalty 부여") - public void giveUserPenaltyRepeatablyWithValidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty"; - //패널티 두번 부여 - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().isCreated()); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 2, "test2")))) - .andExpect(status().isCreated()); - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - //redis 확인 - Assertions.assertThat(penaltyUser).isPresent(); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(5 * 60); - Assertions.assertThat( - Duration.between(penaltyUser.get().getStartTime(), - penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(5 * 60 * 60); - Assertions.assertThat(penaltyUser.get().getReason()); - //mySQL 확인 - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Assertions.assertThat(userPenalties.size()).isEqualTo(2); - Duration duration = Duration.between(userPenalties.get(0).getStartTime(), userPenalties.get(1).getStartTime()); - Assertions.assertThat(duration.getSeconds()).isEqualTo(3 * 60 * 60); - } - - - @Test - @DisplayName("POST 유효하지 않은 intraId에 penalty 부여") - public void giveUserPenaltyWithInvalidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - String intraId = "invalid!"; - String url = "/pingpong/admin/penalty"; - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().is4xxClientError()); - } - - @Test - @DisplayName("GET pagination 유효성 검사") - public void checkPagination() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 20명 넣고 테스트 - for (int i = 0; i < 20; i++) { - User newUser = testDataUtils.createNewUser(); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } - - @Test - @DisplayName("GET parameter 유효성 검사") - public void checkInputException() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/admin/penalty?page=-1&size=10¤t=false"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); - String url2 = "/pingpong/admin/penalty?page=2&size=0¤t=false"; - String contentAsString2 = mockMvc.perform( - get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("GET pagination keyword 유효성 검사") - public void checkPaginationWithKeyword() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 40명 넣고 테스트 - //그중 20명만 intraId에 test포함 - for (int i = 0; i < 20; i++) { - String intraId = UUID.randomUUID().toString().substring(0, 4) + "test" + UUID.randomUUID().toString() - .substring(0, 4); - User newUser = testDataUtils.createNewUser(intraId, "test", "test", RacketType.NONE, SnsType.EMAIL, - RoleType.USER); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - for (int i = 0; i < 20; i++) { - String intraId = "dummy" + String.valueOf(i); - User newUser = testDataUtils.createNewUser(intraId, "test", "test", RacketType.NONE, SnsType.EMAIL, - RoleType.USER); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true&intraId=test"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } - - @Test - @DisplayName("DELETE 패널티 삭제 - 유저 패널티가 1번만 부과된 경우") - public void deleteExistPenaltyUser() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - penaltyAdminService.givePenalty(intraId, 3, "test!"); - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Long penaltyId = userPenalties.get(0).getId(); - String url = "/pingpong/admin/penalty/" + penaltyId.toString(); - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()); - //Redis에 penaltyUser 없는지 확인 - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - Assertions.assertThat(penaltyUser).isEmpty(); - //MySQL에 penalty 없는지 확인 - List afterPenalties = penaltyAdminRepository.findAll(); - boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); - Assertions.assertThat(isPresent).isEqualTo(false); - } - - @Test - @DisplayName("DELETE 패널티 삭제 - 유저 패널티가 2번 부과된 경우") - public void deleteExistPenaltyUserOfTwicePenalty() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - penaltyAdminService.givePenalty(intraId, 3, "test!"); - penaltyAdminService.givePenalty(intraId, 2, "test2"); - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Long penaltyId = userPenalties.get(0).getId(); - String url = "/pingpong/admin/penalty/" + penaltyId.toString(); - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()); - //Redis에 penaltyUser 있는지 확인 - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(2 * 60); - - //MySQL에 penalty 없는지 확인 - List afterPenalties = penaltyAdminRepository.findAll(); - boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); - Assertions.assertThat(isPresent).isEqualTo(false); - } - - @Test - @DisplayName("DELETE 존재하지 않는 패널티 유저 삭제") - public void deleteInvalidPenaltyUser() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //user에 패널티는 부여하지 않는다. - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty/users/" + intraId; - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()); - } - - @Test - @DisplayName("DELETE 존재하지 않는 패널티 유저 삭제") - public void deleteInvalidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //30자 이상 - String intraId = UUID.randomUUID().toString(); - String url = "/pingpong/admin/penalty/users/" + intraId; - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()); - } - - @Test - @DisplayName("get pingpong/admin/penalty?page={page}&size={pageSize}¤t=true") - public void getCurrentPenalties() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 20명 넣고 테스트 - for (int i = 0; i < 20; i++) { - User newUser = testDataUtils.createNewUser(); - users.add(newUser); - } - - //과거 penalty들 db에 저장 - for (int i = 0; i < 20; i++) { - Penalty penalty = new Penalty(users.get(i), PenaltyType.NOSHOW, "test", LocalDateTime.now().minusHours(3), 120); - penaltyAdminRepository.save(penalty); - } - - //현재 패널티 부여 - for (int i = 0; i < 20; i++) { - penaltyAdminService.givePenalty(users.get(i).getIntraId(), 3, "test" + String.valueOf(i)); - } - - - - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } -} +package com.gg.server.admin.penalty.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.penalty.data.PenaltyAdminRepository; +import com.gg.server.domain.penalty.data.Penalty; +import com.gg.server.domain.penalty.redis.RedisPenaltyUser; +import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; +import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; +import com.gg.server.admin.penalty.dto.PenaltyRequestDto; +import com.gg.server.admin.penalty.service.PenaltyAdminService; +import com.gg.server.domain.penalty.type.PenaltyType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles("local") +@Transactional +class PenaltyAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + UserRepository userRepository; + @Autowired + PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; + @Autowired + PenaltyAdminRepository penaltyAdminRepository; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RedisConnectionFactory redisConnectionFactory; + @Autowired + PenaltyAdminService penaltyAdminService; + + private final String headUrl = "/pingpong/admin/"; + + @AfterEach + void clear() { + RedisConnection connection = redisConnectionFactory.getConnection(); + connection.flushDb(); + connection.close(); + } + + @Test + @DisplayName("POST : penalty를 부여받지 않은 유효한 intraId에 penalty 부여") + public void giveUserPenaltyforFirstTimeWithValidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty"; + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().isCreated()); + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + //redis + Assertions.assertThat(penaltyUser).isPresent(); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(3 * 60); + Assertions.assertThat( + Duration.between(penaltyUser.get().getStartTime(), + penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(3 * 60 * 60); + Assertions.assertThat(penaltyUser.get().getReason()); + //mySQL + List penalties = penaltyAdminRepository.findAll(); + Assertions.assertThat(penalties.stream().anyMatch(ele -> ele.getUser().getIntraId().equals(intraId) + && ele.getPenaltyTime().equals(3 * 60))).isEqualTo(true); + } + + @Test + @DisplayName("POST : penalty를 부여받은 유효한 intraId에 penalty 부여") + public void giveUserPenaltyRepeatablyWithValidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty"; + //패널티 두번 부여 + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().isCreated()); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 2, "test2")))) + .andExpect(status().isCreated()); + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + //redis 확인 + Assertions.assertThat(penaltyUser).isPresent(); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(5 * 60); + Assertions.assertThat( + Duration.between(penaltyUser.get().getStartTime(), + penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(5 * 60 * 60); + Assertions.assertThat(penaltyUser.get().getReason()); + //mySQL 확인 + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Assertions.assertThat(userPenalties.size()).isEqualTo(2); + Duration duration = Duration.between(userPenalties.get(0).getStartTime(), userPenalties.get(1).getStartTime()); + Assertions.assertThat(duration.getSeconds()).isEqualTo(3 * 60 * 60); + } + + + @Test + @DisplayName("POST 유효하지 않은 intraId에 penalty 부여") + public void giveUserPenaltyWithInvalidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String intraId = "invalid!"; + String url = "/pingpong/admin/penalty"; + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().is4xxClientError()); + } + + @Test + @DisplayName("GET pagination 유효성 검사") + public void checkPagination() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 20명 넣고 테스트 + for (int i = 0; i < 20; i++) { + User newUser = testDataUtils.createNewUser(); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } + + @Test + @DisplayName("GET parameter 유효성 검사") + public void checkInputException() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/admin/penalty?page=-1&size=10¤t=false"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); + String url2 = "/pingpong/admin/penalty?page=2&size=0¤t=false"; + String contentAsString2 = mockMvc.perform( + get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("GET pagination keyword 유효성 검사") + public void checkPaginationWithKeyword() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 40명 넣고 테스트 + //그중 20명만 intraId에 test포함 + for (int i = 0; i < 20; i++) { + String intraId = UUID.randomUUID().toString().substring(0, 4) + "test" + UUID.randomUUID().toString() + .substring(0, 4); + User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, + RoleType.USER); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + for (int i = 0; i < 20; i++) { + String intraId = "dummy" + String.valueOf(i); + User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, + RoleType.USER); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true&intraId=test"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } + + @Test + @DisplayName("DELETE 패널티 삭제 - 유저 패널티가 1번만 부과된 경우") + public void deleteExistPenaltyUser() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + penaltyAdminService.givePenalty(intraId, 3, "test!"); + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Long penaltyId = userPenalties.get(0).getId(); + String url = "/pingpong/admin/penalty/" + penaltyId.toString(); + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + //Redis에 penaltyUser 없는지 확인 + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + Assertions.assertThat(penaltyUser).isEmpty(); + //MySQL에 penalty 없는지 확인 + List afterPenalties = penaltyAdminRepository.findAll(); + boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); + Assertions.assertThat(isPresent).isEqualTo(false); + } + + @Test + @DisplayName("DELETE 패널티 삭제 - 유저 패널티가 2번 부과된 경우") + public void deleteExistPenaltyUserOfTwicePenalty() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + penaltyAdminService.givePenalty(intraId, 3, "test!"); + penaltyAdminService.givePenalty(intraId, 2, "test2"); + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Long penaltyId = userPenalties.get(0).getId(); + String url = "/pingpong/admin/penalty/" + penaltyId.toString(); + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + //Redis에 penaltyUser 있는지 확인 + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(2 * 60); + + //MySQL에 penalty 없는지 확인 + List afterPenalties = penaltyAdminRepository.findAll(); + boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); + Assertions.assertThat(isPresent).isEqualTo(false); + } + + @Test + @DisplayName("DELETE 존재하지 않는 패널티 유저 삭제") + public void deleteInvalidPenaltyUser() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //user에 패널티는 부여하지 않는다. + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty/users/" + intraId; + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()); + } + + @Test + @DisplayName("DELETE 존재하지 않는 패널티 유저 삭제") + public void deleteInvalidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //30자 이상 + String intraId = UUID.randomUUID().toString(); + String url = "/pingpong/admin/penalty/users/" + intraId; + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()); + } + + @Test + @DisplayName("get pingpong/admin/penalty?page={page}&size={pageSize}¤t=true") + public void getCurrentPenalties() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 20명 넣고 테스트 + for (int i = 0; i < 20; i++) { + User newUser = testDataUtils.createNewUser(); + users.add(newUser); + } + + //과거 penalty들 db에 저장 + for (int i = 0; i < 20; i++) { + Penalty penalty = new Penalty(users.get(i), PenaltyType.NOSHOW, "test", LocalDateTime.now().minusHours(3), 120); + penaltyAdminRepository.save(penalty); + } + + //현재 패널티 부여 + for (int i = 0; i < 20; i++) { + penaltyAdminService.givePenalty(users.get(i).getIntraId(), 3, "test" + String.valueOf(i)); + } + + + + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } +} diff --git a/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java b/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java new file mode 100644 index 000000000..e61870fa9 --- /dev/null +++ b/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java @@ -0,0 +1,83 @@ +package com.gg.server.admin.receipt.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.receipt.data.ReceiptAdminRepository; +import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; +import com.gg.server.admin.receipt.service.ReceiptAdminService; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class ReceiptAdminControllerTest { + @Autowired + ReceiptAdminService receiptAdminService; + @Autowired + ReceiptAdminRepository receiptAdminRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + MockMvc mockMvc; + + @Test + @DisplayName("GET /pingpong/admin/receipt/list") + public void getAllReceipt() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + String url = "/pingpong/admin/receipt/list?page=" + page + "&size=" + size; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + ReceiptListResponseDto expect = receiptAdminService.getAllReceipt(pageable); + ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); + assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo(expect.getReceiptList().get(0).getReceiptId()); + assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo(expect.getReceiptList().get(0).getCreatedAt()); + assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo(expect.getReceiptList().get(0).getItemName()); + assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo(expect.getReceiptList().get(0).getItemPrice()); + } + + @Test + @DisplayName("GET /pingpong/admin/receipt/list") + public void findByIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + String intraId = "sishin"; + String url = "/pingpong/admin/receipt/list?page=" + page + "&size=" + size + "&intraId=" + intraId; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + ReceiptListResponseDto expect = receiptAdminService.findByIntraId(intraId, pageable); + ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); + assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo(expect.getReceiptList().get(0).getReceiptId()); + assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo(expect.getReceiptList().get(0).getCreatedAt()); + assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo(expect.getReceiptList().get(0).getItemName()); + assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo(expect.getReceiptList().get(0).getItemPrice()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java b/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java index 8e5d801b2..740c1ac39 100644 --- a/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java @@ -200,4 +200,28 @@ void updateSeasons() throws Exception { assertThat(seasonAdminRepository.findById(dbSeasonId).get().getSeasonName()) .isEqualTo(seasonUpdateRequestDto.getSeasonName()); } + + @Test + @DisplayName("Fail[Put]/pingpong/admin/seasons/{seasonId}") + void failUpdateSeasons() throws Exception {//현재 시즌을 변경할 때 400번대 상태코드 반환 + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Long nowSeasonId = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).get().getId(); + SeasonUpdateRequestDto seasonUpdateRequestDto = new SeasonUpdateRequestDto( + "putSeasonTestName", + LocalDateTime.now().plusHours(25), + 1000, + 500); + + String content = objectMapper.writeValueAsString(seasonUpdateRequestDto); + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/pingpong/admin/seasons/" + nowSeasonId) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError())//403반환 + .andReturn().getResponse().getContentAsString(); + + } } \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java b/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java index cbf95c49f..2393b08e0 100644 --- a/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java +++ b/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java @@ -1,147 +1,238 @@ -package com.gg.server.admin.user.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.admin.user.dto.UserDetailAdminResponseDto; -import com.gg.server.admin.user.dto.UserSearchAdminDto; -import com.gg.server.admin.user.dto.UserSearchAdminResponseDto; -import com.gg.server.admin.user.service.UserAdminService; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.test.web.servlet.MockMvc; - -import javax.transaction.Transactional; - -import java.util.List; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@SpringBootTest -@AutoConfigureMockMvc -class UserAdminControllerTest { - - @Autowired - UserAdminService userAdminService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - UserAdminRepository userAdminRepository; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - - @Test - @DisplayName("GET /pingpong/admin/users") - @Transactional - public void userSearchAllTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - int page = 1; - int size = 20; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); - String url = "/pingpong/admin/users?page=1"; - String url2 = "/pingpong/admin/users?page=1&intraId=" + user.getIntraId(); - //when - //200 성공 - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - //200 성공 - contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - - //then - List userList1 = userAdminRepository.findAll(pageable).getContent(); - List actureUserList1 = actureResponse1.getUserSearchAdminDtos(); - for (int i = 0; i < userList1.size(); i++) { - Assertions.assertThat(userList1.get(i).getIntraId()).isEqualTo(actureUserList1.get(i).getIntraId()); - } - - List userList2 = userAdminRepository.findAll(pageable).getContent(); - List actureUserList2 = actureResponse2.getUserSearchAdminDtos(); - for (int i = 0; i < userList1.size(); i++) { - Assertions.assertThat(userList2.get(i).getIntraId()).isEqualTo(actureUserList2.get(i).getIntraId()); - } - } - - @Test - @DisplayName("유저 필터링 조회 테스트") - @Transactional - public void 유저필터링조회테스트() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - int page = 1; - int size = 20; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); - String url = "/pingpong/admin/users?page=1&userFilter=\"" + user.getIntraId() + "\""; - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - - List actureUserList = actureResponse.getUserSearchAdminDtos(); - for (UserSearchAdminDto userDto : actureUserList) - Assertions.assertThat(userDto.getIntraId()).isEqualTo(user.getIntraId()); - } - - @Test - @DisplayName("GET /pingpong/admin/users/{intraId}") - @Transactional - public void userGetDetailTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findByIntraId("nheo").get(); - String url = "/pingpong/admin/users/" + user.getIntraId(); - UserDetailAdminResponseDto expectedResponse = userAdminService.getUserDetailByIntraId(user.getIntraId()); - - //when - //200 성공 - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserDetailAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserDetailAdminResponseDto.class); - - //then - Assertions.assertThat(actureResponse.getUserId()).isEqualTo(expectedResponse.getUserId()); - Assertions.assertThat(actureResponse.getIntraId()).isEqualTo(expectedResponse.getIntraId()); - Assertions.assertThat(actureResponse.getUserImageUri()).isEqualTo(expectedResponse.getUserImageUri()); - Assertions.assertThat(actureResponse.getRacketType()).isEqualTo(expectedResponse.getRacketType()); -// Assertions.assertThat(actureResponse.getStatusMessage()).isEqualTo(expecxtedResponse.getStatusMessage()); - Assertions.assertThat(actureResponse.getWins()).isEqualTo(expectedResponse.getWins()); - Assertions.assertThat(actureResponse.getLosses()).isEqualTo(expectedResponse.getLosses()); - Assertions.assertThat(actureResponse.getPpp()).isEqualTo(expectedResponse.getPpp()); - Assertions.assertThat(actureResponse.getEmail()).isEqualTo(expectedResponse.getEmail()); - Assertions.assertThat(actureResponse.getRoleType()).isEqualTo(expectedResponse.getRoleType()); - Assertions.assertThat(actureResponse.getExp()).isEqualTo(expectedResponse.getExp()); - } +package com.gg.server.admin.user.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.admin.user.data.UserAdminRepository; +import com.gg.server.admin.user.data.UserImageAdminRepository; +import com.gg.server.admin.user.dto.*; +import com.gg.server.admin.user.service.UserAdminService; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.web.servlet.MockMvc; + +import javax.transaction.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +class UserAdminControllerTest { + + @Autowired + UserAdminService userAdminService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + UserAdminRepository userAdminRepository; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + UserImageAdminRepository userImageAdminRepository; + + @Test + @DisplayName("GET /pingpong/admin/users") + @Transactional + public void userSearchAllTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + int page = 1; + int size = 20; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); + String url = "/pingpong/admin/users?page=1"; + String url2 = "/pingpong/admin/users?page=1&intraId=" + user.getIntraId(); + //when + //200 성공 + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); + //200 성공 + contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); + + //then + List userList1 = userAdminRepository.findAll(pageable).getContent(); + List actureUserList1 = actureResponse1.getUserSearchAdminDtos(); + for (int i = 0; i < userList1.size(); i++) { + Assertions.assertThat(userList1.get(i).getIntraId()).isEqualTo(actureUserList1.get(i).getIntraId()); + } + + List userList2 = userAdminRepository.findAll(pageable).getContent(); + List actureUserList2 = actureResponse2.getUserSearchAdminDtos(); + for (int i = 0; i < userList1.size(); i++) { + Assertions.assertThat(userList2.get(i).getIntraId()).isEqualTo(actureUserList2.get(i).getIntraId()); + } + } + + @Test + @DisplayName("유저 필터링 조회 테스트") + @Transactional + public void 유저필터링조회테스트() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + int page = 1; + int size = 20; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); + String url = "/pingpong/admin/users?page=1&userFilter=\"" + user.getIntraId() + "\""; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); + + List actureUserList = actureResponse.getUserSearchAdminDtos(); + for (UserSearchAdminDto userDto : actureUserList) + Assertions.assertThat(userDto.getIntraId()).isEqualTo(user.getIntraId()); + } + + @Test + @DisplayName("GET /pingpong/admin/users/{intraId}") + @Transactional + public void userGetDetailTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findByIntraId("nheo").get(); + String url = "/pingpong/admin/users/" + user.getIntraId(); + UserDetailAdminResponseDto expectedResponse = userAdminService.getUserDetailByIntraId(user.getIntraId()); + + //when + //200 성공 + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserDetailAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserDetailAdminResponseDto.class); + + //then + Assertions.assertThat(actureResponse.getUserId()).isEqualTo(expectedResponse.getUserId()); + Assertions.assertThat(actureResponse.getIntraId()).isEqualTo(expectedResponse.getIntraId()); + Assertions.assertThat(actureResponse.getUserImageUri()).isEqualTo(expectedResponse.getUserImageUri()); + Assertions.assertThat(actureResponse.getRacketType()).isEqualTo(expectedResponse.getRacketType()); +// Assertions.assertThat(actureResponse.getStatusMessage()).isEqualTo(expecxtedResponse.getStatusMessage()); + Assertions.assertThat(actureResponse.getWins()).isEqualTo(expectedResponse.getWins()); + Assertions.assertThat(actureResponse.getLosses()).isEqualTo(expectedResponse.getLosses()); + Assertions.assertThat(actureResponse.getPpp()).isEqualTo(expectedResponse.getPpp()); + Assertions.assertThat(actureResponse.getEmail()).isEqualTo(expectedResponse.getEmail()); + Assertions.assertThat(actureResponse.getRoleType()).isEqualTo(expectedResponse.getRoleType()); + Assertions.assertThat(actureResponse.getExp()).isEqualTo(expectedResponse.getExp()); + Assertions.assertThat(actureResponse.getCoin()).isEqualTo(expectedResponse.getCoin()); + } + + @Test + @DisplayName("DELETE /pingpong/admin/users/{intraId}") + @Transactional + public void deleteUserProfileImageTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findByIntraId("klew").get(); + String url = "/pingpong/admin/users/" + user.getIntraId(); + UserImage PrevUserImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); + //when + //200 성공 + mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + + UserImage CurrentUserImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); + Assertions.assertThat(PrevUserImage.getId()).isNotEqualTo(CurrentUserImage.getId()); + } + + @Test + @DisplayName("GET /pingpong/admin/users/delete-list") + @Transactional + public void getUserImageDeleteListTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + int page = 1; + int size = 30; + String url = "/pingpong/admin/users/delete-list?page=1"; + + //when + //200 성공 + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); + + //then + //각 유저의 이미지가 삭제된 이미지인지 확인 + List actureUserImageList = actureResponse.getUserImageList(); + for (UserImageAdminDto userImageDto : actureUserImageList) + Assertions.assertThat(userImageDto.getDeletedAt()).isNotEqualTo(null); + } + + @Test + @DisplayName("GET /pingpong/admin/users/images") + @Transactional + public void getUserImageListTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + String url = "/pingpong/admin/users/images?page=1"; + + //when + //200 성공 + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + //각 유저의 이미지가 삭제된 이미지인지 확인 + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); + assertThat(actureResponse.getUserImageList().size()).isEqualTo(3); + } + + @Test + @DisplayName("GET /pingpong/admin/users/images/{intraId}") + @Transactional + public void getUserImageListByIntraIdTest() throws Exception{ + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + String intraId = "klew"; + String url = "/pingpong/admin/users/images/" + intraId + "?page=1"; + + //when + //200 성공 + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + //각 유저의 이미지가 삭제된 이미지인지 확인 + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); + assertThat(actureResponse.getUserImageList().size()).isEqualTo(2); + } } \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java b/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java new file mode 100644 index 000000000..a12549b07 --- /dev/null +++ b/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java @@ -0,0 +1,138 @@ +package com.gg.server.domain.coin.service; + +import com.gg.server.domain.coin.data.CoinHistory; +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@RequiredArgsConstructor +@Transactional +class CoinHistoryServiceTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinHistoryService coinHistoryService; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("출석 재화이력 등록") + void addAttendanceCoinHistory() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addAttendanceCoinHistory(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for(CoinHistory ch : afterCoinHistory){ + System.out.println("이력 : " + ch.getHistory()); + System.out.println("사용값 : " + ch.getAmount()); + System.out.println("사용자 : " + ch.getUser().getIntraId()); + System.out.println("생성날짜 : " + ch.getCreatedAt()); + } + } + + @Test + @DisplayName("일반게임 재화이력 등록") + void addNormalCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addNormalCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for(CoinHistory ch : afterCoinHistory){ + System.out.println("이력 : " + ch.getHistory()); + System.out.println("사용값 : " + ch.getAmount()); + System.out.println("사용자 : " + ch.getUser().getIntraId()); + System.out.println("생성날짜 : " + ch.getCreatedAt()); + } + + + } + + @Test + @DisplayName("랭크게임 win 재화이력 등록") + void addRankWinCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addRankWinCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for(CoinHistory ch : afterCoinHistory){ + System.out.println("이력 : " + ch.getHistory()); + System.out.println("사용값 : " + ch.getAmount()); + System.out.println("사용자 : " + ch.getUser().getIntraId()); + System.out.println("생성날짜 : " + ch.getCreatedAt()); + } + } + + @Test + @DisplayName("랭크게임 lose 재화이력 등록") + void addRankLoseCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addRankLoseCoin(user); + coinHistoryService.addRankLoseCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 2); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for(CoinHistory ch : afterCoinHistory){ + System.out.println("이력 : " + ch.getHistory()); + System.out.println("사용값 : " + ch.getAmount()); + System.out.println("사용자 : " + ch.getUser().getIntraId()); + System.out.println("생성날짜 : " + ch.getCreatedAt()); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java b/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java new file mode 100644 index 000000000..0ff7aec9e --- /dev/null +++ b/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java @@ -0,0 +1,186 @@ +package com.gg.server.domain.coin.service; + +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import com.gg.server.domain.coin.data.CoinPolicy; +import com.gg.server.domain.coin.data.CoinPolicyRepository; +import com.gg.server.domain.coin.dto.UserGameCoinResultDto; +import com.gg.server.domain.coin.exception.CoinHistoryNotFoundException; +import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.data.ItemRepository; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@RequiredArgsConstructor +@Transactional +class UserCoinChangeServiceTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinHistoryService coinHistoryService; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + CoinPolicyRepository coinPolicyRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + UserCoinChangeService userCoinChangeService; + + @Autowired + ItemRepository itemRepository; + + @Test + @DisplayName("출석시 재화 증가 서비스 테스트") + void addAttendanceCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoin = user.getGgCoin(); + + int coinIncrement = userCoinChangeService.addAttendanceCoin(user); + + assertThat(beforeCoin + coinIncrement).isEqualTo(user.getGgCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getAttendance()).isEqualTo(coinIncrement); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + + try{ + coinIncrement = userCoinChangeService.addAttendanceCoin(user); + }catch (Exception e){ + System.out.println(e.getMessage() + " " + e); + System.out.println("===출석 중복 제거 기능 수행 완료==="); + } + } + + @Test + @DisplayName("아이템 구매시 코인사용 테스트") + void purchaseItemCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + user.addGgCoin(100); + int beforeCoin = user.getGgCoin(); + + Item item = new Item("과자", "111", "1", "1", 100, true, 0, + ItemType.EDGE,LocalDateTime.now(), user.getIntraId()); + itemRepository.save(item); + + userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); + + assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()+coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getAmount()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + try{ + userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); + }catch (Exception e){ + System.out.println(e.getMessage() + " " + e); + System.out.println("===coin이 없을 때 방어로직 기능 수행 완료==="); + } + } + + @Test + @DisplayName("아이템 선물시 코인사용 테스트") + void giftItemCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + user.addGgCoin(100); + int beforeCoin = user.getGgCoin(); + + Item item = new Item("과자", "111", "1", "1", 100, true, 0, + ItemType.EDGE,LocalDateTime.now(), user.getIntraId()); + itemRepository.save(item); + + userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); + + assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory() + +coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getAmount()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + + try{ + userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); + }catch (Exception e){ + System.out.println(e.getMessage() + " " + e); + System.out.println("===coin이 없을 때 방어로직 기능 수행 완료==="); + } + } + + @Test + @DisplayName("노말 게임 재화 증가 서비스 테스트") + void addNormalGameService() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal()).isEqualTo(userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + } + + @Test + @DisplayName("랭크 게임 승리 재화 증가 서비스 테스트") + void addRankWinGameService() { + User user = userRepository.getUserByIntraId("cheolee").orElseThrow(UserNotFoundException::new); + + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addRankGameCoin(3606L, user.getId());//본인의 게임Id와 id 값 + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankWin()).isEqualTo(userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + } + + @Test + @DisplayName("랭크 게임 패배 재화 증가 서비스 테스트") + void addRankLoseGameService() { + User user = userRepository.getUserByIntraId("cheolee").orElseThrow(UserNotFoundException::new); + + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addRankGameCoin(3689L, user.getId()); + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankLose()).isEqualTo(userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java new file mode 100644 index 000000000..e090cb122 --- /dev/null +++ b/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java @@ -0,0 +1,75 @@ +package com.gg.server.domain.item.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.item.dto.ItemGiftRequestDto; +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import javax.transaction.Transactional; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class ItemGiftControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Post]/pingpong/items/gift/{itemId} - success") + public void giftItemSuccessTest() throws Exception { + + // given + Long testItemId = 1L; + UserDto testUser = UserDto.builder() + .id(1L) + .intraId("testIntraId") + .build(); + + ItemGiftRequestDto requestDto = new ItemGiftRequestDto("recipientId"); + + doNothing().when(itemService).giftItem(testItemId, requestDto.getOwnerId(), testUser); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/gift/" + testItemId; + + // when + mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isCreated()); + + } +} diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java new file mode 100644 index 000000000..e58b2d123 --- /dev/null +++ b/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java @@ -0,0 +1,68 @@ +package com.gg.server.domain.item.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; +import javax.transaction.Transactional; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class ItemPurchaseControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Post]/pingpong/items/purchases/{itemId} - success") + public void purchaseItemSuccessTest() throws Exception { + + // given + Long testItemId = 1L; + UserDto testUser = UserDto.builder() + .id(1L) + .intraId("testIntraId") + .build(); + + doNothing().when(itemService).purchaseItem(testItemId, testUser); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/purchases/" + testItemId; + + // when + mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()); + + } +} diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java new file mode 100644 index 000000000..6065aeaad --- /dev/null +++ b/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java @@ -0,0 +1,100 @@ +package com.gg.server.domain.item.controller; + +import com.gg.server.domain.item.data.ItemRepository; +import com.gg.server.domain.item.dto.ItemStoreListResponseDto; +import com.gg.server.domain.item.dto.ItemStoreResponseDto; +import com.gg.server.domain.item.service.ItemService; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static com.gg.server.domain.item.type.ItemType.*; +import static org.assertj.core.api.Assertions.assertThat; +import javax.transaction.Transactional; +import java.util.Arrays; +import java.util.List; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +class ItemStoreListControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ItemRepository itemRepository; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Get]/pingpong/items/store") + public void getAllItemsTest() throws Exception { + + //given + List testItems = Arrays.asList( + new ItemStoreResponseDto(1L, "itemName 1", "mainContent 1","subContent 1", MEGAPHONE, "ImageUrl 1", 1000, 10, 900), + new ItemStoreResponseDto(2L, "itemName 2", "mainContent 2","subContent 2", PROFILE_IMAGE, "ImageUrl 2", 2000, 20, 1800), + new ItemStoreResponseDto(3L, "itemName 3", "mainContent 2","subContent 2", TEXT_COLOR, "ImageUrl 3", 3000, 30, 2700) + ); + ItemStoreListResponseDto testResponse = new ItemStoreListResponseDto(testItems); + when(itemService.getAllItems()).thenReturn(testResponse); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/store"; + + //when + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + ItemStoreListResponseDto result = objectMapper.readValue(contentAsString, ItemStoreListResponseDto.class); + assertThat(result.getItemList()).isNotNull(); + assertThat(result.getItemList()).isNotEmpty(); + assertThat(result.getItemList()).hasSize(testItems.size()); + + for (int i = 0; i < result.getItemList().size(); i++) { + ItemStoreResponseDto actual = result.getItemList().get(i); + ItemStoreResponseDto expected = testItems.get(i); + + assertThat(actual.getItemId()).isEqualTo(expected.getItemId()); + assertThat(actual.getItemName()).isEqualTo(expected.getItemName()); + assertThat(actual.getMainContent()).isEqualTo(expected.getMainContent()); + assertThat(actual.getSubContent()).isEqualTo(expected.getSubContent()); + assertThat(actual.getItemType()).isEqualTo(expected.getItemType()); + assertThat(actual.getImageUri()).isEqualTo(expected.getImageUri()); + assertThat(actual.getOriginalPrice()).isEqualTo(expected.getOriginalPrice()); + assertThat(actual.getDiscount()).isEqualTo(expected.getDiscount()); + assertThat(actual.getSalePrice()).isEqualTo(expected.getSalePrice()); + } + + System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result)); + } +} diff --git a/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java new file mode 100644 index 000000000..63c8edeb0 --- /dev/null +++ b/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java @@ -0,0 +1,49 @@ +package com.gg.server.domain.item.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.item.service.ItemService; +import com.gg.server.utils.TestDataUtils; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +public class UserItemResponseControllerTest { + + @Autowired + ItemService itemService; + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + MockMvc mockMvc; + + @Test + @DisplayName("GET /pingpong/items?page=1&size=20") + public void getItemByUser() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + + Integer page = 1; + Integer size = 20; + + String url = "/pingpong/items?page=" + page + "&size=" + size; + + mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java b/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java index 5b3a1a842..f0a17efa4 100644 --- a/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java +++ b/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java @@ -1,138 +1,136 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; -import com.gg.server.admin.penalty.type.PenaltyKey; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.match.data.RedisMatchTimeRepository; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import lombok.RequiredArgsConstructor; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.transaction.annotation.Transactional; - -@SpringBootTest -@Transactional -@AutoConfigureMockMvc -@ActiveProfiles("local") -@RequiredArgsConstructor -class MatchBothServiceTest { - @Autowired - MatchFindService matchFindService; - @Autowired - MatchService matchService; - @Autowired - RedisMatchTimeRepository redisMatchTimeRepository; - @Autowired - RedisMatchUserRepository redisMatchUserRepository; - @Autowired - RedisConnectionFactory redisConnectionFactory; - @Autowired - RedisTemplate redisTemplate; - @Autowired - MatchTestUtils matchTestSetting; - @Autowired - GameRepository gameRepository; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - PenaltyAdminRepository penaltyAdminRepository; - @Autowired - PenaltyUserRedisRepository penaltyUserRedisRepository; - List users; - List slotTimes; - - Season testSeason; - - - @BeforeEach - void init() { - Random random = new Random(); - Integer userCount = random.nextInt(10) + 5; - Integer pppGap = random.nextInt(100) + 50; - Season season = matchTestSetting.makeTestSeason(pppGap); - this.testSeason = season; - List users = new ArrayList(); - for(int i = 0; i < userCount; i++) { - User user = matchTestSetting.createUser(); - users.add(user); - } - this.users = users; - users.stream().forEach(user -> - matchTestSetting.addUsertoRankRedis(user.getId(), 1000, season.getId())); - SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); - List slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); - this.slotTimes = slotTimes; - } - @AfterEach - void clear() { - RedisConnection connection = redisConnectionFactory.getConnection(); - connection.flushDb(); - connection.close(); - } - - @DisplayName("both 매칭 시뮬레이션") - @Test - void makeGameWithNormalAndBoth() { - System.out.println("this.users = " + this.users); - // 유저 0 slot 2, 3, 0 등록 유저 1 slot 2 - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); - - System.out.println("matchFindService.getAllMatchStatus(users.get(0).getId(), Option.BOTH) = " - + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.BOTH).getMatchBoards().get(0)); - System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); - System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); - System.out.println("matchFindService.getAllMatchStatus(users.get(1).getId(), Option.BOTH) = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), Option.BOTH)); - Optional game1 = gameRepository.findByStartTime(slotTimes.get(2)); - Assertions.assertThat(game1).isPresent(); - matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(2)); - System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); - redisTemplate.delete(PenaltyKey.USER_ADMIN + users.get(0).getIntraId()); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(2)); - System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); - } - - @DisplayName("매칭 경기 상대가 아닌 다른 유저의 매칭 경기 취소") - @Test - void cancelByNotMatchedUser() { - System.out.println("this.users = " + this.users); - // 유저 0 slot 2, 3, 0 등록 유저 1 slot 2 - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); - org.junit.jupiter.api.Assertions.assertThrows(SlotNotFoundException.class, () -> { - matchService.cancelMatch(UserDto.from(users.get(2)), this.slotTimes.get(2)); - }); - } - -} +package com.gg.server.domain.match.service; + +import com.gg.server.admin.penalty.data.PenaltyAdminRepository; +import com.gg.server.admin.penalty.type.PenaltyKey; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.match.data.RedisMatchTimeRepository; +import com.gg.server.domain.match.data.RedisMatchUserRepository; +import com.gg.server.domain.match.exception.SlotNotFoundException; +import com.gg.server.domain.match.type.Option; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.slotmanagement.SlotManagement; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import lombok.RequiredArgsConstructor; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +@SpringBootTest +@Transactional +@AutoConfigureMockMvc +@ActiveProfiles("local") +@RequiredArgsConstructor +class MatchBothServiceTest { + @Autowired + MatchFindService matchFindService; + @Autowired + MatchService matchService; + @Autowired + RedisMatchTimeRepository redisMatchTimeRepository; + @Autowired + RedisMatchUserRepository redisMatchUserRepository; + @Autowired + RedisConnectionFactory redisConnectionFactory; + @Autowired + RedisTemplate redisTemplate; + @Autowired + MatchTestUtils matchTestSetting; + @Autowired + GameRepository gameRepository; + @Autowired + RankRedisRepository rankRedisRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + PenaltyAdminRepository penaltyAdminRepository; + @Autowired + PenaltyUserRedisRepository penaltyUserRedisRepository; + List users; + List slotTimes; + + Season testSeason; + + + @BeforeEach + void init() { + Random random = new Random(); + Integer userCount = random.nextInt(10) + 5; + Integer pppGap = random.nextInt(100) + 50; + Season season = matchTestSetting.makeTestSeason(pppGap); + this.testSeason = season; + List users = new ArrayList(); + for(int i = 0; i < userCount; i++) { + User user = matchTestSetting.createUser(); + users.add(user); + } + this.users = users; + users.stream().forEach(user -> + matchTestSetting.addUsertoRankRedis(user.getId(), 1000, season.getId())); + SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); + List slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); + this.slotTimes = slotTimes; + } + @AfterEach + void clear() { + RedisConnection connection = redisConnectionFactory.getConnection(); + connection.flushDb(); + connection.close(); + } + + @DisplayName("both 매칭 시뮬레이션") + @Test + void makeGameWithNormalAndBoth() { + System.out.println("this.users = " + this.users); + // 유저 0 slot 2, 3, 0 등록 유저 1 slot 2 + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); + + System.out.println("matchFindService.getAllMatchStatus(users.get(0).getId(), Option.BOTH) = " + + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.BOTH).getMatchBoards().get(0)); + System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); + System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); + System.out.println("matchFindService.getAllMatchStatus(users.get(1).getId(), Option.BOTH) = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), Option.BOTH)); + Optional game1 = gameRepository.findByStartTime(slotTimes.get(2)); + Assertions.assertThat(game1).isPresent(); + matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(2)); + System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); + redisTemplate.delete(PenaltyKey.USER_ADMIN + users.get(0).getIntraId()); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(2)); + System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); + } + + @DisplayName("매칭 경기 상대가 아닌 다른 유저의 매칭 경기 취소") + @Test + void cancelByNotMatchedUser() { + System.out.println("this.users = " + this.users); + // 유저 0 slot 2, 3, 0 등록 유저 1 slot 2 + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); + org.junit.jupiter.api.Assertions.assertThrows(SlotNotFoundException.class, () -> { + matchService.cancelMatch(UserDto.from(users.get(2)), this.slotTimes.get(2)); + }); + } + +} diff --git a/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java b/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java index df7eb48de..f7428e90f 100644 --- a/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java +++ b/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java @@ -26,7 +26,7 @@ import com.gg.server.domain.rank.redis.RedisKeyManager; import com.gg.server.domain.season.data.Season; import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.user.User; +import com.gg.server.domain.user.data.User; import com.gg.server.domain.user.dto.UserDto; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/src/test/java/com/gg/server/domain/match/service/MatchTestUtils.java b/src/test/java/com/gg/server/domain/match/service/MatchTestUtils.java index cb9e40dd0..a410355af 100644 --- a/src/test/java/com/gg/server/domain/match/service/MatchTestUtils.java +++ b/src/test/java/com/gg/server/domain/match/service/MatchTestUtils.java @@ -1,114 +1,112 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class MatchTestUtils { - private final UserRepository userRepository; - private final SeasonRepository seasonRepository; - private final RankRedisRepository rankRedisRepository; - private final SlotManagementRepository slotManagementRepository; - - public User createUser() { - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createGuestUser() { - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.GUEST) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public RankRedis addUsertoRankRedis(Long userId, Integer ppp, Long seasonId) { - String randomId = UUID.randomUUID().toString(); - RankRedis rankRedis = new RankRedis(userId, randomId, ppp, 0, 0,"test"); - rankRedisRepository.addRankData(RedisKeyManager.getHashKey(seasonId), userId, rankRedis); - rankRedisRepository.addToZSet(RedisKeyManager.getZSetKey(seasonId), userId, ppp); - return rankRedis; - } - - public List getTestSlotTimes(Integer interval) { - LocalDateTime now = LocalDateTime.now(); - LocalDateTime standard = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth() - , now.getHour(), 0); - List sampleSlots = new ArrayList(); - for (int i = 0; i < 15; i++) { - if (standard.plusMinutes(interval * i).isAfter(now)) { - sampleSlots.add(standard.plusMinutes(interval * i)); - } - } - return sampleSlots; - } - public Season makeTestSeason(Integer pppGap) { - Optional currentSeason = seasonRepository.findCurrentSeason(LocalDateTime.now()); - if (currentSeason.isPresent()) { - return currentSeason.get(); - } - Season season = new Season( - "test", - LocalDateTime.now().minusDays(1), - LocalDateTime.of(9999, 12, 31, 23, 59, 59), - 1000, - pppGap - ); - seasonRepository.save(season); - return season; - } - - public SlotManagement makeTestSlotManagement(Integer interval) { - SlotManagement slotManagement1 = slotManagementRepository.findCurrent(LocalDateTime.now()) - .orElseThrow(SlotNotFoundException::new); - if (slotManagement1 != null) { - return slotManagement1; - } - SlotManagement slotManagement = SlotManagement.builder() - .futureSlotTime(10) - .pastSlotTime(0) - .gameInterval(interval) - .openMinute(5) - .startTime(LocalDateTime.now().minusHours(2)) - .build(); - slotManagementRepository.save(slotManagement); - return slotManagement; - } -} +package com.gg.server.domain.match.service; + +import com.gg.server.domain.match.exception.SlotNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.slotmanagement.SlotManagement; +import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class MatchTestUtils { + private final UserRepository userRepository; + private final SeasonRepository seasonRepository; + private final RankRedisRepository rankRedisRepository; + private final SlotManagementRepository slotManagementRepository; + + public User createUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public User createGuestUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.GUEST) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public RankRedis addUsertoRankRedis(Long userId, Integer ppp, Long seasonId) { + String randomId = UUID.randomUUID().toString(); + RankRedis rankRedis = new RankRedis(userId, randomId, ppp, 0, 0,"test", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + rankRedisRepository.addRankData(RedisKeyManager.getHashKey(seasonId), userId, rankRedis); + rankRedisRepository.addToZSet(RedisKeyManager.getZSetKey(seasonId), userId, ppp); + return rankRedis; + } + + public List getTestSlotTimes(Integer interval) { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime standard = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth() + , now.getHour(), 0); + List sampleSlots = new ArrayList(); + for (int i = 0; i < 15; i++) { + if (standard.plusMinutes(interval * i).isAfter(now)) { + sampleSlots.add(standard.plusMinutes(interval * i)); + } + } + return sampleSlots; + } + public Season makeTestSeason(Integer pppGap) { + Optional currentSeason = seasonRepository.findCurrentSeason(LocalDateTime.now()); + if (currentSeason.isPresent()) { + return currentSeason.get(); + } + Season season = new Season( + "test", + LocalDateTime.now().minusDays(1), + LocalDateTime.of(9999, 12, 31, 23, 59, 59), + 1000, + pppGap + ); + seasonRepository.save(season); + return season; + } + + public SlotManagement makeTestSlotManagement(Integer interval) { + SlotManagement slotManagement1 = slotManagementRepository.findCurrent(LocalDateTime.now()) + .orElseThrow(SlotNotFoundException::new); + if (slotManagement1 != null) { + return slotManagement1; + } + SlotManagement slotManagement = SlotManagement.builder() + .futureSlotTime(10) + .pastSlotTime(0) + .gameInterval(interval) + .openMinute(5) + .startTime(LocalDateTime.now().minusHours(2)) + .build(); + slotManagementRepository.save(slotManagement); + return slotManagement; + } +} diff --git a/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java b/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java new file mode 100644 index 000000000..d48814d44 --- /dev/null +++ b/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java @@ -0,0 +1,133 @@ +package com.gg.server.domain.megaphone.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.megaphone.data.Megaphone; +import com.gg.server.domain.megaphone.data.MegaphoneRepository; +import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.data.ReceiptRepository; +import com.gg.server.domain.receipt.type.ItemStatus; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +class MegaphoneControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + MegaphoneRepository megaphoneRepository; + + @Autowired + ReceiptRepository receiptRepository; + + @Test + @Transactional + @DisplayName("[Post] /pingpong/megaphones") + void useMegaphoneTest() throws Exception { + String intraId = "intra"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + // db에 저장해두고 테스트 + Receipt receipt = receiptRepository.findById(1L).get(); + MegaphoneUseRequestDto megaphoneUseRequestDto = new MegaphoneUseRequestDto(receipt.getId(), "test"); + String content = objectMapper.writeValueAsString(megaphoneUseRequestDto); + String url = "/pingpong/megaphones"; + + mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + Megaphone result = megaphoneRepository.findFirstByOrderByIdDesc(); + assertThat(result.getContent()).isEqualTo(megaphoneUseRequestDto.getContent()); + } + + @Test + @Transactional + @DisplayName("DELETE /pingpong/megaphones/{megaphoneId}") + public void deleteMegaphoneTest() throws Exception { + //given + String intraId = "intra"; + String email = "email"; + String imageUrl = "imageUrl"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + Receipt receipt = receiptRepository.findById(2L).get(); + String url = "/pingpong/megaphones/2"; + + //when + mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse(); + + //then + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.DELETED); + } + + @Test + @Transactional + @DisplayName("[GET] /pingpong/megaphones/receipt/{receiptId}") + void getMegaphoneDetailTest() throws Exception { + String intraId = "intra"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + Receipt receipt = receiptRepository.findById(1L).get(); + String url = "/pingpong/megaphones/receipt/" + receipt.getId(); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("[GET] /pingpong/megaphones") + void getMegaphoneTodayListTest() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + String url = "/pingpong/megaphones"; + mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + } +} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java b/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java index 4d5af57de..512a34f76 100644 --- a/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java +++ b/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java @@ -1,127 +1,124 @@ -package com.gg.server.domain.noti.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.dto.NotiListResponseDto; -import com.gg.server.domain.noti.dto.NotiResponseDto; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.ResponseEntity; -import org.springframework.test.web.servlet.MockMvc; - -import javax.transaction.Transactional; - -import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@SpringBootTest -@AutoConfigureMockMvc -class NotiControllerTest { - - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - private NotiService notiService; - @Autowired - private MockMvc mockMvc; - @Autowired - private ObjectMapper objectMapper; - - @Test - @DisplayName("GET /pingpong/notifications") - @Transactional - public void NotiFindByUserTest() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications"; - - UserDto userDto = UserDto.from(userRepository.getById(userId)); - NotiListResponseDto expectedResponse = new NotiListResponseDto(notiService.findNotiByUser(userDto)); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListResponseDto actureResponse= objectMapper.readValue(contentAsString, NotiListResponseDto.class); - - //then - assertThat(actureResponse).isEqualTo(expectedResponse); - } - - @Test - @DisplayName("PUT /pingpong/notifications/check") - @Transactional - public void checkNotiByUserTest() throws Exception{ - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications/check"; - User user = userRepository.findById(userId).get(); - - notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); - notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); - notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); - //when - String contentAsString = mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - List notiList = notiRepository.findByUser(user); - for (Noti noti : notiList) { - assertThat(noti.getIsChecked()).isTrue(); - } - } - - @Test - @DisplayName("DELETE /notifications") - @Transactional - public void notiRemoveAll() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications"; - User user = userRepository.findById(userId).get(); - - notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); - notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); - notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); - - //when - String contentAsString = mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - List notiList = notiRepository.findByUser(user); - assertThat(notiList.size()).isEqualTo(0); - } +package com.gg.server.domain.noti.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.noti.dto.NotiListResponseDto; +import com.gg.server.domain.noti.service.NotiService; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import javax.transaction.Transactional; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RequiredArgsConstructor +@SpringBootTest +@AutoConfigureMockMvc +class NotiControllerTest { + + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + private NotiService notiService; + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("GET /pingpong/notifications") + @Transactional + public void NotiFindByUserTest() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications"; + + UserDto userDto = UserDto.from(userRepository.getById(userId)); + NotiListResponseDto expectedResponse = new NotiListResponseDto(notiService.findNotiByUser(userDto)); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListResponseDto actureResponse= objectMapper.readValue(contentAsString, NotiListResponseDto.class); + + //then + assertThat(actureResponse).isEqualTo(expectedResponse); + } + + @Test + @DisplayName("PUT /pingpong/notifications/check") + @Transactional + public void checkNotiByUserTest() throws Exception{ + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications/check"; + User user = userRepository.findById(userId).get(); + + notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); + notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); + notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); + //when + String contentAsString = mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + List notiList = notiRepository.findByUser(user); + for (Noti noti : notiList) { + assertThat(noti.getIsChecked()).isTrue(); + } + } + + @Test + @DisplayName("DELETE /notifications") + @Transactional + public void notiRemoveAll() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications"; + User user = userRepository.findById(userId).get(); + + notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); + notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); + notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); + + //when + String contentAsString = mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + List notiList = notiRepository.findByUser(user); + assertThat(notiList.size()).isEqualTo(0); + } } \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java b/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java index 9be547533..b7c29fdf2 100644 --- a/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java +++ b/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java @@ -1,76 +1,73 @@ -package com.gg.server.domain.noti.service; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; -import org.checkerframework.checker.units.qual.A; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import javax.transaction.Transactional; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@RequiredArgsConstructor -@SpringBootTest -@Slf4j -class NotiServiceTest { - - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - NotiService notiService; - @Autowired - NotiRepository notiRepository; - @Autowired - UserRepository userRepository; - - @Test - @DisplayName("NotiService 유저매칭알림 전송 테스트") - @Transactional - public void 유저매칭알림전송테스트() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - UserDto userDto = UserDto.from(user); - LocalDateTime now = LocalDateTime.now(); - String expectedMatchedNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 성사되었습니다."; - String expectedMatchCancelNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 상대에 의해 취소되었습니다."; - - //when - notiService.createMatched(user, now); - notiService.createMatchCancel(user, now); - List actureNotiList = notiRepository.findAllByUser(user); - - //then - Assertions.assertThat(actureNotiList.size()).isEqualTo(2); - for (Noti noti: actureNotiList) { - if (noti.getType() == NotiType.MATCHED) { - Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchedNotiMessage); - log.info("Matched Message : " + noti.getMessage()); - } - else if (noti.getType() == NotiType.CANCELEDBYMAN) { - Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchCancelNotiMessage); - log.info("MatchCancel Message : " + noti.getMessage()); - } - Assertions.assertThat(noti.getIsChecked()).isFalse(); - } - } -} +package com.gg.server.domain.noti.service; + +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.transaction.Transactional; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +@RequiredArgsConstructor +@SpringBootTest +@Slf4j +class NotiServiceTest { + + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + NotiService notiService; + @Autowired + NotiRepository notiRepository; + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("NotiService 유저매칭알림 전송 테스트") + @Transactional + public void 유저매칭알림전송테스트() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + UserDto userDto = UserDto.from(user); + LocalDateTime now = LocalDateTime.now(); + String expectedMatchedNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 성사되었습니다."; + String expectedMatchCancelNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "에 신청한 매칭이 상대에 의해 취소되었습니다."; + + //when + notiService.createMatched(user, now); + notiService.createMatchCancel(user, now); + List actureNotiList = notiRepository.findAllByUser(user); + + //then + Assertions.assertThat(actureNotiList.size()).isEqualTo(2); + for (Noti noti: actureNotiList) { + if (noti.getType() == NotiType.MATCHED) { + Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchedNotiMessage); + log.info("Matched Message : " + noti.getMessage()); + } + else if (noti.getType() == NotiType.CANCELEDBYMAN) { + Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchCancelNotiMessage); + log.info("MatchCancel Message : " + noti.getMessage()); + } + Assertions.assertThat(noti.getIsChecked()).isFalse(); + } + } +} diff --git a/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java b/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java index c9aaf755b..ef67079cd 100644 --- a/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java +++ b/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java @@ -1,169 +1,167 @@ -package com.gg.server.domain.rank.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.service.RedisUploadService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.user.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Comparator; -import java.util.List; - - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - - -@SpringBootTest -@Transactional -@AutoConfigureMockMvc -class RankControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - SeasonRepository seasonRepository; - - @Autowired - RankRedisRepository redisRepository; - - @Autowired - RedisUploadService redisUploadService; - - @BeforeEach - public void flushRedis(){ - redisRepository.deleteAll(); - } - - @AfterEach - public void flushRedisAfter(){ - redisRepository.deleteAll(); - redisUploadService.uploadRedis(); - } - - @Test - @DisplayName("/exp") - void getExpRankPage() throws Exception { - - // given - Season season = testDataUtils.createSeason(); - int myTotalExp = 1000; - User myUser = testDataUtils.createNewUser(myTotalExp); - testDataUtils.createUserRank(myUser, "1", season); - - int otherTotalExp = 2000; - User user1 = testDataUtils.createNewUser(otherTotalExp); - testDataUtils.createUserRank(user1, "2", season); - int otherTotalExp2 = 3000; - User user2 = testDataUtils.createNewUser(otherTotalExp2); - testDataUtils.createUserRank(user2, "3", season); - int otherTotalExp3 = 4000; - User user3 = testDataUtils.createNewUser(otherTotalExp3); - testDataUtils.createUserRank(user3, "4", season); - - int page = 1; - int size = 3; - String url = "/pingpong/exp?page=" + page + "&size=" + size; - String accessToken = tokenProvider.createToken(myUser.getId()); - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - ExpRankPageResponseDto response = objectMapper.readValue(contentAsString, ExpRankPageResponseDto.class); - - //then - Assertions.assertThat(response.getMyRank()).isEqualTo(4); - Assertions.assertThat(response.getCurrentPage()).isEqualTo(page); - Assertions.assertThat(response.getTotalPage()).isEqualTo(2); - Assertions.assertThat(response.getRankList().size()).isEqualTo(3); - } - - @Test - @DisplayName("/pingpong/ranks/{gameType}") - public void getRankPage () throws Exception - { - //given - Season season = testDataUtils.createSeason(); - User myUser = testDataUtils.createNewUser(); - testDataUtils.createUserRank(myUser, "1", season, 1000); - - User user2 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user2, "2", season, 1500); - - User user3 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user3, "3", season, 2000); - - User user4 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user4, "4", season, 2500); - - User user5 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user5, "5", season, 3000); - - User user6 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user6, "6", season, 3500); - - User user7 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user7, "7", season, 4000); - - User user8 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user8, "8", season, 4500); - - User user9 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user9, "9", season, 5000); - - User user10 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user10, "10", season, 5500); - - String accessToken = tokenProvider.createToken(myUser.getId()); - - int page = 4; - int size = 3; - String url = "/pingpong/ranks/single?page=" + page + "&size=" + size; - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - RankPageResponseDto resp = objectMapper.readValue(contentAsString, RankPageResponseDto.class); - - //then - List rankList = resp.getRankList(); - Assertions.assertThat(resp.getCurrentPage()).isEqualTo(4); - Assertions.assertThat(resp.getTotalPage()).isEqualTo(4); - Assertions.assertThat(resp.getMyRank()).isEqualTo(10); - Assertions.assertThat(rankList.size()).isEqualTo(1); - Assertions.assertThat(rankList).isSortedAccordingTo(Comparator.comparing(RankDto::getPpp).reversed()); - } - - +package com.gg.server.domain.rank.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; +import com.gg.server.domain.rank.dto.RankDto; +import com.gg.server.domain.rank.dto.RankPageResponseDto; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.service.RedisUploadService; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Comparator; +import java.util.List; + + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@SpringBootTest +@Transactional +@AutoConfigureMockMvc +class RankControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + SeasonRepository seasonRepository; + + @Autowired + RankRedisRepository redisRepository; + + @Autowired + RedisUploadService redisUploadService; + + @BeforeEach + public void flushRedis(){ + redisRepository.deleteAll(); + } + + @AfterEach + public void flushRedisAfter(){ + redisRepository.deleteAll(); + redisUploadService.uploadRedis(); + } + + @Test + @DisplayName("/exp") + void getExpRankPage() throws Exception { + + // given + Season season = testDataUtils.createSeason(); + int myTotalExp = 1000; + User myUser = testDataUtils.createNewUser(myTotalExp); + testDataUtils.createUserRank(myUser, "1", season); + + int otherTotalExp = 2000; + User user1 = testDataUtils.createNewUser(otherTotalExp); + testDataUtils.createUserRank(user1, "2", season); + int otherTotalExp2 = 3000; + User user2 = testDataUtils.createNewUser(otherTotalExp2); + testDataUtils.createUserRank(user2, "3", season); + int otherTotalExp3 = 4000; + User user3 = testDataUtils.createNewUser(otherTotalExp3); + testDataUtils.createUserRank(user3, "4", season); + + int page = 1; + int size = 3; + String url = "/pingpong/exp?page=" + page + "&size=" + size; + String accessToken = tokenProvider.createToken(myUser.getId()); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + ExpRankPageResponseDto response = objectMapper.readValue(contentAsString, ExpRankPageResponseDto.class); + + //then + Assertions.assertThat(response.getMyRank()).isEqualTo(4); + Assertions.assertThat(response.getCurrentPage()).isEqualTo(page); + Assertions.assertThat(response.getTotalPage()).isEqualTo(2); + Assertions.assertThat(response.getRankList().size()).isEqualTo(3); + } + + @Test + @DisplayName("/pingpong/ranks/{gameType}") + public void getRankPage () throws Exception + { + //given + Season season = testDataUtils.createSeason(); + User myUser = testDataUtils.createNewUser(); + testDataUtils.createUserRank(myUser, "1", season, 1000); + + User user2 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user2, "2", season, 1500); + + User user3 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user3, "3", season, 2000); + + User user4 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user4, "4", season, 2500); + + User user5 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user5, "5", season, 3000); + + User user6 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user6, "6", season, 3500); + + User user7 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user7, "7", season, 4000); + + User user8 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user8, "8", season, 4500); + + User user9 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user9, "9", season, 5000); + + User user10 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user10, "10", season, 5500); + + String accessToken = tokenProvider.createToken(myUser.getId()); + + int page = 4; + int size = 3; + String url = "/pingpong/ranks/single?page=" + page + "&size=" + size; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + RankPageResponseDto resp = objectMapper.readValue(contentAsString, RankPageResponseDto.class); + + //then + List rankList = resp.getRankList(); + Assertions.assertThat(resp.getCurrentPage()).isEqualTo(4); + Assertions.assertThat(resp.getTotalPage()).isEqualTo(4); + Assertions.assertThat(resp.getMyRank()).isEqualTo(10); + Assertions.assertThat(rankList.size()).isEqualTo(1); + Assertions.assertThat(rankList).isSortedAccordingTo(Comparator.comparing(RankDto::getPpp).reversed()); + } + + } \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java b/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java index c6a359c72..f4171702d 100644 --- a/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java +++ b/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java @@ -171,7 +171,7 @@ public void rankCreateSearch () throws Exception int win = 3; int lose = 4; String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage); + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/hand.svg", "#000000"); //when redisRepository.addRankData(hashKey, userId, ranking); @@ -195,7 +195,7 @@ public void updateRank () throws Exception int win = 3; int lose = 4; String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage); + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); redisRepository.addRankData(hashKey, userId, ranking); //when @@ -203,7 +203,7 @@ public void updateRank () throws Exception int newWin = 4; int newLose = 5; String newStatusMessage = "newStatusMessage"; - RankRedis newRanking = new RankRedis(userId, "aa", newPpp, newWin, newLose, newStatusMessage); + RankRedis newRanking = new RankRedis(userId, "aa", newPpp, newWin, newLose, newStatusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); redisRepository.updateRankData(hashKey, userId, newRanking); //then @@ -225,7 +225,7 @@ public void deleteUserRank () throws Exception int win = 3; int lose = 4; String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage); + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); redisRepository.addRankData(hashKey, userId, ranking); //when @@ -249,10 +249,10 @@ void findRanksByUserIds() { int ppp3 = 300; int ppp4 = 400; - RankRedis rank1 = new RankRedis(userId, "aa", ppp, 0, 0, "statusMessage"); - RankRedis rank2 = new RankRedis(userId2,"aa", ppp2, 0, 0, "statusMessage"); - RankRedis rank3 = new RankRedis(userId3, "aa", ppp3, 0, 0, "statusMessage"); - RankRedis rank4 = new RankRedis(userId4, "aa", ppp4, 0, 0, "statusMessage"); + RankRedis rank1 = new RankRedis(userId, "aa", ppp, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank2 = new RankRedis(userId2,"aa", ppp2, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank3 = new RankRedis(userId3, "aa", ppp3, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank4 = new RankRedis(userId4, "aa", ppp4, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); redisRepository.addRankData(hashKey, userId, rank1); redisRepository.addRankData(hashKey, userId2, rank2); redisRepository.addRankData(hashKey, userId3, rank3); diff --git a/src/test/java/com/gg/server/domain/user/controller/UserControllerTest.java b/src/test/java/com/gg/server/domain/user/controller/UserControllerTest.java index eaea6012c..160eac526 100644 --- a/src/test/java/com/gg/server/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/gg/server/domain/user/controller/UserControllerTest.java @@ -1,320 +1,526 @@ -package com.gg.server.domain.user.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.req.RankResultReqDto; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.domain.user.dto.*; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.annotation.Rollback; -import org.springframework.test.web.servlet.MockMvc; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc -@Transactional -class UserControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - UserRepository userRepository; - - @Autowired - RankRedisRepository redisRepository; - - @Autowired - RankRepository rankRepository; - - @Autowired - SeasonRepository seasonRepository; - - @Autowired - GameRepository gameRepository; - - @Autowired - GameService gameService; - - @AfterEach - public void flushRedis() { - redisRepository.deleteAll(); - } - - @Test - @DisplayName("live") - public void userLiveTest() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String liveUrl = "/pingpong/users/live"; - String event = "game"; - int notiCnt = 2; - Mode currentMatchMode = Mode.RANK; - GameInfoDto gameInfo = testDataUtils.addMockDataUserLiveApi(event, notiCnt, currentMatchMode.getCode(), userId); - Game testGame = gameRepository.getById(gameInfo.getGameId()); - - // Rank Live 게임 테스트 - String contentAsString1 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserLiveResponseDto userLiveResponseDto1 = objectMapper.readValue(contentAsString1, UserLiveResponseDto.class); - assertThat(userLiveResponseDto1.getEvent()).isEqualTo(event); - assertThat(userLiveResponseDto1.getNotiCount()).isEqualTo(notiCnt); - assertThat(userLiveResponseDto1.getCurrentMatchMode()).isEqualTo(currentMatchMode); - assertThat(userLiveResponseDto1.getGameId()).isEqualTo(gameInfo.getGameId()); - - // Rank 점수 입력 테스트 - RankResultReqDto rankResultReqDto = new RankResultReqDto(gameInfo.getGameId(), - gameInfo.getEnemyTeamId(), 1, - gameInfo.getMyTeamId(), 2); - assertThat(testGame.getStatus()).isEqualTo(StatusType.LIVE); - gameService.createRankResult(rankResultReqDto, gameInfo.getEnemyUserId()); - assertThat(testGame.getStatus()).isEqualTo(StatusType.END); - - String contentAsString2 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserLiveResponseDto userLiveResponseDto2 = objectMapper.readValue(contentAsString2, UserLiveResponseDto.class); - assertThat(userLiveResponseDto2.getEvent()).isEqualTo(event); - assertThat(userLiveResponseDto2.getNotiCount()).isEqualTo(notiCnt); - assertThat(userLiveResponseDto2.getCurrentMatchMode()).isEqualTo(currentMatchMode); - assertThat(userLiveResponseDto2.getGameId()).isEqualTo(gameInfo.getGameId()); - - // Rank PChange is_checked 테스트 - String contentAsString3 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserLiveResponseDto userLiveResponseDto3 = objectMapper.readValue(contentAsString3, UserLiveResponseDto.class); - assertThat(userLiveResponseDto3.getEvent()).isEqualTo(null); - assertThat(userLiveResponseDto3.getNotiCount()).isEqualTo(notiCnt); - assertThat(userLiveResponseDto3.getCurrentMatchMode()).isEqualTo(null); - assertThat(userLiveResponseDto3.getGameId()).isEqualTo(null); - } - - @Test - @DisplayName("/") - public void userNormalDetail () throws Exception { - //given - String url = "/pingpong/users"; - String intraId = "intra"; - String email = "email"; - String imageUrl = "imageUrl"; - User newUser = testDataUtils.createNewUser(intraId, email, imageUrl, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String accessToken = tokenProvider.createToken(newUser.getId()); - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserNormalDetailResponseDto responseDto = objectMapper.readValue(contentAsString, UserNormalDetailResponseDto.class); - - //then - assertThat(responseDto.getIntraId()).isEqualTo(intraId); - assertThat(responseDto.getUserImageUri()).isEqualTo(imageUrl); - assertThat(responseDto.getIsAdmin()).isTrue(); - } - - @Test - @DisplayName("searches?intraId=${IntraId}") - public void searchUser() throws Exception - { - //given - String intraId[] = {"intraId", "2intra2", "2intra", "aaaa", "bbbb"}; - String email = "email"; - String imageUrl = "imageUrl"; - User user = null; - for (String intra : intraId) { - user = testDataUtils.createNewUser(intra, email, imageUrl, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - } - String accessToken = tokenProvider.createToken(user.getId()); - String keyWord = "intra"; - String url = "/pingpong/users/searches?intraId=" + keyWord; - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchResponseDto userSearchResponseDto = objectMapper.readValue(contentAsString, UserSearchResponseDto.class); - - //then - assertThat(userSearchResponseDto.getUsers().size()).isEqualTo(3); - } - - @Test - @DisplayName("[GET] {targetId}") - public void getUserDetail () throws Exception - { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - String imageUrl = "imageUrl"; - String statusMessage = "statusMessage"; - User newUser = testDataUtils.createNewUser(intraId, email, imageUrl, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String accessToken = tokenProvider.createToken(newUser.getId()); - testDataUtils.createUserRank(newUser, statusMessage, season); - String url = "/pingpong/users/" + newUser.getIntraId(); - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - UserDetailResponseDto responseDto = objectMapper.readValue(contentAsString, UserDetailResponseDto.class); - - //then - Assertions.assertThat(responseDto.getIntraId()).isEqualTo(intraId); - Assertions.assertThat(responseDto.getUserImageUri()).isEqualTo(imageUrl); - Assertions.assertThat(responseDto.getStatusMessage()).isEqualTo(statusMessage); - Assertions.assertThat(responseDto.getLevel()).isEqualTo(1); - Assertions.assertThat(responseDto.getCurrentExp()).isEqualTo(0); - System.out.println(responseDto); - } - - @Test - @DisplayName("/{intraId}/rank?season={seasonId}") - public void userRankDetail () throws Exception - { - //given - Season season = testDataUtils.createSeason(); - User newUser = testDataUtils.createNewUser(); - String accessToken = tokenProvider.createToken(newUser.getId()); - testDataUtils.createUserRank(newUser, "statusMessage", season); - - //when - String url = "/pingpong/users/" + newUser.getIntraId() + "/rank?season=" + season.getId(); - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - UserRankResponseDto responseDto = objectMapper.readValue(contentAsString, UserRankResponseDto.class); - - //then - Assertions.assertThat(responseDto.getRank()).isEqualTo(-1); - Assertions.assertThat(responseDto.getWins()).isEqualTo(0); - Assertions.assertThat(responseDto.getLosses()).isEqualTo(0); - Assertions.assertThat(responseDto.getPpp()).isEqualTo(season.getStartPpp()); - System.out.println(responseDto); - } - - @Test - @DisplayName("/{intraId}/historics?season={seasonId}") - public void getUserHistory () throws Exception - { - //given - Season season = testDataUtils.createSeason(); - User newUser = testDataUtils.createNewUser(); - String accessToken = tokenProvider.createToken(newUser.getId()); - - LocalDateTime startTime = LocalDateTime.now().minusDays(1); - LocalDateTime endTime = startTime.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime, endTime); - - LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); - LocalDateTime endTime1 = startTime1.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); - - LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); - LocalDateTime endTime2 = startTime2.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); - - String url = "/pingpong/users/" + newUser.getIntraId() + "/historics?season=" + season.getId(); - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - UserHistoryResponseDto responseDto = objectMapper.readValue(contentAsString, UserHistoryResponseDto.class); - - - //then - List historics = responseDto.getHistorics(); - Assertions.assertThat(responseDto.getHistorics().size()).isEqualTo(3); - Assertions.assertThat(historics) - .isSortedAccordingTo(Comparator.comparing(UserHistoryData::getDate)); - - } - - @Test - @DisplayName("[put] {intraId}") - public void updateUser() throws Exception - { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - String imageUrl = "imageUrl"; - User newUser = testDataUtils.createNewUser(intraId, email, imageUrl, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String statusMessage = "statusMessage"; - testDataUtils.createUserRank(newUser, statusMessage, season); - String accessToken = tokenProvider.createToken(newUser.getId()); - String url = "/pingpong/users/" + newUser.getIntraId(); - - String newStatusMessage = "newStatusMessage"; - RacketType newRacketType = RacketType.SHAKEHAND; - SnsType newSnsType = SnsType.SLACK; - - //when - mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new UserModifyRequestDto(newRacketType, newStatusMessage, newSnsType)))) - .andExpect(status().isOk()); - //then - String hashKey = RedisKeyManager.getHashKey(season.getId()); - RankRedis rank = redisRepository.findRankByUserId(hashKey, newUser.getId()); - rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).ifPresentOrElse(rank1 -> { - Assertions.assertThat(rank1.getStatusMessage()).isEqualTo(newStatusMessage); - }, () -> { - Assertions.fail("랭크 업데이트 실패"); - }); - userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { - Assertions.assertThat(user.getRacketType()).isEqualTo((newRacketType)); - Assertions.assertThat(user.getSnsNotiOpt()).isEqualTo(newSnsType); - Assertions.assertThat(rank.getStatusMessage()).isEqualTo(newStatusMessage); - }, () -> { - Assertions.fail("유저 업데이트 실패"); - }); - } -} \ No newline at end of file +package com.gg.server.domain.user.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.coin.data.CoinHistoryRepository; +import com.gg.server.domain.coin.data.CoinPolicyRepository; +import com.gg.server.domain.coin.service.CoinHistoryService; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.req.RankResultReqDto; +import com.gg.server.domain.game.service.GameService; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.item.data.Item; +import com.gg.server.domain.item.type.ItemType; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.receipt.data.Receipt; +import com.gg.server.domain.receipt.data.ReceiptRepository; +import com.gg.server.domain.receipt.exception.ReceiptNotFoundException; +import com.gg.server.domain.receipt.type.ItemStatus; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserImage; +import com.gg.server.domain.user.data.UserImageRepository; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.controller.dto.GameInfoDto; +import com.gg.server.domain.user.dto.*; +import com.gg.server.domain.user.exception.UserNotFoundException; +import com.gg.server.domain.user.type.*; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.AfterEach; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.io.FileInputStream; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +@Slf4j +class UserControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + UserRepository userRepository; + + @Autowired + RankRedisRepository redisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + RankRepository rankRepository; + + @Autowired + SeasonRepository seasonRepository; + + @Autowired + GameRepository gameRepository; + + @Autowired + GameService gameService; + + @Autowired + CoinPolicyRepository coinPolicyRepository; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + ReceiptRepository receiptRepository; + + @Autowired + CoinHistoryService coinHistoryService; + + + @AfterEach + public void flushRedis() { + redisRepository.deleteAll(); + } + + @Test + @DisplayName("live") + public void userLiveTest() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String liveUrl = "/pingpong/users/live"; + String event = "game"; + int notiCnt = 2; + Mode currentMatchMode = Mode.RANK; + GameInfoDto gameInfo = testDataUtils.addMockDataUserLiveApi(event, notiCnt, currentMatchMode.getCode(), userId); + Game testGame = gameRepository.getById(gameInfo.getGameId()); + + // Rank Live 게임 테스트 + String contentAsString1 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto1 = objectMapper.readValue(contentAsString1, UserLiveResponseDto.class); + assertThat(userLiveResponseDto1.getEvent()).isEqualTo(event); + assertThat(userLiveResponseDto1.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto1.getCurrentMatchMode()).isEqualTo(currentMatchMode); + assertThat(userLiveResponseDto1.getGameId()).isEqualTo(gameInfo.getGameId()); + + // Rank 점수 입력 테스트 + RankResultReqDto rankResultReqDto = new RankResultReqDto(gameInfo.getGameId(), + gameInfo.getEnemyTeamId(), 1, + gameInfo.getMyTeamId(), 2); + assertThat(testGame.getStatus()).isEqualTo(StatusType.LIVE); + gameService.createRankResult(rankResultReqDto, gameInfo.getEnemyUserId()); + assertThat(testGame.getStatus()).isEqualTo(StatusType.END); + + String contentAsString2 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto2 = objectMapper.readValue(contentAsString2, UserLiveResponseDto.class); + assertThat(userLiveResponseDto2.getEvent()).isEqualTo(event); + assertThat(userLiveResponseDto2.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto2.getCurrentMatchMode()).isEqualTo(currentMatchMode); + assertThat(userLiveResponseDto2.getGameId()).isEqualTo(gameInfo.getGameId()); + + // Rank PChange is_checked 테스트 + String contentAsString3 = mockMvc.perform(get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto3 = objectMapper.readValue(contentAsString3, UserLiveResponseDto.class); + assertThat(userLiveResponseDto3.getEvent()).isEqualTo(null); + assertThat(userLiveResponseDto3.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto3.getCurrentMatchMode()).isEqualTo(null); + assertThat(userLiveResponseDto3.getGameId()).isEqualTo(null); + } + + @Test + @DisplayName("GET /pingpong/users") + public void userNormalDetail() throws Exception { + //given + String url = "/pingpong/users"; + String intraId = "intra"; + String email = "email"; + String imageUrl = "imageUrl"; + + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.ADMIN); + Season season = testDataUtils.createSeason(); + + String accessToken = tokenProvider.createToken(newUser.getId()); + Tier tier = tierRepository.getById(1L); + testDataUtils.createUserRank(newUser, "statusMessage", season, tier); + + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserNormalDetailResponseDto responseDto = objectMapper.readValue(contentAsString, UserNormalDetailResponseDto.class); + + //then + assertThat(responseDto.getIntraId()).isEqualTo(intraId); + assertThat(responseDto.getUserImageUri()).isEqualTo(imageUrl); + assertThat(responseDto.getIsAdmin()).isTrue(); + assertThat(responseDto.getIsAttended()); + } + + @Test + @DisplayName("searches?intraId=${IntraId}") + public void searchUser() throws Exception { + //given + String intraId[] = {"intraId", "2intra2", "2intra", "aaaa", "bbbb"}; + String email = "email"; + User user = null; + for (String intra : intraId) { + user = testDataUtils.createNewUser(intra, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + } + String accessToken = tokenProvider.createToken(user.getId()); + String keyWord = "intra"; + String url = "/pingpong/users/searches?intraId=" + keyWord; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchResponseDto userSearchResponseDto = objectMapper.readValue(contentAsString, UserSearchResponseDto.class); + + //then + assertThat(userSearchResponseDto.getUsers().size()).isEqualTo(3); + } + + @Test + @DisplayName("[GET] {targetId}") + public void getUserDetail() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + String imageUrl = "imageUrl"; + String statusMessage = "statusMessage"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String accessToken = tokenProvider.createToken(newUser.getId()); + Tier tier = tierRepository.getById(1L); + testDataUtils.createUserRank(newUser, statusMessage, season, tier); + String url = "/pingpong/users/" + newUser.getIntraId(); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserDetailResponseDto responseDto = objectMapper.readValue(contentAsString, UserDetailResponseDto.class); + + //then + Assertions.assertThat(responseDto.getIntraId()).isEqualTo(intraId); + Assertions.assertThat(responseDto.getUserImageUri()).isEqualTo(imageUrl); + Assertions.assertThat(responseDto.getStatusMessage()).isEqualTo(statusMessage); + Assertions.assertThat(responseDto.getLevel()).isEqualTo(1); + Assertions.assertThat(responseDto.getCurrentExp()).isEqualTo(0); + System.out.println(responseDto); + } + + @Test + @DisplayName("/{intraId}/rank?season={seasonId}") + public void userRankDetail() throws Exception { + //given + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + String accessToken = tokenProvider.createToken(newUser.getId()); + testDataUtils.createUserRank(newUser, "statusMessage", season); + + //when + String url = "/pingpong/users/" + newUser.getIntraId() + "/rank?season=" + season.getId(); + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserRankResponseDto responseDto = objectMapper.readValue(contentAsString, UserRankResponseDto.class); + + //then + Assertions.assertThat(responseDto.getRank()).isEqualTo(-1); + Assertions.assertThat(responseDto.getWins()).isEqualTo(0); + Assertions.assertThat(responseDto.getLosses()).isEqualTo(0); + Assertions.assertThat(responseDto.getPpp()).isEqualTo(season.getStartPpp()); + System.out.println(responseDto); + } + + @Test + @DisplayName("/{intraId}/historics?season={seasonId}") + public void getUserHistory() throws Exception { + //given + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + String accessToken = tokenProvider.createToken(newUser.getId()); + + LocalDateTime startTime = LocalDateTime.now().minusDays(1); + LocalDateTime endTime = startTime.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime, endTime); + + LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); + LocalDateTime endTime1 = startTime1.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); + + LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); + LocalDateTime endTime2 = startTime2.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); + + String url = "/pingpong/users/" + newUser.getIntraId() + "/historics?season=" + season.getId(); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserHistoryResponseDto responseDto = objectMapper.readValue(contentAsString, UserHistoryResponseDto.class); + + + //then + List historics = responseDto.getHistorics(); + Assertions.assertThat(responseDto.getHistorics().size()).isEqualTo(3); + Assertions.assertThat(historics) + .isSortedAccordingTo(Comparator.comparing(UserHistoryData::getDate)); + + } + + @Test + @DisplayName("[put] {intraId}") + public void updateUser() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + String imageUrl = "imageUrl"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + String url = "/pingpong/users/" + newUser.getIntraId(); + + String newStatusMessage = "newStatusMessage"; + RacketType newRacketType = RacketType.SHAKEHAND; + SnsType newSnsType = SnsType.SLACK; + + //when + mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new UserModifyRequestDto(newRacketType, newStatusMessage, newSnsType)))) + .andExpect(status().isOk()); + //then + String hashKey = RedisKeyManager.getHashKey(season.getId()); + RankRedis rank = redisRepository.findRankByUserId(hashKey, newUser.getId()); + rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).ifPresentOrElse(rank1 -> { + Assertions.assertThat(rank1.getStatusMessage()).isEqualTo(newStatusMessage); + }, () -> { + Assertions.fail("랭크 업데이트 실패"); + }); + userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { + Assertions.assertThat(user.getRacketType()).isEqualTo((newRacketType)); + Assertions.assertThat(user.getSnsNotiOpt()).isEqualTo(newSnsType); + Assertions.assertThat(rank.getStatusMessage()).isEqualTo(newStatusMessage); + }, () -> { + Assertions.fail("유저 업데이트 실패"); + }); + } + + @Test + @DisplayName("[post] /attendance") + public void attendUserTest() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + String url = "/pingpong/users/attendance"; + + //when + String contentAsString = mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserAttendanceResponseDto result = objectMapper.readValue(contentAsString, UserAttendanceResponseDto.class); + + //then + System.out.println(result.getAfterCoin()); + Assertions.assertThat(result.getAfterCoin() - result.getBeforeCoin()).isEqualTo(result.getCoinIncrement()); + } + + @Test + @DisplayName("[patch] text-color") + public void updateTextColorTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + String url = "/pingpong/users/text-color"; + + Receipt receipt = receiptRepository.findById(4L).get(); + String newTextColor = "#FFFFFF"; + + //when + mockMvc.perform(patch(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new UserTextColorDto(4L, newTextColor)))) + .andExpect(status().is2xxSuccessful()); + //then + userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { + Assertions.assertThat(user.getTextColor()).isEqualTo(newTextColor); + }, () -> { + Assertions.fail("유저 업데이트 실패"); + }); + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[patch] edge") + public void updateEdgeTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + + Receipt receipt = receiptRepository.findById(3L).get(); + String url = "/pingpong/users/edge"; + + //when + mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(objectMapper.writeValueAsString(3L)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + log.info("user.getEdge() : {}", newUser.getEdge()); + userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { + Assertions.assertThat(Arrays.stream(EdgeType.values()).anyMatch(v -> v.equals(user.getEdge()))).isEqualTo(true); + }, () -> { + Assertions.fail("유저 업데이트 실패"); + }); + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[get]/pingpong/users/coin") + public void getUserCoin() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + String url = "/pingpong/users/coin"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + UserCoinResponseDto result = objectMapper.readValue(contentAsString, UserCoinResponseDto.class); + int userCoin = userRepository.findById(userId).orElseThrow(() -> new UserNotFoundException()).getGgCoin(); + assertThat(result.getCoin()).isEqualTo(userCoin); + System.out.println(userCoin); + } + + @Test + @DisplayName("[patch] background") + public void updateBackgroundTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + + Receipt receipt = receiptRepository.findById(2L).get(); + String uri = "/pingpong/users/background"; + + //when + mockMvc.perform(patch(uri) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(objectMapper.writeValueAsString(2L)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + log.info("user.getBackground() : {}", newUser.getBackground()); + userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { + Assertions.assertThat(Arrays.stream(BackgroundType.values()).anyMatch(v -> v.equals(user.getBackground()))).isEqualTo(true); + }, () -> { + Assertions.fail("유저 업데이트 실패"); + }); + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[get]/pingpong/users/coinhistory") + public void getUserCoinHistory() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + coinHistoryService.addNormalCoin(user); + coinHistoryService.addRankWinCoin(user); + coinHistoryService.addNormalCoin(user); + String url = "/pingpong/users/coinhistory?page=1&size=5"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + UserCoinHistoryListResponseDto result = objectMapper.readValue(contentAsString, UserCoinHistoryListResponseDto.class); + + System.out.println(result.getTotalPage()); + for(CoinHistoryResponseDto temp : result.getUseCoinList()){ + System.out.println(temp.getHistory() + " " + temp.getAmount() + " " + temp.getCreatedAt()); + } + } + + @Test + @DisplayName("[post]/pingpong/users/profile-image") + public void getUserImage() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + Receipt receipt = receiptRepository.findById(7L).orElseThrow(ReceiptNotFoundException::new); + MockMultipartFile image = new MockMultipartFile("profileImage", "imagefile.jpeg", "image/jpeg", "<>".getBytes()); + MockMultipartFile jsonFile = new MockMultipartFile("userProfileImageDto", "", "application/json", ("{\"receiptId\": " + receipt.getId() + "}").getBytes()); + + String contentAsString = mockMvc.perform(multipart("/pingpong/users/profile-image") + .file(image) + .file(jsonFile) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } +} diff --git a/src/test/java/com/gg/server/game/GameControllerTest.java b/src/test/java/com/gg/server/game/GameControllerTest.java index 37f5832b0..6a26d456e 100644 --- a/src/test/java/com/gg/server/game/GameControllerTest.java +++ b/src/test/java/com/gg/server/game/GameControllerTest.java @@ -1,370 +1,378 @@ -package com.gg.server.game; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.game.service.GameFindService; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GameTeamInfo; -import com.gg.server.domain.game.dto.req.RankResultReqDto; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc -@RequiredArgsConstructor -public class GameControllerTest { - @Autowired - GameRepository gameRepository; - @Autowired - SeasonRepository seasonRepository; - @Autowired - TeamRepository teamRepository; - @Autowired - TeamUserRepository teamUserRepository; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - PChangeRepository pChangeRepository; - @Autowired - RankRedisService rankRedisService; - @Autowired - RankRepository rankRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - GameService gameService; - @Autowired - GameFindService gameFindService; - @Autowired - private MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - private String accessToken; - private Season season; - private User user1; - private User user2; - private Game game1; - private Game game2; - - @BeforeEach - void init() { - season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 5, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), - 1000, 100)); - user1 = testDataUtils.createNewUser("test1", "test1@email", "null1", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - accessToken = tokenProvider.createToken(user1.getId()); - user2 = testDataUtils.createNewUser("test2", "test2@email", "null1", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - rankRepository.save(Rank.from(user1, season, season.getStartPpp())); - rankRepository.save(Rank.from(user2, season, season.getStartPpp())); - RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); - userRank = RankRedis.from(UserDto.from(user2), season.getStartPpp()); - rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank); - for (int i = 0; i < 10; i++) { - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, 1, false)); - Team team2 = teamRepository.save(new Team(game, 2, true)); - List teams = new ArrayList<>(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - gameService.expUpdates(game, teams); - rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game); - game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - team1 = teamRepository.save(new Team(game, 0, false)); - team2 = teamRepository.save(new Team(game, 0, false)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - teams.clear(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - game.updateStatus(); - gameService.expUpdates(game, teams); - pChangeRepository.save(new PChange(game, user1, 0, true)); - pChangeRepository.save(new PChange(game, user2, 0, true)); - } - game1 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game1, 1, false)); - Team team2 = teamRepository.save(new Team(game1, 2, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - game2 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - team1 = teamRepository.save(new Team(game1, 1, false)); - team2 = teamRepository.save(new Team(game1, 2, true)); - List teams = new ArrayList<>(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - gameService.expUpdates(game2, teams); - rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game2); - } - - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - - @Test - @Transactional - void 유저게임정보조회테스트() throws Exception { - //given - String url = "/pingpong/games/" + game1.getId().toString(); - GameTeamInfo expect = gameService.getUserGameInfo(game1.getId(), user1.getId()); - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - GameTeamInfo result = objectMapper.readValue(contentAsString, GameTeamInfo.class); - System.out.println("expect: " + expect); - System.out.println("result: " + result); - assertThat(result.getGameId()).isEqualTo(expect.getGameId()); - assertThat(result.getStartTime()).isEqualTo(expect.getStartTime()); - assertThat(result.getMatchTeamsInfo().getMyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getMyTeam().getTeamId()); - assertThat(result.getMatchTeamsInfo().getEnemyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getEnemyTeam().getTeamId()); - } - - @Test - @Transactional - public void 일반게임목록조회() throws Exception { - //given - String url = "/pingpong/games/normal?page=1&size=10"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.getNormalGameList(pageable); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - public void user일반게임목록조회() throws Exception { - //given - String url = "/pingpong/games/normal?page=1&size=10&intraId=test1"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.normalGameListByIntra(pageable, "test1"); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - public void 랭크게임목록조회() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId(); - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.rankGameList(pageable, season.getId()); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - public void user랭크게임목록조회() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId() + "&nickname=" + "test1"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.rankGameListByIntra(pageable, season.getId(), "test1"); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - public void 랭크게임목록error조회() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=0"; - //then - mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError()) - .andReturn().getResponse().getContentAsString(); - } - @Test - @Transactional - public void 전체게임목록조회() throws Exception { - //given - String url = "/pingpong/games?page=1&size=10"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.allGameList(pageable, null); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(result.getGames().size() - 1).getGameId().equals(expect.getGames().get(expect.getGames().size() - 1).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - public void user전체게임목록조회() throws Exception { - //given - String url = "/pingpong/games?page=1&size=10&nickname=test1"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.allGameListUser(pageable, "test1", null); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(result.getGames().size() - 1).getGameId()).isEqualTo(expect.getGames().get(expect.getGames().size() - 1).getGameId()); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - @Test - @Transactional - void 게임목록조회에러테스트() throws Exception { - String url = "/pingpong/games?pageNum=1&pageSize=10&status=live"; - mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - @Test - @Transactional - void 게임목록조회에러테스트2() throws Exception { - String url = "/pingpong/games?page=1&size=10&status=2"; - mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @Transactional - void 랭크게임결과입력테스트() throws Exception { - String url = "/pingpong/games/rank"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - String ac2 = tokenProvider.createToken(user2.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - teamUserRepository.flush(); - gameRepository.flush(); - teamRepository.flush(); - String content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - // then - System.out.println("======================="); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse(); - System.out.println("======================="); - content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isConflict()) - .andReturn().getResponse(); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - } - - @Test - @Transactional - void 랭크게임결과조회() throws Exception { - String url = "/pingpong/games/" + game2.getId() + "/result/rank"; - String content = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println("result: " + content); - } -} +package com.gg.server.game; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gg.server.domain.game.service.GameFindService; +import com.gg.server.domain.game.service.GameService; +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.GameListResDto; +import com.gg.server.domain.game.dto.GameTeamInfo; +import com.gg.server.domain.game.dto.req.RankResultReqDto; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RankRedisService; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.team.data.Team; +import com.gg.server.domain.team.data.TeamRepository; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.team.data.TeamUserRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@RequiredArgsConstructor +public class GameControllerTest { + @Autowired + GameRepository gameRepository; + @Autowired + SeasonRepository seasonRepository; + @Autowired + TeamRepository teamRepository; + @Autowired + TeamUserRepository teamUserRepository; + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + PChangeRepository pChangeRepository; + @Autowired + RankRedisService rankRedisService; + @Autowired + RankRepository rankRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + GameService gameService; + @Autowired + GameFindService gameFindService; + @Autowired + private MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + private String accessToken; + private Season season; + private User user1; + private User user2; + private Game game1; + private Game game2; + + @BeforeEach + void init() { + season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 7, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), + 1000, 100)); + user1 = testDataUtils.createNewUser("test1", "test1@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + accessToken = tokenProvider.createToken(user1.getId()); + user2 = testDataUtils.createNewUser("test2", "test2@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + rankRepository.save(Rank.from(user1, season, season.getStartPpp(), tier)); + rankRepository.save(Rank.from(user2, season, season.getStartPpp(), tier)); + RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); + userRank = RankRedis.from(UserDto.from(user2), season.getStartPpp(), tier.getImageUri()); + rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank); + for (int i = 0; i < 10; i++) { + Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, 1, false)); + Team team2 = teamRepository.save(new Team(game, 2, true)); + List teams = new ArrayList<>(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + gameService.expUpdates(game, teams); + rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game); + game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + team1 = teamRepository.save(new Team(game, 0, false)); + team2 = teamRepository.save(new Team(game, 0, false)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + teams.clear(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + game.updateStatus(); + gameService.expUpdates(game, teams); + pChangeRepository.save(new PChange(game, user1, 0, true)); + pChangeRepository.save(new PChange(game, user2, 0, true)); + } + game1 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game1, 1, false)); + Team team2 = teamRepository.save(new Team(game1, 2, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + game2 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + team1 = teamRepository.save(new Team(game1, 1, false)); + team2 = teamRepository.save(new Team(game1, 2, true)); + List teams = new ArrayList<>(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + gameService.expUpdates(game2, teams); + rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game2); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + @Test + @Transactional + void 유저게임정보조회테스트() throws Exception { + //given + String url = "/pingpong/games/" + game1.getId().toString(); + GameTeamInfo expect = gameService.getUserGameInfo(game1.getId(), user1.getId()); + // when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + GameTeamInfo result = objectMapper.readValue(contentAsString, GameTeamInfo.class); + System.out.println("expect: " + expect); + System.out.println("result: " + result); + assertThat(result.getGameId()).isEqualTo(expect.getGameId()); + assertThat(result.getStartTime()).isEqualTo(expect.getStartTime()); + assertThat(result.getMatchTeamsInfo().getMyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getMyTeam().getTeamId()); + assertThat(result.getMatchTeamsInfo().getEnemyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getEnemyTeam().getTeamId()); + } + + @Test + @Transactional + public void 일반게임목록조회() throws Exception { + //given + String url = "/pingpong/games/normal?page=1&size=10"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.getNormalGameList(pageable); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + public void user일반게임목록조회() throws Exception { + //given + String url = "/pingpong/games/normal?page=1&size=10&intraId=test1"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.normalGameListByIntra(pageable, "test1"); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + public void 랭크게임목록조회() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId(); + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.rankGameList(pageable, season.getId()); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + public void user랭크게임목록조회() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId() + "&nickname=" + "test1"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.rankGameListByIntra(pageable, season.getId(), "test1"); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + public void 랭크게임목록error조회() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=0"; + //then + mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError()) + .andReturn().getResponse().getContentAsString(); + } + @Test + @Transactional + public void 전체게임목록조회() throws Exception { + //given + String url = "/pingpong/games?page=1&size=10"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.allGameList(pageable, null); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(result.getGames().size() - 1).getGameId().equals(expect.getGames().get(expect.getGames().size() - 1).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + public void user전체게임목록조회() throws Exception { + //given + String url = "/pingpong/games?page=1&size=10&nickname=test1"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.allGameListUser(pageable, "test1", null); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() +", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(result.getGames().size() - 1).getGameId()).isEqualTo(expect.getGames().get(expect.getGames().size() - 1).getGameId()); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + @Test + @Transactional + void 게임목록조회에러테스트() throws Exception { + String url = "/pingpong/games?pageNum=1&pageSize=10&status=live"; + mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + @Test + @Transactional + void 게임목록조회에러테스트2() throws Exception { + String url = "/pingpong/games?page=1&size=10&status=2"; + mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @Transactional + void 랭크게임결과입력테스트() throws Exception { + String url = "/pingpong/games/rank"; + Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + String ac2 = tokenProvider.createToken(user2.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + teamUserRepository.flush(); + gameRepository.flush(); + teamRepository.flush(); + String content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + // then + System.out.println("======================="); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse(); + System.out.println("======================="); + content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isConflict()) + .andReturn().getResponse(); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + } + + @Test + @Transactional + void 랭크게임결과조회() throws Exception { + String url = "/pingpong/games/" + game2.getId() + "/result/rank"; + String content = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println("result: " + content); + } +} diff --git a/src/test/java/com/gg/server/game/service/GameFindServiceTest.java b/src/test/java/com/gg/server/game/service/GameFindServiceTest.java index 5b6c13b76..194b31589 100644 --- a/src/test/java/com/gg/server/game/service/GameFindServiceTest.java +++ b/src/test/java/com/gg/server/game/service/GameFindServiceTest.java @@ -1,96 +1,104 @@ -package com.gg.server.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GameResultResDto; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.service.GameFindService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.Sort; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@SpringBootTest -@RequiredArgsConstructor -@Transactional -public class GameFindServiceTest { - - @Autowired - GameFindService gameFindService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - GameRepository gameRepository; - - @BeforeEach - void init() { - Season season = testDataUtils.createSeason(); - User newUser = testDataUtils.createNewUser(); - String accessToken = tokenProvider.createToken(newUser.getId()); - String statusMsg = "status message test1"; - - LocalDateTime startTime = LocalDateTime.now().minusDays(1); - LocalDateTime endTime = startTime.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime, endTime); - - LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); - LocalDateTime endTime1 = startTime1.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); - - LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); - LocalDateTime endTime2 = startTime2.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); - - testDataUtils.createUserRank(newUser, statusMsg, season); - RankRedis userRank = RankRedis.from(UserDto.from(newUser), season.getStartPpp()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, newUser.getId(), userRank); - } - - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - @Test - void 일반game목록조회() { - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto response = gameFindService.getNormalGameList(pageable); - Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); - GameListResDto expect = new GameListResDto(getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); - assertThat(response).isEqualTo(expect); - } - private List getGameResultList(List games) { - List teamViews = gameRepository.findTeamsByGameIsIn(games); - return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); - } - - -} +package com.gg.server.game.service; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.GameListResDto; +import com.gg.server.domain.game.dto.GameResultResDto; +import com.gg.server.domain.game.dto.GameTeamUser; +import com.gg.server.domain.game.service.GameFindService; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Sort; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@RequiredArgsConstructor +@Transactional +public class GameFindServiceTest { + + @Autowired + GameFindService gameFindService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + GameRepository gameRepository; + + @BeforeEach + void init() { + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + String accessToken = tokenProvider.createToken(newUser.getId()); + String statusMsg = "status message test1"; + + LocalDateTime startTime = LocalDateTime.now().minusDays(1); + LocalDateTime endTime = startTime.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime, endTime); + + LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); + LocalDateTime endTime1 = startTime1.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); + + LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); + LocalDateTime endTime2 = startTime2.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); + + testDataUtils.createUserRank(newUser, statusMsg, season); + RankRedis userRank = RankRedis.from(UserDto.from(newUser), season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, newUser.getId(), userRank); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + @Test + void 일반game목록조회() { + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto response = gameFindService.getNormalGameList(pageable); + Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); + GameListResDto expect = new GameListResDto(getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); + assertThat(response).isEqualTo(expect); + } + private List getGameResultList(List games) { + List teamViews = gameRepository.findTeamsByGameIsIn(games); + return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); + } + + +} diff --git a/src/test/java/com/gg/server/game/service/GameServiceTest.java b/src/test/java/com/gg/server/game/service/GameServiceTest.java index 376a487d4..8080495cf 100644 --- a/src/test/java/com/gg/server/game/service/GameServiceTest.java +++ b/src/test/java/com/gg/server/game/service/GameServiceTest.java @@ -1,112 +1,118 @@ -package com.gg.server.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.req.RankResultReqDto; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.exception.custom.NotExistException; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@SpringBootTest -@RequiredArgsConstructor -@Transactional -public class GameServiceTest { - - @Autowired - RankRedisRepository rankRedisRepository; - - @Autowired - GameRepository gameRepository; - @Autowired - TeamRepository teamRepository; - - @Autowired - TeamUserRepository teamUserRepository; - - @Autowired - RankRepository rankRepository; - - @Autowired - GameService gameService; - - User user1; - User user2; - Game game1; - Team team1, team2; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - - @BeforeEach - void init() { - Season season = testDataUtils.createSeason(); - user1 = testDataUtils.createNewUser(); - user2 = testDataUtils.createNewUser(); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); - game1 = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime, startTime.plusMinutes(15))); - team1 = teamRepository.save(new Team(game1, -1, false)); - team2 = teamRepository.save(new Team(game1, -1, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String statusMsg = "status message test1"; - - testDataUtils.createUserRank(user1, statusMsg, season); - RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); - statusMsg = "status message test2"; - testDataUtils.createUserRank(user2, statusMsg, season); - RankRedis userRank2 = RankRedis.from(UserDto.from(user2), season.getStartPpp()); - rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank2); - } - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - - @Test - void ppp변화량_조회_test() throws Exception { - String key = RedisKeyManager.getHashKey(game1.getSeason().getId()); - Integer user1BeforePpp = rankRedisRepository.findRankByUserId(key, user1.getId()) - .getPpp(); - System.out.println("Before ppp: " + user1BeforePpp); - assertThat(gameService.createRankResult(new RankResultReqDto(game1.getId(), team1.getId(), - 1, team2.getId(), 2), user1.getId())).isEqualTo(true); - Integer user1AfterPpp = rankRedisRepository.findRankByUserId(key, user1.getId()).getPpp(); - System.out.println("After ppp: " + rankRedisRepository.findRankByUserId(key, user1.getId()) - .getPpp()); - Rank rank = rankRepository.findByUserIdAndSeasonId(user1.getId(), game1.getSeason().getId()) - .orElseThrow(RankNotFoundException::new); - assertThat(rank.getPpp()).isEqualTo(user1AfterPpp); - assertThat(user1BeforePpp).isGreaterThan(user1AfterPpp); - } -} +package com.gg.server.game.service; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.dto.req.RankResultReqDto; +import com.gg.server.domain.game.service.GameService; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.exception.RankNotFoundException; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.team.data.Team; +import com.gg.server.domain.team.data.TeamRepository; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.team.data.TeamUserRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.tier.exception.TierNotFoundException; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.dto.UserDto; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@RequiredArgsConstructor +@Transactional +public class GameServiceTest { + + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + GameRepository gameRepository; + @Autowired + TeamRepository teamRepository; + + @Autowired + TeamUserRepository teamUserRepository; + + @Autowired + RankRepository rankRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + GameService gameService; + + User user1; + User user2; + Game game1; + Team team1, team2; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + + @BeforeEach + void init() { + Season season = testDataUtils.createSeason(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + user1 = testDataUtils.createNewUser(); + user2 = testDataUtils.createNewUser(); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); + game1 = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime, startTime.plusMinutes(15))); + team1 = teamRepository.save(new Team(game1, -1, false)); + team2 = teamRepository.save(new Team(game1, -1, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String statusMsg = "status message test1"; + + testDataUtils.createUserRank(user1, statusMsg, season); + RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); + statusMsg = "status message test2"; + testDataUtils.createUserRank(user2, statusMsg, season); + RankRedis userRank2 = RankRedis.from(UserDto.from(user2), season.getStartPpp(), tier.getImageUri()); + rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank2); + } + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + @Test + void ppp변화량_조회_test() throws Exception { + String key = RedisKeyManager.getHashKey(game1.getSeason().getId()); + Integer user1BeforePpp = rankRedisRepository.findRankByUserId(key, user1.getId()) + .getPpp(); + System.out.println("Before ppp: " + user1BeforePpp); + assertThat(gameService.createRankResult(new RankResultReqDto(game1.getId(), team1.getId(), + 1, team2.getId(), 2), user1.getId())).isEqualTo(true); + Integer user1AfterPpp = rankRedisRepository.findRankByUserId(key, user1.getId()).getPpp(); + System.out.println("After ppp: " + rankRedisRepository.findRankByUserId(key, user1.getId()) + .getPpp()); + Rank rank = rankRepository.findByUserIdAndSeasonId(user1.getId(), game1.getSeason().getId()) + .orElseThrow(RankNotFoundException::new); + assertThat(rank.getPpp()).isEqualTo(user1AfterPpp); + assertThat(user1BeforePpp).isGreaterThan(user1AfterPpp); + } +} diff --git a/src/test/java/com/gg/server/game/service/GameStatusServiceTest.java b/src/test/java/com/gg/server/game/service/GameStatusServiceTest.java index 480c2c2e6..fc011c887 100644 --- a/src/test/java/com/gg/server/game/service/GameStatusServiceTest.java +++ b/src/test/java/com/gg/server/game/service/GameStatusServiceTest.java @@ -1,104 +1,104 @@ -package com.gg.server.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.service.GameStatusService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@SpringBootTest -@RequiredArgsConstructor -@Transactional -public class GameStatusServiceTest { - @Autowired - private GameRepository gameRepository; - @Autowired private SeasonRepository seasonRepository; - @Autowired - private GameStatusService gameStatusService; - @Autowired - private RankRedisRepository rankRedisRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - private TeamRepository teamRepository; - @Autowired - private TeamUserRepository teamUserRepository; - private Season season; - User user1; - User user2; - Game game1; - Game liveGame; - - @BeforeEach - void init() { - season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 5, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), - 1000, 100)); - user1 = testDataUtils.createNewUser("test2", "test2@naver.com", "null1", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - user2 = testDataUtils.createNewUser("test3", "test3@naver.com", "null1", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); - game1 = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.RANK, startTime, startTime.plusMinutes(15))); - Team team1 = teamRepository.save(new Team(game1, 1, false)); - Team team2 = teamRepository.save(new Team(game1, 2, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - liveGame = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime.minusMinutes(15), startTime)); - } - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - @Test - void gameBefore상태변경테스트() throws Exception{ - System.out.println("g1.startTime: " + game1.getStartTime()); - System.out.println(game1.getStatus()); - gameStatusService.updateBeforeToLiveStatus(); - assertThat(game1.getStatus()).isEqualTo(StatusType.LIVE); - } - - @Test - void gameLIVE상태변경테스트() throws Exception{ - gameStatusService.updateLiveToWaitStatus(); - assertThat(liveGame.getStatus()).isEqualTo(StatusType.WAIT); - } - - @Test - void game5분전알림테스트() throws Exception{ - LocalDateTime now = LocalDateTime.now(); - LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); - System.out.println(startTime.plusMinutes(5)); - Game game = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.RANK, startTime.plusMinutes(5), startTime.plusMinutes(20))); - Team team1 = teamRepository.save(new Team(game, 0, false)); - Team team2 = teamRepository.save(new Team(game, 0, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - gameRepository.flush(); - teamRepository.flush(); - teamUserRepository.flush(); - System.out.println("=============="); - gameStatusService.imminentGame(); - } -} +package com.gg.server.game.service; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.game.service.GameStatusService; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.team.data.Team; +import com.gg.server.domain.team.data.TeamRepository; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.team.data.TeamUserRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.utils.TestDataUtils; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@RequiredArgsConstructor +@Transactional +public class GameStatusServiceTest { + @Autowired + private GameRepository gameRepository; + @Autowired private SeasonRepository seasonRepository; + @Autowired + private GameStatusService gameStatusService; + @Autowired + private RankRedisRepository rankRedisRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + private TeamRepository teamRepository; + @Autowired + private TeamUserRepository teamUserRepository; + private Season season; + User user1; + User user2; + Game game1; + Game liveGame; + + @BeforeEach + void init() { + season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 5, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), + 1000, 100)); + user1 = testDataUtils.createNewUser("test2", "test2@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + user2 = testDataUtils.createNewUser("test3", "test3@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); + game1 = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.RANK, startTime, startTime.plusMinutes(15))); + Team team1 = teamRepository.save(new Team(game1, 1, false)); + Team team2 = teamRepository.save(new Team(game1, 2, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + liveGame = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime.minusMinutes(15), startTime)); + } + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + @Test + void gameBefore상태변경테스트() throws Exception{ + System.out.println("g1.startTime: " + game1.getStartTime()); + System.out.println(game1.getStatus()); + gameStatusService.updateBeforeToLiveStatus(); + assertThat(game1.getStatus()).isEqualTo(StatusType.LIVE); + } + + @Test + void gameLIVE상태변경테스트() throws Exception{ + gameStatusService.updateLiveToWaitStatus(); + assertThat(liveGame.getStatus()).isEqualTo(StatusType.WAIT); + } + + @Test + void game5분전알림테스트() throws Exception{ + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); + System.out.println(startTime.plusMinutes(5)); + Game game = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.RANK, startTime.plusMinutes(5), startTime.plusMinutes(20))); + Team team1 = teamRepository.save(new Team(game, 0, false)); + Team team2 = teamRepository.save(new Team(game, 0, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + gameRepository.flush(); + teamRepository.flush(); + teamUserRepository.flush(); + System.out.println("=============="); + gameStatusService.imminentGame(); + } +} diff --git a/src/test/java/com/gg/server/utils/TestDataUtils.java b/src/test/java/com/gg/server/utils/TestDataUtils.java index debc2cd41..81d926355 100644 --- a/src/test/java/com/gg/server/utils/TestDataUtils.java +++ b/src/test/java/com/gg/server/utils/TestDataUtils.java @@ -1,239 +1,257 @@ -package com.gg.server.utils; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.User; -import com.gg.server.domain.user.UserRepository; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.parameters.P; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.UUID; - -@Component -@RequiredArgsConstructor -public class TestDataUtils { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - private final NotiRepository notiRepository; - private final SeasonRepository seasonRepository; - private final GameRepository gameRepository; - private final TeamUserRepository teamUserRepository; - private final TeamRepository teamRepository; - private final RankRedisRepository redisRepository; - private final PChangeRepository pChangeRepository; - private final RankRepository rankRepository; - - public String getLoginAccessToken() { - User user = User.builder() - .eMail("email") - .intraId("intraId") - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return tokenProvider.createToken(user.getId()); - } - - public String getAdminLoginAccessToken() { - User user = User.builder() - .eMail("email") - .intraId("intraId") - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.ADMIN) - .totalExp(1000) - .build(); - userRepository.save(user); - return tokenProvider.createToken(user.getId()); - } - - public User createNewUser(){ - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(String intraId, String email, String imageUrl, RacketType racketType, - SnsType snsType, RoleType roleType){ - User user = User.builder() - .eMail(email) - .intraId(intraId) - .imageUri(imageUrl) - .racketType(racketType) - .snsNotiOpt(snsType) - .roleType(roleType) - .totalExp(0) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(int totalExp){ - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .imageUri("image") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(totalExp) - .build(); - userRepository.save(user); - return user; - } - - public GameInfoDto addMockDataUserLiveApi(String event, int notiCnt, String currentMatchMode, Long userId) { - User curUser = userRepository.findById(userId).get(); - for (int i = 0; i < notiCnt; i++) { - Noti noti = new Noti(curUser, NotiType.ANNOUNCE, String.valueOf(i), false); - notiRepository.save(noti); - } - LocalDateTime startTime, endTime; - Season season = createSeason(); - createUserRank(curUser, "testUserMessage", season); - Mode mode = (currentMatchMode == "RANK")? Mode.RANK : Mode.NORMAL; - createGame(curUser, LocalDateTime.now().minusMinutes(100), LocalDateTime.now().minusMinutes(85), season, mode); - createGame(curUser, LocalDateTime.now().minusMinutes(50), LocalDateTime.now().minusMinutes(35), season, mode); - LocalDateTime now = LocalDateTime.now(); - if (event.equals("match")){ - startTime = now.plusMinutes(10); - endTime = startTime.plusMinutes(15); - return createGame(curUser, startTime, endTime, season, mode); - }else if (event.equals("game")){ - startTime = now.minusMinutes(5); - endTime = startTime.plusMinutes(15); - return createGame(curUser, startTime, endTime, season, mode); - } - return null; - } - - public GameInfoDto createGame(User curUser, LocalDateTime startTime, LocalDateTime endTime, Season season, Mode mode) { - LocalDateTime now = LocalDateTime.now(); - Game game; - if (now.isBefore(startTime)) - game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); - else if (now.isAfter(startTime) && now.isBefore(endTime)) - game = new Game(season, StatusType.LIVE, mode, startTime, endTime); - else - game = new Game(season, StatusType.END, mode, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, -1, false); - TeamUser teamUser = new TeamUser(myTeam, curUser); - Team enemyTeam = new Team(game, -1, false); - User enemyUser = createNewUser(); - createUserRank(curUser, "statusMessage", season); - createUserRank(enemyUser, "enemyUserMeassage", season); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), enemyUser.getId()); - } - - - public Season createSeason(){ - LocalDateTime startTime = LocalDateTime.now(); - LocalDateTime endTime = startTime.plusMonths(1); - Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()).orElse(null); - if (season == null) - season = new Season("name", startTime, endTime, 1000, 300); - seasonRepository.save(season); - return season; - } - - public void createUserRank(User newUser, String statusMessage, Season season) { - if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) - return ; - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - redisRepository.addRankData(hashKey, newUser.getId(), - new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage)); - Rank userRank = Rank.builder() - .user(newUser) - .season(season) - .ppp(season.getStartPpp()) - .wins(0) - .losses(0) - .statusMessage(statusMessage) - .build(); - rankRepository.save(userRank); - } - - public void createUserRank(User newUser, String statusMessage, Season season, int ppp) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - redisRepository.addToZSet(zSetKey, newUser.getId(), ppp); - redisRepository.addRankData(hashKey, newUser.getId(), - new RankRedis(newUser.getId(), "aa", ppp, 1, 0, statusMessage)); - Rank userRank = Rank.builder() - .user(newUser) - .season(season) - .ppp(ppp) - .wins(1) - .losses(0) - .statusMessage(statusMessage) - .build(); - rankRepository.save(userRank); - } - - public void createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime) { - Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, 0, false); - TeamUser teamUser = new TeamUser(myTeam, newUser); - Team enemyTeam = new Team(game, 0, false); - User enemyUser = createNewUser(); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - PChange pChange1 = new PChange(game, newUser, 1100, true); - PChange pChange2 = new PChange(game, enemyUser, 900, true); - - pChangeRepository.save(pChange1); - pChangeRepository.save(pChange2); - } -} +package com.gg.server.utils; + +import com.gg.server.domain.game.data.Game; +import com.gg.server.domain.game.data.GameRepository; +import com.gg.server.domain.noti.data.Noti; +import com.gg.server.domain.noti.data.NotiRepository; +import com.gg.server.domain.noti.type.NotiType; +import com.gg.server.domain.pchange.data.PChange; +import com.gg.server.domain.pchange.data.PChangeRepository; +import com.gg.server.domain.rank.data.Rank; +import com.gg.server.domain.rank.data.RankRepository; +import com.gg.server.domain.rank.redis.RankRedis; +import com.gg.server.domain.rank.redis.RankRedisRepository; +import com.gg.server.domain.rank.redis.RedisKeyManager; +import com.gg.server.domain.season.data.Season; +import com.gg.server.domain.season.data.SeasonRepository; +import com.gg.server.domain.team.data.Team; +import com.gg.server.domain.team.data.TeamRepository; +import com.gg.server.domain.team.data.TeamUser; +import com.gg.server.domain.team.data.TeamUserRepository; +import com.gg.server.domain.tier.data.Tier; +import com.gg.server.domain.tier.data.TierRepository; +import com.gg.server.domain.user.data.User; +import com.gg.server.domain.user.data.UserRepository; +import com.gg.server.domain.user.controller.dto.GameInfoDto; +import com.gg.server.domain.user.type.RacketType; +import com.gg.server.domain.user.type.RoleType; +import com.gg.server.domain.user.type.SnsType; +import com.gg.server.global.security.jwt.utils.AuthTokenProvider; +import com.gg.server.domain.game.type.Mode; +import com.gg.server.domain.game.type.StatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Component +@RequiredArgsConstructor +public class TestDataUtils { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + private final NotiRepository notiRepository; + private final SeasonRepository seasonRepository; + private final GameRepository gameRepository; + private final TeamUserRepository teamUserRepository; + private final TeamRepository teamRepository; + private final RankRedisRepository redisRepository; + private final PChangeRepository pChangeRepository; + private final RankRepository rankRepository; + private final TierRepository tierRepository; + + public String getLoginAccessToken() { + User user = User.builder() + .eMail("email") + .intraId("intraId") + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return tokenProvider.createToken(user.getId()); + } + + public String getAdminLoginAccessToken() { + User user = User.builder() + .eMail("email") + .intraId("intraId") + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.ADMIN) + .totalExp(1000) + .build(); + userRepository.save(user); + return tokenProvider.createToken(user.getId()); + } + + public User createNewUser(){ + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser(String intraId, String email, RacketType racketType, + SnsType snsType, RoleType roleType){ + User user = User.builder() + .eMail(email) + .intraId(intraId) + .racketType(racketType) + .snsNotiOpt(snsType) + .roleType(roleType) + .totalExp(0) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser(int totalExp){ + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(totalExp) + .build(); + userRepository.save(user); + return user; + } + + public GameInfoDto addMockDataUserLiveApi(String event, int notiCnt, String currentMatchMode, Long userId) { + User curUser = userRepository.findById(userId).get(); + for (int i = 0; i < notiCnt; i++) { + Noti noti = new Noti(curUser, NotiType.ANNOUNCE, String.valueOf(i), false); + notiRepository.save(noti); + } + LocalDateTime startTime, endTime; + Season season = createSeason(); + createUserRank(curUser, "testUserMessage", season); + Mode mode = (currentMatchMode == "RANK")? Mode.RANK : Mode.NORMAL; + createGame(curUser, LocalDateTime.now().minusMinutes(100), LocalDateTime.now().minusMinutes(85), season, mode); + createGame(curUser, LocalDateTime.now().minusMinutes(50), LocalDateTime.now().minusMinutes(35), season, mode); + LocalDateTime now = LocalDateTime.now(); + if (event.equals("match")){ + startTime = now.plusMinutes(10); + endTime = startTime.plusMinutes(15); + return createGame(curUser, startTime, endTime, season, mode); + }else if (event.equals("game")){ + startTime = now.minusMinutes(5); + endTime = startTime.plusMinutes(15); + return createGame(curUser, startTime, endTime, season, mode); + } + return null; + } + + public GameInfoDto createGame(User curUser, LocalDateTime startTime, LocalDateTime endTime, Season season, Mode mode) { + LocalDateTime now = LocalDateTime.now(); + Game game; + if (now.isBefore(startTime)) + game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); + else if (now.isAfter(startTime) && now.isBefore(endTime)) + game = new Game(season, StatusType.LIVE, mode, startTime, endTime); + else + game = new Game(season, StatusType.END, mode, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, -1, false); + TeamUser teamUser = new TeamUser(myTeam, curUser); + Team enemyTeam = new Team(game, -1, false); + User enemyUser = createNewUser(); + createUserRank(curUser, "statusMessage", season); + createUserRank(enemyUser, "enemyUserMeassage", season); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), enemyUser.getId()); + } + + + public Season createSeason(){ + LocalDateTime startTime = LocalDateTime.now(); + LocalDateTime endTime = startTime.plusMonths(1); + Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()).orElse(null); + if (season == null) + season = new Season("name", startTime, endTime, 1000, 300); + seasonRepository.save(season); + return season; + } + + public void createUserRank(User newUser, String statusMessage, Season season) { + if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) + return ; + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(season.getStartPpp()) + .wins(0) + .losses(0) + .statusMessage(statusMessage) + .build(); + rankRepository.save(userRank); + } + + public void createUserRank(User newUser, String statusMessage, Season season, Tier tier) { + if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) + return ; + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(season.getStartPpp()) + .wins(0) + .losses(0) + .statusMessage(statusMessage) + .tier(tier) + .build(); + rankRepository.save(userRank); + } + + public void createUserRank(User newUser, String statusMessage, Season season, int ppp) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + Tier tier = tierRepository.getById(1L); + redisRepository.addToZSet(zSetKey, newUser.getId(), ppp); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", ppp, 1, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(ppp) + .wins(1) + .losses(0) + .statusMessage(statusMessage) + .tier(tier) + .build(); + rankRepository.save(userRank); + } + + public void createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime) { + Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, 0, false); + TeamUser teamUser = new TeamUser(myTeam, newUser); + Team enemyTeam = new Team(game, 0, false); + User enemyUser = createNewUser(); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + PChange pChange1 = new PChange(game, newUser, 1100, true); + PChange pChange2 = new PChange(game, enemyUser, 900, true); + + pChangeRepository.save(pChange1); + pChangeRepository.save(pChange2); + } +} diff --git a/version2.sql b/version2.sql new file mode 100644 index 000000000..f1854e9be --- /dev/null +++ b/version2.sql @@ -0,0 +1,96 @@ +-- item 삽입 -- +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (1, '2023-08-22 14:35:36.000000', 50, '/image/fallBackSrc.jpeg', false, '이미지 변경권', 84, 'taehkwon', 'hyobicho', 'PROFILE_IMAGE', '잘 지내? 프사 바꿨네', '프로필 이미지를 원하는 이미지로 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (2, '2023-08-22 14:37:06.000000', 50, '/image/fallBackSrc.jpeg', false, '확성기', 42, 'taehkwon', 'hyobicho', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - mryoo ??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다. 사용 다음날 적용됩니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (3, '2023-08-22 14:37:09.000000', 60, '/image/fallBackSrc.jpeg', false, '배경 뽑기', 5, 'taehkwon', 'hyobicho', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (4, '2023-08-22 14:37:12.000000', 60, '/image/fallBackSrc.jpeg', false, 'Edge 뽑기', 5, 'taehkwon', 'hyungjpa', 'EDGE', '난 \'Edge\'로 말해.. - sishin', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (5, '2023-08-22 14:40:29.000000', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 10, 'taehkwon', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (6, '2023-09-07 14:25:32.860487', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000000, 'hyobicho', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (7, '2023-09-07 14:43:45.486791', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000001, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (8, '2023-09-07 14:46:14.803651', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000002, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (9, '2023-09-07 14:49:56.836802', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000003, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (10, '2023-09-07 14:50:15.478127', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000004, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (11, '2023-09-07 14:56:39.419190', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000005, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (12, '2023-09-07 14:59:39.706389', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 1000005, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (13, '2023-09-07 16:20:07.594046', 50, '/image/fallBackSrc.jpeg', false, 'ID 색깔 변경권', 100, 'hyungjpa', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (14, '2023-09-07 18:49:57.274774', 60, '/image/fallBackSrc.jpeg', false, 'Edge 뽑기', 10000001, 'hyungjpa', 'sishin', 'EDGE', '난 \'Edge\'로 말해.. - sishin', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (15, '2023-09-07 21:19:06.689943', 60, '/image/fallBackSrc.jpeg', false, 'Edge 뽑기', 50, 'sishin', 'hyobicho', 'EDGE', '난 \'Edge\'로 말해.. - sishin', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (16, '2023-09-08 11:06:30.357904', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID 색깔 변경권', 100, 'hyobicho', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (17, '2023-09-08 11:09:54.808571', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/Edge%20%EB%BD%91%EA%B8%B0-4f2cc34d-a972-422d-b170-97902794b75f.jpeg', false, 'Edge 뽑기', 500000, 'hyobicho', 'hyobicho', 'EDGE', '난 \'Edge\'로 말해.. - sishin', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (18, '2023-09-08 11:10:19.901788', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/Edge%20%EB%BD%91%EA%B8%B0-4f2cc34d-a972-422d-b170-97902794b75f.jpeg', false, 'Edge 뽑기', 500000, 'hyobicho', 'sishin', 'EDGE', '난 \'Edge\'로 말해.. - sishin', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (19, '2023-09-08 11:10:45.220300', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5, 'hyobicho', 'hyobicho', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (20, '2023-09-08 11:11:07.098652', 50, '/image/fallBackSrc.jpeg', false, '확성기', 42, 'hyobicho', 'hyobicho', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - mryoo ?', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다. 사용 다음날 적용됩니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (21, '2023-09-08 11:11:34.309956', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'hyobicho', 'jeyoon', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - mryoo ?', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다. 사용 다음날 적용됩니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (22, '2023-09-08 11:11:56.429412', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EC%9D%B4%EB%AF%B8%EC%A7%80%20%EB%B3%80%EA%B2%BD%EA%B6%8C-665c9d5d-faf1-4114-9786-ed3be3014f69.jpeg', false, '이미지 변경권', 84, 'hyobicho', 'hyobicho', 'PROFILE_IMAGE', '잘 지내? 프사 바꿨네 - taehkwon', '프로필 이미지를 원하는 이미지로 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (23, '2023-09-08 11:14:21.271245', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/Edge%20%EB%BD%91%EA%B8%B0-4f2cc34d-a972-422d-b170-97902794b75f.jpeg', false, 'Edge 뽑기', 20, 'sishin', 'hyobicho', 'EDGE', '난 \'Edge\'로 말해.. - sishin?', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (24, '2023-09-08 11:59:44.397320', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EC%9D%B4%EB%AF%B8%EC%A7%80%20%EB%B3%80%EA%B2%BD%EA%B6%8C-665c9d5d-faf1-4114-9786-ed3be3014f69.jpeg', true, '프로필 변경', 84, 'hyobicho', null, 'PROFILE_IMAGE', '잘 지내? 프사 바꿨네 - taehkwon', '프로필 이미지를 원하는 이미지로 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (25, '2023-09-08 11:59:52.300983', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 100, 'hyobicho', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (26, '2023-09-08 12:00:29.804308', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5000000, 'hyobicho', 'jeyoon', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (27, '2023-09-08 13:03:58.770124', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 100, 'hyobicho', 'jeyoon', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요✨', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (28, '2023-09-08 14:32:30.497522', 90, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5000000, 'jeyoon', 'hyobicho', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (29, '2023-09-08 14:35:25.008156', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 100, 'jeyoon', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (30, '2023-09-08 14:46:18.458206', 40, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'jeyoon', 'taehkwon', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - mryoo??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다. 사용 다음날 적용됩니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (31, '2023-09-08 15:46:24.475018', 90, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5, 'hyobicho', 'sishin', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (32, '2023-09-08 15:46:45.129730', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 1000000, 'hyobicho', 'sishin', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (33, '2023-09-08 21:40:36.371683', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 50, 'sishin', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (34, '2023-09-09 14:54:15.161525', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 5000000, 'hyobicho', 'sishin', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (35, '2023-09-11 15:01:34.037890', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 500, 'sishin', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (36, '2023-09-12 10:32:10.583894', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 501, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (37, '2023-09-12 10:38:27.648500', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 502, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (38, '2023-09-12 10:41:22.608031', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 503, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (39, '2023-09-12 10:45:27.686939', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 504, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (40, '2023-09-12 10:45:51.547954', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 505, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (41, '2023-09-12 10:51:33.271699', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 504, 'hyungjpa', 'hyungjpa', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요?', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (42, '2023-09-12 10:54:28.684097', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 505, 'hyungjpa', 'taehkwon', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (43, '2023-09-12 11:16:13.791072', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 505, 'taehkwon', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (44, '2023-09-12 11:16:26.258550', 40, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'taehkwon', null, 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - mryoo ??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다. 사용 다음날 적용됩니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (45, '2023-09-12 11:34:17.000000', 20, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'taehkwon', 'hyobicho', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 - ??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (46, '2023-09-12 11:39:57.908793', 90, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5, 'sishin', 'hyungjpa', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (47, '2023-09-12 11:46:30.148192', 80, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5, 'hyungjpa', 'hyobicho', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (48, '2023-09-12 14:11:30.618603', 20, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'hyobicho', 'hyobicho', 'MEGAPHONE', '오늘 42GG는 내가 접수한다??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (49, '2023-09-12 14:11:50.159040', 20, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'hyobicho', 'hyobicho', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 ??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (50, '2023-09-12 14:12:19.335975', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 뽑기', 5, 'hyobicho', 'hyungjpa', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (51, '2023-09-12 14:12:35.457404', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/Edge%20%EB%BD%91%EA%B8%B0-4f2cc34d-a972-422d-b170-97902794b75f.jpeg', false, 'Edge 뽑기', 5, 'hyobicho', 'jeyoon', 'EDGE', '난 \'Edge\'로 말해.. - sishin?', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (52, '2023-09-12 14:12:49.003946', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'hyobicho', 'jeyoon', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 ??', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (53, '2023-09-12 14:13:02.626201', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 50000000, 'hyobicho', 'hyobicho', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (54, '2023-09-12 14:13:15.572310', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 50000000, 'hyobicho', 'hyobicho', 'TEXT_COLOR', '(테스트)남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (55, '2023-09-12 15:03:09.397488', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 10, 'hyobicho', 'jeyoon', 'TEXT_COLOR', '남들과는 다르게! ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (56, '2023-09-12 15:22:44.392857', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', false, 'ID색깔 변경', 10, 'jeyoon', 'jeyoon', 'TEXT_COLOR', '남들과는 다르게! >_< ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (57, '2023-09-12 15:45:23.881988', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', false, '확성기', 42, 'jeyoon', 'jeyoon', 'MEGAPHONE', '오늘 42GG는 내가 접수한다 ?', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (58, '2023-09-12 15:46:03.038523', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%ED%99%95%EC%84%B1%EA%B8%B0-21d5dccf-0a5a-48e3-a29c-014776a33cbf.jpeg', true, '확성기', 42, 'jeyoon', null, 'MEGAPHONE', '오늘 42GG는 내가 접수한다 ?', '24시간 동안 모든 페이지 상단에 메시지를 띄울 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (59, '2023-09-13 11:27:29.751601', 50, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/ID%20%EC%83%89%EA%B9%94%20%EB%B3%80%EA%B2%BD%EA%B6%8C-8f558fa8-c5f5-4c76-9aad-fb12850034a5.jpeg', true, 'ID색깔 변경', 10, 'jeyoon', null, 'TEXT_COLOR', '남들과는 다르게!? ID 색깔을 바꿔보세요!', '색상코드를 직접 입력하여 랭킹 페이지의 ID 색상을 바꿀 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (60, '2023-09-15 12:43:42.907735', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/Edge%20%EB%BD%91%EA%B8%B0-4f2cc34d-a972-422d-b170-97902794b75f.jpeg', true, '엣지 ★ 뽑기', 5, 'jeyoon', null, 'EDGE', '난 \'Edge\'로 말해.. - sishin?', '랜덤으로 프로필 테두리 색상을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (61, '2023-09-15 13:48:31.443011', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경★뽑기', 5, 'hyungjpa', 'hyungjpa', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (62, '2023-09-15 13:49:02.078651', 60, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', false, '배경 ★ 뽑기', 5, 'hyungjpa', 'jeyoon', 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +INSERT INTO MAIN.item (id, created_at, discount, image_uri, is_visible, name, price, creator_intra_id, deleter_intra_id, type, main_content, sub_content) VALUES (63, '2023-09-18 23:41:36.279521', 0, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/images/%EB%B0%B0%EA%B2%BD%20%EB%BD%91%EA%B8%B0-5aefd489-224b-4481-b2fa-d08da21fef92.jpeg', true, '배경 ★ 뽑기', 5, 'jeyoon', null, 'BACKGROUND', '난 \'Background\'부터가 달라 - klew ?', '랜덤으로 내 프로필 페이지의 배경을 변경할 수 있는 아이템입니다.'); +-- tier 삽입 -- +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (1, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/hand.png', '손바닥'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (2, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/new_red.png', '빨강 탁구채'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (3, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/yellow.png', '노랑 탁구채'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (4, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/new_green.png', '초록 탁구채'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (5, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/blue.png', '파랑 탁구채'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (6, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/black.png', '검정 탁구채'); +INSERT INTO MAIN.tier (id, image_uri, name) VALUES (7, 'https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/new_rainbow.png', '무지개 탁구채'); +-- coin policy 삽입 -- +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (1, 519, 0, '2023-08-23 11:13:56.679461', 2, 4, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (2, 519, 0, '2023-08-23 11:32:24.664774', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (3, 519, 0, '2023-08-23 13:14:44.954698', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (4, 479, 0, '2023-08-24 10:54:28.328821', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (5, 479, 0, '2023-08-24 10:56:58.974651', 10, 10, 10); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (6, 479, 0, '2023-08-24 10:57:28.292756', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (7, 538, 0, '2023-08-24 11:44:08.657610', 20, 20, 20); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (8, 538, 0, '2023-08-24 11:44:55.125563', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (9, 519, 0, '2023-09-12 10:09:21.339375', 2, 1, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (10, 519, 0, '2023-09-12 10:09:31.922474', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (11, 519, 0, '2023-09-13 11:45:44.627234', 2, 1, 1); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (12, 519, 0, '2023-09-13 11:46:09.009349', 2, 100, 97); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (13, 519, 0, '2023-09-13 11:46:16.664177', 2, 100, 101); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (14, 519, 0, '2023-09-13 11:46:29.574440', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (15, 519, 0, '2023-09-13 11:48:57.729986', 2, 1, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (16, 519, 0, '2023-09-13 11:49:02.751738', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (17, 538, 0, '2023-09-14 10:37:39.008358', 100, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (18, 538, 0, '2023-09-14 10:37:45.892845', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (19, 538, 0, '2023-09-14 10:38:19.264695', 2, 0, 9); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (20, 538, 0, '2023-09-14 10:38:34.185202', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (21, 479, 0, '2023-09-14 11:00:39.986649', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (22, 479, 0, '2023-09-14 11:02:04.693812', 2, 0, 5); +INSERT INTO MAIN.coin_policy (id, user_id, attendance, created_at, normal, rank_lose, rank_win) VALUES (23, 519, 1, '2023-09-19 16:37:05.665019', 2, 0, 5);