diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 14d5ec6..65900bd 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -2,7 +2,7 @@ name: Backend CD # actions 이름 on: push: - branches: [ feat/qa-check ] + branches: [ feat/toss-payment ] jobs: deploy: diff --git a/api-module/src/main/java/com/likelion/apimodule/order/presentation/OrderController.java b/api-module/src/main/java/com/likelion/apimodule/order/presentation/OrderController.java index 0bdc7b3..2cecfc1 100644 --- a/api-module/src/main/java/com/likelion/apimodule/order/presentation/OrderController.java +++ b/api-module/src/main/java/com/likelion/apimodule/order/presentation/OrderController.java @@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -32,6 +33,24 @@ public class OrderController { private final PaymentService paymentService; private final OrderDeleteUseCase orderDeleteUseCase; + // 주문번호 생성 + @GetMapping("/generatenum") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "주문번호 생성", + useReturnTypeSchema = true + ) + } + ) + @Operation(summary = "주문번호 생성 API", description = "주문번호 생성 API 입니다.") + public ApplicationResponse makeOrderNum() { + + String orderNum = paymentService.generateOrderNumber(LocalDateTime.now()); + return ApplicationResponse.ok(orderNum); + } + // 주문내역 조회 @GetMapping @ApiResponses( diff --git a/api-module/src/main/java/com/likelion/apimodule/payment/dto/request/ApprovalRequest.java b/api-module/src/main/java/com/likelion/apimodule/payment/dto/request/ApprovalRequest.java index 39b800c..866af1e 100644 --- a/api-module/src/main/java/com/likelion/apimodule/payment/dto/request/ApprovalRequest.java +++ b/api-module/src/main/java/com/likelion/apimodule/payment/dto/request/ApprovalRequest.java @@ -4,7 +4,12 @@ public record ApprovalRequest( List menuIds, + String orderNum, String paymentKey, - Integer amount + Integer amount, + String pickUpRoute, + Integer visitHour, + Integer visitMin, + String phoneNum ) { } diff --git a/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentClient.java b/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentClient.java index b0408e2..a9a0ed9 100644 --- a/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentClient.java +++ b/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentClient.java @@ -32,11 +32,11 @@ public PaymentClient(WebClient webClient, PaymentAuthorizationHeaderProvider.Fac } - public TossPaymentResponse confirmPayment(ApprovalRequest request, String orderNum) { + public TossPaymentResponse confirmPayment(ApprovalRequest request) { ApproveFinalReq finalReq = new ApproveFinalReq( request.amount(), - orderNum, + request.orderNum(), request.paymentKey() ); diff --git a/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentService.java b/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentService.java index 3f51e32..58fff7a 100644 --- a/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentService.java +++ b/api-module/src/main/java/com/likelion/apimodule/payment/service/PaymentService.java @@ -37,6 +37,7 @@ public class PaymentService { private final JwtUtil jwtUtil; private static final DateTimeFormatter ORDER_NUMBER_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd"); + private static final String ALPHANUMERIC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static final SecureRandom random = new SecureRandom(); private final MenuQueryService menuQueryService; @@ -46,15 +47,15 @@ public ApprovalResponse approval(String accessToken, ApprovalRequest request) { User user = userQueryService.findByEmail(email); Store store = storeQueryService.findStoreById(request.menuIds().get(0)); - String orderNum = generateOrderNumber(LocalDateTime.now()); - // 토스 페이 결제 승인 - TossPaymentResponse tossPaymentResponse = paymentClient.confirmPayment(request, orderNum); + TossPaymentResponse tossPaymentResponse = paymentClient.confirmPayment(request); // 방문 리스트 준비 중으로 저장 + 주문 테이블 저장 marketQueryService.saveVisitListToPreparing(store.getId(), user.getEmail()); - final Order order = Order.builder().orderNum(orderNum).user(user).build(); + final Order order = Order.builder().orderNum(request.orderNum()).user(user). + phoneNum(request.phoneNum()).pickUpRoute(request.pickUpRoute()). + visitHour(request.visitHour()).visitMin(request.visitMin()).build(); orderQueryService.saveOrder(order); for (int i = 0; i < request.menuIds().size(); i++) { @@ -71,13 +72,17 @@ public ApprovalResponse approval(String accessToken, ApprovalRequest request) { public String generateOrderNumber(LocalDateTime createdAt) { String datePart = createdAt.format(ORDER_NUMBER_DATE_FORMAT); - String orderNumberPart = generateRandomNumber(); - return datePart + orderNumberPart; + String randomAlphaNumeric = generateRandomAlphaNumeric(); + return datePart + randomAlphaNumeric; } - private String generateRandomNumber() { - int number = random.nextInt(10000); - return String.format("%04d", number); + private String generateRandomAlphaNumeric() { + StringBuilder alphaNumeric = new StringBuilder(4); + for (int i = 0; i < 4; i++) { + int index = random.nextInt(ALPHANUMERIC.length()); + alphaNumeric.append(ALPHANUMERIC.charAt(index)); + } + return alphaNumeric.toString(); } } diff --git a/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewFindUseCase.java b/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewFindUseCase.java index 01015df..4070cda 100644 --- a/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewFindUseCase.java +++ b/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewFindUseCase.java @@ -79,7 +79,7 @@ public List findAllReviews(String accessToken, Long menuId) { reviewImages.add(image.getImageUrl()); } - String likeCount = reviewQueryService.findLikeCountByReviewId(review.getId()).toString(); + String likeCount = reviewQueryService.countReviewLikeAndUserId(user.getUserId(), review.getId()).toString(); Store store = storeQueryService.findStoreById(menus.get(0).getStore().getId()); String storeName = store.getName(); @@ -91,7 +91,7 @@ public List findAllReviews(String accessToken, Long menuId) { Integer weekDifference = dayDifference / 7; boolean isMine = user.getUserId().equals(myUser.getUserId()); - boolean helpfulYn = reviewQueryService.countLikeCountByMine(user.getUserId(), review.getId()) > 0; + boolean helpfulYn = reviewQueryService.countLikeCountByMine(myUser.getUserId(), review.getId()) > 0; Integer helpfulCnt = reviewQueryService.countAllLikeCount(review.getId()); ReviewInfo reviewInfo = new ReviewInfo(id, name, picture, rating, content, reviewImages, diff --git a/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewSaveUseCase.java b/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewSaveUseCase.java index 2779285..3f37020 100644 --- a/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewSaveUseCase.java +++ b/api-module/src/main/java/com/likelion/apimodule/review/application/ReviewSaveUseCase.java @@ -82,4 +82,16 @@ public void saveReviewLike(Long reviewId, String accessToken) { } } + + public void deleteReviewLike(String accessToken, Long reviewId) { + String email = jwtUtil.getEmail(accessToken); + User user = userQueryService.findByEmail(email); + + if (reviewQueryService.countReviewLikeAndUserId(reviewId, user.getUserId()) > 0) { + ReviewLike reviewLike = reviewQueryService.findReviewLike(reviewId, user.getUserId()); + reviewQueryService.deleteReviewLike(reviewLike.getId()); + } else { + throw new ReviewException(ReviewErrorCode.NO_REVIEW_LIKE); + } + } } diff --git a/api-module/src/main/java/com/likelion/apimodule/review/presentation/ReviewController.java b/api-module/src/main/java/com/likelion/apimodule/review/presentation/ReviewController.java index 62fc182..baae6d9 100644 --- a/api-module/src/main/java/com/likelion/apimodule/review/presentation/ReviewController.java +++ b/api-module/src/main/java/com/likelion/apimodule/review/presentation/ReviewController.java @@ -105,4 +105,22 @@ public ApplicationResponse saveReviewLike(@RequestHeader(AuthConsts.ACCE reviewSaveUseCase.saveReviewLike(reviewId, accessToken); return ApplicationResponse.ok("도움이 돼요 저장 완료"); } + + @DeleteMapping ("/{reviewId}/like/delete") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "도움이 돼요 저장 성공", + useReturnTypeSchema = true + ) + } + ) + @Operation(summary = "도움이 돼요 삭제 API", description = "도움이 돼요 삭제 API 입니다.") + public ApplicationResponse deleteReviewLike(@RequestHeader(AuthConsts.ACCESS_TOKEN_HEADER) String accessToken, + @PathVariable Long reviewId) { + + reviewSaveUseCase.deleteReviewLike(accessToken, reviewId); + return ApplicationResponse.ok("도움이 돼요 삭제 완료"); + } } diff --git a/core-module/src/main/java/com/likelion/coremodule/order/domain/Order.java b/core-module/src/main/java/com/likelion/coremodule/order/domain/Order.java index a9f0345..43da810 100644 --- a/core-module/src/main/java/com/likelion/coremodule/order/domain/Order.java +++ b/core-module/src/main/java/com/likelion/coremodule/order/domain/Order.java @@ -22,5 +22,11 @@ public class Order extends BaseEntity { @JoinColumn(name = "user_id") private User user; + @Column(nullable = false, unique = true) private String orderNum; + + private String phoneNum; + private Integer visitHour; + private Integer visitMin; + private String pickUpRoute; } diff --git a/core-module/src/main/java/com/likelion/coremodule/review/exception/ReviewErrorCode.java b/core-module/src/main/java/com/likelion/coremodule/review/exception/ReviewErrorCode.java index 42e4049..d4b3dac 100644 --- a/core-module/src/main/java/com/likelion/coremodule/review/exception/ReviewErrorCode.java +++ b/core-module/src/main/java/com/likelion/coremodule/review/exception/ReviewErrorCode.java @@ -13,6 +13,7 @@ public enum ReviewErrorCode implements BaseErrorCode { NO_MENU_INFO(HttpStatus.BAD_REQUEST, "2000", "메뉴 정보가 존재하지 않습니다."), NO_REVIEW_INFO(HttpStatus.BAD_REQUEST, "2000", "리뷰가 존재하지 않습니다."), NO_REVIEW_MINE(HttpStatus.BAD_REQUEST, "2000", "본인의 작성 리뷰가 아닙니다."), + NO_REVIEW_LIKE(HttpStatus.BAD_REQUEST, "2000", "도움이 돼요가 존재하지 않습니다."), EXIST_REVIEW_LIKE(HttpStatus.BAD_REQUEST, "2000", "이미 도움이 돼요에 참여하셨습니다.");; private final HttpStatus httpStatus; diff --git a/core-module/src/main/java/com/likelion/coremodule/review/repository/ReviewLikeRepository.java b/core-module/src/main/java/com/likelion/coremodule/review/repository/ReviewLikeRepository.java index 79930ed..b3d6226 100644 --- a/core-module/src/main/java/com/likelion/coremodule/review/repository/ReviewLikeRepository.java +++ b/core-module/src/main/java/com/likelion/coremodule/review/repository/ReviewLikeRepository.java @@ -1,16 +1,14 @@ package com.likelion.coremodule.review.repository; import com.likelion.coremodule.review.domain.ReviewLike; -import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; public interface ReviewLikeRepository extends JpaRepository { - @Query("SELECT COUNT(rl) FROM ReviewLike rl WHERE rl.review.id = :reviewId") - Long countByReviewId(@Param("reviewId") Long reviewId); - Integer countAllByUserUserIdAndReviewId(Long userId, Long reviewId); Integer countAllByReviewId(Long reviewId); + + ReviewLike findReviewLikeByReviewIdAndUserUserId(Long reviewId, Long userId); + } diff --git a/core-module/src/main/java/com/likelion/coremodule/review/service/ReviewQueryService.java b/core-module/src/main/java/com/likelion/coremodule/review/service/ReviewQueryService.java index 59f93a1..ae74414 100644 --- a/core-module/src/main/java/com/likelion/coremodule/review/service/ReviewQueryService.java +++ b/core-module/src/main/java/com/likelion/coremodule/review/service/ReviewQueryService.java @@ -25,6 +25,10 @@ public Review findReviewById(Long id) { return reviewRepository.findById(id).orElseThrow(() -> new ReviewException(ReviewErrorCode.NO_MENU_INFO)); } + public ReviewLike findReviewLike(Long reviewId, Long userId) { + return reviewLikeRepository.findReviewLikeByReviewIdAndUserUserId(reviewId, userId); + } + public List findImagesByReviewId(Long reviewId) { return reviewImageRepository.findAllByReviewId(reviewId); } @@ -37,10 +41,6 @@ public Review findReviewByOrderAndUser(Long orderId, Long userId) { return reviewRepository.findReviewByOrderIdAndUserUserId(orderId, userId); } - public Long findLikeCountByReviewId(Long reviewId) { - return reviewLikeRepository.countByReviewId(reviewId); - } - public Integer countAllLikeCount(Long reviewId) { return reviewLikeRepository.countAllByReviewId(reviewId); } @@ -67,5 +67,10 @@ public Integer countReviewLikeAndUserId(Long reviewId, Long userId) { public void deleteReview(Long id) { reviewRepository.deleteById(id); + + } + + public void deleteReviewLike(Long id) { + reviewLikeRepository.deleteById(id); } -} +} \ No newline at end of file