From 16eed0cbed6861ad8b3f93171a538bac67139e12 Mon Sep 17 00:00:00 2001 From: Kim DongHyo <60608509+kdhyo@users.noreply.github.com> Date: Fri, 8 Jul 2022 11:33:21 +0900 Subject: [PATCH] =?UTF-8?q?[User]=20=ED=9A=8C=EC=9B=90=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EB=B0=8F=20?= =?UTF-8?q?Exception=20Method=20=ED=95=9C=20=EA=B3=B3=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: findPayments * refactor: Exception Method 한 곳으로 이동 --- .../server/global/exception/ErrorCode.java | 40 +++++++++++ .../ticketing/server/movie/domain/Seat.java | 10 +-- .../ticketing/server/movie/domain/Ticket.java | 5 +- .../movie/service/MovieTimeServiceImpl.java | 34 ++++----- .../server/movie/setup/MovieSetupService.java | 9 +-- .../server/payment/domain/Payment.java | 35 +++++++-- .../domain/repository/PaymentRepository.java | 2 + .../payment/service/PaymentServiceImpl.java | 17 +++++ .../payment/service/dto/CreatePaymentDto.java | 30 ++++++++ .../payment/service/dto/SimplePaymentDto.java | 25 +++++++ .../service/interfaces/PaymentService.java | 4 ++ .../server/user/api/PaymentClient.java | 10 +++ .../dto/request/SimplePaymentsRequest.java | 18 +++++ .../dto/response/SimplePaymentsResponse.java | 21 ++++++ .../user/api/impl/PaymentClientImpl.java | 21 ++++++ .../user/application/UserController.java | 8 +++ .../SimplePaymentDetailsResponse.java | 21 ++++++ .../ticketing/server/user/domain/User.java | 9 +-- .../service/AuthenticationServiceImpl.java | 12 ++-- .../service/CustomUserDetailsService.java | 6 +- .../server/user/service/UserServiceImpl.java | 28 +++++--- .../user/service/interfaces/UserService.java | 4 ++ .../service/PaymentServiceImplTest.java | 71 +++++++++++++++++++ .../user/service/UserServiceImplTest.java | 40 +++++++++++ 24 files changed, 411 insertions(+), 69 deletions(-) create mode 100644 server/src/main/java/com/ticketing/server/payment/service/dto/CreatePaymentDto.java create mode 100644 server/src/main/java/com/ticketing/server/payment/service/dto/SimplePaymentDto.java create mode 100644 server/src/main/java/com/ticketing/server/user/api/PaymentClient.java create mode 100644 server/src/main/java/com/ticketing/server/user/api/dto/request/SimplePaymentsRequest.java create mode 100644 server/src/main/java/com/ticketing/server/user/api/dto/response/SimplePaymentsResponse.java create mode 100644 server/src/main/java/com/ticketing/server/user/api/impl/PaymentClientImpl.java create mode 100644 server/src/main/java/com/ticketing/server/user/application/response/SimplePaymentDetailsResponse.java create mode 100644 server/src/test/java/com/ticketing/server/payment/service/PaymentServiceImplTest.java diff --git a/server/src/main/java/com/ticketing/server/global/exception/ErrorCode.java b/server/src/main/java/com/ticketing/server/global/exception/ErrorCode.java index 454a848..cea053a 100644 --- a/server/src/main/java/com/ticketing/server/global/exception/ErrorCode.java +++ b/server/src/main/java/com/ticketing/server/global/exception/ErrorCode.java @@ -18,6 +18,7 @@ public enum ErrorCode { UNAVAILABLE_REFRESH_TOKEN(BAD_REQUEST, "사용할 수 없는 토큰 입니다."), /* 404 NOT_FOUND : Resource 를 찾을 수 없음 */ + USER_NOT_FOUND(NOT_FOUND, "해당 유저 정보를 찾을 수 없습니다."), EMAIL_NOT_FOUND(NOT_FOUND, "해당 이메일을 찾을 수 없습니다."), MOVIE_NOT_FOUND(NOT_FOUND, "해당 제목의 영화를 찾을 수 없습니다."), REFRESH_TOKEN_NOT_FOUND(NOT_FOUND, "리프레쉬 토큰을 찾을 수 없습니다."), @@ -29,4 +30,43 @@ public enum ErrorCode { private final HttpStatus httpStatus; private final String detail; + /* 400 BAD_REQUEST : 잘못된 요청 */ + public static TicketingException throwMismatchPassword() { + throw new TicketingException(MISMATCH_PASSWORD); + } + + public static TicketingException throwTokenType() { + throw new TicketingException(TOKEN_TYPE); + } + + public static TicketingException throwUnavailableRefreshToken() { + throw new TicketingException(UNAVAILABLE_REFRESH_TOKEN); + } + + /* 404 NOT_FOUND : Resource 를 찾을 수 없음 */ + public static TicketingException throwUserNotFound() { + throw new TicketingException(USER_NOT_FOUND); + } + + public static TicketingException throwEmailNotFound() { + throw new TicketingException(EMAIL_NOT_FOUND); + } + + public static TicketingException throwMovieNotFound() { + throw new TicketingException(MOVIE_NOT_FOUND); + } + + public static TicketingException throwRefreshTokenNotFound() { + throw new TicketingException(REFRESH_TOKEN_NOT_FOUND); + } + + /* 409 CONFLICT : Resource 의 현재 상태와 충돌. 보통 중복된 데이터 존재 */ + public static TicketingException throwDuplicateEmail() { + throw new TicketingException(DUPLICATE_EMAIL); + } + + public static TicketingException throwDeletedEmail() { + throw new TicketingException(DELETED_EMAIL); + } + } diff --git a/server/src/main/java/com/ticketing/server/movie/domain/Seat.java b/server/src/main/java/com/ticketing/server/movie/domain/Seat.java index 340b082..89190d2 100644 --- a/server/src/main/java/com/ticketing/server/movie/domain/Seat.java +++ b/server/src/main/java/com/ticketing/server/movie/domain/Seat.java @@ -18,15 +18,15 @@ public class Seat extends AbstractEntity { @JoinColumn(name = "theater_id", referencedColumnName = "id", updatable = false) private Theater theater; - @NotNull - private Integer seatColumn; - @NotNull private Integer seatRow; - public Seat(Integer seatColumn, Integer seatRow, Theater theater) { - this.seatColumn = seatColumn; + @NotNull + private Integer seatColumn; + + public Seat(Integer seatRow, Integer seatColumn, Theater theater) { this.seatRow = seatRow; + this.seatColumn = seatColumn; setTheater(theater); } diff --git a/server/src/main/java/com/ticketing/server/movie/domain/Ticket.java b/server/src/main/java/com/ticketing/server/movie/domain/Ticket.java index 957af7f..7507ebf 100644 --- a/server/src/main/java/com/ticketing/server/movie/domain/Ticket.java +++ b/server/src/main/java/com/ticketing/server/movie/domain/Ticket.java @@ -1,7 +1,6 @@ package com.ticketing.server.movie.domain; import com.ticketing.server.global.dto.repository.AbstractEntity; -import com.ticketing.server.payment.domain.Payment; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; @@ -26,9 +25,7 @@ public class Ticket extends AbstractEntity { @JoinColumn(name = "movie_times_id", referencedColumnName = "id", updatable = false) private MovieTime movieTime; - @ManyToOne - @JoinColumn(name = "payment_id", referencedColumnName = "id", updatable = false) - private Payment payment; + private Long paymentId; @NotNull @Enumerated(EnumType.STRING) diff --git a/server/src/main/java/com/ticketing/server/movie/service/MovieTimeServiceImpl.java b/server/src/main/java/com/ticketing/server/movie/service/MovieTimeServiceImpl.java index 18631c0..72d2752 100644 --- a/server/src/main/java/com/ticketing/server/movie/service/MovieTimeServiceImpl.java +++ b/server/src/main/java/com/ticketing/server/movie/service/MovieTimeServiceImpl.java @@ -1,8 +1,6 @@ package com.ticketing.server.movie.service; -import static com.ticketing.server.global.exception.ErrorCode.MOVIE_NOT_FOUND; - -import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.global.exception.ErrorCode; import com.ticketing.server.movie.domain.Movie; import com.ticketing.server.movie.domain.MovieTime; import com.ticketing.server.movie.domain.repository.MovieRepository; @@ -22,28 +20,24 @@ import org.springframework.stereotype.Service; @Slf4j public class MovieTimeServiceImpl implements MovieTimeService { - private final MovieRepository movieRepository; + private final MovieRepository movieRepository; - private final MovieTimeRepository movieTimeRepository; + private final MovieTimeRepository movieTimeRepository; - @Override - public List getMovieTimes(String title, LocalDate runningDate) { - Movie movie = movieRepository.findByTitle(title) - .orElseThrow(MovieTimeServiceImpl::throwMovieNotFound); + @Override + public List getMovieTimes(String title, LocalDate runningDate) { + Movie movie = movieRepository.findByTitle(title) + .orElseThrow(ErrorCode::throwMovieNotFound); - LocalDateTime startOfDay = runningDate.atStartOfDay().plusHours(6); - LocalDateTime endOfDay = startOfDay.plusDays(1); + LocalDateTime startOfDay = runningDate.atStartOfDay().plusHours(6); + LocalDateTime endOfDay = startOfDay.plusDays(1); - List movieTimes = movieTimeRepository.findValidMovieTimes(movie, startOfDay, endOfDay); + List movieTimes = movieTimeRepository.findValidMovieTimes(movie, startOfDay, endOfDay); - return movieTimes.stream() - .map(MovieTimeDto::from) - .collect(Collectors.toList()); + return movieTimes.stream() + .map(MovieTimeDto::from) + .collect(Collectors.toList()); - } - - private static RuntimeException throwMovieNotFound() { - throw new TicketingException(MOVIE_NOT_FOUND); - } + } } diff --git a/server/src/main/java/com/ticketing/server/movie/setup/MovieSetupService.java b/server/src/main/java/com/ticketing/server/movie/setup/MovieSetupService.java index 5d75567..aab9e62 100644 --- a/server/src/main/java/com/ticketing/server/movie/setup/MovieSetupService.java +++ b/server/src/main/java/com/ticketing/server/movie/setup/MovieSetupService.java @@ -19,7 +19,8 @@ import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -public class MovieSetupService { +public class +MovieSetupService { private final MovieRepository movieRepository; private final MovieTimeRepository movieTimeRepository; @@ -53,9 +54,9 @@ public class MovieSetupService { ); for (Theater theater : theaters) { - for (int i = 1; i <= 2; i++) { - for (int j = 1; j <= 10; j++) { - new Seat(i, j, theater); + for (int row = 1; row <= 2; row++) { + for (int col = 1; col <= 10; col++) { + new Seat(row, col, theater); } } } diff --git a/server/src/main/java/com/ticketing/server/payment/domain/Payment.java b/server/src/main/java/com/ticketing/server/payment/domain/Payment.java index 22865ab..4ffef40 100644 --- a/server/src/main/java/com/ticketing/server/payment/domain/Payment.java +++ b/server/src/main/java/com/ticketing/server/payment/domain/Payment.java @@ -1,23 +1,26 @@ package com.ticketing.server.payment.domain; import com.ticketing.server.global.dto.repository.AbstractEntity; -import com.ticketing.server.user.domain.User; +import com.ticketing.server.payment.service.dto.CreatePaymentDto; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Payment extends AbstractEntity { @NotNull - @ManyToOne - @JoinColumn(name = "user_id", referencedColumnName = "id", updatable = false) - private User user; + private Long userId; + + @NotEmpty + private String movieTitle; @NotNull @Enumerated(value = EnumType.STRING) @@ -29,10 +32,28 @@ public class Payment extends AbstractEntity { private String failedMessage; - @NotNull + @NotEmpty private String paymentNumber; @NotNull private Integer totalPrice; + private Payment(Long userId, String movieTitle, PaymentType type, PaymentStatus status, String paymentNumber, Integer totalPrice) { + this.userId = userId; + this.movieTitle = movieTitle; + this.type = type; + this.status = status; + this.paymentNumber = paymentNumber; + this.totalPrice = totalPrice; + } + + public static Payment from(CreatePaymentDto dto) { + return new Payment(dto.getUserId(), + dto.getMovieTitle(), + dto.getType(), + dto.getStatus(), + dto.getPaymentNumber(), + dto.getTotalPrice()); + } + } diff --git a/server/src/main/java/com/ticketing/server/payment/domain/repository/PaymentRepository.java b/server/src/main/java/com/ticketing/server/payment/domain/repository/PaymentRepository.java index 530012b..0feab8d 100644 --- a/server/src/main/java/com/ticketing/server/payment/domain/repository/PaymentRepository.java +++ b/server/src/main/java/com/ticketing/server/payment/domain/repository/PaymentRepository.java @@ -1,10 +1,12 @@ package com.ticketing.server.payment.domain.repository; import com.ticketing.server.payment.domain.Payment; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface PaymentRepository extends JpaRepository { + List findByUserId(Long userId); } diff --git a/server/src/main/java/com/ticketing/server/payment/service/PaymentServiceImpl.java b/server/src/main/java/com/ticketing/server/payment/service/PaymentServiceImpl.java index 925f853..85e9cb1 100644 --- a/server/src/main/java/com/ticketing/server/payment/service/PaymentServiceImpl.java +++ b/server/src/main/java/com/ticketing/server/payment/service/PaymentServiceImpl.java @@ -1,9 +1,26 @@ package com.ticketing.server.payment.service; +import com.ticketing.server.payment.domain.repository.PaymentRepository; +import com.ticketing.server.payment.service.dto.SimplePaymentDto; import com.ticketing.server.payment.service.interfaces.PaymentService; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service +@RequiredArgsConstructor public class PaymentServiceImpl implements PaymentService { + private final PaymentRepository paymentRepository; + + @Override + public SimplePaymentsResponse findSimplePayments(Long userId) { + return paymentRepository.findByUserId(userId) + .stream() + .map(SimplePaymentDto::from) + .collect(Collectors.collectingAndThen(Collectors.toList() + , list -> SimplePaymentsResponse.from(userId, list))); + } + } diff --git a/server/src/main/java/com/ticketing/server/payment/service/dto/CreatePaymentDto.java b/server/src/main/java/com/ticketing/server/payment/service/dto/CreatePaymentDto.java new file mode 100644 index 0000000..d5bde24 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/payment/service/dto/CreatePaymentDto.java @@ -0,0 +1,30 @@ +package com.ticketing.server.payment.service.dto; + +import com.ticketing.server.payment.domain.PaymentStatus; +import com.ticketing.server.payment.domain.PaymentType; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class CreatePaymentDto { + + private Long userId; + private String movieTitle; + private PaymentType type; + private PaymentStatus status; + private String paymentNumber; + private Integer totalPrice; + + public static CreatePaymentDto of( + Long userId, + String movieTitle, + PaymentType type, + PaymentStatus status, + String paymentNumber, + Integer totalPrice) { + return new CreatePaymentDto(userId, movieTitle, type, status, paymentNumber, totalPrice); + } + +} diff --git a/server/src/main/java/com/ticketing/server/payment/service/dto/SimplePaymentDto.java b/server/src/main/java/com/ticketing/server/payment/service/dto/SimplePaymentDto.java new file mode 100644 index 0000000..4fdbf8b --- /dev/null +++ b/server/src/main/java/com/ticketing/server/payment/service/dto/SimplePaymentDto.java @@ -0,0 +1,25 @@ +package com.ticketing.server.payment.service.dto; + +import com.ticketing.server.payment.domain.Payment; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class SimplePaymentDto { + + private Long paymentId; + private String movieTitle; + private String paymentNumber; + private Integer totalPrice; + + public static SimplePaymentDto from(Payment payment) { + return new SimplePaymentDto( + payment.getId(), + payment.getMovieTitle(), + payment.getPaymentNumber(), + payment.getTotalPrice() + ); + } +} diff --git a/server/src/main/java/com/ticketing/server/payment/service/interfaces/PaymentService.java b/server/src/main/java/com/ticketing/server/payment/service/interfaces/PaymentService.java index 6d8489b..076b93b 100644 --- a/server/src/main/java/com/ticketing/server/payment/service/interfaces/PaymentService.java +++ b/server/src/main/java/com/ticketing/server/payment/service/interfaces/PaymentService.java @@ -1,5 +1,9 @@ package com.ticketing.server.payment.service.interfaces; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; + public interface PaymentService { + SimplePaymentsResponse findSimplePayments(Long userId); + } diff --git a/server/src/main/java/com/ticketing/server/user/api/PaymentClient.java b/server/src/main/java/com/ticketing/server/user/api/PaymentClient.java new file mode 100644 index 0000000..8a284eb --- /dev/null +++ b/server/src/main/java/com/ticketing/server/user/api/PaymentClient.java @@ -0,0 +1,10 @@ +package com.ticketing.server.user.api; + +import com.ticketing.server.user.api.dto.request.SimplePaymentsRequest; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; + +public interface PaymentClient { + + SimplePaymentsResponse getSimplePayments(SimplePaymentsRequest request); + +} diff --git a/server/src/main/java/com/ticketing/server/user/api/dto/request/SimplePaymentsRequest.java b/server/src/main/java/com/ticketing/server/user/api/dto/request/SimplePaymentsRequest.java new file mode 100644 index 0000000..f86eba6 --- /dev/null +++ b/server/src/main/java/com/ticketing/server/user/api/dto/request/SimplePaymentsRequest.java @@ -0,0 +1,18 @@ +package com.ticketing.server.user.api.dto.request; + +import com.ticketing.server.user.domain.User; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class SimplePaymentsRequest { + + private Long userId; + + public static SimplePaymentsRequest from(User user) { + return new SimplePaymentsRequest(user.getId()); + } + +} diff --git a/server/src/main/java/com/ticketing/server/user/api/dto/response/SimplePaymentsResponse.java b/server/src/main/java/com/ticketing/server/user/api/dto/response/SimplePaymentsResponse.java new file mode 100644 index 0000000..3e4dfbe --- /dev/null +++ b/server/src/main/java/com/ticketing/server/user/api/dto/response/SimplePaymentsResponse.java @@ -0,0 +1,21 @@ +package com.ticketing.server.user.api.dto.response; + +import com.ticketing.server.payment.service.dto.SimplePaymentDto; +import java.util.List; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class SimplePaymentsResponse { + + private Long userId; + + private List payments; + + public static SimplePaymentsResponse from(Long userId, List simplePayments) { + return new SimplePaymentsResponse(userId, simplePayments); + } + +} diff --git a/server/src/main/java/com/ticketing/server/user/api/impl/PaymentClientImpl.java b/server/src/main/java/com/ticketing/server/user/api/impl/PaymentClientImpl.java new file mode 100644 index 0000000..b7b5c6d --- /dev/null +++ b/server/src/main/java/com/ticketing/server/user/api/impl/PaymentClientImpl.java @@ -0,0 +1,21 @@ +package com.ticketing.server.user.api.impl; + +import com.ticketing.server.payment.service.PaymentServiceImpl; +import com.ticketing.server.user.api.PaymentClient; +import com.ticketing.server.user.api.dto.request.SimplePaymentsRequest; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PaymentClientImpl implements PaymentClient { + + private final PaymentServiceImpl paymentService; + + @Override + public SimplePaymentsResponse getSimplePayments(SimplePaymentsRequest request) { + return paymentService.findSimplePayments(request.getUserId()); + } + +} diff --git a/server/src/main/java/com/ticketing/server/user/application/UserController.java b/server/src/main/java/com/ticketing/server/user/application/UserController.java index 0164c1f..4639dab 100644 --- a/server/src/main/java/com/ticketing/server/user/application/UserController.java +++ b/server/src/main/java/com/ticketing/server/user/application/UserController.java @@ -4,6 +4,7 @@ import com.ticketing.server.user.application.request.SignUpRequest; import com.ticketing.server.user.application.request.UserChangePasswordRequest; import com.ticketing.server.user.application.request.UserDeleteRequest; import com.ticketing.server.user.application.response.SignUpResponse; +import com.ticketing.server.user.application.response.SimplePaymentDetailsResponse; import com.ticketing.server.user.application.response.UserChangePasswordResponse; import com.ticketing.server.user.application.response.UserDeleteResponse; import com.ticketing.server.user.application.response.UserDetailResponse; @@ -65,4 +66,11 @@ public class UserController { return ResponseEntity.status(HttpStatus.OK).body(UserChangePasswordResponse.from(user)); } + @GetMapping("/payments") + @Secured("ROLE_GUEST") + public ResponseEntity getPayments(@AuthenticationPrincipal UserDetails userRequest) { + SimplePaymentDetailsResponse paymentDetails = userService.findSimplePaymentDetails(userRequest.getUsername()); + return ResponseEntity.status(HttpStatus.OK).body(paymentDetails); + } + } diff --git a/server/src/main/java/com/ticketing/server/user/application/response/SimplePaymentDetailsResponse.java b/server/src/main/java/com/ticketing/server/user/application/response/SimplePaymentDetailsResponse.java new file mode 100644 index 0000000..2988e5f --- /dev/null +++ b/server/src/main/java/com/ticketing/server/user/application/response/SimplePaymentDetailsResponse.java @@ -0,0 +1,21 @@ +package com.ticketing.server.user.application.response; + +import com.ticketing.server.payment.service.dto.SimplePaymentDto; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import java.util.List; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class SimplePaymentDetailsResponse { + + private String email; + private List payments; + + public static SimplePaymentDetailsResponse of(String email, SimplePaymentsResponse paymentsResponse) { + return new SimplePaymentDetailsResponse(email, paymentsResponse.getPayments()); + } + +} diff --git a/server/src/main/java/com/ticketing/server/user/domain/User.java b/server/src/main/java/com/ticketing/server/user/domain/User.java index d6475d2..2936ffe 100644 --- a/server/src/main/java/com/ticketing/server/user/domain/User.java +++ b/server/src/main/java/com/ticketing/server/user/domain/User.java @@ -1,10 +1,7 @@ package com.ticketing.server.user.domain; -import static com.ticketing.server.global.exception.ErrorCode.DELETED_EMAIL; -import static com.ticketing.server.global.exception.ErrorCode.MISMATCH_PASSWORD; - import com.ticketing.server.global.dto.repository.AbstractEntity; -import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.global.exception.ErrorCode; import com.ticketing.server.global.validator.constraints.Phone; import com.ticketing.server.user.service.dto.ChangePasswordDTO; import com.ticketing.server.user.service.dto.DeleteUserDTO; @@ -62,7 +59,7 @@ public class User extends AbstractEntity { public User delete(DeleteUserDTO deleteUser) { if (isDeleted) { - throw new TicketingException(DELETED_EMAIL); + throw ErrorCode.throwDeletedEmail(); } checkPassword(deleteUser); @@ -81,7 +78,7 @@ public class User extends AbstractEntity { public void checkPassword(PasswordMatches passwordMatches) { if (!passwordMatches.passwordMatches(password)) { - throw new TicketingException(MISMATCH_PASSWORD); + throw ErrorCode.throwMismatchPassword(); } } diff --git a/server/src/main/java/com/ticketing/server/user/service/AuthenticationServiceImpl.java b/server/src/main/java/com/ticketing/server/user/service/AuthenticationServiceImpl.java index cbfca8f..8f656cc 100644 --- a/server/src/main/java/com/ticketing/server/user/service/AuthenticationServiceImpl.java +++ b/server/src/main/java/com/ticketing/server/user/service/AuthenticationServiceImpl.java @@ -1,10 +1,6 @@ package com.ticketing.server.user.service; -import static com.ticketing.server.global.exception.ErrorCode.REFRESH_TOKEN_NOT_FOUND; -import static com.ticketing.server.global.exception.ErrorCode.TOKEN_TYPE; -import static com.ticketing.server.global.exception.ErrorCode.UNAVAILABLE_REFRESH_TOKEN; - -import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.global.exception.ErrorCode; import com.ticketing.server.global.redis.RefreshRedisRepository; import com.ticketing.server.global.redis.RefreshToken; import com.ticketing.server.global.security.jwt.JwtProperties; @@ -63,11 +59,11 @@ public class AuthenticationServiceImpl implements AuthenticationService { // Redis 에 토큰이 있는지 검증 RefreshToken findTokenEntity = refreshRedisRepository.findByEmail(authentication.getName()) - .orElseThrow(() -> new TicketingException(REFRESH_TOKEN_NOT_FOUND)); + .orElseThrow(ErrorCode::throwRefreshTokenNotFound); // redis 토큰과 input 토큰이 일치한지 확인 if (!refreshToken.equals(findTokenEntity.getToken())) { - throw new TicketingException(UNAVAILABLE_REFRESH_TOKEN); + throw ErrorCode.throwUnavailableRefreshToken(); } // 토큰 발급 @@ -94,7 +90,7 @@ public class AuthenticationServiceImpl implements AuthenticationService { if (StringUtils.hasText(bearerToken) && jwtProperties.hasTokenStartsWith(bearerToken)) { return bearerToken.substring(7); } - throw new TicketingException(TOKEN_TYPE); + throw ErrorCode.throwTokenType(); } } diff --git a/server/src/main/java/com/ticketing/server/user/service/CustomUserDetailsService.java b/server/src/main/java/com/ticketing/server/user/service/CustomUserDetailsService.java index bd90e5d..0ba78f2 100644 --- a/server/src/main/java/com/ticketing/server/user/service/CustomUserDetailsService.java +++ b/server/src/main/java/com/ticketing/server/user/service/CustomUserDetailsService.java @@ -1,8 +1,6 @@ package com.ticketing.server.user.service; -import static com.ticketing.server.global.exception.ErrorCode.EMAIL_NOT_FOUND; - -import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.global.exception.ErrorCode; import com.ticketing.server.user.domain.User; import com.ticketing.server.user.domain.repository.UserRepository; import java.util.Collections; @@ -23,7 +21,7 @@ public class CustomUserDetailsService implements UserDetailsService { public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { return userRepository.findByEmailAndIsDeletedFalse(email) .map(this::createUserDetails) - .orElseThrow(() -> new TicketingException(EMAIL_NOT_FOUND)); + .orElseThrow(ErrorCode::throwEmailNotFound); } private UserDetails createUserDetails(User user) { diff --git a/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java b/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java index 0dddf86..07f1202 100644 --- a/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java +++ b/server/src/main/java/com/ticketing/server/user/service/UserServiceImpl.java @@ -1,9 +1,10 @@ package com.ticketing.server.user.service; -import static com.ticketing.server.global.exception.ErrorCode.DUPLICATE_EMAIL; -import static com.ticketing.server.global.exception.ErrorCode.EMAIL_NOT_FOUND; - -import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.global.exception.ErrorCode; +import com.ticketing.server.user.api.PaymentClient; +import com.ticketing.server.user.api.dto.request.SimplePaymentsRequest; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import com.ticketing.server.user.application.response.SimplePaymentDetailsResponse; import com.ticketing.server.user.domain.User; import com.ticketing.server.user.domain.repository.UserRepository; import com.ticketing.server.user.service.dto.ChangePasswordDTO; @@ -26,6 +27,7 @@ import org.springframework.validation.annotation.Validated; public class UserServiceImpl implements UserService { private final UserRepository userRepository; + private final PaymentClient paymentClient; @Override @Transactional @@ -35,7 +37,7 @@ public class UserServiceImpl implements UserService { return userRepository.save(signUpDto.toUser()); } - throw new TicketingException(DUPLICATE_EMAIL); + throw ErrorCode.throwDuplicateEmail(); } @Override @@ -55,16 +57,20 @@ public class UserServiceImpl implements UserService { @Override public User findByEmail(String email) { return userRepository.findByEmail(email) - .orElseThrow(UserServiceImpl::throwEmailNotFound); + .orElseThrow(ErrorCode::throwEmailNotFound); + } + + @Override + public SimplePaymentDetailsResponse findSimplePaymentDetails(String email) { + User user = findNotDeletedUserByEmail(email); + SimplePaymentsResponse simplePayments = paymentClient.getSimplePayments(SimplePaymentsRequest.from(user)); + + return SimplePaymentDetailsResponse.of(email, simplePayments); } private User findNotDeletedUserByEmail(String email) { return userRepository.findByEmailAndIsDeletedFalse(email) - .orElseThrow(UserServiceImpl::throwEmailNotFound); - } - - private static RuntimeException throwEmailNotFound() { - throw new TicketingException(EMAIL_NOT_FOUND); + .orElseThrow(ErrorCode::throwEmailNotFound); } } diff --git a/server/src/main/java/com/ticketing/server/user/service/interfaces/UserService.java b/server/src/main/java/com/ticketing/server/user/service/interfaces/UserService.java index 805c470..223a2c0 100644 --- a/server/src/main/java/com/ticketing/server/user/service/interfaces/UserService.java +++ b/server/src/main/java/com/ticketing/server/user/service/interfaces/UserService.java @@ -1,5 +1,6 @@ package com.ticketing.server.user.service.interfaces; +import com.ticketing.server.user.application.response.SimplePaymentDetailsResponse; import com.ticketing.server.user.domain.User; import com.ticketing.server.user.service.dto.ChangePasswordDTO; import com.ticketing.server.user.service.dto.DeleteUserDTO; @@ -15,4 +16,7 @@ public interface UserService { User changePassword(@Valid ChangePasswordDTO changePasswordDto); User findByEmail(String email); + + SimplePaymentDetailsResponse findSimplePaymentDetails(String email); + } diff --git a/server/src/test/java/com/ticketing/server/payment/service/PaymentServiceImplTest.java b/server/src/test/java/com/ticketing/server/payment/service/PaymentServiceImplTest.java new file mode 100644 index 0000000..ff60a7e --- /dev/null +++ b/server/src/test/java/com/ticketing/server/payment/service/PaymentServiceImplTest.java @@ -0,0 +1,71 @@ +package com.ticketing.server.payment.service; + +import static com.ticketing.server.payment.domain.PaymentStatus.COMPLETED; +import static com.ticketing.server.payment.domain.PaymentType.KAKAO_PAY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.when; + +import com.ticketing.server.payment.domain.Payment; +import com.ticketing.server.payment.domain.repository.PaymentRepository; +import com.ticketing.server.payment.service.dto.CreatePaymentDto; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class PaymentServiceImplTest { + + @Mock + PaymentRepository paymentRepository; + + @InjectMocks + PaymentServiceImpl paymentService; + + @Test + @DisplayName("유저 ID로 결제내역이 없을 경우") + void findSimplePaymentsZero() { + // given + when(paymentRepository.findByUserId(2L)).thenReturn(Collections.emptyList()); + + // when + SimplePaymentsResponse simplePayments = paymentService.findSimplePayments(2L); + + // then + assertAll( + () -> assertThat(simplePayments.getUserId()).isEqualTo(2L) + , () -> assertThat(simplePayments.getPayments()).isEmpty() + ); + } + + @ParameterizedTest + @DisplayName("유저 ID로 간소 결제내역 조회 성공") + @ValueSource(longs = {1L, 2L, 100L, 154L}) + void findSimplePaymentsSuccess(Long userId) { + // given + List payments = Arrays.asList( + Payment.from(CreatePaymentDto.of(userId, "범죄도시2", KAKAO_PAY, COMPLETED, "004-323-77542", 15_000)), + Payment.from(CreatePaymentDto.of(userId, "토르", KAKAO_PAY, COMPLETED, "004-323-77544", 30_000)) + ); + when(paymentRepository.findByUserId(userId)).thenReturn(payments); + + // when + SimplePaymentsResponse simplePayments = paymentService.findSimplePayments(userId); + + // then + assertAll( + () -> assertThat(simplePayments.getUserId()).isEqualTo(userId) + , () -> assertThat(simplePayments.getPayments()).hasSize(2) + ); + } + +} diff --git a/server/src/test/java/com/ticketing/server/user/service/UserServiceImplTest.java b/server/src/test/java/com/ticketing/server/user/service/UserServiceImplTest.java index 14668a8..38a7397 100644 --- a/server/src/test/java/com/ticketing/server/user/service/UserServiceImplTest.java +++ b/server/src/test/java/com/ticketing/server/user/service/UserServiceImplTest.java @@ -1,5 +1,7 @@ package com.ticketing.server.user.service; +import static com.ticketing.server.payment.domain.PaymentStatus.COMPLETED; +import static com.ticketing.server.payment.domain.PaymentType.KAKAO_PAY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; @@ -7,6 +9,13 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import com.ticketing.server.global.exception.TicketingException; +import com.ticketing.server.payment.domain.Payment; +import com.ticketing.server.payment.service.dto.CreatePaymentDto; +import com.ticketing.server.payment.service.dto.SimplePaymentDto; +import com.ticketing.server.user.api.PaymentClient; +import com.ticketing.server.user.api.dto.request.SimplePaymentsRequest; +import com.ticketing.server.user.api.dto.response.SimplePaymentsResponse; +import com.ticketing.server.user.application.response.SimplePaymentDetailsResponse; import com.ticketing.server.user.domain.User; import com.ticketing.server.user.domain.UserGrade; import com.ticketing.server.user.domain.repository.UserRepository; @@ -14,6 +23,8 @@ import com.ticketing.server.user.service.dto.ChangePasswordDTO; import com.ticketing.server.user.service.dto.DeleteUserDTO; import com.ticketing.server.user.service.dto.DeleteUserDtoTest; import com.ticketing.server.user.service.dto.SignUpDTO; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -34,6 +45,9 @@ class UserServiceImplTest { @Mock UserRepository userRepository; + @Mock + PaymentClient paymentClient; + @InjectMocks UserServiceImpl userService; @@ -124,4 +138,30 @@ class UserServiceImplTest { assertThat(user).isNotNull(); } + @Test + @DisplayName("회원 결제목록 조회") + void findSimplePaymentDetailsSuccess() { + // given + List paymentDtos = Arrays.asList( + SimplePaymentDto.from( + Payment.from( + CreatePaymentDto.of(1L, "범죄도시2", KAKAO_PAY, COMPLETED, "004-323-77542", 15_000))), + SimplePaymentDto.from( + Payment.from( + CreatePaymentDto.of(1L, "토르", KAKAO_PAY, COMPLETED, "004-323-77544", 30_000))) + ); + + when(userRepository.findByEmailAndIsDeletedFalse("ticketing@gmail.com")).thenReturn(Optional.of(user)); + when(paymentClient.getSimplePayments(any())).thenReturn(SimplePaymentsResponse.from(1L, paymentDtos)); + + // when + SimplePaymentDetailsResponse paymentDetails = userService.findSimplePaymentDetails("ticketing@gmail.com"); + + // then + assertAll( + () -> assertThat(paymentDetails.getEmail()).isEqualTo("ticketing@gmail.com") + , () -> assertThat(paymentDetails.getPayments()).hasSize(2) + ); + } + }