diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dea1a3f8..fce69f8d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,10 +11,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up SSH - uses: webfactory/ssh-agent@v0.5.3 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} diff --git a/.github/workflows/testcode.yml b/.github/workflows/testcode.yml new file mode 100644 index 00000000..8827ab70 --- /dev/null +++ b/.github/workflows/testcode.yml @@ -0,0 +1,36 @@ +name: Run Tests on Pull Request + +on: + pull_request: + branches: + - Weekly + +jobs: + test: + runs-on: ubuntu-latest + + services: + redis: + image: redis:alpine + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Run Tests + env: + JWT_SECRET: ${{ secrets.JWT_SECRET }} + run: ./gradlew test diff --git a/src/main/java/com/example/sinitto/auth/controller/AuthControllerAdvice.java b/src/main/java/com/example/sinitto/auth/controller/AuthControllerAdvice.java deleted file mode 100644 index 621239a4..00000000 --- a/src/main/java/com/example/sinitto/auth/controller/AuthControllerAdvice.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.example.sinitto.auth.controller; - -import com.example.sinitto.auth.exception.*; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.auth") -public class AuthControllerAdvice { - - private static final String UNAUTHORIZED_ACCESS_URI = "/errors/unauthorized-access"; - private static final String JWT_EXPIRATION_URI = "/errors/unauthorized-access-by-jwt-expiration"; - private static final String TOKEN_NOT_FOUND_URI = "/errors/token-not-found"; - private static final String KAKAO_REFRESH_TOKEN_EXPIRATION_URI = "/errors/unauthorized-access-by-kakao-refresh-token-expiration"; - private static final String KAKAO_EMAIL_NOT_FOUND_URI = "/errors/kakao-email-not-found"; - - @ExceptionHandler(UnauthorizedException.class) - public ResponseEntity handleUnauthorizedException(UnauthorizedException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, - ex.getMessage()); - problemDetail.setType(URI.create(UNAUTHORIZED_ACCESS_URI)); - problemDetail.setTitle("Unauthorized Access"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(problemDetail); - } - - @ExceptionHandler(JWTExpirationException.class) - public ResponseEntity handleJWTExpirationException(JWTExpirationException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, - ex.getMessage()); - problemDetail.setType(URI.create(JWT_EXPIRATION_URI)); - problemDetail.setTitle("Unauthorized Access By JWT Expiration"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(problemDetail); - } - - @ExceptionHandler(TokenNotFoundException.class) - public ResponseEntity handleTokenNotFoundException(TokenNotFoundException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, - ex.getMessage()); - problemDetail.setType(URI.create(TOKEN_NOT_FOUND_URI)); - problemDetail.setTitle("Token Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(KakaoRefreshTokenExpirationException.class) - public ResponseEntity handleKakaoRefreshTokenExpirationException(KakaoRefreshTokenExpirationException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, - ex.getMessage()); - problemDetail.setType(URI.create(KAKAO_REFRESH_TOKEN_EXPIRATION_URI)); - problemDetail.setTitle("Unauthorized Access By Kakao Refresh Token Expiration"); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(problemDetail); - } - - @ExceptionHandler(KakaoEmailNotFoundException.class) - public ResponseEntity handleKakaoEmailNotFoundException(KakaoEmailNotFoundException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, - ex.getMessage()); - problemDetail.setType(URI.create(KAKAO_EMAIL_NOT_FOUND_URI)); - problemDetail.setTitle("Kakao Email Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/auth/exception/JWTExpirationException.java b/src/main/java/com/example/sinitto/auth/exception/JWTExpirationException.java deleted file mode 100644 index f8ba7ea8..00000000 --- a/src/main/java/com/example/sinitto/auth/exception/JWTExpirationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.auth.exception; - -public class JWTExpirationException extends RuntimeException { - public JWTExpirationException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/auth/exception/KakaoEmailNotFoundException.java b/src/main/java/com/example/sinitto/auth/exception/KakaoEmailNotFoundException.java deleted file mode 100644 index 3661d546..00000000 --- a/src/main/java/com/example/sinitto/auth/exception/KakaoEmailNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.auth.exception; - -public class KakaoEmailNotFoundException extends RuntimeException { - public KakaoEmailNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/auth/exception/KakaoRefreshTokenExpirationException.java b/src/main/java/com/example/sinitto/auth/exception/KakaoRefreshTokenExpirationException.java deleted file mode 100644 index 8ef82500..00000000 --- a/src/main/java/com/example/sinitto/auth/exception/KakaoRefreshTokenExpirationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.auth.exception; - -public class KakaoRefreshTokenExpirationException extends RuntimeException { - public KakaoRefreshTokenExpirationException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/auth/exception/TokenNotFoundException.java b/src/main/java/com/example/sinitto/auth/exception/TokenNotFoundException.java deleted file mode 100644 index 6c295bb6..00000000 --- a/src/main/java/com/example/sinitto/auth/exception/TokenNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.auth.exception; - -public class TokenNotFoundException extends RuntimeException { - public TokenNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/auth/service/KakaoApiService.java b/src/main/java/com/example/sinitto/auth/service/KakaoApiService.java index d337e233..22514abd 100644 --- a/src/main/java/com/example/sinitto/auth/service/KakaoApiService.java +++ b/src/main/java/com/example/sinitto/auth/service/KakaoApiService.java @@ -2,7 +2,7 @@ import com.example.sinitto.auth.dto.KakaoTokenResponse; import com.example.sinitto.auth.dto.KakaoUserResponse; -import com.example.sinitto.auth.exception.KakaoEmailNotFoundException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.common.properties.KakaoProperties; import org.springframework.http.*; import org.springframework.stereotype.Service; @@ -81,7 +81,7 @@ public KakaoUserResponse getUserInfo(String accessToken) { url, HttpMethod.POST, request, KakaoUserResponse.class); if (response.getBody().kakaoAccount().email() == null) { - throw new KakaoEmailNotFoundException("카카오 계정으로부터 전달받은 이메일이 없습니다."); + throw new NotFoundException("카카오 계정으로부터 전달받은 이메일이 없습니다."); } return response.getBody(); diff --git a/src/main/java/com/example/sinitto/auth/service/KakaoTokenService.java b/src/main/java/com/example/sinitto/auth/service/KakaoTokenService.java index 97f2b6c5..53f00e72 100644 --- a/src/main/java/com/example/sinitto/auth/service/KakaoTokenService.java +++ b/src/main/java/com/example/sinitto/auth/service/KakaoTokenService.java @@ -2,9 +2,9 @@ import com.example.sinitto.auth.dto.KakaoTokenResponse; import com.example.sinitto.auth.entity.KakaoToken; -import com.example.sinitto.auth.exception.KakaoRefreshTokenExpirationException; -import com.example.sinitto.auth.exception.TokenNotFoundException; import com.example.sinitto.auth.repository.KakaoTokenRepository; +import com.example.sinitto.common.exception.NotFoundException; +import com.example.sinitto.common.exception.UnauthorizedException; import jakarta.transaction.Transactional; import org.springframework.stereotype.Service; @@ -36,11 +36,11 @@ public void saveKakaoToken(String email, KakaoTokenResponse kakaoTokenResponse) @Transactional public String getValidAccessTokenInServer(String email) { KakaoToken kakaoToken = kakaoTokenRepository.findByMemberEmail(email) - .orElseThrow(() -> new TokenNotFoundException("email에 해당하는 카카오 토큰이 없습니다.")); + .orElseThrow(() -> new NotFoundException("email에 해당하는 카카오 토큰이 없습니다.")); if (kakaoToken.isAccessTokenExpired()) { if (kakaoToken.isRefreshTokenExpired()) { - throw new KakaoRefreshTokenExpirationException("카카오 리프레쉬 토큰이 만료되었습니다. 카카오 재 로그인 필요"); + throw new UnauthorizedException("카카오 리프레쉬 토큰이 만료되었습니다. 카카오 재 로그인 필요"); } KakaoTokenResponse kakaoTokenResponse = kakaoApiService.refreshAccessToken(kakaoToken.getRefreshToken()); kakaoToken.updateKakaoToken(kakaoTokenResponse.accessToken(), kakaoTokenResponse.refreshToken(), kakaoTokenResponse.expiresIn(), kakaoTokenResponse.refreshTokenExpiresIn()); diff --git a/src/main/java/com/example/sinitto/auth/service/TokenService.java b/src/main/java/com/example/sinitto/auth/service/TokenService.java index 57b2cb42..c5db8744 100644 --- a/src/main/java/com/example/sinitto/auth/service/TokenService.java +++ b/src/main/java/com/example/sinitto/auth/service/TokenService.java @@ -1,8 +1,10 @@ package com.example.sinitto.auth.service; import com.example.sinitto.auth.dto.TokenResponse; -import com.example.sinitto.auth.exception.JWTExpirationException; -import com.example.sinitto.auth.exception.UnauthorizedException; +import com.example.sinitto.common.exception.AccessTokenExpiredException; +import com.example.sinitto.common.exception.InvalidJwtException; +import com.example.sinitto.common.exception.RefreshTokenStolenException; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; @@ -53,14 +55,19 @@ public String generateRefreshToken(String email) { public String extractEmail(String token) { - var claims = Jwts.parserBuilder() - .setSigningKey(secretKey) - .build() - .parseClaimsJws(token) - .getBody(); + Claims claims; + try { + claims = Jwts.parserBuilder() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token) + .getBody(); + } catch (Exception e) { + throw new InvalidJwtException(e.getMessage()); + } if (claims.getExpiration().before(new Date())) { - throw new JWTExpirationException("토큰이 만료되었습니다. 재로그인이 필요합니다."); + throw new AccessTokenExpiredException("액세스 토큰이 만료되었습니다. 리프레시 토큰으로 다시 액세스 토큰을 발급받으세요."); } return claims.getSubject(); @@ -70,8 +77,13 @@ public TokenResponse refreshAccessToken(String refreshToken) { String email = extractEmail(refreshToken); String storedRefreshToken = redisTemplate.opsForValue().get(email); - if (storedRefreshToken == null || !storedRefreshToken.equals(refreshToken)) { - throw new UnauthorizedException("만료되거나 이미 한번 사용된 리프레쉬 토큰입니다. 재로그인이 필요합니다."); + + if (storedRefreshToken == null) { + throw new InvalidJwtException("토큰이 만료되었습니다. 재로그인이 필요합니다."); + } + + if (!storedRefreshToken.equals(refreshToken)) { + throw new RefreshTokenStolenException("이미 한번 사용된 리프레시 토큰입니다. 리프레시 토큰이 탈취되었을 가능성이 있습니다."); } redisTemplate.delete(email); diff --git a/src/main/java/com/example/sinitto/callback/controller/CallbackControllerAdvice.java b/src/main/java/com/example/sinitto/callback/controller/CallbackControllerAdvice.java deleted file mode 100644 index bc352f2a..00000000 --- a/src/main/java/com/example/sinitto/callback/controller/CallbackControllerAdvice.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.example.sinitto.callback.controller; - -import com.example.sinitto.callback.exception.ConflictException; -import com.example.sinitto.callback.exception.ForbiddenException; -import com.example.sinitto.callback.exception.NotFoundException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.callback") -public class CallbackControllerAdvice { - - @ExceptionHandler(ForbiddenException.class) - public ResponseEntity handleForbiddenException(ForbiddenException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.FORBIDDEN, e.getMessage()); - problemDetail.setType(URI.create("/errors/forbidden")); - problemDetail.setTitle("Forbidden"); - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(problemDetail); - } - - @ExceptionHandler(ConflictException.class) - public ResponseEntity handleConflictException(ConflictException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); - problemDetail.setType(URI.create("/errors/conflict")); - problemDetail.setTitle("Conflict"); - return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); - } - - @ExceptionHandler(NotFoundException.class) - public ResponseEntity handleNotFoundException(NotFoundException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/errors/not-found")); - problemDetail.setTitle("Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - -} diff --git a/src/main/java/com/example/sinitto/callback/entity/Callback.java b/src/main/java/com/example/sinitto/callback/entity/Callback.java index 89f67932..421fb152 100644 --- a/src/main/java/com/example/sinitto/callback/entity/Callback.java +++ b/src/main/java/com/example/sinitto/callback/entity/Callback.java @@ -1,9 +1,6 @@ package com.example.sinitto.callback.entity; -import com.example.sinitto.callback.exception.AlreadyCompleteException; -import com.example.sinitto.callback.exception.AlreadyInProgressException; -import com.example.sinitto.callback.exception.AlreadyPendingCompleteException; -import com.example.sinitto.callback.exception.AlreadyWaitingException; +import com.example.sinitto.common.exception.ConflictException; import com.example.sinitto.member.entity.Senior; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; @@ -100,16 +97,16 @@ public void changeStatusToComplete() { private void throwStatusException(String message) { if (this.status == Status.PENDING_COMPLETE) { - throw new AlreadyPendingCompleteException("완료 대기 상태의 콜백 입니다. " + message); + throw new ConflictException("완료 대기 상태의 콜백 입니다. " + message); } if (this.status == Status.COMPLETE) { - throw new AlreadyCompleteException("완료 상태의 콜백 입니다. " + message); + throw new ConflictException("완료 상태의 콜백 입니다. " + message); } if (this.status == Status.WAITING) { - throw new AlreadyWaitingException("대기 상태의 콜백 입니다. " + message); + throw new ConflictException("대기 상태의 콜백 입니다. " + message); } if (this.status == Status.IN_PROGRESS) { - throw new AlreadyInProgressException("진행 상태의 콜백 입니다. " + message); + throw new ConflictException("진행 상태의 콜백 입니다. " + message); } } diff --git a/src/main/java/com/example/sinitto/callback/exception/AlreadyCompleteException.java b/src/main/java/com/example/sinitto/callback/exception/AlreadyCompleteException.java deleted file mode 100644 index b4619861..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/AlreadyCompleteException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class AlreadyCompleteException extends ConflictException { - - public AlreadyCompleteException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/AlreadyInProgressException.java b/src/main/java/com/example/sinitto/callback/exception/AlreadyInProgressException.java deleted file mode 100644 index 38df51ab..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/AlreadyInProgressException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class AlreadyInProgressException extends ConflictException { - - public AlreadyInProgressException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/AlreadyPendingCompleteException.java b/src/main/java/com/example/sinitto/callback/exception/AlreadyPendingCompleteException.java deleted file mode 100644 index c3b8aaa8..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/AlreadyPendingCompleteException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class AlreadyPendingCompleteException extends ConflictException { - - public AlreadyPendingCompleteException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/AlreadyWaitingException.java b/src/main/java/com/example/sinitto/callback/exception/AlreadyWaitingException.java deleted file mode 100644 index f113e5fe..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/AlreadyWaitingException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class AlreadyWaitingException extends ConflictException { - - public AlreadyWaitingException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/GuardMismatchException.java b/src/main/java/com/example/sinitto/callback/exception/GuardMismatchException.java deleted file mode 100644 index 13ff0e83..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/GuardMismatchException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class GuardMismatchException extends NotFoundException { - - public GuardMismatchException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java b/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java deleted file mode 100644 index 77f44b55..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class MemberHasInProgressCallbackException extends ConflictException { - - public MemberHasInProgressCallbackException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/NotAssignedException.java b/src/main/java/com/example/sinitto/callback/exception/NotAssignedException.java deleted file mode 100644 index fcac4ec3..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/NotAssignedException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class NotAssignedException extends ForbiddenException { - - public NotAssignedException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/NotExistCallbackException.java b/src/main/java/com/example/sinitto/callback/exception/NotExistCallbackException.java deleted file mode 100644 index 3a518753..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/NotExistCallbackException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class NotExistCallbackException extends NotFoundException { - - public NotExistCallbackException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/NotMemberException.java b/src/main/java/com/example/sinitto/callback/exception/NotMemberException.java deleted file mode 100644 index ff6247a7..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/NotMemberException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class NotMemberException extends NotFoundException { - - public NotMemberException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/exception/NotSinittoException.java b/src/main/java/com/example/sinitto/callback/exception/NotSinittoException.java deleted file mode 100644 index 58db96d6..00000000 --- a/src/main/java/com/example/sinitto/callback/exception/NotSinittoException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.callback.exception; - -public class NotSinittoException extends ForbiddenException { - - public NotSinittoException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/callback/service/CallbackService.java b/src/main/java/com/example/sinitto/callback/service/CallbackService.java index 300cbc93..c43ace73 100644 --- a/src/main/java/com/example/sinitto/callback/service/CallbackService.java +++ b/src/main/java/com/example/sinitto/callback/service/CallbackService.java @@ -3,16 +3,17 @@ import com.example.sinitto.callback.dto.CallbackResponse; import com.example.sinitto.callback.dto.CallbackUsageHistoryResponse; import com.example.sinitto.callback.entity.Callback; -import com.example.sinitto.callback.exception.*; import com.example.sinitto.callback.repository.CallbackRepository; import com.example.sinitto.callback.util.TwilioHelper; +import com.example.sinitto.common.exception.ConflictException; +import com.example.sinitto.common.exception.ForbiddenException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.point.entity.Point; import com.example.sinitto.point.entity.PointLog; -import com.example.sinitto.point.exception.PointNotFoundException; import com.example.sinitto.point.repository.PointLogRepository; import com.example.sinitto.point.repository.PointRepository; import org.springframework.data.domain.Page; @@ -62,7 +63,7 @@ public void acceptCallbackBySinitto(Long memberId, Long callbackId) { checkAuthorization(memberId); if (callbackRepository.existsByAssignedMemberIdAndStatus(memberId, Callback.Status.IN_PROGRESS)) { - throw new MemberHasInProgressCallbackException("이 요청을 한 시니또는 이미 진행중인 콜백이 있습니다."); + throw new ConflictException("이 요청을 한 시니또는 이미 진행중인 콜백이 있습니다."); } Callback callback = getCallbackOrThrow(callbackId); @@ -93,7 +94,7 @@ public void changeCallbackStatusToCompleteByGuard(Long memberId, Long callbackId Long guardId = senior.getMember().getId(); if (!guardId.equals(memberId)) { - throw new GuardMismatchException("이 API를 요청한 보호자는 이 콜백을 요청 한 시니어의 보호자가 아닙니다."); + throw new ForbiddenException("이 API를 요청한 보호자는 이 콜백을 요청 한 시니어의 보호자가 아닙니다."); } earnPointForSinitto(callback.getAssignedMemberId()); @@ -103,7 +104,7 @@ public void changeCallbackStatusToCompleteByGuard(Long memberId, Long callbackId private void earnPointForSinitto(Long sinittoMemberId) { Point sinittoPoint = pointRepository.findByMemberId(sinittoMemberId) - .orElseThrow(() -> new PointNotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); + .orElseThrow(() -> new NotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); sinittoPoint.earn(CALLBACK_PRICE); @@ -186,7 +187,7 @@ public CallbackResponse getAcceptedCallback(Long memberId) { checkAuthorization(memberId); Callback callback = callbackRepository.findByAssignedMemberIdAndStatus(memberId, Callback.Status.IN_PROGRESS) - .orElseThrow(() -> new NotExistCallbackException("요청한 시니또에 할당된 콜백이 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 시니또에 할당된 콜백이 없습니다")); return new CallbackResponse(callback.getId(), callback.getSeniorName(), callback.getPostTime(), callback.getStatus(), callback.getSeniorId()); } @@ -194,23 +195,23 @@ public CallbackResponse getAcceptedCallback(Long memberId) { private void checkAuthorization(Long memberId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new NotMemberException("멤버가 아닙니다")); + .orElseThrow(() -> new NotFoundException("멤버가 아닙니다")); if (!member.isSinitto()) { - throw new NotSinittoException("시니또가 아닙니다"); + throw new ForbiddenException("시니또가 아닙니다"); } } private Callback getCallbackOrThrow(Long callbackId) { return callbackRepository.findById(callbackId) - .orElseThrow(() -> new NotExistCallbackException("존재하지 않는 콜백입니다")); + .orElseThrow(() -> new NotFoundException("존재하지 않는 콜백입니다")); } private void checkAssignment(Long memberId, Long assignedMemberId) { if (!assignedMemberId.equals(memberId)) { - throw new NotAssignedException("이 콜백에 할당된 시니또가 아닙니다"); + throw new ForbiddenException("이 콜백에 할당된 시니또가 아닙니다"); } } @@ -218,7 +219,7 @@ private void checkAssignment(Long memberId, Long assignedMemberId) { public Page getCallbackHistoryOfGuard(Long memberId, Pageable pageable) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new NotMemberException("멤버가 아닙니다")); + .orElseThrow(() -> new NotFoundException("멤버가 아닙니다")); List seniors = seniorRepository.findAllByMember(member); @@ -230,7 +231,7 @@ public Page getCallbackHistoryOfGuard(Long memberI public CallbackResponse getCallback(Long callbackId) { Callback callback = callbackRepository.findById(callbackId) - .orElseThrow(() -> new NotExistCallbackException("해당 콜백 id에 해당하는 콜백이 없습니다.")); + .orElseThrow(() -> new NotFoundException("해당 콜백 id에 해당하는 콜백이 없습니다.")); return new CallbackResponse(callback.getId(), callback.getSeniorName(), callback.getPostTime(), callback.getStatus(), callback.getSeniorId()); } diff --git a/src/main/java/com/example/sinitto/common/dummy/InitialData.java b/src/main/java/com/example/sinitto/common/dummy/InitialData.java index 3a19edff..6f5997ff 100644 --- a/src/main/java/com/example/sinitto/common/dummy/InitialData.java +++ b/src/main/java/com/example/sinitto/common/dummy/InitialData.java @@ -373,6 +373,131 @@ private void initial() { guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior5)); guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior5)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior6)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior6)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior6)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior6)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior7)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior7)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior7)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior7)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior8)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior8)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior8)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior8)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior9)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior9)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior9)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior9)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior10)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior10)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior10)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior10)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior11)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior11)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior11)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior11)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior12)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior12)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior12)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior12)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior13)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior13)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior13)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior3)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior14)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior14)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior14)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior14)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior15)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior15)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior15)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior15)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior16)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior16)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior16)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior16)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior17)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior17)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior17)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior17)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior18)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior18)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior18)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior18)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior19)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior19)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior19)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior19)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior20)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior20)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior20)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior20)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior21)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior21)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior21)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior21)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior22)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior22)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior22)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior22)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior23)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior23)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior23)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior23)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior24)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior24)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior24)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior24)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior25)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior25)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior25)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior25)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior26)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior26)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior26)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior26)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior27)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior27)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior27)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior27)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior28)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior28)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior28)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior28)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior29)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior29)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior29)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior29)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior30)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior30)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior30)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior30)); + //안부전화 HelloCall helloCall1 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 5), LocalDate.of(2024, 10, 1), 13000, 10, "어머님께서 매일 아침 등산을 하시는 걸 좋아하세요. 요즘 날씨가 추워졌는데, 건강하게 등산을 잘 다니시는지 여쭤봐 주세요. 등산 이야기를 하면 기분이 좋아지실 거예요.", senior1)); HelloCall helloCall2 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 2), LocalDate.of(2024, 10, 1), 14000, 10, "어머님께서 손주들 이야기를 굉장히 좋아하십니다. 최근에 손주들이 학교에서 무엇을 하고 있는지 말씀드리면 아주 즐거워하세요. 손주들과 관련된 이야기로 대화를 시작해 주세요.", senior2)); diff --git a/src/main/java/com/example/sinitto/common/exception/AccessTokenExpiredException.java b/src/main/java/com/example/sinitto/common/exception/AccessTokenExpiredException.java new file mode 100644 index 00000000..78a2ce8e --- /dev/null +++ b/src/main/java/com/example/sinitto/common/exception/AccessTokenExpiredException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.common.exception; + +public class AccessTokenExpiredException extends RuntimeException { + + public AccessTokenExpiredException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/common/exception/BadRequestException.java b/src/main/java/com/example/sinitto/common/exception/BadRequestException.java new file mode 100644 index 00000000..e0b2fc02 --- /dev/null +++ b/src/main/java/com/example/sinitto/common/exception/BadRequestException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.common.exception; + +public class BadRequestException extends RuntimeException { + + public BadRequestException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/callback/exception/ConflictException.java b/src/main/java/com/example/sinitto/common/exception/ConflictException.java similarity index 74% rename from src/main/java/com/example/sinitto/callback/exception/ConflictException.java rename to src/main/java/com/example/sinitto/common/exception/ConflictException.java index ebe3df60..52e08d83 100644 --- a/src/main/java/com/example/sinitto/callback/exception/ConflictException.java +++ b/src/main/java/com/example/sinitto/common/exception/ConflictException.java @@ -1,4 +1,4 @@ -package com.example.sinitto.callback.exception; +package com.example.sinitto.common.exception; public class ConflictException extends RuntimeException { diff --git a/src/main/java/com/example/sinitto/callback/exception/ForbiddenException.java b/src/main/java/com/example/sinitto/common/exception/ForbiddenException.java similarity index 74% rename from src/main/java/com/example/sinitto/callback/exception/ForbiddenException.java rename to src/main/java/com/example/sinitto/common/exception/ForbiddenException.java index 099e6d1c..5abf5ea2 100644 --- a/src/main/java/com/example/sinitto/callback/exception/ForbiddenException.java +++ b/src/main/java/com/example/sinitto/common/exception/ForbiddenException.java @@ -1,4 +1,4 @@ -package com.example.sinitto.callback.exception; +package com.example.sinitto.common.exception; public class ForbiddenException extends RuntimeException { diff --git a/src/main/java/com/example/sinitto/common/exception/GlobalExceptionHandler.java b/src/main/java/com/example/sinitto/common/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..9f7264a2 --- /dev/null +++ b/src/main/java/com/example/sinitto/common/exception/GlobalExceptionHandler.java @@ -0,0 +1,77 @@ +package com.example.sinitto.common.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(ForbiddenException.class) + public ResponseEntity handleForbiddenException(ForbiddenException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.FORBIDDEN, e.getMessage()); + problemDetail.setTitle("Forbidden"); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(problemDetail); + } + + @ExceptionHandler(ConflictException.class) + public ResponseEntity handleConflictException(ConflictException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); + problemDetail.setTitle("Conflict"); + return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); + } + + @ExceptionHandler(NotFoundException.class) + public ResponseEntity handleNotFoundException(NotFoundException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); + problemDetail.setTitle("Not Found"); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); + } + + @ExceptionHandler(UnauthorizedException.class) + public ResponseEntity handleUnauthorizedException(UnauthorizedException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, e.getMessage()); + problemDetail.setTitle("Unauthorized"); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(problemDetail); + } + + @ExceptionHandler(BadRequestException.class) + public ResponseEntity handleBadRequestException(BadRequestException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); + problemDetail.setTitle("Bad Request"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); + } + + @ExceptionHandler(InvalidJwtException.class) + public ResponseEntity handleInvalidJwtException(InvalidJwtException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(460), e.getMessage()); + problemDetail.setTitle("Invalid Jwt"); + return ResponseEntity.status(HttpStatusCode.valueOf(460)).body(problemDetail); + } + + @ExceptionHandler(AccessTokenExpiredException.class) + public ResponseEntity handleAccessTokenExpiredException(AccessTokenExpiredException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(461), e.getMessage()); + problemDetail.setTitle("Access Token Expired"); + return ResponseEntity.status(HttpStatusCode.valueOf(461)).body(problemDetail); + } + + @ExceptionHandler(RefreshTokenStolenException.class) + public ResponseEntity handleRefreshTokenStolenException(RefreshTokenStolenException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(462), e.getMessage()); + problemDetail.setTitle("Refresh Token Stolen"); + return ResponseEntity.status(HttpStatusCode.valueOf(462)).body(problemDetail); + } + +} diff --git a/src/main/java/com/example/sinitto/common/exception/InvalidJwtException.java b/src/main/java/com/example/sinitto/common/exception/InvalidJwtException.java new file mode 100644 index 00000000..63e2b81f --- /dev/null +++ b/src/main/java/com/example/sinitto/common/exception/InvalidJwtException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.common.exception; + +public class InvalidJwtException extends RuntimeException { + + public InvalidJwtException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/callback/exception/NotFoundException.java b/src/main/java/com/example/sinitto/common/exception/NotFoundException.java similarity index 74% rename from src/main/java/com/example/sinitto/callback/exception/NotFoundException.java rename to src/main/java/com/example/sinitto/common/exception/NotFoundException.java index c6750b07..59fa148e 100644 --- a/src/main/java/com/example/sinitto/callback/exception/NotFoundException.java +++ b/src/main/java/com/example/sinitto/common/exception/NotFoundException.java @@ -1,4 +1,4 @@ -package com.example.sinitto.callback.exception; +package com.example.sinitto.common.exception; public class NotFoundException extends RuntimeException { diff --git a/src/main/java/com/example/sinitto/common/exception/RefreshTokenStolenException.java b/src/main/java/com/example/sinitto/common/exception/RefreshTokenStolenException.java new file mode 100644 index 00000000..9093a978 --- /dev/null +++ b/src/main/java/com/example/sinitto/common/exception/RefreshTokenStolenException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.common.exception; + +public class RefreshTokenStolenException extends RuntimeException { + + public RefreshTokenStolenException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/auth/exception/UnauthorizedException.java b/src/main/java/com/example/sinitto/common/exception/UnauthorizedException.java similarity index 76% rename from src/main/java/com/example/sinitto/auth/exception/UnauthorizedException.java rename to src/main/java/com/example/sinitto/common/exception/UnauthorizedException.java index 3726632f..a6207d45 100644 --- a/src/main/java/com/example/sinitto/auth/exception/UnauthorizedException.java +++ b/src/main/java/com/example/sinitto/common/exception/UnauthorizedException.java @@ -1,8 +1,8 @@ -package com.example.sinitto.auth.exception; +package com.example.sinitto.common.exception; public class UnauthorizedException extends RuntimeException { + public UnauthorizedException(String message) { super(message); } - } diff --git a/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java b/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java index fb32b1d1..141a3c85 100644 --- a/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java +++ b/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java @@ -1,7 +1,7 @@ package com.example.sinitto.common.resolver; -import com.example.sinitto.auth.exception.UnauthorizedException; import com.example.sinitto.common.annotation.MemberId; +import com.example.sinitto.common.exception.UnauthorizedException; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/example/sinitto/guard/controller/GuardControllerAdvice.java b/src/main/java/com/example/sinitto/guard/controller/GuardControllerAdvice.java deleted file mode 100644 index e651db7b..00000000 --- a/src/main/java/com/example/sinitto/guard/controller/GuardControllerAdvice.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.sinitto.guard.controller; - -import com.example.sinitto.guard.exception.SeniorNotFoundException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.guard") -public class GuardControllerAdvice { - @ExceptionHandler(SeniorNotFoundException.class) - public ResponseEntity handleSeniorNotFoundException(SeniorNotFoundException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/error/senior-not-found")); - problemDetail.setTitle("Senior Not Found"); - - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/guard/exception/SeniorNotFoundException.java b/src/main/java/com/example/sinitto/guard/exception/SeniorNotFoundException.java deleted file mode 100644 index dcfd10b1..00000000 --- a/src/main/java/com/example/sinitto/guard/exception/SeniorNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.guard.exception; - -public class SeniorNotFoundException extends RuntimeException { - public SeniorNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/guard/service/GuardService.java b/src/main/java/com/example/sinitto/guard/service/GuardService.java index ecdbc7f5..90934323 100644 --- a/src/main/java/com/example/sinitto/guard/service/GuardService.java +++ b/src/main/java/com/example/sinitto/guard/service/GuardService.java @@ -1,14 +1,13 @@ package com.example.sinitto.guard.service; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.guard.dto.GuardRequest; import com.example.sinitto.guard.dto.GuardResponse; import com.example.sinitto.guard.dto.SeniorRequest; import com.example.sinitto.guard.dto.SeniorResponse; -import com.example.sinitto.guard.exception.SeniorNotFoundException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,7 +27,7 @@ public GuardService(MemberRepository memberRepository, SeniorRepository seniorRe @Transactional public GuardResponse readGuard(Long memberId) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); return new GuardResponse(member.getName(), member.getEmail(), member.getPhoneNumber()); @@ -37,7 +36,7 @@ public GuardResponse readGuard(Long memberId) { @Transactional public void updateGuard(Long memberId, GuardRequest guardRequest) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); member.updateMember(guardRequest.name(), guardRequest.email(), guardRequest.phoneNumber()); @@ -46,7 +45,7 @@ public void updateGuard(Long memberId, GuardRequest guardRequest) { @Transactional public void deleteGuard(Long memberId) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); memberRepository.delete(member); @@ -55,7 +54,7 @@ public void deleteGuard(Long memberId) { @Transactional public void createSenior(Long memberId, SeniorRequest seniorRequest) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); Senior senior = new Senior(seniorRequest.seniorName(), seniorRequest.seniorPhoneNumber(), member); @@ -73,7 +72,7 @@ public List readSeniors(Long memberId) { @Transactional public SeniorResponse readOneSenior(Long memberId, Long seniorId) { Senior senior = seniorRepository.findByIdAndMemberId(seniorId, memberId).orElseThrow( - () -> new SeniorNotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") ); return new SeniorResponse(senior.getId(), senior.getName(), senior.getPhoneNumber()); @@ -82,7 +81,7 @@ public SeniorResponse readOneSenior(Long memberId, Long seniorId) { @Transactional public void updateSenior(Long memberId, Long seniorId, SeniorRequest seniorRequest) { Senior senior = seniorRepository.findByIdAndMemberId(seniorId, memberId).orElseThrow( - () -> new SeniorNotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") ); senior.updateSenior(seniorRequest.seniorName(), seniorRequest.seniorPhoneNumber()); @@ -91,7 +90,7 @@ public void updateSenior(Long memberId, Long seniorId, SeniorRequest seniorReque @Transactional public void deleteSenior(Long memberId, Long seniorId) { Senior senior = seniorRepository.findByIdAndMemberId(seniorId, memberId).orElseThrow( - () -> new SeniorNotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.") ); seniorRepository.delete(senior); diff --git a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java index 9cddc806..02f372d7 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java +++ b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java @@ -19,7 +19,9 @@ public class GuardGuidelineController { private final GuardGuidelineService guardGuidelineService; - public GuardGuidelineController(GuardGuidelineService guardGuidelineService) {this.guardGuidelineService = guardGuidelineService;} + public GuardGuidelineController(GuardGuidelineService guardGuidelineService) { + this.guardGuidelineService = guardGuidelineService; + } @Operation(summary = "가이드라인 추가", description = "보호자가 시니어별 가이드라인을 추가합니다.") @PostMapping @@ -43,15 +45,23 @@ public ResponseEntity updateGuardGuideline(@MemberId Long memberId, @Pat @Operation(summary = "모든 가이드라인 조회(시니어별로)", description = "보호자가 가이드라인 수정을 위해 시니어별로 모든 가이드라인을 요청할 때 필요합니다.") @GetMapping("/{seniorId}") - public ResponseEntity> getAllGuardGuidelinesBySenior(@PathVariable Long seniorId) { + public ResponseEntity> getAllGuardGuidelinesBySenior(@MemberId Long memberId, @PathVariable Long seniorId) { - return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesBySenior(seniorId)); + return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesBySenior(memberId, seniorId)); } @Operation(summary = "특정 가이드라인 조회", description = "보호자용 API입니다.") - @GetMapping("/{guidelineId}") - public ResponseEntity getGuardGuideline(@PathVariable Long guidelineId) { - return ResponseEntity.ok(guardGuidelineService.readGuardGuideline(guidelineId)); + @GetMapping("/detail") + public ResponseEntity getGuardGuideline(@RequestParam("callbackId") Long callbackId, @RequestParam("guidelineId") Long guidelineId) { + return ResponseEntity.ok(guardGuidelineService.readGuardGuideline(callbackId, guidelineId)); + } + + @Operation(summary = "특정 가이드라인 삭제", description = "보호자용 API입니다.") + @DeleteMapping("/delete") + public ResponseEntity deleteGuardGuideline(@MemberId Long memberId, @RequestParam("guidelineId") Long guidelineId) { + guardGuidelineService.deleteGuardGuideline(memberId, guidelineId); + return ResponseEntity.ok("가이드라인이 삭제되었습니다."); } + } diff --git a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java deleted file mode 100644 index c7543ec9..00000000 --- a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.example.sinitto.guardGuideline.controller; - -import com.example.sinitto.guardGuideline.exception.GuardGuidelineNotFoundException; -import com.example.sinitto.guardGuideline.exception.SeniorAndGuardMemberMismatchException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.guardGuideline") -public class GuardGuidelineControllerAdvice { - - @ExceptionHandler(GuardGuidelineNotFoundException.class) - public ResponseEntity handleGuardGuidelineNotFoundException(GuardGuidelineNotFoundException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/error/guideline-not-found")); - problemDetail.setTitle("Guideline Not Found"); - - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(SeniorAndGuardMemberMismatchException.class) - public ResponseEntity handleSeniorAndGuardMemberMismatchException(SeniorAndGuardMemberMismatchException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); - problemDetail.setType(URI.create("/error/member-mismatch")); - problemDetail.setTitle("Senior and Guard Member Mismatch"); - - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java index a30db103..5c97cc6b 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java +++ b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java @@ -7,4 +7,5 @@ public record GuardGuidelineRequest( GuardGuideline.Type type, String title, String content -) {} +) { +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java index 06ebce6a..c787764a 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java +++ b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java @@ -3,6 +3,7 @@ import com.example.sinitto.guardGuideline.entity.GuardGuideline; public record GuardGuidelineResponse( + Long id, GuardGuideline.Type type, String title, String content) { diff --git a/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java b/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java deleted file mode 100644 index c488a16d..00000000 --- a/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.sinitto.guardGuideline.exception; - -public class GuardGuidelineNotFoundException extends RuntimeException { - public GuardGuidelineNotFoundException(String message) {super(message);} -} diff --git a/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java b/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java deleted file mode 100644 index 87d643de..00000000 --- a/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.guardGuideline.exception; - -public class SeniorAndGuardMemberMismatchException extends RuntimeException { - public SeniorAndGuardMemberMismatchException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java b/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java index c1e36b91..8558982a 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java +++ b/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java @@ -1,14 +1,15 @@ package com.example.sinitto.guardGuideline.service; -import com.example.sinitto.guard.exception.SeniorNotFoundException; +import com.example.sinitto.callback.entity.Callback; +import com.example.sinitto.callback.repository.CallbackRepository; +import com.example.sinitto.common.exception.BadRequestException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.guardGuideline.dto.GuardGuidelineRequest; import com.example.sinitto.guardGuideline.dto.GuardGuidelineResponse; import com.example.sinitto.guardGuideline.entity.GuardGuideline; import com.example.sinitto.guardGuideline.entity.GuardGuideline.Type; -import com.example.sinitto.guardGuideline.exception.GuardGuidelineNotFoundException; -import com.example.sinitto.guardGuideline.exception.SeniorAndGuardMemberMismatchException; import com.example.sinitto.guardGuideline.repository.GuardGuidelineRepository; import com.example.sinitto.member.entity.Senior; import org.springframework.stereotype.Service; @@ -21,66 +22,91 @@ public class GuardGuidelineService { private final GuardGuidelineRepository guardGuidelineRepository; private final SeniorRepository seniorRepository; + private final CallbackRepository callbackRepository; - public GuardGuidelineService (GuardGuidelineRepository guardGuidelineRepository, SeniorRepository seniorRepository){ + public GuardGuidelineService(GuardGuidelineRepository guardGuidelineRepository, SeniorRepository seniorRepository, CallbackRepository callbackRepository) { this.guardGuidelineRepository = guardGuidelineRepository; this.seniorRepository = seniorRepository; + this.callbackRepository = callbackRepository; } @Transactional public void addGuardGuideline(Long memberId, GuardGuidelineRequest guardGuidelineRequest) { Senior senior = seniorRepository.findById(guardGuidelineRequest.seniorId()).orElseThrow( - () -> new SeniorNotFoundException("시니어를 찾을 수 없습니다.") + () -> new NotFoundException("시니어를 찾을 수 없습니다.") ); if (senior.isNotGuard(memberId)) { - throw new SeniorAndGuardMemberMismatchException("해당 Guard의 Senior가 아닙니다."); + throw new BadRequestException("해당 Guard의 Senior가 아닙니다."); } guardGuidelineRepository.save(new GuardGuideline(guardGuidelineRequest.type(), guardGuidelineRequest.title(), guardGuidelineRequest.content(), senior)); } @Transactional(readOnly = true) - public List readAllGuardGuidelinesByCategory(Long seniorId, Type type){ + public List readAllGuardGuidelinesByCategory(Long seniorId, Type type) { List guardGuidelines = guardGuidelineRepository.findBySeniorIdAndType(seniorId, type); return guardGuidelines.stream() - .map(m -> new GuardGuidelineResponse(m.getType(), m.getTitle(), m.getContent())) + .map(m -> new GuardGuidelineResponse(m.getId(), m.getType(), m.getTitle(), m.getContent())) .toList(); } @Transactional public void updateGuardGuideline(Long memberId, Long guidelineId, GuardGuidelineRequest guardGuidelineRequest) { GuardGuideline guardGuideline = guardGuidelineRepository.findById(guidelineId).orElseThrow( - ()-> new GuardGuidelineNotFoundException("해당 가이드라인이 존재하지 않습니다.") + () -> new NotFoundException("해당 가이드라인이 존재하지 않습니다.") ); Senior senior = seniorRepository.findById(guardGuidelineRequest.seniorId()).orElseThrow( - () -> new SeniorNotFoundException("시니어를 찾을 수 없습니다.") + () -> new NotFoundException("시니어를 찾을 수 없습니다.") ); if (senior.isNotGuard(memberId)) { - throw new SeniorAndGuardMemberMismatchException("해당 Guard의 Senior가 아닙니다."); + throw new BadRequestException("해당 Guard의 Senior가 아닙니다."); } guardGuideline.updateGuardGuideline(guardGuidelineRequest.type(), guardGuidelineRequest.title(), guardGuidelineRequest.content()); } + @Transactional + public void deleteGuardGuideline(Long memberId, Long guidelineId) { + GuardGuideline guardGuideline = guardGuidelineRepository.findById(guidelineId).orElseThrow( + () -> new NotFoundException("해당 가이드라인이 존재하지 않습니다.") + ); + if (guardGuideline.getSenior().isNotGuard(memberId)) { + throw new BadRequestException("해당 Guard의 Senior가 아닙니다."); + } + guardGuidelineRepository.delete(guardGuideline); + } + @Transactional(readOnly = true) - public List readAllGuardGuidelinesBySenior(Long seniorId){ + public List readAllGuardGuidelinesBySenior(Long memberId, Long seniorId) { + Senior senior = seniorRepository.findById(seniorId).orElseThrow( + () -> new NotFoundException("시니어를 찾을 수 없습니다.") + ); + if (senior.isNotGuard(memberId)) { + throw new BadRequestException("해당 Guard의 Senior가 아닙니다."); + } List guardGuidelines = guardGuidelineRepository.findBySeniorId(seniorId); - return guardGuidelines.stream() - .map(m -> new GuardGuidelineResponse(m.getType(), m.getTitle(), m.getContent())) + .map(m -> new GuardGuidelineResponse(m.getId(), m.getType(), m.getTitle(), m.getContent())) .toList(); } @Transactional(readOnly = true) - public GuardGuidelineResponse readGuardGuideline(Long guidelineId){ + public GuardGuidelineResponse readGuardGuideline(Long callbackId, Long guidelineId) { + + Callback callback = callbackRepository.findById(callbackId) + .orElseThrow(() -> new NotFoundException("존재하지 않는 콜백입니다")); + GuardGuideline guardGuideline = guardGuidelineRepository.findById(guidelineId).orElseThrow( - ()-> new GuardGuidelineNotFoundException("해당 가이드라인이 존재하지 않습니다.") + () -> new NotFoundException("해당 가이드라인이 존재하지 않습니다.") ); - return new GuardGuidelineResponse(guardGuideline.getType(), guardGuideline.getTitle(), guardGuideline.getContent()); - } + if (!callback.getSenior().equals(guardGuideline.getSenior())) { + throw new BadRequestException("해당 Senior의 가이드라인이 아닙니다."); + } + return new GuardGuidelineResponse(guardGuideline.getId(), guardGuideline.getType(), guardGuideline.getTitle(), guardGuideline.getContent()); + } } diff --git a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallControllerAdvice.java b/src/main/java/com/example/sinitto/helloCall/controller/HelloCallControllerAdvice.java deleted file mode 100644 index 5fba1452..00000000 --- a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallControllerAdvice.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.example.sinitto.helloCall.controller; - -import com.example.sinitto.helloCall.exception.*; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.helloCall") -public class HelloCallControllerAdvice { - - @ExceptionHandler(TimeRuleException.class) - public ResponseEntity handleTimeRuleException(TimeRuleException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/time-rule-exception")); - problemDetail.setTitle("Time Rule Exception"); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); - } - - @ExceptionHandler(HelloCallAlreadyExistsException.class) - public ResponseEntity handleHelloCallAlreadyExistsException(HelloCallAlreadyExistsException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/hello-call-already-exist")); - problemDetail.setTitle("Hello Call Already Exist"); - return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); - } - - @ExceptionHandler(HelloCallNotFoundException.class) - public ResponseEntity handleHelloCallNotFoundException(HelloCallNotFoundException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/hello-call-not-found")); - problemDetail.setTitle("Hello Call Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(InvalidStatusException.class) - public ResponseEntity handleInvalidStatusException(InvalidStatusException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/invalid-status-exception")); - problemDetail.setTitle("Invalid Status Exception"); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); - } - - @ExceptionHandler(CompletionConditionNotFulfilledException.class) - public ResponseEntity handleCompletionConditionNotFulfilledException(CompletionConditionNotFulfilledException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/completion-condition-not-fulfilled")); - problemDetail.setTitle("Completion Condition Not Fulfilled"); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); - } - - @ExceptionHandler(TimeLogSequenceException.class) - public ResponseEntity handleTimeLogSequenceException(TimeLogSequenceException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/time-log-sequence-exception")); - problemDetail.setTitle("Time Log Sequence Exception"); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java b/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java index 47877d29..a7bb2931 100644 --- a/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java +++ b/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java @@ -1,8 +1,7 @@ package com.example.sinitto.helloCall.entity; -import com.example.sinitto.auth.exception.UnauthorizedException; -import com.example.sinitto.helloCall.exception.InvalidStatusException; -import com.example.sinitto.helloCall.exception.TimeRuleException; +import com.example.sinitto.common.exception.BadRequestException; +import com.example.sinitto.common.exception.UnauthorizedException; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import jakarta.persistence.*; @@ -35,22 +34,22 @@ public class HelloCall { @Enumerated(EnumType.STRING) private HelloCall.Status status; - @OneToOne + @ManyToOne @JoinColumn(name = "senior_id") @NotNull @OnDelete(action = OnDeleteAction.CASCADE) private Senior senior; - @OneToMany(mappedBy = "helloCall", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "helloCall") private List timeSlots = new ArrayList<>(); @ManyToOne @JoinColumn(name = "member_id") private Member member; - @OneToMany(mappedBy = "helloCall", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "helloCall") private List helloCallTimeLogs = new ArrayList<>(); public HelloCall(LocalDate startDate, LocalDate endDate, int price, int serviceTime, String requirement, Senior senior) { if (startDate.isAfter(endDate)) { - throw new TimeRuleException("시작날짜가 종료날짜 이후일 수 없습니다."); + throw new BadRequestException("시작날짜가 종료날짜 이후일 수 없습니다."); } this.startDate = startDate; this.endDate = endDate; @@ -123,7 +122,7 @@ public String getMemberName() { public void checkStatusIsWaiting() { if (status.canNotModifyOrDelete()) { - throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 삭제가 가능합니다."); + throw new BadRequestException("안부전화 서비스가 수행 대기중일 때만 삭제가 가능합니다."); } } @@ -149,38 +148,38 @@ public void checkMemberIsRightSinitto(Member member) { public void changeStatusToInProgress() { if (status.canNotProgressStatus(Status.IN_PROGRESS)) { - throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); + throw new BadRequestException("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.IN_PROGRESS; } public void changeStatusToWaiting() { if (status.canNotRollBackStatus()) { - throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 진행중 상태로 돌아갈 수 있습니다. 현재 상태 : " + this.status); + throw new BadRequestException("안부전화 서비스가 수행중일 때만 진행중 상태로 돌아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.WAITING; } public void changeStatusToPendingComplete() { if (status.canNotProgressStatus(Status.PENDING_COMPLETE)) { - throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 완료 대기 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); + throw new BadRequestException("안부전화 서비스가 수행중일 때만 완료 대기 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.PENDING_COMPLETE; } public void changeStatusToComplete() { if (status.canNotProgressStatus(Status.COMPLETE)) { - throw new InvalidStatusException("안부전화 서비스가 완료 대기 일때만 완료 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); + throw new BadRequestException("안부전화 서비스가 완료 대기 일때만 완료 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.COMPLETE; } public void updateHelloCall(LocalDate startDate, LocalDate endDate, int price, int serviceTime, String requirement) { if (status.canNotModifyOrDelete()) { - throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 수정이 가능합니다."); + throw new BadRequestException("안부전화 서비스가 수행 대기중일 때만 수정이 가능합니다."); } if (startDate.isAfter(endDate)) { - throw new TimeRuleException("시작날짜가 종료날짜 이후일 수 없습니다."); + throw new BadRequestException("시작날짜가 종료날짜 이후일 수 없습니다."); } this.startDate = startDate; this.endDate = endDate; diff --git a/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java b/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java index 4b1a3bdc..0133c297 100644 --- a/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java +++ b/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java @@ -2,6 +2,8 @@ import com.example.sinitto.member.entity.Member; import jakarta.persistence.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import java.time.LocalDateTime; @@ -14,9 +16,11 @@ public class HelloCallTimeLog { private LocalDateTime startDateAndTime; private LocalDateTime endDateAndTime; @ManyToOne + @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name = "helloCall_id") private HelloCall helloCall; @ManyToOne + @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name = "sinitto_id") private Member member; diff --git a/src/main/java/com/example/sinitto/helloCall/entity/TimeSlot.java b/src/main/java/com/example/sinitto/helloCall/entity/TimeSlot.java index 14c47735..d73f7e97 100644 --- a/src/main/java/com/example/sinitto/helloCall/entity/TimeSlot.java +++ b/src/main/java/com/example/sinitto/helloCall/entity/TimeSlot.java @@ -1,8 +1,10 @@ package com.example.sinitto.helloCall.entity; -import com.example.sinitto.helloCall.exception.TimeRuleException; +import com.example.sinitto.common.exception.BadRequestException; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import java.time.LocalTime; @@ -19,12 +21,13 @@ public class TimeSlot { @NotNull private LocalTime endTime; @ManyToOne + @OnDelete(action = OnDeleteAction.CASCADE) @JoinColumn(name = "hellocall_id") private HelloCall helloCall; public TimeSlot(String dayName, LocalTime startTime, LocalTime endTime, HelloCall helloCall) { if (startTime.isAfter(endTime)) { - throw new TimeRuleException("시작시간이 종료시간 이후일 수 없습니다."); + throw new BadRequestException("시작시간이 종료시간 이후일 수 없습니다."); } this.dayName = dayName; this.startTime = startTime; @@ -54,7 +57,7 @@ public HelloCall getHelloCall() { public void updateTimeSlot(LocalTime startTime, LocalTime endTime) { if (startTime.isAfter(endTime)) { - throw new TimeRuleException("시작시간이 종료시간 이후일 수 없습니다."); + throw new BadRequestException("시작시간이 종료시간 이후일 수 없습니다."); } this.startTime = startTime; this.endTime = endTime; diff --git a/src/main/java/com/example/sinitto/helloCall/exception/CompletionConditionNotFulfilledException.java b/src/main/java/com/example/sinitto/helloCall/exception/CompletionConditionNotFulfilledException.java deleted file mode 100644 index 1974b425..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/CompletionConditionNotFulfilledException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class CompletionConditionNotFulfilledException extends RuntimeException { - public CompletionConditionNotFulfilledException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/exception/HelloCallAlreadyExistsException.java b/src/main/java/com/example/sinitto/helloCall/exception/HelloCallAlreadyExistsException.java deleted file mode 100644 index 4d9d4b2f..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/HelloCallAlreadyExistsException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class HelloCallAlreadyExistsException extends RuntimeException { - public HelloCallAlreadyExistsException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/exception/HelloCallNotFoundException.java b/src/main/java/com/example/sinitto/helloCall/exception/HelloCallNotFoundException.java deleted file mode 100644 index 6f862114..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/HelloCallNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class HelloCallNotFoundException extends RuntimeException { - public HelloCallNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/exception/InvalidStatusException.java b/src/main/java/com/example/sinitto/helloCall/exception/InvalidStatusException.java deleted file mode 100644 index 013c8322..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/InvalidStatusException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class InvalidStatusException extends RuntimeException { - public InvalidStatusException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/exception/TimeLogSequenceException.java b/src/main/java/com/example/sinitto/helloCall/exception/TimeLogSequenceException.java deleted file mode 100644 index 22a1b854..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/TimeLogSequenceException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class TimeLogSequenceException extends RuntimeException { - public TimeLogSequenceException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/exception/TimeRuleException.java b/src/main/java/com/example/sinitto/helloCall/exception/TimeRuleException.java deleted file mode 100644 index eb3756b5..00000000 --- a/src/main/java/com/example/sinitto/helloCall/exception/TimeRuleException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.helloCall.exception; - -public class TimeRuleException extends RuntimeException { - public TimeRuleException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/helloCall/service/HelloCallPriceService.java b/src/main/java/com/example/sinitto/helloCall/service/HelloCallPriceService.java index 59b5240d..8f8c6830 100644 --- a/src/main/java/com/example/sinitto/helloCall/service/HelloCallPriceService.java +++ b/src/main/java/com/example/sinitto/helloCall/service/HelloCallPriceService.java @@ -1,5 +1,6 @@ package com.example.sinitto.helloCall.service; +import com.example.sinitto.common.exception.BadRequestException; import com.example.sinitto.helloCall.dto.HelloCallPriceRequest; import com.example.sinitto.helloCall.dto.HelloCallPriceResponse; import org.springframework.stereotype.Service; @@ -44,7 +45,7 @@ private DayOfWeek convertDayStringToDayOfWeek(String dayName) { case "금" -> DayOfWeek.FRIDAY; case "토" -> DayOfWeek.SATURDAY; case "일" -> DayOfWeek.SUNDAY; - default -> throw new IllegalArgumentException("잘못된 dayName 입니다 : " + dayName); + default -> throw new BadRequestException("잘못된 dayName 입니다 : " + dayName); }; } diff --git a/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java b/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java index 7eed19b3..7beb5405 100644 --- a/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java +++ b/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java @@ -1,27 +1,22 @@ package com.example.sinitto.helloCall.service; -import com.example.sinitto.auth.exception.UnauthorizedException; -import com.example.sinitto.guard.exception.SeniorNotFoundException; +import com.example.sinitto.common.exception.BadRequestException; +import com.example.sinitto.common.exception.ConflictException; +import com.example.sinitto.common.exception.NotFoundException; +import com.example.sinitto.common.exception.UnauthorizedException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.helloCall.dto.*; import com.example.sinitto.helloCall.entity.HelloCall; import com.example.sinitto.helloCall.entity.HelloCallTimeLog; import com.example.sinitto.helloCall.entity.TimeSlot; -import com.example.sinitto.helloCall.exception.CompletionConditionNotFulfilledException; -import com.example.sinitto.helloCall.exception.HelloCallAlreadyExistsException; -import com.example.sinitto.helloCall.exception.HelloCallNotFoundException; -import com.example.sinitto.helloCall.exception.TimeLogSequenceException; import com.example.sinitto.helloCall.repository.HelloCallRepository; import com.example.sinitto.helloCall.repository.HelloCallTimeLogRepository; import com.example.sinitto.helloCall.repository.TimeSlotRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.point.entity.Point; import com.example.sinitto.point.entity.PointLog; -import com.example.sinitto.point.exception.NotEnoughPointException; -import com.example.sinitto.point.exception.PointNotFoundException; import com.example.sinitto.point.repository.PointLogRepository; import com.example.sinitto.point.repository.PointRepository; import org.springframework.data.domain.Page; @@ -62,10 +57,10 @@ public HelloCallService(HelloCallRepository helloCallRepository, TimeSlotReposit @Transactional public void createHelloCallByGuard(Long memberId, HelloCallRequest helloCallRequest) { Senior senior = seniorRepository.findByIdAndMemberId(helloCallRequest.seniorId(), memberId) - .orElseThrow(() -> new SeniorNotFoundException("보호자님과 연관된 시니어가 아니거나, 시니어를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("보호자님과 연관된 시니어가 아니거나, 시니어를 찾을 수 없습니다.")); if (helloCallRepository.existsBySeniorAndStatusIn(senior, List.of(HelloCall.Status.WAITING, HelloCall.Status.IN_PROGRESS))) { - throw new HelloCallAlreadyExistsException("이미 해당 시니어에게 할당되어 대기중 또는 진행중인 안부 전화 서비스가 존재합니다."); + throw new ConflictException("이미 해당 시니어에게 할당되어 대기중 또는 진행중인 안부 전화 서비스가 존재합니다."); } HelloCall helloCall = new HelloCall(helloCallRequest.startDate(), helloCallRequest.endDate(), @@ -79,10 +74,10 @@ public void createHelloCallByGuard(Long memberId, HelloCallRequest helloCallRequ } Point point = pointRepository.findByMemberIdWithWriteLock(memberId) - .orElseThrow(() -> new PointNotFoundException("멤버에 연관된 포인트가 없습니다.")); + .orElseThrow(() -> new NotFoundException("멤버에 연관된 포인트가 없습니다.")); if (!point.isSufficientForDeduction(helloCall.getPrice())) { - throw new NotEnoughPointException("포인트가 부족합니다."); + throw new BadRequestException("포인트가 부족합니다."); } point.deduct(helloCall.getPrice()); @@ -135,7 +130,7 @@ public Page readAllWaitingHelloCallsBySinitto(Pageable pageab @Transactional(readOnly = true) public HelloCallDetailResponse readHelloCallDetail(Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); List timeSlots = helloCall.getTimeSlots().stream() .map(timeSlot -> new HelloCallDetailResponse.TimeSlot( @@ -149,10 +144,10 @@ public HelloCallDetailResponse readHelloCallDetail(Long helloCallId) { @Transactional public void updateHelloCallByGuard(Long memberId, Long helloCallId, HelloCallDetailUpdateRequest helloCallDetailUpdateRequest) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkGuardIsCorrect(member); @@ -176,15 +171,15 @@ private void updateTimeSlots(HelloCall helloCall, List new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkGuardIsCorrect(member); Point point = pointRepository.findByMemberIdWithWriteLock(memberId) - .orElseThrow(() -> new PointNotFoundException("멤버에 연관된 포인트가 없습니다.")); + .orElseThrow(() -> new NotFoundException("멤버에 연관된 포인트가 없습니다.")); point.earn(helloCall.getPrice()); @@ -203,10 +198,10 @@ public void deleteHellCallByGuard(Long memberId, Long helloCallId) { @Transactional(readOnly = true) public List readHelloCallTimeLogByGuard(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkGuardIsCorrect(member); @@ -226,15 +221,15 @@ public List readHelloCallTimeLogByGuard(Long memberId, @Transactional(readOnly = true) public HelloCallReportResponse readHelloCallReportByGuard(Long memberId, Long helloCallId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); helloCall.checkGuardIsCorrect(member); if (!helloCall.checkReportIsNotNull()) { - throw new CompletionConditionNotFulfilledException("아직 안부전화 서비스가 완료되지 않았습니다."); + throw new BadRequestException("아직 안부전화 서비스가 완료되지 않았습니다."); } return new HelloCallReportResponse(helloCall.getStartDate(), @@ -244,17 +239,17 @@ public HelloCallReportResponse readHelloCallReportByGuard(Long memberId, Long he @Transactional public void makeCompleteHelloCallByGuard(Long memberId, Long helloCallId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); helloCall.checkGuardIsCorrect(member); helloCall.changeStatusToComplete(); Point sinittoPoint = pointRepository.findByMember(helloCall.getMember()) - .orElseThrow(() -> new PointNotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); + .orElseThrow(() -> new NotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); sinittoPoint.earn(helloCall.getPrice()); @@ -286,10 +281,10 @@ public List readAllHelloCallReportByAdmin() { @Transactional public void acceptHelloCallBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버가 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); if (!member.isSinitto()) { throw new UnauthorizedException("시니또가 아닙니다."); @@ -302,10 +297,10 @@ public void acceptHelloCallBySinitto(Long memberId, Long helloCallId) { @Transactional public void writeHelloCallStartTimeBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkMemberIsRightSinitto(member); @@ -313,7 +308,7 @@ public void writeHelloCallStartTimeBySinitto(Long memberId, Long helloCallId) { .findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(member, helloCall); if (recentLog.isPresent() && recentLog.get().getEndDateAndTime() == null) { - throw new TimeLogSequenceException("이미 시작된 안부전화가 있습니다. 종료를 먼저 완료해주세요."); + throw new BadRequestException("이미 시작된 안부전화가 있습니다. 종료를 먼저 완료해주세요."); } HelloCallTimeLog helloCallTimeLog = new HelloCallTimeLog(helloCall, member); @@ -325,19 +320,19 @@ public void writeHelloCallStartTimeBySinitto(Long memberId, Long helloCallId) { @Transactional public void writeHelloCallEndTimeBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkMemberIsRightSinitto(member); HelloCallTimeLog helloCallTimeLog = helloCallTimeLogRepository .findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(member, helloCall) - .orElseThrow(() -> new HelloCallNotFoundException("안부전화 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("안부전화 로그를 찾을 수 없습니다.")); if (helloCallTimeLog.getEndDateAndTime() != null) { - throw new TimeLogSequenceException("이미 종료된 안부전화입니다."); + throw new BadRequestException("이미 종료된 안부전화입니다."); } helloCallTimeLog.setEndDateAndTime(LocalDateTime.now()); @@ -346,10 +341,10 @@ public void writeHelloCallEndTimeBySinitto(Long memberId, Long helloCallId) { @Transactional public void cancelHelloCallBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkMemberIsRightSinitto(member); @@ -360,15 +355,15 @@ public void cancelHelloCallBySinitto(Long memberId, Long helloCallId) { @Transactional public void sendReportBySinitto(Long memberId, HelloCallReportRequest helloCallReportRequest) { HelloCall helloCall = helloCallRepository.findById(helloCallReportRequest.helloCallId()) - .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); helloCall.checkMemberIsRightSinitto(member); if (helloCall.checkIsNotAfterEndDate()) { - throw new CompletionConditionNotFulfilledException("서비스 종료 날짜보다 이른 날짜에 종료할 수 없습니다."); + throw new BadRequestException("서비스 종료 날짜보다 이른 날짜에 종료할 수 없습니다."); } helloCall.setReport(helloCallReportRequest.report()); @@ -378,7 +373,7 @@ public void sendReportBySinitto(Long memberId, HelloCallReportRequest helloCallR @Transactional(readOnly = true) public List readOwnHelloCallBySinitto(Long memberId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); List helloCalls = helloCallRepository.findAllByMember(member); diff --git a/src/main/java/com/example/sinitto/member/controller/MemberControllerAdvice.java b/src/main/java/com/example/sinitto/member/controller/MemberControllerAdvice.java deleted file mode 100644 index 5078274d..00000000 --- a/src/main/java/com/example/sinitto/member/controller/MemberControllerAdvice.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.sinitto.member.controller; - -import com.example.sinitto.member.exception.MemberNotFoundException; -import com.example.sinitto.member.exception.NotUniqueException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.member") -public class MemberControllerAdvice { - - @ExceptionHandler(MemberNotFoundException.class) - public ResponseEntity handleMemberNotFoundException(MemberNotFoundException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/member-not-found")); - problemDetail.setTitle("Member Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(NotUniqueException.class) - public ResponseEntity handleNotUniqueException(NotUniqueException ex) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.MULTI_STATUS, - ex.getMessage()); - problemDetail.setType(URI.create("/errors/not-unique-state")); - problemDetail.setTitle("Not Unique State"); - return ResponseEntity.status(HttpStatus.MULTI_STATUS).body(problemDetail); - } - -} diff --git a/src/main/java/com/example/sinitto/member/exception/MemberNotFoundException.java b/src/main/java/com/example/sinitto/member/exception/MemberNotFoundException.java deleted file mode 100644 index e294fd51..00000000 --- a/src/main/java/com/example/sinitto/member/exception/MemberNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.member.exception; - -public class MemberNotFoundException extends RuntimeException { - public MemberNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/member/exception/NotUniqueException.java b/src/main/java/com/example/sinitto/member/exception/NotUniqueException.java deleted file mode 100644 index b7f988c6..00000000 --- a/src/main/java/com/example/sinitto/member/exception/NotUniqueException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.member.exception; - -public class NotUniqueException extends RuntimeException { - public NotUniqueException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/member/service/MemberService.java b/src/main/java/com/example/sinitto/member/service/MemberService.java index f473aa17..ffa871b1 100644 --- a/src/main/java/com/example/sinitto/member/service/MemberService.java +++ b/src/main/java/com/example/sinitto/member/service/MemberService.java @@ -6,11 +6,11 @@ import com.example.sinitto.auth.service.KakaoApiService; import com.example.sinitto.auth.service.KakaoTokenService; import com.example.sinitto.auth.service.TokenService; +import com.example.sinitto.common.exception.ConflictException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.common.resolver.MemberIdProvider; import com.example.sinitto.member.dto.RegisterResponse; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.exception.MemberNotFoundException; -import com.example.sinitto.member.exception.NotUniqueException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.point.entity.Point; import com.example.sinitto.point.repository.PointRepository; @@ -42,7 +42,7 @@ public MemberService(MemberRepository memberRepository, TokenService tokenServic public Long getMemberIdByToken(String token) { String email = tokenService.extractEmail(token); Member member = memberRepository.findByEmail(email).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); return member.getId(); } @@ -71,7 +71,7 @@ public LoginResponse kakaoLogin(String authorizationCode) { public RegisterResponse registerNewMember(String name, String phoneNumber, String email, boolean isSinitto) { if (memberRepository.existsByEmail(email)) { - throw new NotUniqueException("이미 존재하는 이메일입니다."); + throw new ConflictException("이미 존재하는 이메일입니다."); } Member newMember = new Member(name, phoneNumber, email, isSinitto); @@ -87,7 +87,7 @@ public RegisterResponse registerNewMember(String name, String phoneNumber, Strin public void memberLogout(Long memberId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버가 없습니다.")); + .orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); String storedRefreshToken = redisTemplate.opsForValue().get(member.getEmail()); diff --git a/src/main/java/com/example/sinitto/point/controller/PointAdminController.java b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java index ae8b530e..bf8326be 100644 --- a/src/main/java/com/example/sinitto/point/controller/PointAdminController.java +++ b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java @@ -1,7 +1,7 @@ package com.example.sinitto.point.controller; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.point.dto.PointLogWithBankInfo; import com.example.sinitto.point.dto.PointLogWithDepositMessage; @@ -35,7 +35,7 @@ public String showAllChargeRequest(Model model) { for (PointLog pointLog : pointLogs) { Member member = memberRepository.findById(pointLog.getMember().getId()) - .orElseThrow(() -> new MemberNotFoundException("멤버를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("멤버를 찾을 수 없습니다")); PointLogWithDepositMessage pointLogWithDepositMessage = new PointLogWithDepositMessage( pointLog.getId(), diff --git a/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java b/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java deleted file mode 100644 index c6d6c4c3..00000000 --- a/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.example.sinitto.point.controller; - -import com.example.sinitto.point.exception.InvalidPointLogStatusException; -import com.example.sinitto.point.exception.PointLogNotFoundException; -import com.example.sinitto.point.exception.PointNotFoundException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -import java.net.URI; - -@ControllerAdvice(basePackages = "com.example.sinitto.point") -public class PointAdminControllerAdvice { - - @ExceptionHandler(PointNotFoundException.class) - public ResponseEntity handlePointNotFoundException(PointNotFoundException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/errors/not-found")); - problemDetail.setTitle("Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(InvalidPointLogStatusException.class) - public ResponseEntity handleInvalidPointStatusException(InvalidPointLogStatusException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); - problemDetail.setType(URI.create("/errors/conflict")); - problemDetail.setTitle("Conflict"); - return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); - } - - @ExceptionHandler(PointLogNotFoundException.class) - public ResponseEntity handlePointLogNotFoundException(PointLogNotFoundException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/errors/not-found")); - problemDetail.setTitle("Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java b/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java deleted file mode 100644 index 893451f7..00000000 --- a/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.example.sinitto.point.controller; - -import com.example.sinitto.point.exception.NotEnoughPointException; -import com.example.sinitto.point.exception.PointNotFoundException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.point") -public class PointControllerAdvice { - - @ExceptionHandler(PointNotFoundException.class) - public ResponseEntity handlePointNotFoundException(PointNotFoundException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/errors/not-found")); - problemDetail.setTitle("Not Found"); - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } - - @ExceptionHandler(NotEnoughPointException.class) - public ResponseEntity handleNotEnoughPointException(NotEnoughPointException e) { - - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); - problemDetail.setType(URI.create("/errors/conflict")); - problemDetail.setTitle("Conflict"); - return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/point/entity/Point.java b/src/main/java/com/example/sinitto/point/entity/Point.java index 5eab55b1..a407eaf8 100644 --- a/src/main/java/com/example/sinitto/point/entity/Point.java +++ b/src/main/java/com/example/sinitto/point/entity/Point.java @@ -1,7 +1,7 @@ package com.example.sinitto.point.entity; +import com.example.sinitto.common.exception.BadRequestException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.point.exception.NotEnoughPointException; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; @@ -46,7 +46,7 @@ public void earn(int priceToAdd) { public void deduct(int priceToDeduct) { if (this.price < priceToDeduct) { - throw new NotEnoughPointException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", this.price)); + throw new BadRequestException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", this.price)); } this.price -= priceToDeduct; diff --git a/src/main/java/com/example/sinitto/point/entity/PointLog.java b/src/main/java/com/example/sinitto/point/entity/PointLog.java index 440acca6..7d8f1a64 100644 --- a/src/main/java/com/example/sinitto/point/entity/PointLog.java +++ b/src/main/java/com/example/sinitto/point/entity/PointLog.java @@ -1,7 +1,7 @@ package com.example.sinitto.point.entity; +import com.example.sinitto.common.exception.ConflictException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.point.exception.InvalidPointLogStatusException; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; @@ -90,7 +90,7 @@ public void changeStatusToWithdrawFail() { private void checkStatusChange(Status wantStatus) { if (this.status != wantStatus) { - throw new InvalidPointLogStatusException(String.format("현재 %s 상태입니다. 이 상태에서는 %s 로의 전환이 불가합니다.", this.status, wantStatus)); + throw new ConflictException(String.format("현재 %s 상태입니다. 이 상태에서는 %s 로의 전환이 불가합니다.", this.status, wantStatus)); } } @@ -133,11 +133,11 @@ public enum Status { } public enum Content { - COMPLETE_CALLBACK_AND_EARN("콜백 완료로 인한 포인트 적립"), - COMPLETE_HELLO_CALL_AND_EARN("안부 전화 완료로 인한 포인트 적립"), - SPEND_COMPLETE_CALLBACK("콜백 신청으로 인한 포인트 차감"), - SPEND_COMPLETE_HELLO_CALL("안부전화 신청으로 인한 포인트 차감"), - SPEND_CANCEL_HELLO_CALL("안부전화 신청 취소로 인한 포인트 환불"), + COMPLETE_CALLBACK_AND_EARN("콜백 수행 완료"), + COMPLETE_HELLO_CALL_AND_EARN("안부전화 수행 완료"), + SPEND_COMPLETE_CALLBACK("콜백 신청"), + SPEND_COMPLETE_HELLO_CALL("안부전화 신청"), + SPEND_CANCEL_HELLO_CALL("안부전화 신청 취소"), CHARGE_REQUEST("포인트 충전"), WITHDRAW_REQUEST("포인트 출금"); diff --git a/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java b/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java deleted file mode 100644 index 344141cb..00000000 --- a/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.point.exception; - -public class InvalidPointLogStatusException extends RuntimeException { - - public InvalidPointLogStatusException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java b/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java deleted file mode 100644 index 882f119a..00000000 --- a/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.point.exception; - -public class NotEnoughPointException extends RuntimeException { - - public NotEnoughPointException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java b/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java deleted file mode 100644 index 809503c3..00000000 --- a/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.point.exception; - -public class PointLogNotFoundException extends RuntimeException { - - public PointLogNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java b/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java deleted file mode 100644 index 732e19cc..00000000 --- a/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.point.exception; - -public class PointNotFoundException extends RuntimeException { - - public PointNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/point/service/PointAdminService.java b/src/main/java/com/example/sinitto/point/service/PointAdminService.java index 940dccf3..4bd24611 100644 --- a/src/main/java/com/example/sinitto/point/service/PointAdminService.java +++ b/src/main/java/com/example/sinitto/point/service/PointAdminService.java @@ -1,12 +1,12 @@ package com.example.sinitto.point.service; -import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.point.dto.PointLogWithBankInfo; import com.example.sinitto.point.entity.Point; import com.example.sinitto.point.entity.PointLog; -import com.example.sinitto.point.exception.PointLogNotFoundException; import com.example.sinitto.point.repository.PointLogRepository; import com.example.sinitto.point.repository.PointRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,7 +36,7 @@ public List readAllNotCompletedPointChargeRequest() { public void changeChargeLogToWaiting(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다")); pointLog.changeStatusToChargeWaiting(); } @@ -45,10 +45,10 @@ public void changeChargeLogToWaiting(Long pointLogId) { public void earnPointAndChangeToChargeComplete(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다.")); Point point = pointRepository.findByMember(pointLog.getMember()) - .orElseThrow(() -> new PointLogNotFoundException("포인트를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트를 찾을 수 없습니다.")); pointLog.changeStatusToChargeComplete(); point.earn(pointLog.getPrice()); @@ -58,7 +58,7 @@ public void earnPointAndChangeToChargeComplete(Long pointLogId) { public void changeChargeLogToFail(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다.")); pointLog.changeStatusToChargeFail(); } @@ -67,7 +67,7 @@ public void changeChargeLogToFail(Long pointLogId) { public void changeWithdrawLogToWaiting(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다.")); pointLog.changeStatusToWithdrawWaiting(); } @@ -76,7 +76,7 @@ public void changeWithdrawLogToWaiting(Long pointLogId) { public void changeWithdrawLogToComplete(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다.")); pointLog.changeStatusToWithdrawComplete(); } @@ -85,10 +85,10 @@ public void changeWithdrawLogToComplete(Long pointLogId) { public void changeWithdrawLogToFail(Long pointLogId) { PointLog pointLog = pointLogRepository.findById(pointLogId) - .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트 로그를 찾을 수 없습니다.")); Point point = pointRepository.findByMember(pointLog.getMember()) - .orElseThrow(() -> new PointLogNotFoundException("포인트를 찾을 수 없습니다.")); + .orElseThrow(() -> new NotFoundException("포인트를 찾을 수 없습니다.")); point.earn(pointLog.getPrice()); diff --git a/src/main/java/com/example/sinitto/point/service/PointService.java b/src/main/java/com/example/sinitto/point/service/PointService.java index 0348aeda..986b7da6 100644 --- a/src/main/java/com/example/sinitto/point/service/PointService.java +++ b/src/main/java/com/example/sinitto/point/service/PointService.java @@ -1,19 +1,17 @@ package com.example.sinitto.point.service; -import com.example.sinitto.callback.exception.NotSinittoException; +import com.example.sinitto.common.exception.BadRequestException; +import com.example.sinitto.common.exception.ForbiddenException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.point.dto.PointChargeResponse; import com.example.sinitto.point.dto.PointLogResponse; import com.example.sinitto.point.dto.PointResponse; import com.example.sinitto.point.entity.Point; import com.example.sinitto.point.entity.PointLog; -import com.example.sinitto.point.exception.NotEnoughPointException; -import com.example.sinitto.point.exception.PointNotFoundException; import com.example.sinitto.point.repository.PointLogRepository; import com.example.sinitto.point.repository.PointRepository; -import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -39,10 +37,10 @@ public PointService(MemberRepository memberRepository, PointRepository pointRepo public PointResponse getPoint(Long memberId) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버를 찾을 수 없습니다")); Point point = pointRepository.findByMember(member) - .orElseThrow(() -> new PointNotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); return new PointResponse(point.getPrice()); } @@ -50,7 +48,7 @@ public PointResponse getPoint(Long memberId) { public Page getPointLogs(Long memberId, Pageable pageable) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버를 찾을 수 없습니다")); return pointLogRepository.findAllByMember(member, pageable) .map(pointLog -> new PointLogResponse( @@ -65,7 +63,7 @@ public Page getPointLogs(Long memberId, Pageable pageable) { public PointChargeResponse savePointChargeRequest(Long memberId, int price) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버를 찾을 수 없습니다")); pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), member, price, PointLog.Status.CHARGE_REQUEST)); @@ -76,23 +74,23 @@ public PointChargeResponse savePointChargeRequest(Long memberId, int price) { public void savePointWithdrawRequest(Long memberId, int price) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버를 찾을 수 없습니다")); if (!member.isSinitto()) { - throw new NotSinittoException("출금 요청은 시니또만 가능합니다. 지금 요청은 시니또가 요청하지 않았습니다."); + throw new ForbiddenException("출금 요청은 시니또만 가능합니다. 지금 요청은 시니또가 요청하지 않았습니다."); } if (!sinittoBankInfoRepository.existsByMemberId(memberId)) { - throw new SinittoBankInfoNotFoundException("시니또의 은행 계좌 정보가 없습니다. 계좌를 등록해야 합니다."); + throw new NotFoundException("시니또의 은행 계좌 정보가 없습니다. 계좌를 등록해야 합니다."); } Point point = pointRepository.findByMember(member) - .orElseThrow(() -> new PointNotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); + .orElseThrow(() -> new NotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); int adjustedPrice = (int) (price * WITHDRAWAL_FEE_RATE); if (!point.isSufficientForDeduction(price)) { - throw new NotEnoughPointException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", point.getPrice())); + throw new BadRequestException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", point.getPrice())); } point.deduct(price); diff --git a/src/main/java/com/example/sinitto/review/service/ReviewService.java b/src/main/java/com/example/sinitto/review/service/ReviewService.java index 4db11a55..83876be4 100644 --- a/src/main/java/com/example/sinitto/review/service/ReviewService.java +++ b/src/main/java/com/example/sinitto/review/service/ReviewService.java @@ -1,7 +1,7 @@ package com.example.sinitto.review.service; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.review.dto.ReviewRequest; import com.example.sinitto.review.dto.ReviewResponse; @@ -32,7 +32,7 @@ public List readAllReviews() { @Transactional public void createReview(Long memberId, ReviewRequest reviewRequest) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); Review review = new Review(reviewRequest.starCountForRequest(), reviewRequest.starCountForService(), diff --git a/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java b/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java deleted file mode 100644 index da30208d..00000000 --- a/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.sinitto.sinitto.controller; - -import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.net.URI; - -@RestControllerAdvice(basePackages = "com.example.sinitto.sinitto") -public class SinittoControllerAdvice { - @ExceptionHandler(SinittoBankInfoNotFoundException.class) - public ResponseEntity handleSinittoNotFoundException(SinittoBankInfoNotFoundException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); - problemDetail.setType(URI.create("/error/sinitto-not-found")); - problemDetail.setTitle("SinittoBankInfo Not Found"); - - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); - } -} diff --git a/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java b/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java deleted file mode 100644 index b7be2b58..00000000 --- a/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.sinitto.exception; - -public class SinittoBankInfoNotFoundException extends RuntimeException { - public SinittoBankInfoNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java b/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java index 76d48698..61bbd600 100644 --- a/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java +++ b/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java @@ -1,13 +1,12 @@ package com.example.sinitto.sinitto.service; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.sinitto.dto.SinittoBankRequest; import com.example.sinitto.sinitto.dto.SinittoRequest; import com.example.sinitto.sinitto.dto.SinittoResponse; import com.example.sinitto.sinitto.entity.SinittoBankInfo; -import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,7 +28,7 @@ public SinittoService(MemberRepository memberRepository, SinittoBankInfoReposito @Transactional public void createSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankRequest) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); SinittoBankInfo sinittoBankInfo = new SinittoBankInfo(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber(), member); sinittoBankInfoRepository.save(sinittoBankInfo); @@ -38,10 +37,10 @@ public void createSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankR @Transactional(readOnly = true) public SinittoResponse readSinitto(Long memberId) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); return new SinittoResponse(member.getName(), member.getPhoneNumber(), member.getEmail(), sinittoBankInfo.getAccountNumber(), sinittoBankInfo.getBankName()); } @@ -49,7 +48,7 @@ public SinittoResponse readSinitto(Long memberId) { @Transactional public void updateSinitto(Long memberId, SinittoRequest sinittoRequest) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); member.updateMember(sinittoRequest.name(), sinittoRequest.email(), sinittoRequest.phoneNumber()); } @@ -57,7 +56,7 @@ public void updateSinitto(Long memberId, SinittoRequest sinittoRequest) { @Transactional public void updateSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankRequest) { SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); sinittoBankInfo.updateSinitto(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber()); } @@ -65,7 +64,7 @@ public void updateSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankR @Transactional public void deleteSinitto(Long memberId) { Member member = memberRepository.findById(memberId).orElseThrow( - () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); memberRepository.delete(member); } @@ -73,7 +72,7 @@ public void deleteSinitto(Long memberId) { @Transactional public void deleteSinittoBankInfo(Long memberId) { SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + () -> new NotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); sinittoBankInfoRepository.delete(sinittoBankInfo); } diff --git a/src/test/java/com/example/sinitto/SinittoApplicationTests.java b/src/test/java/com/example/sinitto/SinittoApplicationTests.java index b4b7d602..be2f259e 100644 --- a/src/test/java/com/example/sinitto/SinittoApplicationTests.java +++ b/src/test/java/com/example/sinitto/SinittoApplicationTests.java @@ -1,13 +1,20 @@ package com.example.sinitto; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; +import static org.hibernate.validator.internal.util.Contracts.assertNotNull; + @SpringBootTest class SinittoApplicationTests { + @Value("${jwt.secret}") + private String jwtSecret; + @Test void contextLoads() { + assertNotNull(jwtSecret); } } diff --git a/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java b/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java index c9879f2e..31897ee1 100644 --- a/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java +++ b/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java @@ -1,10 +1,7 @@ package com.example.sinitto.callback.entity; -import com.example.sinitto.callback.exception.AlreadyCompleteException; -import com.example.sinitto.callback.exception.AlreadyInProgressException; -import com.example.sinitto.callback.exception.AlreadyPendingCompleteException; -import com.example.sinitto.callback.exception.AlreadyWaitingException; import com.example.sinitto.callback.repository.CallbackRepository; +import com.example.sinitto.common.exception.ConflictException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; @@ -63,7 +60,7 @@ void changeStatusToInProgress_fail1() { testCallback.changeStatusToPendingComplete(); //when then - assertThrows(AlreadyPendingCompleteException.class, () -> testCallback.changeStatusToInProgress()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToInProgress()); } @Test @@ -73,7 +70,7 @@ void changeStatusToInProgress_fail2() { testCallback.changeStatusToInProgress(); //when then - assertThrows(AlreadyInProgressException.class, () -> testCallback.changeStatusToInProgress()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToInProgress()); } @Test @@ -93,7 +90,7 @@ void changeStatusToPendingComplete() { @DisplayName("Waiting -> Pending Complete - 예외 발생") void changeStatusToPendingComplete_fail1() { //when then - assertThrows(AlreadyWaitingException.class, () -> testCallback.changeStatusToPendingComplete()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToPendingComplete()); } @Test @@ -104,7 +101,7 @@ void changeStatusToPendingComplete_fail2() { testCallback.changeStatusToPendingComplete(); //when then - assertThrows(AlreadyPendingCompleteException.class, () -> testCallback.changeStatusToPendingComplete()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToPendingComplete()); } @Test @@ -124,7 +121,7 @@ void changeStatusToWaiting() { @DisplayName("Waiting -> Waiting - 예외 발생") void changeStatusToWaiting_fain1() { //when then - assertThrows(AlreadyWaitingException.class, () -> testCallback.changeStatusToWaiting()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToWaiting()); } @Test @@ -135,7 +132,7 @@ void changeStatusToWaiting_fail2() { testCallback.changeStatusToPendingComplete(); //when then - assertThrows(AlreadyPendingCompleteException.class, () -> testCallback.changeStatusToWaiting()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToWaiting()); } @Test @@ -158,7 +155,7 @@ void checkAssignedMemberId_fail1() { testCallback.changeStatusToInProgress(); //when then - assertThrows(AlreadyInProgressException.class, () -> testCallback.assignMember(3L)); + assertThrows(ConflictException.class, () -> testCallback.assignMember(3L)); } @Test @@ -169,7 +166,7 @@ void checkAssignedMemberId_fail2() { testCallback.changeStatusToPendingComplete(); //when then - assertThrows(AlreadyPendingCompleteException.class, () -> testCallback.assignMember(3L)); + assertThrows(ConflictException.class, () -> testCallback.assignMember(3L)); } @Test @@ -181,7 +178,7 @@ void checkAssignedMemberId_fail3() { testCallback.changeStatusToComplete(); //when then - assertThrows(AlreadyCompleteException.class, () -> testCallback.assignMember(3L)); + assertThrows(ConflictException.class, () -> testCallback.assignMember(3L)); } @Test @@ -207,14 +204,14 @@ void cancelAssignment_fail1() { testCallback.changeStatusToPendingComplete(); //when then - assertThrows(AlreadyPendingCompleteException.class, () -> testCallback.cancelAssignment()); + assertThrows(ConflictException.class, () -> testCallback.cancelAssignment()); } @Test @DisplayName("Waiting 상태에서 할당 취소 - 예외 발생") void cancelAssignment_fail2() { //when then - assertThrows(AlreadyWaitingException.class, () -> testCallback.cancelAssignment()); + assertThrows(ConflictException.class, () -> testCallback.cancelAssignment()); } @Test @@ -226,7 +223,7 @@ void cancelAssignment_fail3() { testCallback.changeStatusToComplete(); //when then - assertThrows(AlreadyCompleteException.class, () -> testCallback.cancelAssignment()); + assertThrows(ConflictException.class, () -> testCallback.cancelAssignment()); } @Test @@ -250,14 +247,14 @@ void changeStatusToComplete_fail() { testCallback.changeStatusToComplete(); //then - assertThrows(AlreadyCompleteException.class, () -> testCallback.changeStatusToComplete()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToComplete()); } @Test @DisplayName("Waiting -> Complete - 예외 발생") void changeStatusToComplete_fail1() { //when then - assertThrows(AlreadyWaitingException.class, () -> testCallback.changeStatusToComplete()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToComplete()); } @Test @@ -267,7 +264,7 @@ void changeStatusToComplete_fail2() { testCallback.changeStatusToInProgress(); //when then - assertThrows(AlreadyInProgressException.class, () -> testCallback.changeStatusToComplete()); + assertThrows(ConflictException.class, () -> testCallback.changeStatusToComplete()); } @Test diff --git a/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java b/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java index f4a0a436..4fdf702b 100644 --- a/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java +++ b/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java @@ -2,12 +2,10 @@ import com.example.sinitto.callback.dto.CallbackResponse; import com.example.sinitto.callback.entity.Callback; -import com.example.sinitto.callback.exception.GuardMismatchException; -import com.example.sinitto.callback.exception.NotExistCallbackException; -import com.example.sinitto.callback.exception.NotMemberException; -import com.example.sinitto.callback.exception.NotSinittoException; import com.example.sinitto.callback.repository.CallbackRepository; import com.example.sinitto.callback.util.TwilioHelper; +import com.example.sinitto.common.exception.ForbiddenException; +import com.example.sinitto.common.exception.NotFoundException; import com.example.sinitto.guard.repository.SeniorRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; @@ -87,7 +85,7 @@ void getWaitingCallbacks_Fail_WhenNotMember() { when(memberRepository.findById(memberId)).thenReturn(Optional.empty()); //when then - assertThrows(NotMemberException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); + assertThrows(NotFoundException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); } @Test @@ -102,7 +100,7 @@ void getCallbacks_Fail_WhenNotSinitto() { when(member.isSinitto()).thenReturn(false); //when then - assertThrows(NotSinittoException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); + assertThrows(ForbiddenException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); } @Test @@ -307,7 +305,7 @@ void changeCallbackStatusToCompleteByGuardByGuard_fail() { when(senior.getMember().getId()).thenReturn(1L); //when then - assertThrows(GuardMismatchException.class, () -> callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId)); + assertThrows(ForbiddenException.class, () -> callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId)); } @Test @@ -342,7 +340,7 @@ void getAcceptedCallback_fail() { when(callbackRepository.findByAssignedMemberIdAndStatus(memberId, Callback.Status.IN_PROGRESS)).thenReturn(Optional.empty()); //when then - assertThrows(NotExistCallbackException.class, () -> callbackService.getAcceptedCallback(memberId)); + assertThrows(NotFoundException.class, () -> callbackService.getAcceptedCallback(memberId)); } @Test diff --git a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java index 66b993a1..e92c2701 100644 --- a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java +++ b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java @@ -1,8 +1,7 @@ package com.example.sinitto.hellocall.entity; +import com.example.sinitto.common.exception.BadRequestException; import com.example.sinitto.helloCall.entity.HelloCall; -import com.example.sinitto.helloCall.exception.InvalidStatusException; -import com.example.sinitto.helloCall.exception.TimeRuleException; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import org.junit.jupiter.api.BeforeEach; @@ -48,7 +47,7 @@ void constructorTest() { @Test @DisplayName("시작날짜가 종료날짜 이후일 때 예외 발생 테스트") - void constructorThrowsTimeRuleException() { + void constructorThrowsBadRequestException() { assertThatThrownBy(() -> new HelloCall( LocalDate.of(2024, 10, 11), LocalDate.of(2024, 10, 10), @@ -56,7 +55,7 @@ void constructorThrowsTimeRuleException() { 30, "Invalid Requirement", senior - )).isInstanceOf(TimeRuleException.class) + )).isInstanceOf(BadRequestException.class) .hasMessage("시작날짜가 종료날짜 이후일 수 없습니다."); } @@ -75,17 +74,17 @@ void changeStatusTest() { @Test @DisplayName("상태 변경 예외 발생 테스트") - void changeStatusThrowsInvalidStatusException() { + void changeStatusThrowsBadRequestException() { helloCall.changeStatusToInProgress(); assertThatThrownBy(() -> helloCall.changeStatusToInProgress()) - .isInstanceOf(InvalidStatusException.class) + .isInstanceOf(BadRequestException.class) .hasMessage("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 나아갈 수 있습니다. 현재 상태 : " + HelloCall.Status.IN_PROGRESS); helloCall.changeStatusToPendingComplete(); assertThatThrownBy(() -> helloCall.changeStatusToWaiting()) - .isInstanceOf(InvalidStatusException.class) + .isInstanceOf(BadRequestException.class) .hasMessage("안부전화 서비스가 수행중일 때만 진행중 상태로 돌아갈 수 있습니다. 현재 상태 : " + HelloCall.Status.PENDING_COMPLETE); } @@ -109,7 +108,7 @@ void updateHelloCallTest() { @Test @DisplayName("Update HelloCall 예외 발생 테스트") - void updateHelloCallThrowsInvalidStatusException() { + void updateHelloCallThrowsBadRequestException() { helloCall.changeStatusToInProgress(); assertThatThrownBy(() -> helloCall.updateHelloCall( @@ -118,7 +117,7 @@ void updateHelloCallThrowsInvalidStatusException() { 12000, 45, "Updated Requirement" - )).isInstanceOf(InvalidStatusException.class) + )).isInstanceOf(BadRequestException.class) .hasMessage("안부전화 서비스가 수행 대기중일 때만 수정이 가능합니다."); } } diff --git a/src/test/java/com/example/sinitto/hellocall/entity/TimeSlotTest.java b/src/test/java/com/example/sinitto/hellocall/entity/TimeSlotTest.java index 384d0849..312db619 100644 --- a/src/test/java/com/example/sinitto/hellocall/entity/TimeSlotTest.java +++ b/src/test/java/com/example/sinitto/hellocall/entity/TimeSlotTest.java @@ -1,8 +1,8 @@ package com.example.sinitto.hellocall.entity; +import com.example.sinitto.common.exception.BadRequestException; import com.example.sinitto.helloCall.entity.HelloCall; import com.example.sinitto.helloCall.entity.TimeSlot; -import com.example.sinitto.helloCall.exception.TimeRuleException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -38,7 +38,7 @@ void constructorTest_ValidInput() { @DisplayName("TimeSlot 생성자 테스트 - 잘못된 시간 순서") void constructorTest_InvalidTimeOrder() { assertThatThrownBy(() -> new TimeSlot("Monday", LocalTime.of(10, 0), LocalTime.of(9, 0), helloCall)) - .isInstanceOf(TimeRuleException.class) + .isInstanceOf(BadRequestException.class) .hasMessage("시작시간이 종료시간 이후일 수 없습니다."); } @@ -61,7 +61,7 @@ void updateTimeSlot_InvalidTimeOrder() { LocalTime newEndTime = LocalTime.of(10, 0); assertThatThrownBy(() -> timeSlot.updateTimeSlot(newStartTime, newEndTime)) - .isInstanceOf(TimeRuleException.class) + .isInstanceOf(BadRequestException.class) .hasMessage("시작시간이 종료시간 이후일 수 없습니다."); } } diff --git a/src/test/java/com/example/sinitto/point/entity/PointLogTest.java b/src/test/java/com/example/sinitto/point/entity/PointLogTest.java index a564e1e4..c415f672 100644 --- a/src/test/java/com/example/sinitto/point/entity/PointLogTest.java +++ b/src/test/java/com/example/sinitto/point/entity/PointLogTest.java @@ -1,7 +1,7 @@ package com.example.sinitto.point.entity; +import com.example.sinitto.common.exception.ConflictException; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.point.exception.InvalidPointLogStatusException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -37,7 +37,7 @@ void changeStatusToChargeWaiting_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeWaiting); + assertThrows(ConflictException.class, pointLog::changeStatusToChargeWaiting); } @Test @@ -62,7 +62,7 @@ void changeStatusToChargeComplete_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeComplete); + assertThrows(ConflictException.class, pointLog::changeStatusToChargeComplete); } @Test @@ -79,7 +79,7 @@ void changeStatusToChargeFail() { } @ParameterizedTest - @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE","WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE","CHARGE_FAIL"}) + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL"}) @DisplayName("포인트 로그 ChargeFail 상태로 전환 실패") void changeStatusToChargeFail_fail(String initialStatus) { //given @@ -87,7 +87,7 @@ void changeStatusToChargeFail_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeFail); + assertThrows(ConflictException.class, pointLog::changeStatusToChargeFail); } @Test @@ -104,7 +104,7 @@ void changeStatusToWithdrawWaiting() { } @ParameterizedTest - @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL","CHARGE_WAITING"}) + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL", "CHARGE_WAITING"}) @DisplayName("포인트 로그 WithdrawWaiting 상태로 전환 실패") void changeStatusToWithdrawWaiting_fail(String initialStatus) { //given @@ -112,7 +112,7 @@ void changeStatusToWithdrawWaiting_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawWaiting); + assertThrows(ConflictException.class, pointLog::changeStatusToWithdrawWaiting); } @Test @@ -137,7 +137,7 @@ void changeStatusToWithdrawComplete_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawComplete); + assertThrows(ConflictException.class, pointLog::changeStatusToWithdrawComplete); } @Test @@ -162,6 +162,6 @@ void changeStatusToWithdrawFail_fail(String initialStatus) { PointLog pointLog = new PointLog("content", member, 1000, status); //when then - assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawFail); + assertThrows(ConflictException.class, pointLog::changeStatusToWithdrawFail); } }