diff --git a/README.md b/README.md index 1d821fb..4a661be 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ 해당 프로젝트는 SOPT 32th APPJAM 프로젝트입니다. +Sparkle, 연인과 승부를 통한 설렘 가득 소원권 내기 앱 서비스입니다. + ## Contributors [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) @@ -94,3 +96,21 @@ hotfix : 출시 버전에서 발생한 버그를 수정 하는 브랜치 └── test ``` + +### 역할 분담 +``` +박진수 +DB 설계, AWS 인프라, CD 구성, User 도메인 및 소셜 로그인 api, 잡일 +``` +``` +이영주 +DB 설계, CI구성, 소원권 및 미션 카테고리 api +``` +``` +신지연 +DB 설계, 한판 승부 및 승부 히스토리 api +``` + +### Architecture + +image diff --git a/src/main/java/com/universe/uni/controller/ShortGameController.java b/src/main/java/com/universe/uni/controller/ShortGameController.java new file mode 100644 index 0000000..2243e6d --- /dev/null +++ b/src/main/java/com/universe/uni/controller/ShortGameController.java @@ -0,0 +1,28 @@ +package com.universe.uni.controller; + +import javax.validation.Valid; + +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 com.universe.uni.dto.request.CreateShortGameRequestDto; +import com.universe.uni.dto.response.CreateShortGameResponseDto; +import com.universe.uni.service.GameService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/game/short") +public class ShortGameController { + + private final GameService gameService; + + @PostMapping + public CreateShortGameResponseDto createShortGame(@RequestBody @Valid final CreateShortGameRequestDto createShortGameRequestDto) { + return gameService.createShortGame(createShortGameRequestDto); + } + +} diff --git a/src/main/java/com/universe/uni/controller/WishCouponController.java b/src/main/java/com/universe/uni/controller/WishCouponController.java index c4b4beb..2dc9a74 100644 --- a/src/main/java/com/universe/uni/controller/WishCouponController.java +++ b/src/main/java/com/universe/uni/controller/WishCouponController.java @@ -1,7 +1,9 @@ package com.universe.uni.controller; import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; @@ -9,6 +11,7 @@ import com.universe.uni.dto.request.UpdateWishCouponRequestDto; import com.universe.uni.dto.response.UpdateWishCouponResponseDto; +import com.universe.uni.dto.response.WishCouponResponseDto; import com.universe.uni.service.WishCouponService; import lombok.RequiredArgsConstructor; @@ -22,9 +25,19 @@ public class WishCouponController { @PatchMapping @ResponseStatus(HttpStatus.OK) - public UpdateWishCouponResponseDto updateWishCoupon( - @RequestBody UpdateWishCouponRequestDto requestDto - ) { + public UpdateWishCouponResponseDto updateWishCoupon(@RequestBody UpdateWishCouponRequestDto requestDto) { return wishCouponService.uploadWishCoupon(requestDto); } + + @PatchMapping("/{wishCouponId}") + @ResponseStatus(HttpStatus.OK) + public void useWishCoupon(@PathVariable Long wishCouponId) { + wishCouponService.useWishCoupon(wishCouponId); + } + + @GetMapping("/{wishCouponId}") + @ResponseStatus(HttpStatus.OK) + public WishCouponResponseDto wishCouponResponseDto(@PathVariable Long wishCouponId) { + return wishCouponService.getWishCoupon(wishCouponId); + } } diff --git a/src/main/java/com/universe/uni/domain/GameResult.java b/src/main/java/com/universe/uni/domain/GameResult.java index 0dceae4..ca375b7 100644 --- a/src/main/java/com/universe/uni/domain/GameResult.java +++ b/src/main/java/com/universe/uni/domain/GameResult.java @@ -4,7 +4,7 @@ import java.util.Objects; public enum GameResult { - WIN, LOSE, DRAW; + WIN, LOSE, DRAW, UNDECIDED; public static GameResult findMatchResultBy(String gameResultName) { return Arrays.stream(values()) diff --git a/src/main/java/com/universe/uni/domain/entity/Game.java b/src/main/java/com/universe/uni/domain/entity/Game.java index 3c6bee6..f877eae 100644 --- a/src/main/java/com/universe/uni/domain/entity/Game.java +++ b/src/main/java/com/universe/uni/domain/entity/Game.java @@ -41,4 +41,9 @@ public class Game { @Column(name = "finish_at") private LocalDateTime finishAt; + + public Game(Couple couple) { + this.couple = couple; + this.enable = Boolean.TRUE; + } } diff --git a/src/main/java/com/universe/uni/domain/entity/MissionCategory.java b/src/main/java/com/universe/uni/domain/entity/MissionCategory.java index 6f07671..11f07f7 100644 --- a/src/main/java/com/universe/uni/domain/entity/MissionCategory.java +++ b/src/main/java/com/universe/uni/domain/entity/MissionCategory.java @@ -9,13 +9,14 @@ import javax.persistence.Table; import com.universe.uni.domain.MissionType; -import com.universe.uni.domain.entity.convertor.GameResultAttributeConverter; import com.universe.uni.domain.entity.convertor.MissionTypeAttributeConverter; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; @Entity +@Getter @Table(name = "mission_category") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class MissionCategory { diff --git a/src/main/java/com/universe/uni/domain/entity/RoundGame.java b/src/main/java/com/universe/uni/domain/entity/RoundGame.java index 0d5ecba..6ee7fa6 100644 --- a/src/main/java/com/universe/uni/domain/entity/RoundGame.java +++ b/src/main/java/com/universe/uni/domain/entity/RoundGame.java @@ -11,6 +11,7 @@ import javax.persistence.Table; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -39,4 +40,11 @@ public class RoundGame { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_game_history_id") private UserGameHistory userGameHistory; + + @Builder + public RoundGame(Game game, MissionCategory missionCategory) { + this.game = game; + this.missionCategory = missionCategory; + this.enable = Boolean.TRUE; + } } diff --git a/src/main/java/com/universe/uni/domain/entity/RoundMission.java b/src/main/java/com/universe/uni/domain/entity/RoundMission.java index 488a50e..bf04560 100644 --- a/src/main/java/com/universe/uni/domain/entity/RoundMission.java +++ b/src/main/java/com/universe/uni/domain/entity/RoundMission.java @@ -17,6 +17,7 @@ import com.universe.uni.domain.entity.convertor.GameResultAttributeConverter; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -53,4 +54,13 @@ public class RoundMission { @Column(name = "final_result") @Convert(converter = GameResultAttributeConverter.class) private GameResult finalResult; + + @Builder + public RoundMission(RoundGame roundGame, MissionContent missionContent, User user) { + this.roundGame = roundGame; + this.missionContent = missionContent; + this.user = user; + this.result = GameResult.UNDECIDED; + this.finalResult = GameResult.UNDECIDED; + } } diff --git a/src/main/java/com/universe/uni/domain/entity/ShortGame.java b/src/main/java/com/universe/uni/domain/entity/ShortGame.java index 12fbf13..b8075bd 100644 --- a/src/main/java/com/universe/uni/domain/entity/ShortGame.java +++ b/src/main/java/com/universe/uni/domain/entity/ShortGame.java @@ -5,6 +5,7 @@ import javax.persistence.PrimaryKeyJoinColumn; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -15,4 +16,8 @@ @PrimaryKeyJoinColumn(name = "game_id") public class ShortGame extends Game { + @Builder + public ShortGame(Couple couple) { + super(couple); + } } diff --git a/src/main/java/com/universe/uni/domain/entity/User.java b/src/main/java/com/universe/uni/domain/entity/User.java index fc1ce0e..85436f9 100644 --- a/src/main/java/com/universe/uni/domain/entity/User.java +++ b/src/main/java/com/universe/uni/domain/entity/User.java @@ -11,6 +11,7 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.universe.uni.domain.SnsType; import com.universe.uni.domain.entity.convertor.SnsTypeAttributeConverter; diff --git a/src/main/java/com/universe/uni/domain/entity/UserGameHistory.java b/src/main/java/com/universe/uni/domain/entity/UserGameHistory.java index b1db018..45ce0f2 100644 --- a/src/main/java/com/universe/uni/domain/entity/UserGameHistory.java +++ b/src/main/java/com/universe/uni/domain/entity/UserGameHistory.java @@ -26,7 +26,7 @@ import static lombok.AccessLevel.PROTECTED; @Entity -@Table(name = "user_match_history") +@Table(name = "user_game_history") @NoArgsConstructor(access = PROTECTED) @AllArgsConstructor(access = AccessLevel.PROTECTED) @Getter diff --git a/src/main/java/com/universe/uni/domain/entity/WishCoupon.java b/src/main/java/com/universe/uni/domain/entity/WishCoupon.java index b43262b..7339aa4 100644 --- a/src/main/java/com/universe/uni/domain/entity/WishCoupon.java +++ b/src/main/java/com/universe/uni/domain/entity/WishCoupon.java @@ -49,7 +49,7 @@ public class WishCoupon { private LocalDateTime usedAt; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id", nullable = false) + @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) @@ -61,15 +61,12 @@ public class WishCoupon { private GameType gameType; @Builder - public WishCoupon(Long id, String image, String content, boolean isVisible, boolean isUsed, LocalDateTime usedAt, - User user, Game game, GameType gameType) { - this.id = id; + public WishCoupon(String image, String content, boolean isVisible, + Game game, GameType gameType) { this.image = image; this.content = content; this.isVisible = isVisible; - this.isUsed = isUsed; - this.usedAt = usedAt; - this.user = user; + this.isUsed = Boolean.FALSE; this.game = game; this.gameType = gameType; } @@ -81,4 +78,9 @@ public void updateContent(String content) { public void makeVisible() { this.isVisible = true; } + + public void useWishCoupon() { + this.isUsed = true; + this.usedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/universe/uni/dto/request/CreateShortGameRequestDto.java b/src/main/java/com/universe/uni/dto/request/CreateShortGameRequestDto.java new file mode 100644 index 0000000..3cfa9f8 --- /dev/null +++ b/src/main/java/com/universe/uni/dto/request/CreateShortGameRequestDto.java @@ -0,0 +1,15 @@ +package com.universe.uni.dto.request; + +import javax.validation.constraints.NotNull; + +import lombok.Getter; + +@Getter +public class CreateShortGameRequestDto { + + @NotNull + private Long missionCategoryId; + + @NotNull + private String wishContent; +} diff --git a/src/main/java/com/universe/uni/dto/response/CreateShortGameResponseDto.java b/src/main/java/com/universe/uni/dto/response/CreateShortGameResponseDto.java new file mode 100644 index 0000000..0b5fdd8 --- /dev/null +++ b/src/main/java/com/universe/uni/dto/response/CreateShortGameResponseDto.java @@ -0,0 +1,18 @@ +package com.universe.uni.dto.response; + +import com.universe.uni.domain.entity.RoundMission; +import com.universe.uni.domain.entity.ShortGame; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class CreateShortGameResponseDto { + private ShortGameDto shortGame; + private RoundMissionDto roundMission; + + public static CreateShortGameResponseDto of(ShortGame shortGame, RoundMission roundMission) { + return new CreateShortGameResponseDto(new ShortGameDto(shortGame), new RoundMissionDto(roundMission)); + } +} diff --git a/src/main/java/com/universe/uni/dto/response/RoundMissionDto.java b/src/main/java/com/universe/uni/dto/response/RoundMissionDto.java new file mode 100644 index 0000000..305f8c3 --- /dev/null +++ b/src/main/java/com/universe/uni/dto/response/RoundMissionDto.java @@ -0,0 +1,26 @@ +package com.universe.uni.dto.response; + +import java.time.LocalDateTime; + +import com.universe.uni.domain.GameResult; +import com.universe.uni.domain.entity.MissionContent; +import com.universe.uni.domain.entity.RoundMission; + +import lombok.Getter; + +@Getter +public class RoundMissionDto { + private long roundMissionId; + private MissionContent missionContent; + private GameResult result; + private GameResult finalResult; + private LocalDateTime updatedAt; + + public RoundMissionDto(RoundMission roundMission){ + this.roundMissionId = roundMission.getId(); + this.missionContent = roundMission.getMissionContent(); + this.result = roundMission.getResult(); + this.finalResult = roundMission.getFinalResult(); + this.updatedAt = roundMission.getUpdatedAt(); + } +} diff --git a/src/main/java/com/universe/uni/dto/response/ShortGameDto.java b/src/main/java/com/universe/uni/dto/response/ShortGameDto.java new file mode 100644 index 0000000..85df1eb --- /dev/null +++ b/src/main/java/com/universe/uni/dto/response/ShortGameDto.java @@ -0,0 +1,21 @@ +package com.universe.uni.dto.response; + +import java.time.LocalDateTime; + +import com.universe.uni.domain.entity.ShortGame; + +import lombok.Getter; + +@Getter +public class ShortGameDto { + private Long id; + private Boolean enable; + private LocalDateTime finishAt; + + public ShortGameDto(ShortGame shortGame) { + this.id = shortGame.getId(); + this.enable = shortGame.getEnable(); + this.finishAt = shortGame.getFinishAt(); + } + +} diff --git a/src/main/java/com/universe/uni/dto/response/WishCouponResponseDto.java b/src/main/java/com/universe/uni/dto/response/WishCouponResponseDto.java new file mode 100644 index 0000000..09ac96e --- /dev/null +++ b/src/main/java/com/universe/uni/dto/response/WishCouponResponseDto.java @@ -0,0 +1,20 @@ +package com.universe.uni.dto.response; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import lombok.Builder; + +@JsonPropertyOrder({"id", "isMine", "image", "content", "isVisible", "isUsed", "usedAt", "gameType"}) +@Builder +public record WishCouponResponseDto( + Long id, + boolean isMine, + String image, + String content, + @JsonProperty("isVisible") boolean visible, + @JsonProperty("isUsed") boolean used, + String usedAt, + String gameType +) { +} diff --git a/src/main/java/com/universe/uni/exception/dto/ErrorType.java b/src/main/java/com/universe/uni/exception/dto/ErrorType.java index 71aeb37..2a4493b 100644 --- a/src/main/java/com/universe/uni/exception/dto/ErrorType.java +++ b/src/main/java/com/universe/uni/exception/dto/ErrorType.java @@ -17,6 +17,8 @@ public enum ErrorType { "요청 방식이 잘못된 경우입니다. 요청 방식 자체가 잘못된 경우입니다."), VALIDATION_TOKEN_MISSING_EXCEPTION(HttpStatus.BAD_REQUEST, "UE1002", "요청 시 토큰이 누락되어 토큰 값이 없는 경우입니다."), + ALREADY_GAME_CREATED(HttpStatus.BAD_REQUEST, "UE1003", + "이미 생성된 승부가 있습니다."), /** * 401 Unauthorized @@ -32,6 +34,9 @@ public enum ErrorType { "잘못된 endpoint에 요청한 경우입니다."), USER_NOT_FOUND_EXCEPTION(HttpStatus.NOT_FOUND, "UE5002", "조회한 유저가 존재하지 않는 경우 입니다."), + NOT_FOUND_MISSION_CATEGORY_EXCEPTION(HttpStatus.NOT_FOUND, "UE5003", "존재하지 않는 미션 카테고리입니다"), + NOT_FOUND_MISSION_CONTENT(HttpStatus.NOT_FOUND, "UE5004", "해당 카테고리 미션이 존재하지 않습니다."), + NOT_FOUND_ROUND_MISSION(HttpStatus.NOT_FOUND, "UE5005", "해당 라운드 미션이 존재하지 않습니다."), /** * 406 Not Acceptable diff --git a/src/main/java/com/universe/uni/repository/GameRepository.java b/src/main/java/com/universe/uni/repository/GameRepository.java new file mode 100644 index 0000000..b547eee --- /dev/null +++ b/src/main/java/com/universe/uni/repository/GameRepository.java @@ -0,0 +1,11 @@ +package com.universe.uni.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.universe.uni.domain.entity.Couple; +import com.universe.uni.domain.entity.Game; + +public interface GameRepository extends JpaRepository { + + boolean existsByCoupleAndEnable(Couple couple, boolean enable); +} diff --git a/src/main/java/com/universe/uni/repository/MissionCategoryRepository.java b/src/main/java/com/universe/uni/repository/MissionCategoryRepository.java new file mode 100644 index 0000000..845a481 --- /dev/null +++ b/src/main/java/com/universe/uni/repository/MissionCategoryRepository.java @@ -0,0 +1,8 @@ +package com.universe.uni.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.universe.uni.domain.entity.MissionCategory; + +public interface MissionCategoryRepository extends JpaRepository { +} diff --git a/src/main/java/com/universe/uni/repository/MissionContentRepository.java b/src/main/java/com/universe/uni/repository/MissionContentRepository.java new file mode 100644 index 0000000..121d21a --- /dev/null +++ b/src/main/java/com/universe/uni/repository/MissionContentRepository.java @@ -0,0 +1,12 @@ +package com.universe.uni.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.universe.uni.domain.entity.MissionCategory; +import com.universe.uni.domain.entity.MissionContent; + +public interface MissionContentRepository extends JpaRepository { + List findByMissionCategory(MissionCategory missionCategory); +} diff --git a/src/main/java/com/universe/uni/repository/RoundGameRepository.java b/src/main/java/com/universe/uni/repository/RoundGameRepository.java new file mode 100644 index 0000000..74acdc0 --- /dev/null +++ b/src/main/java/com/universe/uni/repository/RoundGameRepository.java @@ -0,0 +1,8 @@ +package com.universe.uni.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.universe.uni.domain.entity.RoundGame; + +public interface RoundGameRepository extends JpaRepository { +} diff --git a/src/main/java/com/universe/uni/repository/RoundMissionRepository.java b/src/main/java/com/universe/uni/repository/RoundMissionRepository.java new file mode 100644 index 0000000..6943ba7 --- /dev/null +++ b/src/main/java/com/universe/uni/repository/RoundMissionRepository.java @@ -0,0 +1,13 @@ +package com.universe.uni.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.universe.uni.domain.entity.RoundGame; +import com.universe.uni.domain.entity.RoundMission; +import com.universe.uni.domain.entity.User; + +public interface RoundMissionRepository extends JpaRepository { + Optional findByRoundGameAndUser(RoundGame roundGame, User user); +} diff --git a/src/main/java/com/universe/uni/repository/UserRepository.java b/src/main/java/com/universe/uni/repository/UserRepository.java index 87b8c74..b885fba 100644 --- a/src/main/java/com/universe/uni/repository/UserRepository.java +++ b/src/main/java/com/universe/uni/repository/UserRepository.java @@ -1,8 +1,13 @@ package com.universe.uni.repository; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import com.universe.uni.domain.entity.Couple; import com.universe.uni.domain.entity.User; public interface UserRepository extends JpaRepository { + List findByCouple(Couple couple); + } diff --git a/src/main/java/com/universe/uni/service/GameService.java b/src/main/java/com/universe/uni/service/GameService.java new file mode 100644 index 0000000..7dcb315 --- /dev/null +++ b/src/main/java/com/universe/uni/service/GameService.java @@ -0,0 +1,109 @@ +package com.universe.uni.service; + +import static com.universe.uni.exception.dto.ErrorType.*; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.universe.uni.domain.entity.Couple; +import com.universe.uni.domain.entity.MissionCategory; +import com.universe.uni.domain.entity.RoundGame; +import com.universe.uni.domain.entity.RoundMission; +import com.universe.uni.domain.entity.ShortGame; +import com.universe.uni.domain.entity.User; +import com.universe.uni.domain.entity.WishCoupon; +import com.universe.uni.dto.request.CreateShortGameRequestDto; +import com.universe.uni.dto.response.CreateShortGameResponseDto; +import com.universe.uni.exception.BadRequestException; +import com.universe.uni.exception.NotFoundException; +import com.universe.uni.repository.GameRepository; +import com.universe.uni.repository.RoundGameRepository; +import com.universe.uni.repository.RoundMissionRepository; +import com.universe.uni.repository.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class GameService { + + private final GameRepository gameRepository; + private final RoundGameRepository roundGameRepository; + private final RoundMissionRepository roundMissionRepository; + private final UserRepository userRepository; + private final MissionService missionService; + private final WishCouponService wishCouponService; + + @Transactional + public CreateShortGameResponseDto createShortGame(CreateShortGameRequestDto createShortGameRequestDto) { + + User user = getUser(); + Couple couple = user.getCouple(); + + verifyOngoingGame(couple); + + //한판승부 생성 + ShortGame shortGame = ShortGame.builder() + .couple(couple) + .build(); + + //미션 카테고리 가져와서 + MissionCategory missionCategory= missionService + .getMissionCategoryById(createShortGameRequestDto.getMissionCategoryId()); + + //roundGame 생성 + RoundGame roundGame = RoundGame.builder() + .game(shortGame) + .missionCategory(missionCategory) + .build(); + + //커플 유저 둘 다 가져와서 roundMission 만들어주기 + List userList = userRepository.findByCouple(getUser().getCouple()); + List roundMissionList = userList.stream() + .map(u -> createRoundMission(roundGame, u)) + .collect(Collectors.toList()); + + //소원권 생성 + WishCoupon wishCoupon = wishCouponService.issueWishCoupon(createShortGameRequestDto.getWishContent(), + shortGame); + + gameRepository.save(shortGame); + roundGameRepository.save(roundGame); + roundMissionRepository.saveAll(roundMissionList); + wishCouponService.saveWishCoupon(wishCoupon); + + + RoundMission myRoundMission = getRoundMissionByRoundGameAndUser(roundGame, user); + + return CreateShortGameResponseDto.of(shortGame, myRoundMission); + } + + private RoundMission createRoundMission(RoundGame roundGame, User user) { + return RoundMission.builder() + .roundGame(roundGame) + .user(user) + .missionContent(missionService.getMissionContentByRandom(roundGame.getMissionCategory())) + .build(); + } + + private RoundMission getRoundMissionByRoundGameAndUser(RoundGame roundGame, User user) { + return roundMissionRepository.findByRoundGameAndUser(roundGame, user) + .orElseThrow(() -> new NotFoundException(NOT_FOUND_ROUND_MISSION)); + } + + //임시 : 유저 가져오는 함수 + private User getUser() { + Optional byId = userRepository.findById(1L); + return byId.get(); + } + + private void verifyOngoingGame(Couple couple) { + if(gameRepository.existsByCoupleAndEnable(couple, true)) { + throw new BadRequestException(ALREADY_GAME_CREATED); + } + } +} diff --git a/src/main/java/com/universe/uni/service/MissionService.java b/src/main/java/com/universe/uni/service/MissionService.java new file mode 100644 index 0000000..8eb9fc1 --- /dev/null +++ b/src/main/java/com/universe/uni/service/MissionService.java @@ -0,0 +1,41 @@ +package com.universe.uni.service; + +import static com.universe.uni.exception.dto.ErrorType.*; + +import java.util.List; +import java.util.Random; + +import org.springframework.stereotype.Service; + +import com.universe.uni.domain.entity.MissionCategory; +import com.universe.uni.domain.entity.MissionContent; +import com.universe.uni.exception.NotFoundException; +import com.universe.uni.repository.MissionCategoryRepository; +import com.universe.uni.repository.MissionContentRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MissionService { + + private final MissionCategoryRepository missionCategoryRepository; + private final MissionContentRepository missionContentRepository; + + public MissionCategory getMissionCategoryById(Long missionCategoryId) { + return missionCategoryRepository.findById(missionCategoryId) + .orElseThrow(() -> new NotFoundException(NOT_FOUND_MISSION_CATEGORY_EXCEPTION)); + } + + public MissionContent getMissionContentByRandom(MissionCategory missionCategory) { + List missionContentList = missionContentRepository + .findByMissionCategory(missionCategory); + + try { + int randomIndex = new Random().nextInt(missionContentList.size()); + return missionContentList.get(randomIndex); + } catch (Exception exception) { + throw new NotFoundException(NOT_FOUND_MISSION_CONTENT); + } + } +} diff --git a/src/main/java/com/universe/uni/service/WishCouponService.java b/src/main/java/com/universe/uni/service/WishCouponService.java index 0b1c1d7..687ada2 100644 --- a/src/main/java/com/universe/uni/service/WishCouponService.java +++ b/src/main/java/com/universe/uni/service/WishCouponService.java @@ -6,10 +6,13 @@ import org.springframework.transaction.annotation.Transactional; import com.universe.uni.domain.GameType; +import com.universe.uni.domain.entity.Game; import com.universe.uni.domain.entity.WishCoupon; import com.universe.uni.dto.request.UpdateWishCouponRequestDto; import com.universe.uni.dto.response.UpdateWishCouponResponseDto; +import com.universe.uni.dto.response.WishCouponResponseDto; import com.universe.uni.exception.BadRequestException; +import com.universe.uni.exception.NotFoundException; import com.universe.uni.exception.dto.ErrorType; import com.universe.uni.repository.WishCouponRepository; @@ -25,8 +28,8 @@ public class WishCouponService { @Transactional public UpdateWishCouponResponseDto uploadWishCoupon(UpdateWishCouponRequestDto requestDto) { GameType gameType = GameType.valueOf(requestDto.gameType()); - List wishCouponList = wishCouponRepository.findByGameTypeAndIsVisibleFalseAndIsUsedFalseAndUsedAtIsNull( - gameType); + List wishCouponList = wishCouponRepository + .findByGameTypeAndIsVisibleFalseAndIsUsedFalseAndUsedAtIsNull(gameType); if (wishCouponList.isEmpty()) { throw new BadRequestException(ErrorType.INVALID_REQUEST_METHOD); @@ -37,10 +40,23 @@ public UpdateWishCouponResponseDto uploadWishCoupon(UpdateWishCouponRequestDto r wishCoupon.updateContent(requestDto.content()); wishCoupon.makeVisible(); - return fromWishCoupon(wishCoupon); + return fromWishCouponToUpdateWishCouponResponseDto(wishCoupon); } - private UpdateWishCouponResponseDto fromWishCoupon(WishCoupon wishCoupon) { + public void useWishCoupon(Long wishCouponId) { + WishCoupon wishCoupon = wishCouponRepository.findById(wishCouponId) + .orElseThrow(() -> new NotFoundException(ErrorType.INVALID_ENDPOINT_EXCEPTION)); + + wishCoupon.useWishCoupon(); + } + + public WishCouponResponseDto getWishCoupon(Long wishCouponId) { + WishCoupon wishCoupon = wishCouponRepository.findById(wishCouponId) + .orElseThrow(() -> new NotFoundException(ErrorType.INVALID_ENDPOINT_EXCEPTION)); + return fromWishCouponToWishCouponResponseDto(wishCoupon); + } + + private UpdateWishCouponResponseDto fromWishCouponToUpdateWishCouponResponseDto(WishCoupon wishCoupon) { String usedAt = wishCoupon.getUsedAt() != null ? wishCoupon.getUsedAt().toString() : null; return UpdateWishCouponResponseDto.builder() @@ -53,4 +69,43 @@ private UpdateWishCouponResponseDto fromWishCoupon(WishCoupon wishCoupon) { .gameType(String.valueOf(wishCoupon.getGameType())) .build(); } + + public WishCoupon issueWishCoupon(String content, Game game) { + if(content == null || content.isEmpty()) { + return createWishCoupon(content, game, false); + } else { + return createWishCoupon(content, game, true); + } + } + + private WishCoupon createWishCoupon(String content, Game game, Boolean isVisible) { + return WishCoupon.builder() + .content(content) + .isVisible(isVisible) + .game(game) + .gameType(GameType.SHORT) + .build(); + } + + @Transactional + public void saveWishCoupon(WishCoupon wishCoupon) { + wishCouponRepository.save(wishCoupon); + } + + private WishCouponResponseDto fromWishCouponToWishCouponResponseDto(WishCoupon wishCoupon) { + /** TODO 영주 : 추후 1L 내 userId로 바꾸기*/ + boolean isMine = wishCoupon.getUser().getId() == 1L; + String usedAt = wishCoupon.getUsedAt() != null ? wishCoupon.getUsedAt().toString() : null; + + return WishCouponResponseDto.builder() + .id(wishCoupon.getId()) + .isMine(isMine) + .image(wishCoupon.getImage()) + .content(wishCoupon.getContent()) + .visible(wishCoupon.isVisible()) + .used(wishCoupon.isUsed()) + .usedAt(usedAt) + .gameType(String.valueOf(wishCoupon.getGameType())) + .build(); + } } diff --git a/uni-config b/uni-config index baa0dcf..b67041c 160000 --- a/uni-config +++ b/uni-config @@ -1 +1 @@ -Subproject commit baa0dcf1874699992f482592db35d16b7914d0a3 +Subproject commit b67041c002d29e44401cf562ee2411baf2e5789c