From 1d89dcf6031aea77b32e4ca7dffba1dec9f60878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Fri, 19 Jan 2024 22:03:59 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20-=20#85=20=EA=B8=B0=ED=9A=8D?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EB=8A=94=20app=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B4=80=EB=A0=A8=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/sopt/org/HMH/domain/app/domain/AppConstants.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/sopt/org/HMH/domain/app/domain/AppConstants.java diff --git a/src/main/java/sopt/org/HMH/domain/app/domain/AppConstants.java b/src/main/java/sopt/org/HMH/domain/app/domain/AppConstants.java new file mode 100644 index 00000000..45d79d2d --- /dev/null +++ b/src/main/java/sopt/org/HMH/domain/app/domain/AppConstants.java @@ -0,0 +1,6 @@ +package sopt.org.HMH.domain.app.domain; + +public abstract class AppConstants { + public static final Long MINIMUM_APP_TIME = 0L; + public static final Long MAXIMUM_APP_TIME = 3659000L; +} \ No newline at end of file From 9747f827e246b6c567240f495b868a4d8c7b905b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Fri, 19 Jan 2024 22:04:20 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat=20-=20#85=20=EC=95=B1=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B8=EB=93=A4=EB=A7=81=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/app/domain/exception/AppError.java | 34 +++++++++++++++++++ .../app/domain/exception/AppException.java | 10 ++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java create mode 100644 src/main/java/sopt/org/HMH/domain/app/domain/exception/AppException.java diff --git a/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java new file mode 100644 index 00000000..c1dfadba --- /dev/null +++ b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java @@ -0,0 +1,34 @@ +package sopt.org.HMH.domain.app.domain.exception; + +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import sopt.org.HMH.global.common.exception.base.ErrorBase; + +@AllArgsConstructor +public enum AppError implements ErrorBase { + + APP_NOT_FOUND(HttpStatus.NOT_FOUND, "앱을 찾을 수 없습니다."), + APP_EXIST_ALREADY(HttpStatus.ALREADY_REPORTED, "이미 추가된 앱입니다."), + INVALID_APP_CODE_NULL(HttpStatus.BAD_REQUEST, "앱코드 값이 비어있습니다"), + INVALID_TIME_RANGE(HttpStatus.BAD_REQUEST, "앱 시간의 범위가 유효한지 확인해주세요"), + INVALID_TIME_NULL(HttpStatus.BAD_REQUEST, "앱 시간을 입력해주세요"), + ; + + private final HttpStatus status; + private final String errorMessage; + + @Override + public int getHttpStatusCode() { + return status.value(); + } + + @Override + public HttpStatus getHttpStatus() { + return this.status; + } + + @Override + public String getErrorMessage() { + return this.errorMessage; + } +} \ No newline at end of file diff --git a/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppException.java b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppException.java new file mode 100644 index 00000000..0445c339 --- /dev/null +++ b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppException.java @@ -0,0 +1,10 @@ +package sopt.org.HMH.domain.app.domain.exception; + +import sopt.org.HMH.global.common.exception.base.ExceptionBase; + +public class AppException extends ExceptionBase { + + public AppException(AppError error) { + super(error); + } +} \ No newline at end of file From 5f31467703f86d2be13b9f6983870ecf17d276cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Fri, 19 Jan 2024 22:04:43 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat=20-=20#85=20appRepository=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=95=B1=20=EB=B0=9C=EA=B2=AC=20=EB=AA=BB=ED=95=A0?= =?UTF-8?q?=20=EC=8B=9C=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HMH/domain/app/repository/AppRepository.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/sopt/org/HMH/domain/app/repository/AppRepository.java b/src/main/java/sopt/org/HMH/domain/app/repository/AppRepository.java index 243f6007..5d585cf7 100644 --- a/src/main/java/sopt/org/HMH/domain/app/repository/AppRepository.java +++ b/src/main/java/sopt/org/HMH/domain/app/repository/AppRepository.java @@ -2,8 +2,19 @@ import org.springframework.data.jpa.repository.JpaRepository; import sopt.org.HMH.domain.app.domain.App; +import sopt.org.HMH.domain.app.domain.exception.AppError; +import sopt.org.HMH.domain.app.domain.exception.AppException; + +import java.util.Optional; public interface AppRepository extends JpaRepository { - App findByDailyChallengeIdAndAppCodeAndOs(Long dailyChallengeId, String appCode, String os); + Optional findFirstByDailyChallengeIdAndAppCodeAndOs(Long dailyChallengeId, String appCode, String os); + + default App findFirstByDailyChallengeIdAndAppCodeAndOsOrElseThrow(Long dailyChallengeId, String appCode, String os) { + return findFirstByDailyChallengeIdAndAppCodeAndOs(dailyChallengeId, appCode, os).orElseThrow(() -> new AppException( + AppError.APP_NOT_FOUND)); + } + + boolean existsByDailyChallengeIdAndAppCodeAndOs(Long dailyChallengeId, String appCode, String os); } \ No newline at end of file From 55198ae592893aeddf14ba04b56180fcfa4853f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Fri, 19 Jan 2024 22:07:08 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat=20-=20#85=20=EC=95=B1=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EC=99=80=20=EC=82=AD=EC=A0=9C=EC=8B=9C=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HMH/domain/app/service/AppService.java | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/sopt/org/HMH/domain/app/service/AppService.java b/src/main/java/sopt/org/HMH/domain/app/service/AppService.java index 01d239a3..8c631621 100644 --- a/src/main/java/sopt/org/HMH/domain/app/service/AppService.java +++ b/src/main/java/sopt/org/HMH/domain/app/service/AppService.java @@ -4,6 +4,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import sopt.org.HMH.domain.app.domain.App; +import sopt.org.HMH.domain.app.domain.AppConstants; +import sopt.org.HMH.domain.app.domain.exception.AppError; +import sopt.org.HMH.domain.app.domain.exception.AppException; import sopt.org.HMH.domain.app.dto.request.AppDeleteRequest; import sopt.org.HMH.domain.app.dto.request.AppGoalTimeRequest; import sopt.org.HMH.domain.app.repository.AppRepository; @@ -15,27 +18,26 @@ @Service @RequiredArgsConstructor public class AppService { - private final AppRepository appRepository; private final DailyChallengeService dailyChallengeService; @Transactional public void addAppsAndUpdateRemainingDailyChallenge(Long userId, List requests, String os) { - dailyChallengeService.getRemainingDailyChallengesByUserId(userId).stream() + dailyChallengeService.getRemainingDailyChallengesByUserId(userId) .forEach(dailyChallenge -> addApps(dailyChallenge, requests, os)); } @Transactional public void removeAppAndUpdateRemainingDailyChallenge(Long userId, AppDeleteRequest request, String os) { - dailyChallengeService.getRemainingDailyChallengesByUserId(userId).stream() + dailyChallengeService.getRemainingDailyChallengesByUserId(userId) .forEach(dailyChallenge -> removeApp(dailyChallenge, request, os)); } - @Transactional public void removeApp(DailyChallenge dailyChallenge, AppDeleteRequest request, String os) { - appRepository.delete(appRepository.findByDailyChallengeIdAndAppCodeAndOs( + validateAppCode(request.appCode()); + appRepository.delete(appRepository.findFirstByDailyChallengeIdAndAppCodeAndOsOrElseThrow( dailyChallenge.getId(), request.appCode(), os)); @@ -44,12 +46,38 @@ public void removeApp(DailyChallenge dailyChallenge, AppDeleteRequest request, S @Transactional public List addApps(DailyChallenge dailyChallenge, List requests, String os) { List appStream = requests.stream() - .map(request -> App.builder().dailyChallenge(dailyChallenge) - .appCode(request.appCode()) - .goalTime(request.goalTime()) - .os(os).build() - ).toList(); + .map(request -> { + validateAppExist(dailyChallenge.getId(), request.appCode(), os); + validateAppCode(request.appCode()); + validateAppTime(request.goalTime()); + return App.builder() + .dailyChallenge(dailyChallenge) + .appCode(request.appCode()) + .goalTime(request.goalTime()) + .os(os) + .build(); + }).toList(); return appRepository.saveAll(appStream); } + + private void validateAppExist(Long dailyChallengeId, String appCode, String os) { + if (appRepository.existsByDailyChallengeIdAndAppCodeAndOs(dailyChallengeId, appCode, os)) { + throw new AppException(AppError.APP_EXIST_ALREADY); + } + } + + private void validateAppCode(String appCode) { + if (appCode == "") { + throw new AppException(AppError.INVALID_APP_CODE_NULL); + } + } + + private void validateAppTime(Long appTime) { + if (appTime == null) { + throw new AppException(AppError.INVALID_TIME_NULL); + } + if (appTime > AppConstants.MAXIMUM_APP_TIME || appTime < AppConstants.MINIMUM_APP_TIME) + throw new AppException(AppError.INVALID_TIME_RANGE); + } } \ No newline at end of file From b36321757ff81507de66cc33dcf4e80d7f332bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Fri, 19 Jan 2024 22:07:48 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat=20-=20#85=20=EC=9E=90=EC=A0=95?= =?UTF-8?q?=EC=97=90=20=EC=B1=8C=EB=A6=B0=EC=A7=80=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=20=EC=95=B1?= =?UTF-8?q?=EC=97=90=20=EC=82=AC=EC=9A=A9=EC=8B=9C=EA=B0=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=A0=20=EB=95=8C=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/DailyChallengeService.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/sopt/org/HMH/domain/dailychallenge/service/DailyChallengeService.java b/src/main/java/sopt/org/HMH/domain/dailychallenge/service/DailyChallengeService.java index decc74d0..96204452 100644 --- a/src/main/java/sopt/org/HMH/domain/dailychallenge/service/DailyChallengeService.java +++ b/src/main/java/sopt/org/HMH/domain/dailychallenge/service/DailyChallengeService.java @@ -4,6 +4,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import sopt.org.HMH.domain.app.domain.App; +import sopt.org.HMH.domain.app.domain.AppConstants; +import sopt.org.HMH.domain.app.domain.exception.AppError; +import sopt.org.HMH.domain.app.domain.exception.AppException; import sopt.org.HMH.domain.app.dto.request.AppUsageTimeRequest; import sopt.org.HMH.domain.app.repository.AppRepository; import sopt.org.HMH.domain.challenge.domain.Challenge; @@ -49,7 +52,8 @@ public void modifyDailyChallengeStatus(Long userId, List re DailyChallenge todayDailyChallenge = getTodayDailyChallengeByUserId(userId); long successCount = requests.stream() .filter(request -> { - App app = appRepository.findByDailyChallengeIdAndAppCodeAndOs( + validateModifyDailyChallenge(request.appCode(), request.usageTime()); + App app = appRepository.findFirstByDailyChallengeIdAndAppCodeAndOsOrElseThrow( todayDailyChallenge.getId(), request.appCode(), os); app.setUsageTime(request.usageTime()); return (request.usageTime() <= app.getGoalTime()); @@ -58,6 +62,17 @@ public void modifyDailyChallengeStatus(Long userId, List re todayDailyChallenge.setStatus(status); } + private void validateModifyDailyChallenge(String appCode, Long usageTime) { + if (appCode == "") { + throw new AppException(AppError.INVALID_APP_CODE_NULL); + } + if (usageTime == null) { + throw new AppException(AppError.INVALID_TIME_NULL); + } + if (usageTime > AppConstants.MAXIMUM_APP_TIME || usageTime < AppConstants.MINIMUM_APP_TIME) + throw new AppException(AppError.INVALID_TIME_RANGE); + } + public DailyChallenge getTodayDailyChallengeByUserId(Long userId) { Challenge challenge = challengeRepository.findFirstByUserIdOrderByCreatedAtDescOrElseThrow(userId); From 601112bc1aa099a308625bfcc5bba010f7e7cca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=AE=E1=84=86?= =?UTF-8?q?=E1=85=B5=E1=86=AB?= Date: Sat, 20 Jan 2024 12:34:27 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor=20-=20#85=20HttpStatus=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/org/HMH/domain/app/domain/exception/AppError.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java index c1dfadba..cdd4dc24 100644 --- a/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java +++ b/src/main/java/sopt/org/HMH/domain/app/domain/exception/AppError.java @@ -8,8 +8,8 @@ public enum AppError implements ErrorBase { APP_NOT_FOUND(HttpStatus.NOT_FOUND, "앱을 찾을 수 없습니다."), - APP_EXIST_ALREADY(HttpStatus.ALREADY_REPORTED, "이미 추가된 앱입니다."), - INVALID_APP_CODE_NULL(HttpStatus.BAD_REQUEST, "앱코드 값이 비어있습니다"), + APP_EXIST_ALREADY(HttpStatus.CONFLICT, "이미 추가된 앱입니다."), + INVALID_APP_CODE_NULL(HttpStatus.BAD_REQUEST, "앱 코드 값이 비어있습니다"), INVALID_TIME_RANGE(HttpStatus.BAD_REQUEST, "앱 시간의 범위가 유효한지 확인해주세요"), INVALID_TIME_NULL(HttpStatus.BAD_REQUEST, "앱 시간을 입력해주세요"), ;