Skip to content

Commit

Permalink
Merge pull request #73 from 28th-meetup/feat/fcmOrderManage
Browse files Browse the repository at this point in the history
Feat/fcm order manage
  • Loading branch information
summit45 committed Nov 22, 2023
2 parents 978c8a5 + 1c40466 commit ddbcbde
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public enum ErrorCode {
ORDER_NOT_EXISTS_BY_ORDER_STATUS_ERROR(false, HttpStatus.BAD_REQUEST.value(), "해당 주문 상태의 주문이 존재하지 않습니다."),
UNAUTHORIZED_ACCESS_ERROR(false, HttpStatus.BAD_REQUEST.value(), "해당 주문에 접근할 권한이 없습니다."),
ORDER_STATUS_ALREADY_EXISTS_ERROR(false, HttpStatus.BAD_REQUEST.value(), "이미 해당 주문 상태입니다."),
ALREADY_EXISTS_REVIEW_ERROR(false, HttpStatus.BAD_REQUEST.value(), "이미 리뷰를 작성한 주문입니다."),
;

private Boolean isSuccess;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public String sendNotificationByToken(FCMRequestDto dto) {
Optional <User> user = userRepository.findById(dto.getUserId());

if (user.isPresent()){
log.info("fcm토큰" + user.get().getFcmToken());
log.info("fcm token" + user.get().getFcmToken());
if (user.get().getFcmToken() != null) {

Message message = Message.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
package com.kusitms.jipbap.notification;public class NotificationRepository {
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,11 @@ public CommonResponse<?> handleOrderStatusAlreadyExistsException(OrderStatusAlre
return new CommonResponse<>(ErrorCode.ORDER_STATUS_ALREADY_EXISTS_ERROR);
}

@ExceptionHandler(AlreadyExistsReviewException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public CommonResponse<?> handleAlreadyExistsReviewException(AlreadyExistsReviewException e, HttpServletRequest request) {
log.warn("ORDER-007> 요청 URI: " + request.getRequestURI() + ", 에러 메세지: " + e.getMessage());
return new CommonResponse<>(ErrorCode.ALREADY_EXISTS_REVIEW_ERROR);
}

}
9 changes: 2 additions & 7 deletions src/main/java/com/kusitms/jipbap/order/OrderRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.kusitms.jipbap.food.Food;
import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

Expand All @@ -10,13 +11,7 @@

public interface OrderRepository extends JpaRepository <Order, Long> {

// @Query("SELECT o.orderDetail.food, SUM(o.orderCount) as totalSales FROM Order o WHERE o.regionId= :regionId GROUP BY o.food ORDER BY totalSales DESC, MAX(o.createdAt) DESC")
// List<Food> findTop10BestSellingFoodsInRegion(@Param("regionId") Long regionId);

Optional<List<Order>> findByStore_IdAndStatus(Long storeId, OrderStatus status);

// @Query("SELECT o.food FROM Order o WHERE o.regionId = :regionId ORDER BY o.id DESC LIMIT 4")
// List<Food> findLatestFoodsByRegionId(@Param("regionId") Long regionId);
Optional<List<Order>> findByStore_IdAndStatus(Long storeId, OrderStatus status, Sort sort);

Optional<List<Order>> findByUser_Id(Long userId);

Expand Down
31 changes: 24 additions & 7 deletions src/main/java/com/kusitms/jipbap/order/OrderService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.kusitms.jipbap.food.exception.FoodOptionNotExistsException;
import com.kusitms.jipbap.notification.FCMNotificationService;
import com.kusitms.jipbap.notification.FCMRequestDto;
import com.kusitms.jipbap.notification.NotificationRepository;
import com.kusitms.jipbap.order.dto.*;
import com.kusitms.jipbap.order.exception.*;
import com.kusitms.jipbap.store.Store;
Expand All @@ -18,6 +19,7 @@
import com.kusitms.jipbap.user.exception.UserNotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -35,6 +37,7 @@ public class OrderService {
private final UserRepository userRepository;
private final FoodRepository foodRepository;
private final FoodOptionRepository foodOptionRepository;
private final NotificationRepository notificationRepository;
private final StoreRepository storeRepository;
private final FCMNotificationService fcmNotificationService;

Expand Down Expand Up @@ -107,7 +110,7 @@ public OwnerOrderStatusResponse getStoreOrderHistoryByOrderStatus(String email,

OrderStatus status = OrderStatus.fromString(orderStatus);

List<Order> orderList = orderRepository.findByStore_IdAndStatus(store.getId(), status)
List<Order> orderList = orderRepository.findByStore_IdAndStatus(store.getId(), status, Sort.by(Sort.Direction.DESC, "createdAt"))
.orElseThrow(() -> new OrderNotExistsByOrderStatusException("해당 가게의 주문상태에 따른 주문 내역이 존재하지 않습니다."));

List<OrderPreviewResponse> orderPreviewResponses = orderList.stream()
Expand Down Expand Up @@ -136,13 +139,27 @@ public void processOrder(String email, Long orderId, String status) {
if(order.getStatus() == newStatus){
throw new OrderStatusAlreadyExistsException("이미 해당 주문 상태입니다.");
}
order.setStatus(newStatus); // 주문 상태 변경

// 알림 등 로직 추가 가능
FCMRequestDto dto = new FCMRequestDto(seller.getId(), "주문이 들어왔습니다", "주문을 확인해주세요.");
String ans = fcmNotificationService.sendNotificationByToken(dto);
log.info(ans);
order.setStatus(newStatus); // 주문 상태 변경
orderRepository.save(order);

User buyer = order.getUser();
if(newStatus.equals(OrderStatus.ACCEPTED)) { //판매자가 주문을 수락함
FCMRequestDto dto = new FCMRequestDto(buyer.getId(), "가게가 주문을 수락했습니다.", "맛있는 한식 집밥이 곧 찾아갑니다!");
String ans = fcmNotificationService.sendNotificationByToken(dto);
log.info("판매자가 주문을 수락, 구매자에게 알림 전송 결과: " + ans);

}
else if(newStatus.equals(OrderStatus.REJECTED)) { //판매자가 주문을 취소함
FCMRequestDto dto = new FCMRequestDto(buyer.getId(), "가게가 주문을 취소했습니다.", "다른 상품을 주문해 주세요.");
String ans = fcmNotificationService.sendNotificationByToken(dto);
log.info("판매자가 주문을 거절, 구매자에게 알림 전송 결과: " + ans);
}
else if(newStatus.equals(OrderStatus.COMPLETED)) { //판매자가 주문을 완료함
FCMRequestDto dto = new FCMRequestDto(buyer.getId(), "음식이 완료되었습니다.", "한식 집밥, 맛있게 즐기세요!");
String ans = fcmNotificationService.sendNotificationByToken(dto);
log.info("판매자가 주문을 완료, 구매자에게 알림 전송 결과: " + ans);
}
}

public List<OrderHistoryResponse> getMyOrderHistory(String email) {
Expand All @@ -168,7 +185,7 @@ public StoreProcessingResponse getStoreProcessingOrder(String email) {
.orElseThrow(() -> new StoreNotExistsException("해당 유저의 가게를 찾을 수 없습니다."));

//전체 주문내역에서 해당 가게에 속하는 주문내역만 가져오기
List<Order> orderList = orderRepository.findByStore_IdAndStatus(store.getId(), OrderStatus.ACCEPTED)
List<Order> orderList = orderRepository.findByStore_IdAndStatus(store.getId(), OrderStatus.ACCEPTED, Sort.by(Sort.Direction.DESC, "createdAt"))
.orElseThrow(() -> new OrderNotExistsByOrderStatusException("해당 가게의 주문상태에 따른 주문 내역이 존재하지 않습니다."));

//주문내역 중에서 음식별로 묶기
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/kusitms/jipbap/order/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.kusitms.jipbap.common.entity.DateEntity;
import com.kusitms.jipbap.food.Food;
import com.kusitms.jipbap.store.Store;
import com.kusitms.jipbap.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -29,4 +30,5 @@ public class Review extends DateEntity {
private Long rating;
private String message;
private String image;

}
4 changes: 4 additions & 0 deletions src/main/java/com/kusitms/jipbap/order/ReviewRepository.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.kusitms.jipbap.order;

import com.kusitms.jipbap.store.Store;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ReviewRepository extends JpaRepository <Review, Long>, ReviewRepositoryExtension {
List<Review> findAllReviewsByOrder_Store(Store store);
}
42 changes: 29 additions & 13 deletions src/main/java/com/kusitms/jipbap/order/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import com.amazonaws.services.s3.AmazonS3;
import com.kusitms.jipbap.common.exception.S3RegisterFailureException;
import com.kusitms.jipbap.common.utils.S3Utils;
import com.kusitms.jipbap.notification.FCMNotificationService;
import com.kusitms.jipbap.notification.FCMRequestDto;
import com.kusitms.jipbap.order.dto.GetRegisteredReviewsResponseDto;
import com.kusitms.jipbap.order.dto.RegisterReviewRequestDto;
import com.kusitms.jipbap.order.dto.ReviewDto;
import com.kusitms.jipbap.order.exception.AlreadyExistsReviewException;
import com.kusitms.jipbap.order.exception.OrderNotExistsException;
import com.kusitms.jipbap.store.Store;
import com.kusitms.jipbap.store.StoreRepository;
Expand Down Expand Up @@ -33,6 +36,7 @@ public class ReviewService {
private final UserRepository userRepository;
private final OrderRepository orderRepository;
private final StoreRepository storeRepository;
private final FCMNotificationService fcmNotificationService;

private final AmazonS3 amazonS3;

Expand All @@ -41,12 +45,19 @@ public class ReviewService {

@Transactional
public ReviewDto registerReview(String email, RegisterReviewRequestDto dto, MultipartFile image) {
userRepository.findByEmail(email).orElseThrow(()-> new UserNotFoundException("유저 정보가 존재하지 않습니다."));
Order order = orderRepository.findById(dto.getOrderId()).orElseThrow(()-> new OrderNotExistsException("orderId: "+dto.getOrderId()+"에 해당하는 주문이 존재하지 않습니다."));
userRepository.findByEmail(email)
.orElseThrow(()-> new UserNotFoundException("유저 정보가 존재하지 않습니다."));

Order order = orderRepository.findById(dto.getOrderId())
.orElseThrow(()-> new OrderNotExistsException("orderId: "+dto.getOrderId()+"에 해당하는 주문이 존재하지 않습니다."));

if(order.getReview() != null){
throw new AlreadyExistsReviewException("이미 리뷰를 작성한 주문입니다.");
}

Store store = order.getStore();

String imageUri = null;

// 이미지가 null이 아닌 경우 s3 업로드
if(image!=null) {
try {
Expand All @@ -56,13 +67,18 @@ public ReviewDto registerReview(String email, RegisterReviewRequestDto dto, Mult
}
}

// 리뷰 작성
Review review = reviewRepository.save(new Review(null, order, dto.getRating(), dto.getMessage(), imageUri));
// 리뷰 개수 업데이트
store.increaseReviewCount();
// 평점 업데이트
store.updateAvgRate(Double.parseDouble(String.valueOf(dto.getRating())));

return new ReviewDto(review.getId(), review.getOrder().getId(), review.getRating(), review.getMessage(), review.getImage());
store.increaseReviewCount(); // 리뷰 개수 업데이트
store.updateAvgRate(Double.parseDouble(String.valueOf(dto.getRating()))); // 평점 업데이트

// 주문내역에 리뷰 추가 및 판매자에게 리뷰 작성되었다는 알림 전송
order.setReview(review);
FCMRequestDto fcmRequestDto = new FCMRequestDto(store.getOwner().getId(), "고객이 리뷰를 작성했습니다.", "내용을 확인해 보시겠어요?");
String ans = fcmNotificationService.sendNotificationByToken(fcmRequestDto);
log.info("구매자가 리뷰 작성 완료 알림 전송: " + ans);
return new ReviewDto(review.getId(), review.getOrder().getId(), review.getOrder().getUser().getUsername(), review.getCreatedAt().toString(), review.getOrder().getOrderDetail().get(0).getFood().getName(), review.getRating(), review.getMessage(), review.getImage());
}

@Transactional
Expand All @@ -73,20 +89,20 @@ public GetRegisteredReviewsResponseDto getUserRegisteredReviews(String email) {

return new GetRegisteredReviewsResponseDto(
reviews.stream()
.map(r -> new ReviewDto(r.getId(), r.getOrder().getId(), r.getRating(), r.getMessage(), r.getImage()))
.map(r -> new ReviewDto(r.getId(), r.getOrder().getId(), r.getOrder().getUser().getUsername(), r.getCreatedAt().toString(), r.getOrder().getOrderDetail().get(0).getFood().getName(), r.getRating(), r.getMessage(), r.getImage()))
.collect(Collectors.toList())
);
}

@Transactional
public GetRegisteredReviewsResponseDto getStoreRegisteredReviews(Long storeId) {
Store store = storeRepository.findById(storeId).orElseThrow(()-> new StoreNotExistsException("storeId: "+storeId+"에 해당하는 가게가 존재하지 않습니다."));

List<Review> reviews = reviewRepository.findAllReviewsByStore(store);
Store store = storeRepository.findById(storeId)
.orElseThrow(()-> new StoreNotExistsException("storeId: "+storeId+"에 해당하는 가게가 존재하지 않습니다."));
List<Review> reviews = reviewRepository.findAllReviewsByOrder_Store(store);

return new GetRegisteredReviewsResponseDto(
reviews.stream()
.map(r -> new ReviewDto(r.getId(), r.getOrder().getId(), r.getRating(), r.getMessage(), r.getImage()))
.map(r -> new ReviewDto(r.getId(), r.getOrder().getId(), r.getOrder().getUser().getUsername(), r.getCreatedAt().toString(), r.getOrder().getOrderDetail().get(0).getFood().getName(), r.getRating(), r.getMessage(), r.getImage()))
.collect(Collectors.toList())
);
}
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/com/kusitms/jipbap/order/dto/ReviewDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
public class ReviewDto {

private Long id;

private Long orderId;

private String writerName;
private String time;
private String foodName;
private Long rating;

private String message;
private String image;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.kusitms.jipbap.order.exception;

public class AlreadyExistsReviewException extends RuntimeException {
public AlreadyExistsReviewException(String message) { super(message); }
}

0 comments on commit ddbcbde

Please sign in to comment.