From e7ecebd6f67e44c7deb57b8dbd6733c7b33c2cc6 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 12:05:31 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[NAYB-158]=20chore:=20NAYB-157=20=EB=B8=8C?= =?UTF-8?q?=EB=9E=9C=EC=B9=98=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nabmart/domain/delivery/Delivery.java | 8 +++ .../prgrms/nabmart/domain/order/Order.java | 4 ++ .../order/controller/OrderController.java | 14 +++++ .../request/FindPayedOrdersRequest.java | 12 ++++ .../exception/UnauthorizedOrderException.java | 8 +++ .../order/repository/OrderRepository.java | 3 + .../domain/order/service/OrderService.java | 21 +++++++ .../response/FindPayedOrdersResponse.java | 33 ++++++++++ .../request/FindPayedOrdersCommand.java | 8 +++ .../global/config/WebSecurityConfig.java | 3 +- .../delivery/DeliveryIntegrationTest.java | 3 + .../nabmart/domain/delivery/DeliveryTest.java | 45 +++++++++++++- .../delivery/service/DeliveryServiceTest.java | 2 +- .../delivery/support/DeliveryFixture.java | 2 + .../order/controller/OrderControllerTest.java | 52 ++++++++++++++++ .../order/service/OrderServiceTest.java | 62 +++++++++++++++++++ .../domain/order/support/OrderFixture.java | 8 +++ 17 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/prgrms/nabmart/domain/order/controller/request/FindPayedOrdersRequest.java create mode 100644 src/main/java/com/prgrms/nabmart/domain/order/exception/UnauthorizedOrderException.java create mode 100644 src/main/java/com/prgrms/nabmart/domain/order/service/response/FindPayedOrdersResponse.java create mode 100644 src/main/java/com/prgrms/nabmart/domain/payment/service/request/FindPayedOrdersCommand.java diff --git a/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java b/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java index 4e698eca1..f3cbe23e6 100644 --- a/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java +++ b/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java @@ -71,6 +71,8 @@ public class Delivery extends BaseTimeEntity { @Builder public Delivery(final Order order, final int estimateMinutes) { + validateOrderStatus(order); + validateEstimateMinutes(estimateMinutes); this.order = order; this.deliveryStatus = DeliveryStatus.ACCEPTING_ORDER; this.address = order.getAddress(); @@ -81,6 +83,12 @@ public Delivery(final Order order, final int estimateMinutes) { order.updateOrderStatus(OrderStatus.DELIVERING); } + private void validateOrderStatus(Order order) { + if(!order.isPayed()) { + throw new InvalidDeliveryException("결제 완료된 주문이 아닙니다."); + } + } + public boolean isOwnByUser(final User user) { return this.order.isOwnByUser(user); } diff --git a/src/main/java/com/prgrms/nabmart/domain/order/Order.java b/src/main/java/com/prgrms/nabmart/domain/order/Order.java index 230e4814c..0a46b8e18 100644 --- a/src/main/java/com/prgrms/nabmart/domain/order/Order.java +++ b/src/main/java/com/prgrms/nabmart/domain/order/Order.java @@ -161,4 +161,8 @@ public void unUseCoupon() { userCoupon.unUse(); } } + + public boolean isPayed() { + return this.status == OrderStatus.PAYED; + } } diff --git a/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java b/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java index 3f39ece8f..6759bafb2 100644 --- a/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java +++ b/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java @@ -1,7 +1,9 @@ package com.prgrms.nabmart.domain.order.controller; import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest; +import com.prgrms.nabmart.domain.order.controller.request.FindPayedOrdersRequest; import com.prgrms.nabmart.domain.order.exception.OrderException; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; import com.prgrms.nabmart.domain.order.service.OrderService; import com.prgrms.nabmart.domain.order.service.request.CreateOrdersCommand; import com.prgrms.nabmart.domain.order.service.request.UpdateOrderByCouponCommand; @@ -9,6 +11,7 @@ import com.prgrms.nabmart.domain.order.service.response.FindOrderDetailResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrdersResponse; import com.prgrms.nabmart.domain.order.service.response.UpdateOrderByCouponResponse; +import com.prgrms.nabmart.domain.payment.service.request.FindPayedOrdersCommand; import com.prgrms.nabmart.global.auth.LoginUser; import com.prgrms.nabmart.global.util.ErrorTemplate; import jakarta.validation.Valid; @@ -83,6 +86,17 @@ public ResponseEntity deleteOrder( return ResponseEntity.noContent().build(); } + @GetMapping("/payed") + public ResponseEntity findPayedOrders( + @RequestBody @Valid FindPayedOrdersRequest findPayedOrdersRequest, + @LoginUser Long userId) { + FindPayedOrdersCommand command = FindPayedOrdersCommand.of( + userId, + findPayedOrdersRequest.page()); + FindPayedOrdersResponse orders = orderService.findPayedOrders(command); + return ResponseEntity.ok(orders); + } + @ExceptionHandler(OrderException.class) public ResponseEntity handleException( final OrderException orderException) { diff --git a/src/main/java/com/prgrms/nabmart/domain/order/controller/request/FindPayedOrdersRequest.java b/src/main/java/com/prgrms/nabmart/domain/order/controller/request/FindPayedOrdersRequest.java new file mode 100644 index 000000000..e9caff59b --- /dev/null +++ b/src/main/java/com/prgrms/nabmart/domain/order/controller/request/FindPayedOrdersRequest.java @@ -0,0 +1,12 @@ +package com.prgrms.nabmart.domain.order.controller.request; + +import jakarta.validation.constraints.PositiveOrZero; + +public record FindPayedOrdersRequest( + @PositiveOrZero(message = "페이지 번호는 음수일 수 없습니다.") + Integer page) { + + public FindPayedOrdersRequest { + page = 0; + } +} diff --git a/src/main/java/com/prgrms/nabmart/domain/order/exception/UnauthorizedOrderException.java b/src/main/java/com/prgrms/nabmart/domain/order/exception/UnauthorizedOrderException.java new file mode 100644 index 000000000..9d75b07fb --- /dev/null +++ b/src/main/java/com/prgrms/nabmart/domain/order/exception/UnauthorizedOrderException.java @@ -0,0 +1,8 @@ +package com.prgrms.nabmart.domain.order.exception; + +public class UnauthorizedOrderException extends OrderException { + + public UnauthorizedOrderException(String message) { + super(message); + } +} diff --git a/src/main/java/com/prgrms/nabmart/domain/order/repository/OrderRepository.java b/src/main/java/com/prgrms/nabmart/domain/order/repository/OrderRepository.java index 4bde90fd4..cb93bb2b4 100644 --- a/src/main/java/com/prgrms/nabmart/domain/order/repository/OrderRepository.java +++ b/src/main/java/com/prgrms/nabmart/domain/order/repository/OrderRepository.java @@ -31,4 +31,7 @@ List findByStatusInBeforeExpiredTime(@Param("expiredTime") LocalDateTime @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("select o from Order o where o.orderId = :orderId") Optional findByIdPessimistic(@Param("orderId") Long orderId); + + @Query("select o from Order o where o.status = com.prgrms.nabmart.domain.order.OrderStatus.PAYED") + Page findAllStatusIsPayed(Pageable pageable); } diff --git a/src/main/java/com/prgrms/nabmart/domain/order/service/OrderService.java b/src/main/java/com/prgrms/nabmart/domain/order/service/OrderService.java index 84eace35f..3847f4eac 100644 --- a/src/main/java/com/prgrms/nabmart/domain/order/service/OrderService.java +++ b/src/main/java/com/prgrms/nabmart/domain/order/service/OrderService.java @@ -14,13 +14,16 @@ import com.prgrms.nabmart.domain.order.OrderStatus; import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest.CreateOrderItemRequest; import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException; +import com.prgrms.nabmart.domain.order.exception.UnauthorizedOrderException; import com.prgrms.nabmart.domain.order.repository.OrderRepository; import com.prgrms.nabmart.domain.order.service.request.CreateOrdersCommand; import com.prgrms.nabmart.domain.order.service.request.UpdateOrderByCouponCommand; import com.prgrms.nabmart.domain.order.service.response.CreateOrderResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrderDetailResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrdersResponse; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; import com.prgrms.nabmart.domain.order.service.response.UpdateOrderByCouponResponse; +import com.prgrms.nabmart.domain.payment.service.request.FindPayedOrdersCommand; import com.prgrms.nabmart.domain.user.User; import com.prgrms.nabmart.domain.user.exception.NotFoundUserException; import com.prgrms.nabmart.domain.user.repository.UserRepository; @@ -156,6 +159,24 @@ private void validationCoupon(Order order, Coupon coupon) { } } + @Transactional(readOnly = true) + public FindPayedOrdersResponse findPayedOrders(FindPayedOrdersCommand findPayedOrdersCommand) { + checkUserHasEmployeeAuthority(findPayedOrdersCommand.userId()); + PageRequest pageRequest = PageRequest.of(findPayedOrdersCommand.page(), PAGE_SIZE); + Page findOrders = orderRepository.findAllStatusIsPayed(pageRequest); + return FindPayedOrdersResponse.of( + findOrders.getContent(), + findOrders.getNumber(), + findOrders.getTotalElements()); + } + + private void checkUserHasEmployeeAuthority(Long userId) { + User user = findUserByUserId(userId); + if(!user.isEmployee()) { + throw new UnauthorizedOrderException("권한이 없습니다."); + } + } + public Order getOrderByOrderIdAndUserId(final Long orderId, final Long userId) { return orderRepository.findByOrderIdAndUser_UserId(orderId, userId) .orElseThrow(() -> new NotFoundOrderException("order 가 존재하지 않습니다")); diff --git a/src/main/java/com/prgrms/nabmart/domain/order/service/response/FindPayedOrdersResponse.java b/src/main/java/com/prgrms/nabmart/domain/order/service/response/FindPayedOrdersResponse.java new file mode 100644 index 000000000..58accdd2d --- /dev/null +++ b/src/main/java/com/prgrms/nabmart/domain/order/service/response/FindPayedOrdersResponse.java @@ -0,0 +1,33 @@ +package com.prgrms.nabmart.domain.order.service.response; + +import com.prgrms.nabmart.domain.order.Order; +import java.util.List; + +public record FindPayedOrdersResponse( + List orders, + int page, + long totalElements) { + + public static FindPayedOrdersResponse of( + List orders, + int page, + long totalElements) { + List content = orders.stream() + .map(FindPayedOrderResponse::from) + .toList(); + return new FindPayedOrdersResponse(content, page, totalElements); + } + + public record FindPayedOrderResponse( + Long orderId, + String name, + int price) { + + public static FindPayedOrderResponse from(Order order) { + return new FindPayedOrderResponse( + order.getOrderId(), + order.getName(), + order.getPrice()); + } + } +} diff --git a/src/main/java/com/prgrms/nabmart/domain/payment/service/request/FindPayedOrdersCommand.java b/src/main/java/com/prgrms/nabmart/domain/payment/service/request/FindPayedOrdersCommand.java new file mode 100644 index 000000000..e8b1c4608 --- /dev/null +++ b/src/main/java/com/prgrms/nabmart/domain/payment/service/request/FindPayedOrdersCommand.java @@ -0,0 +1,8 @@ +package com.prgrms.nabmart.domain.payment.service.request; + +public record FindPayedOrdersCommand(Long userId, int page) { + + public static FindPayedOrdersCommand of(Long userId, int page) { + return new FindPayedOrdersCommand(userId, page); + } +} diff --git a/src/main/java/com/prgrms/nabmart/global/config/WebSecurityConfig.java b/src/main/java/com/prgrms/nabmart/global/config/WebSecurityConfig.java index 9d3c2b643..78d4f1ae9 100644 --- a/src/main/java/com/prgrms/nabmart/global/config/WebSecurityConfig.java +++ b/src/main/java/com/prgrms/nabmart/global/config/WebSecurityConfig.java @@ -99,7 +99,8 @@ private RequestMatcher[] requestHasRoleRider() { private RequestMatcher[] requestHasRoleEmployee() { List requestMatchers = List.of( - antMatcher(POST, "/api/v1/orders/*/deliveries") + antMatcher(POST, "/api/v1/orders/*/deliveries"), + antMatcher(GET, "/api/v1/orders/payed") ); return requestMatchers.toArray(RequestMatcher[]::new); } diff --git a/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryIntegrationTest.java b/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryIntegrationTest.java index e17c9c7d7..e1ea9ec01 100644 --- a/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryIntegrationTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryIntegrationTest.java @@ -17,6 +17,7 @@ import com.prgrms.nabmart.domain.item.support.ItemFixture; import com.prgrms.nabmart.domain.order.Order; import com.prgrms.nabmart.domain.order.OrderItem; +import com.prgrms.nabmart.domain.order.OrderStatus; import com.prgrms.nabmart.domain.order.repository.OrderItemRepository; import com.prgrms.nabmart.domain.order.repository.OrderRepository; import com.prgrms.nabmart.domain.user.User; @@ -40,6 +41,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.ReflectionTestUtils; @SpringBootTest public class DeliveryIntegrationTest { @@ -108,6 +110,7 @@ void setUpData() { mainCategoryRepository.save(mainCategory); subCategoryRepository.save(subCategory); itemRepository.save(item); + ReflectionTestUtils.setField(order, "status", OrderStatus.PAYED); orderRepository.save(order); } diff --git a/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryTest.java b/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryTest.java index 3d7019d7d..49124302a 100644 --- a/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/delivery/DeliveryTest.java @@ -1,11 +1,15 @@ package com.prgrms.nabmart.domain.delivery; -import static com.prgrms.nabmart.domain.order.support.OrderFixture.deliveringOrder; +import static com.prgrms.nabmart.domain.order.support.OrderFixture.payingOrder; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.prgrms.nabmart.domain.delivery.exception.InvalidDeliveryException; import com.prgrms.nabmart.domain.order.Order; +import com.prgrms.nabmart.domain.order.OrderStatus; import com.prgrms.nabmart.domain.user.User; import com.prgrms.nabmart.domain.user.support.UserFixture; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -17,21 +21,58 @@ class DeliveryTest { class NewDeliveryTest { User user = UserFixture.user(); - Order order = deliveringOrder(1L, user); + Order order = payingOrder(1L, user); + + @BeforeEach + void setUp() { + order.updateOrderStatus(OrderStatus.PAYED); + } @Test @DisplayName("성공") void success() { //given String address = "주소지"; + int estimateMinutes = 30; //when Delivery delivery = Delivery.builder() .order(order) + .estimateMinutes(estimateMinutes) .build(); //then assertThat(delivery.getOrder()).isEqualTo(order); } + + @Test + @DisplayName("예외: 배송 예상 완료 시간이 음수") + void throwExceptionWhenEstimateMinutesIsMinus() { + //given + int estimateMinutes = -1; + + //when + //then + assertThatThrownBy(() -> Delivery.builder() + .order(order) + .estimateMinutes(estimateMinutes) + .build()) + .isInstanceOf(InvalidDeliveryException.class); + } + + @Test + @DisplayName("예외: 결제 완료된 주문이 아님") + void throwExceptionWhenOrderIsNotPayed() { + //given + Order noPayedOrder = payingOrder(1L, user); + + //when + //then + assertThatThrownBy(() -> Delivery.builder() + .order(noPayedOrder) + .estimateMinutes(30) + .build()) + .isInstanceOf(InvalidDeliveryException.class); + } } } diff --git a/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java b/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java index 807d7b5c3..8950ffa2f 100644 --- a/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java @@ -86,7 +86,7 @@ class DeliveryServiceTest { class RegisterDeliveryTest { User employee = UserFixture.employee(); - Order order = OrderFixture.payingOrder(1L, user); + Order order = OrderFixture.payedOrder(1L, user); RegisterDeliveryCommand registerDeliveryCommand = RegisterDeliveryCommand.of( 1L, 1L, diff --git a/src/test/java/com/prgrms/nabmart/domain/delivery/support/DeliveryFixture.java b/src/test/java/com/prgrms/nabmart/domain/delivery/support/DeliveryFixture.java index 1d072a0b7..7e4c03411 100644 --- a/src/test/java/com/prgrms/nabmart/domain/delivery/support/DeliveryFixture.java +++ b/src/test/java/com/prgrms/nabmart/domain/delivery/support/DeliveryFixture.java @@ -8,6 +8,7 @@ import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse.FindWaitingDeliveryResponse; import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryDetailResponse; import com.prgrms.nabmart.domain.order.Order; +import com.prgrms.nabmart.domain.order.OrderStatus; import java.time.LocalDateTime; import java.util.List; import lombok.AccessLevel; @@ -33,6 +34,7 @@ public final class DeliveryFixture { private static final String RIDER_ADDRESS = "address"; public static Delivery waitingDelivery(Order order) { + order.updateOrderStatus(OrderStatus.PAYED); return Delivery.builder() .order(order) .build(); diff --git a/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java b/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java index 6f77c5413..34c954bb5 100644 --- a/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java @@ -10,14 +10,19 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.when; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.JsonFieldType.ARRAY; import static org.springframework.restdocs.payload.JsonFieldType.NUMBER; import static org.springframework.restdocs.payload.JsonFieldType.STRING; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @@ -28,6 +33,9 @@ import com.prgrms.nabmart.domain.coupon.UserCoupon; import com.prgrms.nabmart.domain.order.Order; import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest; +import com.prgrms.nabmart.domain.order.controller.request.FindPayedOrdersRequest; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse.FindPayedOrderResponse; import com.prgrms.nabmart.domain.order.service.response.CreateOrderResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrderDetailResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrdersResponse; @@ -224,4 +232,48 @@ void deleteOrder() throws Exception { )); } } + + @Nested + @DisplayName("결제 완료된 주문 목록 조회 api 호출 시") + class FindPayedOrdersTest { + + @Test + @DisplayName("성공") + void findPayedOrders() throws Exception { + //given + int page = 0; + FindPayedOrdersRequest findPayedOrdersRequest = new FindPayedOrdersRequest(page); + FindPayedOrderResponse findPayedOrderResponse + = new FindPayedOrderResponse(1L, "비비고 왕교자 외 2개", 20000); + FindPayedOrdersResponse findPayedOrdersResponse = new FindPayedOrdersResponse( + List.of(findPayedOrderResponse), 0, 1); + + given(orderService.findPayedOrders(any())).willReturn(findPayedOrdersResponse); + + //when + ResultActions resultActions = mockMvc.perform(get("/api/v1/orders/payed") + .header(AUTHORIZATION, accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(findPayedOrdersRequest))); + + //then + resultActions.andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(AUTHORIZATION).description("액세스 토큰") + ), + requestFields( + fieldWithPath("page").type(NUMBER).description("페이지 번호") + ), + responseFields( + fieldWithPath("orders").type(ARRAY).description("주문 목록"), + fieldWithPath("orders[].orderId").type(NUMBER).description("주문 ID"), + fieldWithPath("orders[].name").type(STRING).description("주문 이름"), + fieldWithPath("orders[].price").type(NUMBER).description("주문 가격"), + fieldWithPath("page").type(NUMBER).description("페이지 번호"), + fieldWithPath("totalElements").type(NUMBER).description("총 요소 개수") + ) + )); + } + } } diff --git a/src/test/java/com/prgrms/nabmart/domain/order/service/OrderServiceTest.java b/src/test/java/com/prgrms/nabmart/domain/order/service/OrderServiceTest.java index 5433805ab..ca5c915cc 100644 --- a/src/test/java/com/prgrms/nabmart/domain/order/service/OrderServiceTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/order/service/OrderServiceTest.java @@ -11,9 +11,11 @@ import static com.prgrms.nabmart.domain.order.support.OrderFixture.updateOrderByCouponCommand; import static com.prgrms.nabmart.domain.user.support.UserFixture.user; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchException; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,17 +34,23 @@ import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest; import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest.CreateOrderItemRequest; import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException; +import com.prgrms.nabmart.domain.order.exception.UnauthorizedOrderException; import com.prgrms.nabmart.domain.order.repository.OrderRepository; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse.FindPayedOrderResponse; import com.prgrms.nabmart.domain.order.service.request.CreateOrdersCommand; import com.prgrms.nabmart.domain.order.service.request.UpdateOrderByCouponCommand; import com.prgrms.nabmart.domain.order.service.response.CreateOrderResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrderDetailResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrdersResponse; import com.prgrms.nabmart.domain.order.service.response.UpdateOrderByCouponResponse; +import com.prgrms.nabmart.domain.payment.service.request.FindPayedOrdersCommand; import com.prgrms.nabmart.domain.user.User; import com.prgrms.nabmart.domain.user.repository.UserRepository; +import com.prgrms.nabmart.domain.user.support.UserFixture; import java.util.List; import java.util.Optional; +import java.util.stream.IntStream; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -341,4 +349,58 @@ void success() { verify(orderRepository, times(1)).delete(order); } } + + @Nested + @DisplayName("findPayedOrders 메서드 실행 시") + class FindOrdersWaitingDeliveryTest { + + User user = UserFixture.user(); + User employee = UserFixture.employee(); + FindPayedOrdersCommand findPayedOrdersCommand + = FindPayedOrdersCommand.of(1L, 0); + Item item = item(); + int orderItemQuantity = 5; + + private List createOrders(int end) { + return IntStream.range(0, end) + .mapToObj(i -> { + OrderItem orderItem = new OrderItem(item, orderItemQuantity); + return new Order(user, List.of(orderItem)); + }).toList(); + } + + @Test + @DisplayName("성공") + void success() { + //given + List orders = createOrders(5); + PageImpl ordersPage = new PageImpl<>(orders); + + given(userRepository.findById(any())).willReturn(Optional.ofNullable(employee)); + given(orderRepository.findAllStatusIsPayed(any())).willReturn(ordersPage); + + //when + FindPayedOrdersResponse result = orderService.findPayedOrders( + findPayedOrdersCommand); + + //then + int expectedPrice = item.getPrice() * orderItemQuantity; + assertThat(result.orders()).hasSize(5); + assertThat(result.orders()).map(FindPayedOrderResponse::price) + .containsOnly(expectedPrice); + } + + @Test + @DisplayName("예외: 로그인 유저가 employee가 아님") + void throwExceptionWhenLoginUserIsNotEmployee() { + //given + given(userRepository.findById(any())).willReturn(Optional.ofNullable(user)); + + //when + //then + assertThatThrownBy( + () -> orderService.findPayedOrders(findPayedOrdersCommand)) + .isInstanceOf(UnauthorizedOrderException.class); + } + } } diff --git a/src/test/java/com/prgrms/nabmart/domain/order/support/OrderFixture.java b/src/test/java/com/prgrms/nabmart/domain/order/support/OrderFixture.java index a069b142e..3ce4043f3 100644 --- a/src/test/java/com/prgrms/nabmart/domain/order/support/OrderFixture.java +++ b/src/test/java/com/prgrms/nabmart/domain/order/support/OrderFixture.java @@ -43,6 +43,14 @@ public static Order payingOrder(long orderId, User user) { return order; } + + public static Order payedOrder(long orderId, User user) { + Order order = payingOrder(orderId, user); + ReflectionTestUtils.setField(order, "orderId", orderId); + ReflectionTestUtils.setField(order, "status", OrderStatus.PAYED); + + return order; + } public static Order deliveringOrder(long orderId, User user) { Order order = new Order(user, List.of(orderItem())); From 51226158f0c007b0bf0289775024102d193fcfab Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 13:47:13 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[NAYB-158]=20feat:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=EC=9D=84=20=EC=9C=84=ED=95=B4=20`Delivery`?= =?UTF-8?q?=EC=97=90=20`userId`=EB=A5=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/prgrms/nabmart/domain/delivery/Delivery.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java b/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java index f3cbe23e6..29f10fff7 100644 --- a/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java +++ b/src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java @@ -69,6 +69,9 @@ public class Delivery extends BaseTimeEntity { @Column private Integer deliveryFee; + @Column + private Long userId; + @Builder public Delivery(final Order order, final int estimateMinutes) { validateOrderStatus(order); @@ -80,6 +83,7 @@ public Delivery(final Order order, final int estimateMinutes) { this.riderRequest = order.getRiderRequest(); this.deliveryFee = order.getDeliveryFee(); this.arrivedAt = LocalDateTime.now().plusMinutes(estimateMinutes); + this.userId = order.getUser().getUserId(); order.updateOrderStatus(OrderStatus.DELIVERING); } From fdb68c8346b96bb3f214c82ea28f9d3227991eea Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 14:18:55 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[NAYB-158]=20feat:=20`Notification`=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=9C=EB=AA=A9=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?`title`=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/Notification.java | 15 +++- .../service/NotificationService.java | 2 + .../request/SendNotificationCommand.java | 4 +- .../response/NotificationResponse.java | 2 + .../domain/notification/NotificationTest.java | 71 +++++++++++++++++++ 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java index 5f258431f..7c7ec8921 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java @@ -20,12 +20,16 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Notification extends BaseTimeEntity { + private static final int TITLE_LENGTH = 20; private static final int CONTENT_LENGTH = 50; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long notificationId; + @Column(nullable = false) + private String title; + @Column(nullable = false) private String content; @@ -37,17 +41,26 @@ public class Notification extends BaseTimeEntity { @Builder public Notification( + String title, String content, Long userId, NotificationType notificationType) { + validateTitle(title); validateContent(content); + this.title = title; this.content = content; this.notificationType = notificationType; this.userId = userId; } + private void validateTitle(String title) { + if (Objects.nonNull(title) && title.length() > TITLE_LENGTH) { + throw new InvalidNotificationException("제목의 길이는 20자 이하여야 합니다."); + } + } + private void validateContent(String content) { - if(Objects.nonNull(content) && content.length() > CONTENT_LENGTH) { + if (Objects.nonNull(content) && content.length() > CONTENT_LENGTH) { throw new InvalidNotificationException("내용의 길이는 50자 이하여야 합니다."); } } diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java index f28b5dd1f..3d6ccd719 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java @@ -69,11 +69,13 @@ private void send(SseEmitter emitter, String emitterId, Object data) { @Transactional public void sendNotification(SendNotificationCommand sendNotificationCommand) { Long userId = sendNotificationCommand.userId(); + String title = sendNotificationCommand.title(); String content = sendNotificationCommand.content(); NotificationType notificationType = sendNotificationCommand.notificationType(); verifyExistsUser(userId); Notification notification = Notification.builder() + .title(title) .content(content) .userId(userId) .notificationType(notificationType) diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/request/SendNotificationCommand.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/request/SendNotificationCommand.java index 3a02512dc..f460e50d7 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/request/SendNotificationCommand.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/request/SendNotificationCommand.java @@ -4,13 +4,15 @@ public record SendNotificationCommand( Long userId, + String title, String content, NotificationType notificationType) { public static SendNotificationCommand of( final Long userId, + final String title, final String content, final NotificationType notificationType) { - return new SendNotificationCommand(userId, content, notificationType); + return new SendNotificationCommand(userId, title, content, notificationType); } } diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java index 43e1753be..f7b02a48e 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java @@ -6,6 +6,7 @@ public record NotificationResponse( Long notificationId, + String title, String content, NotificationType notificationType, Long userId, @@ -14,6 +15,7 @@ public record NotificationResponse( public static NotificationResponse from(Notification notification) { return new NotificationResponse( notification.getNotificationId(), + notification.getTitle(), notification.getContent(), notification.getNotificationType(), notification.getUserId(), diff --git a/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java b/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java new file mode 100644 index 000000000..2662fd068 --- /dev/null +++ b/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java @@ -0,0 +1,71 @@ +package com.prgrms.nabmart.domain.notification; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.prgrms.nabmart.domain.notification.exception.InvalidNotificationException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class NotificationTest { + + @Nested + @DisplayName("notification 생성 시") + class NewNotificationTest { + + @Test + @DisplayName("성공") + void success() { + //given + String title = "제목"; + String content = "내용"; + + //when + Notification notification = Notification.builder() + .title(title) + .content(content) + .userId(1L) + .notificationType(NotificationType.DELIVERY) + .build(); + + //then + assertThat(notification.getTitle()).isEqualTo(title); + assertThat(notification.getContent()).isEqualTo(content); + } + + @Test + @DisplayName("예외: 제목 길이가 20자를 초과") + void throwExceptionWhenTitleLengthGGraterThan20() { + //given + String titleGT20 = "a".repeat(21); + + //when + //then + assertThatThrownBy(() -> Notification.builder() + .title(titleGT20) + .content("내용") + .userId(1L) + .notificationType(NotificationType.DELIVERY) + .build()) + .isInstanceOf(InvalidNotificationException.class); + } + + @Test + @DisplayName("예외: 내용 길이가 50자를 초과") + void throwExceptionWhenContentLengthGraterThan50() { + //given + String contentGT50 = "a".repeat(51); + + //when + //then + assertThatThrownBy(() -> Notification.builder() + .title("title") + .content(contentGT50) + .userId(1L) + .notificationType(NotificationType.DELIVERY) + .build()) + .isInstanceOf(InvalidNotificationException.class); + } + } +} From 2f50a654ff8e47d5c45b4243133d29641b2568cd Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 15:35:05 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[NAYB-158]=20feat:=20`Notification`=20=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=A1=B0=EA=B1=B4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/Notification.java | 4 ++-- .../domain/notification/NotificationTest.java | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java index 7c7ec8921..f527b0c16 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java @@ -20,8 +20,8 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Notification extends BaseTimeEntity { - private static final int TITLE_LENGTH = 20; - private static final int CONTENT_LENGTH = 50; + private static final int TITLE_LENGTH = 30; + private static final int CONTENT_LENGTH = 100; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java b/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java index 2662fd068..d592311f3 100644 --- a/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/notification/NotificationTest.java @@ -35,15 +35,15 @@ void success() { } @Test - @DisplayName("예외: 제목 길이가 20자를 초과") - void throwExceptionWhenTitleLengthGGraterThan20() { + @DisplayName("예외: 제목 길이가 30자를 초과") + void throwExceptionWhenTitleLengthGGraterThan31() { //given - String titleGT20 = "a".repeat(21); + String titleGT30 = "a".repeat(31); //when //then assertThatThrownBy(() -> Notification.builder() - .title(titleGT20) + .title(titleGT30) .content("내용") .userId(1L) .notificationType(NotificationType.DELIVERY) @@ -52,16 +52,16 @@ void throwExceptionWhenTitleLengthGGraterThan20() { } @Test - @DisplayName("예외: 내용 길이가 50자를 초과") - void throwExceptionWhenContentLengthGraterThan50() { + @DisplayName("예외: 내용 길이가 100자를 초과") + void throwExceptionWhenContentLengthGraterThan100() { //given - String contentGT50 = "a".repeat(51); + String contentGT100 = "a".repeat(101); //when //then assertThatThrownBy(() -> Notification.builder() .title("title") - .content(contentGT50) + .content(contentGT100) .userId(1L) .notificationType(NotificationType.DELIVERY) .build()) From 00ae9a9a4c320f1b46f095b6917714914c41e352 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 15:35:33 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[NAYB-158]=20feat:=20=EB=B0=B0=EB=8B=AC=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EB=B3=80=EA=B2=BD=20=EC=8B=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delivery/service/DeliveryService.java | 53 ++++++++++++++++++- .../notification/NotificationMessage.java | 21 ++++++++ .../delivery/service/DeliveryServiceTest.java | 37 +++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/prgrms/nabmart/domain/notification/NotificationMessage.java diff --git a/src/main/java/com/prgrms/nabmart/domain/delivery/service/DeliveryService.java b/src/main/java/com/prgrms/nabmart/domain/delivery/service/DeliveryService.java index 93d5c3319..4e4d7e3f9 100644 --- a/src/main/java/com/prgrms/nabmart/domain/delivery/service/DeliveryService.java +++ b/src/main/java/com/prgrms/nabmart/domain/delivery/service/DeliveryService.java @@ -1,5 +1,9 @@ package com.prgrms.nabmart.domain.delivery.service; +import static com.prgrms.nabmart.domain.notification.NotificationMessage.COMPLETE_DELIVERY; +import static com.prgrms.nabmart.domain.notification.NotificationMessage.REGISTER_DELIVERY; +import static com.prgrms.nabmart.domain.notification.NotificationMessage.START_DELIVERY; + import com.prgrms.nabmart.domain.delivery.Delivery; import com.prgrms.nabmart.domain.delivery.Rider; import com.prgrms.nabmart.domain.delivery.exception.AlreadyRegisteredDeliveryException; @@ -18,6 +22,9 @@ import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryDetailResponse; import com.prgrms.nabmart.domain.delivery.service.response.FindRiderDeliveriesResponse; import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse; +import com.prgrms.nabmart.domain.notification.NotificationType; +import com.prgrms.nabmart.domain.notification.service.NotificationService; +import com.prgrms.nabmart.domain.notification.service.request.SendNotificationCommand; import com.prgrms.nabmart.domain.order.Order; import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException; import com.prgrms.nabmart.domain.order.repository.OrderRepository; @@ -37,6 +44,7 @@ public class DeliveryService { private final UserRepository userRepository; private final RiderRepository riderRepository; private final OrderRepository orderRepository; + private final NotificationService notificationService; @Transactional public Long registerDelivery(RegisterDeliveryCommand registerDeliveryCommand) { @@ -45,12 +53,29 @@ public Long registerDelivery(RegisterDeliveryCommand registerDeliveryCommand) { checkAlreadyRegisteredDelivery(order); Delivery delivery = new Delivery(order, registerDeliveryCommand.estimateMinutes()); deliveryRepository.save(delivery); + + sendRegisterDeliveryNotification(registerDeliveryCommand, delivery, order); + return delivery.getDeliveryId(); } + private void sendRegisterDeliveryNotification( + RegisterDeliveryCommand registerDeliveryCommand, + Delivery delivery, + Order order) { + SendNotificationCommand notificationCommand = SendNotificationCommand.of( + delivery.getUserId(), + REGISTER_DELIVERY.getTitle(), + REGISTER_DELIVERY.getContentFromFormat( + order.getName(), + registerDeliveryCommand.estimateMinutes()), + NotificationType.DELIVERY); + notificationService.sendNotification(notificationCommand); + } + private void checkUserHasRegisterDeliveryAuthority(final Long userId) { User user = findUserByUserId(userId); - if(!user.isEmployee()) { + if (!user.isEmployee()) { throw new UnauthorizedDeliveryException("권한이 없습니다."); } } @@ -61,7 +86,7 @@ private Order findOrderByOrderIdPessimistic(RegisterDeliveryCommand registerDeli } private void checkAlreadyRegisteredDelivery(final Order order) { - if(deliveryRepository.existsByOrder(order)) { + if (deliveryRepository.existsByOrder(order)) { throw new AlreadyRegisteredDeliveryException("이미 배달이 생성된 주문입니다."); } } @@ -99,6 +124,19 @@ public void startDelivery(StartDeliveryCommand startDeliveryCommand) { Delivery delivery = findDeliveryByDeliveryId(startDeliveryCommand.deliveryId()); delivery.checkAuthority(rider); delivery.startDelivery(startDeliveryCommand.deliveryEstimateMinutes()); + + sendStartDeliveryNotification(startDeliveryCommand, delivery); + } + + private void sendStartDeliveryNotification( + StartDeliveryCommand startDeliveryCommand, + Delivery delivery) { + SendNotificationCommand notificationCommand = SendNotificationCommand.of( + delivery.getUserId(), + START_DELIVERY.getTitle(), + START_DELIVERY.getContentFromFormat(startDeliveryCommand.deliveryEstimateMinutes()), + NotificationType.DELIVERY); + notificationService.sendNotification(notificationCommand); } @Transactional @@ -107,6 +145,17 @@ public void completeDelivery(CompleteDeliveryCommand completeDeliveryCommand) { Delivery delivery = findDeliveryByDeliveryId(completeDeliveryCommand.deliveryId()); delivery.checkAuthority(rider); delivery.completeDelivery(); + + sendCompleteDeliveryNotification(delivery); + } + + private void sendCompleteDeliveryNotification(Delivery delivery) { + SendNotificationCommand notificationCommand = SendNotificationCommand.of( + delivery.getUserId(), + COMPLETE_DELIVERY.getTitle(), + COMPLETE_DELIVERY.getContentFromFormat(), + NotificationType.DELIVERY); + notificationService.sendNotification(notificationCommand); } private Rider findRiderByRiderId(final Long riderId) { diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/NotificationMessage.java b/src/main/java/com/prgrms/nabmart/domain/notification/NotificationMessage.java new file mode 100644 index 000000000..441a540d7 --- /dev/null +++ b/src/main/java/com/prgrms/nabmart/domain/notification/NotificationMessage.java @@ -0,0 +1,21 @@ +package com.prgrms.nabmart.domain.notification; + +import java.text.MessageFormat; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NotificationMessage { + REGISTER_DELIVERY("주문이 접수되었습니다.", + "주문하신 {0} 이(가) {1}분 내에 도착할 예정입니다."), + START_DELIVERY("라이더가 주문을 픽업하였습니다.", "약 {0}분 후에 도착할 예정입니다."), + COMPLETE_DELIVERY("배달이 완료되었습니다.", "네이B마트를 이용해주셔서 감사합니다."); + + private final String title; + private final String contentFormat; + + public String getContentFromFormat(Object... arguments) { + return MessageFormat.format(contentFormat, arguments); + } +} diff --git a/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java b/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java index 8950ffa2f..7fdc7c25b 100644 --- a/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/delivery/service/DeliveryServiceTest.java @@ -31,6 +31,7 @@ import com.prgrms.nabmart.domain.delivery.service.response.FindRiderDeliveriesResponse.FindRiderDeliveryResponse; import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse; import com.prgrms.nabmart.domain.delivery.support.DeliveryFixture; +import com.prgrms.nabmart.domain.notification.service.NotificationService; import com.prgrms.nabmart.domain.order.Order; import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException; import com.prgrms.nabmart.domain.order.repository.OrderRepository; @@ -75,6 +76,9 @@ class DeliveryServiceTest { @Mock OrderRepository orderRepository; + @Mock + NotificationService notificationService; + User user = UserFixture.user(); Order order = deliveringOrder(1L, user); Rider rider = DeliveryFixture.rider(); @@ -106,6 +110,7 @@ void success() { //then then(deliveryRepository).should().save(any()); + then(notificationService).should().sendNotification(any()); } @Test @@ -262,6 +267,24 @@ void success() { assertThat(delivery.getDeliveryStatus()).isEqualTo(DeliveryStatus.START_DELIVERY); } + @Test + @DisplayName("성공: 배달 시작 알림 전송") + void successThenNotify() { + //given + int deliveryEstimateMinutes = 20; + StartDeliveryCommand startDeliveryCommand + = StartDeliveryCommand.of(1L, deliveryEstimateMinutes, 1L); + + given(riderRepository.findById(any())).willReturn(Optional.ofNullable(rider)); + given(deliveryRepository.findById(any())).willReturn(Optional.ofNullable(delivery)); + + //when + deliveryService.startDelivery(startDeliveryCommand); + + //then + then(notificationService).should().sendNotification(any()); + } + @Test @DisplayName("예외: 존재하지 않는 라이더") void throwExceptionWhenNotFoundRider() { @@ -349,6 +372,20 @@ void success() { assertThat(delivery.getDeliveryStatus()).isEqualTo(DeliveryStatus.DELIVERED); } + @Test + @DisplayName("성공: 배달 완료 알림 전송") + void successThenNotify() { + //given + given(riderRepository.findById(any())).willReturn(Optional.ofNullable(rider)); + given(deliveryRepository.findById(any())).willReturn(Optional.ofNullable(delivery)); + + //when + deliveryService.completeDelivery(completeDeliveryCommand); + + //then + then(notificationService).should().sendNotification(any()); + } + @Test @DisplayName("예외: 존재하지 않는 라이더") void throwExceptionWhenNotFoundRider() { From 7c83980316ad0417e317130ecf8c898ec9ee8676 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 15:52:13 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[NAYB-158]=20feat:=20`Notification`=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=EC=97=90=EC=84=9C=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=AA=A8=EB=8D=B8=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/Notification.java | 19 ------------------- .../repository/NotificationRepository.java | 8 -------- .../service/NotificationService.java | 3 --- .../response/NotificationResponse.java | 2 -- 4 files changed, 32 deletions(-) delete mode 100644 src/main/java/com/prgrms/nabmart/domain/notification/repository/NotificationRepository.java diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java index f527b0c16..59b21fc5d 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/Notification.java @@ -2,20 +2,12 @@ import com.prgrms.nabmart.domain.notification.exception.InvalidNotificationException; import com.prgrms.nabmart.global.BaseTimeEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; import java.util.Objects; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -@Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Notification extends BaseTimeEntity { @@ -23,20 +15,9 @@ public class Notification extends BaseTimeEntity { private static final int TITLE_LENGTH = 30; private static final int CONTENT_LENGTH = 100; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long notificationId; - - @Column(nullable = false) private String title; - - @Column(nullable = false) private String content; - - @Enumerated(EnumType.STRING) private NotificationType notificationType; - - @Column(nullable = false) private Long userId; @Builder diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/repository/NotificationRepository.java b/src/main/java/com/prgrms/nabmart/domain/notification/repository/NotificationRepository.java deleted file mode 100644 index 0c87b21cb..000000000 --- a/src/main/java/com/prgrms/nabmart/domain/notification/repository/NotificationRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.prgrms.nabmart.domain.notification.repository; - -import com.prgrms.nabmart.domain.notification.Notification; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface NotificationRepository extends JpaRepository { - -} diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java index 3d6ccd719..a3152bc0d 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java @@ -6,7 +6,6 @@ import com.prgrms.nabmart.domain.notification.NotificationType; import com.prgrms.nabmart.domain.notification.controller.request.ConnectNotificationCommand; import com.prgrms.nabmart.domain.notification.repository.EmitterRepository; -import com.prgrms.nabmart.domain.notification.repository.NotificationRepository; import com.prgrms.nabmart.domain.notification.service.request.SendNotificationCommand; import com.prgrms.nabmart.domain.notification.service.response.NotificationResponse; import com.prgrms.nabmart.domain.user.exception.NotFoundUserException; @@ -27,7 +26,6 @@ public class NotificationService { private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 120; private final EmitterRepository emitterRepository; - private final NotificationRepository notificationRepository; private final UserRepository userRepository; public SseEmitter connectNotification(ConnectNotificationCommand connectNotificationCommand) { @@ -80,7 +78,6 @@ public void sendNotification(SendNotificationCommand sendNotificationCommand) { .userId(userId) .notificationType(notificationType) .build(); - notificationRepository.save(notification); Map emitters = emitterRepository.findAllByIdStartWith(userId); emitters.forEach((key, emitter) -> { diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java index f7b02a48e..6c04b5c27 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/response/NotificationResponse.java @@ -5,7 +5,6 @@ import java.time.LocalDateTime; public record NotificationResponse( - Long notificationId, String title, String content, NotificationType notificationType, @@ -14,7 +13,6 @@ public record NotificationResponse( public static NotificationResponse from(Notification notification) { return new NotificationResponse( - notification.getNotificationId(), notification.getTitle(), notification.getContent(), notification.getNotificationType(), From e584653c36505d5b218b1148d1865b302dab480c Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Thu, 21 Sep 2023 16:38:46 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[NAYB-158]=20fix:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=8A=B8=EB=9E=9C=EC=9E=AD=EC=85=98=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/service/NotificationService.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java index a3152bc0d..f4b792da1 100644 --- a/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java +++ b/src/main/java/com/prgrms/nabmart/domain/notification/service/NotificationService.java @@ -10,7 +10,6 @@ import com.prgrms.nabmart.domain.notification.service.response.NotificationResponse; import com.prgrms.nabmart.domain.user.exception.NotFoundUserException; import com.prgrms.nabmart.domain.user.repository.UserRepository; -import jakarta.transaction.Transactional; import java.io.IOException; import java.util.Map; import lombok.RequiredArgsConstructor; @@ -63,8 +62,7 @@ private void send(SseEmitter emitter, String emitterId, Object data) { log.error("알림 전송에 실패했습니다.", ex); } } - - @Transactional + public void sendNotification(SendNotificationCommand sendNotificationCommand) { Long userId = sendNotificationCommand.userId(); String title = sendNotificationCommand.title();