From b6583eaec2f934c13d22495dd603fb6badce5da6 Mon Sep 17 00:00:00 2001 From: hoon7566 Date: Tue, 8 Mar 2022 17:14:25 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat(customer-vue,=20order-service):=20?= =?UTF-8?q?=EC=83=81=ED=92=88=20=EC=83=81=EC=84=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80,=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 상품 상세페이지 - 장바구니 기능 추가 --- customer-vue/src/api/order.js | 8 + customer-vue/src/api/store.js | 2 +- customer-vue/src/router/router.js | 5 + customer-vue/src/views/HomeView.vue | 2 +- customer-vue/src/views/ItemDetail.vue | 183 ++++++++++++++++++ .../domain/order/entity/Order.java | 16 ++ .../order/repository/OrderRepository.java | 4 +- .../domain/order/service/OrderService.java | 2 + .../order/service/OrderServiceImpl.java | 35 ++++ .../order/web/OrderCustomerApiController.java | 39 +++- .../domain/orderItem/dto/OrderItemDto.java | 18 +- .../domain/orderItem/entity/OrderItem.java | 11 ++ .../dto/OrderItemOptionDto.java | 14 ++ .../entity/OrderItemOption.java | 7 + .../repository/OrderItemOptionRepository.java | 8 + .../src/main/resources/application.yml | 2 +- .../item/web/ItemCustomerApiController.java | 81 ++++++++ .../src/main/resources/application.yml | 2 +- .../userservice/UserServiceApplication.java | 2 - 19 files changed, 429 insertions(+), 12 deletions(-) create mode 100644 customer-vue/src/views/ItemDetail.vue create mode 100644 order-service/src/main/java/com/justpickup/orderservice/domain/orderItemOption/dto/OrderItemOptionDto.java create mode 100644 order-service/src/main/java/com/justpickup/orderservice/domain/orderItemOption/repository/OrderItemOptionRepository.java create mode 100644 store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemCustomerApiController.java diff --git a/customer-vue/src/api/order.js b/customer-vue/src/api/order.js index 7cccf7b..bb473b2 100644 --- a/customer-vue/src/api/order.js +++ b/customer-vue/src/api/order.js @@ -8,5 +8,13 @@ export default { } } return axios.get(process.env.VUE_APP_ORDER_API_URL + "/order/history", options); + }, + addItemToBasket(item) { + item.itemOptionIds =[]; + for (const itemId of item.otherOptions) { + item.itemOptionIds.push(itemId) + } + item.itemOptionIds.push(item.requireOption) + return axios.post(process.env.VUE_APP_ORDER_API_URL+'/order/item', item); } } \ No newline at end of file diff --git a/customer-vue/src/api/store.js b/customer-vue/src/api/store.js index 9fae59a..22f0b11 100644 --- a/customer-vue/src/api/store.js +++ b/customer-vue/src/api/store.js @@ -29,7 +29,7 @@ export default { }) }, getItemById(itemId){ - return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/item/'+itemId) + return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+itemId) }, saveItem(method, itemData){ return axios({ diff --git a/customer-vue/src/router/router.js b/customer-vue/src/router/router.js index 8be971a..54d96f9 100644 --- a/customer-vue/src/router/router.js +++ b/customer-vue/src/router/router.js @@ -61,6 +61,11 @@ const routes = [ }, ] }, + { + path: "/item/:storeId/:itemId", + name: 'itemDetail', + component: () => import('../views/ItemDetail') + }, { path: '/auth', diff --git a/customer-vue/src/views/HomeView.vue b/customer-vue/src/views/HomeView.vue index 2ce4121..160486a 100644 --- a/customer-vue/src/views/HomeView.vue +++ b/customer-vue/src/views/HomeView.vue @@ -1,5 +1,5 @@ diff --git a/customer-vue/src/router/router.js b/customer-vue/src/router/router.js index 54d96f9..2737a03 100644 --- a/customer-vue/src/router/router.js +++ b/customer-vue/src/router/router.js @@ -59,13 +59,19 @@ const routes = [ name: 'login', component: () => import('../views/LoginPage') }, + { + path: "/item/:storeId/:itemId", + name: 'itemDetail', + component: () => import('../views/ItemDetail') + }, + { + path: "/order", + name: 'orderPage', + component: () => import('../views/OrderPage') + }, ] }, - { - path: "/item/:storeId/:itemId", - name: 'itemDetail', - component: () => import('../views/ItemDetail') - }, + { path: '/auth', diff --git a/customer-vue/src/views/ItemDetail.vue b/customer-vue/src/views/ItemDetail.vue index e45a33e..da391a2 100644 --- a/customer-vue/src/views/ItemDetail.vue +++ b/customer-vue/src/views/ItemDetail.vue @@ -1,6 +1,5 @@ \ No newline at end of file diff --git a/customer-vue/src/views/OrderPage.vue b/customer-vue/src/views/OrderPage.vue new file mode 100644 index 0000000..c5f79a3 --- /dev/null +++ b/customer-vue/src/views/OrderPage.vue @@ -0,0 +1,120 @@ + + + + + \ No newline at end of file diff --git a/order-service/build.gradle b/order-service/build.gradle index 9bd342f..f4ad1b7 100644 --- a/order-service/build.gradle +++ b/order-service/build.gradle @@ -35,7 +35,7 @@ dependencies { /*implementation 'org.springframework.boot:spring-boot-starter-amqp'*/ /*implementation 'org.springframework.boot:spring-boot-starter-security'*/ /*implementation 'org.springframework.cloud:spring-cloud-starter-config'*/ - /*implementation 'org.springframework.kafka:spring-kafka'*/ + implementation 'org.springframework.kafka:spring-kafka' // https://mvnrepository.com/artifact/com.github.gavlyukovskiy/p6spy-spring-boot-starter implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0' @@ -46,7 +46,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' // testImplementation 'org.springframework.amqp:spring-rabbit-test' -// testImplementation 'org.springframework.kafka:spring-kafka-test' + testImplementation 'org.springframework.kafka:spring-kafka-test' // testImplementation 'org.springframework.security:spring-security-test' testImplementation 'com.h2database:h2' diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java new file mode 100644 index 0000000..e002ef8 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java @@ -0,0 +1,49 @@ +package com.justpickup.orderservice.domain.order.dto; + +import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; +import com.justpickup.orderservice.domain.orderItem.entity.OrderItem; +import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@NoArgsConstructor +public class FetchOrderDto { + private Long id; + + private Long userId; + + private String userName; + + private Long userCouponId; + + private Long orderPrice; + + private Long storeId; + + private LocalDateTime orderTime; + + private Long usedPoint; + + private OrderStatus orderStatus; + + private List orderItemDtoList; + + + public FetchOrderDto(Order order) { + this.id = order.getId(); + this.userId = order.getUserId(); + this.orderPrice = order.getOrderPrice(); + this.storeId = order.getStoreId(); + this.orderItemDtoList = order.getOrderItems().stream() + .map(orderItem -> OrderItemDto.of(orderItem.getId(),orderItem.getItemId(),orderItem.getPrice(),orderItem.getCount(),orderItem.getOrderItemOptions().stream().map(orderItemOption -> new OrderItemOptionDto(orderItemOption.getId())).collect(Collectors.toList()))) + .collect(Collectors.toList()); + } + +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java index f93393f..4574286 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java @@ -84,6 +84,8 @@ public class OrderDto { } + + // == 변수 변경 메소드 == // public void setUserName(String userName) { this.userName = userName; diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java index f7759d2..94c114d 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java @@ -85,8 +85,10 @@ public class Order extends BaseEntity { transaction.setOrder(this); } - public void addOrderItem(OrderItem orderItem) { + public Order addOrderItem(OrderItem orderItem) { this.orderItems.add(orderItem); + this.orderPrice += orderItem.getPrice(); orderItem.setOrder(this); + return this; } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepository.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepository.java index 95bfa0f..337e2b9 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepository.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepository.java @@ -1,10 +1,11 @@ package com.justpickup.orderservice.domain.order.repository; import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface OrderRepository extends JpaRepository { - Optional findByUserId(Long userId); + Optional findByUserIdAndOrderStatus(Long userId, OrderStatus orderStatus); } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java index 9dc4317..e90e0a5 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/repository/OrderRepositoryCustom.java @@ -3,6 +3,7 @@ package com.justpickup.orderservice.domain.order.repository; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -14,8 +15,12 @@ import org.springframework.stereotype.Repository; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import static com.justpickup.orderservice.domain.order.entity.QOrder.order; +import static com.justpickup.orderservice.domain.orderItem.entity.QOrderItem.orderItem; +import static com.justpickup.orderservice.domain.orderItemOption.entity.QOrderItemOption.orderItemOption; +import static com.justpickup.orderservice.domain.transaction.entity.QTransaction.transaction; @Repository @RequiredArgsConstructor @@ -104,4 +109,19 @@ public class OrderRepositoryCustom { return new SliceImpl<>(contents, pageable, hasNext); } + + public Optional fetchOrder(Long userId){ + + return Optional.ofNullable(queryFactory.selectFrom(order) + .leftJoin(order.orderItems, orderItem).fetchJoin() + .leftJoin(orderItem.orderItemOptions,orderItemOption) + .leftJoin(order.transaction,transaction) + .where( + order.userId.eq(userId), + order.orderStatus.eq(OrderStatus.PENDING) + ) + .distinct() + .fetchOne()); + + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java index c08a9ff..6f9f98c 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderService.java @@ -1,5 +1,6 @@ package com.justpickup.orderservice.domain.order.service; +import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; @@ -15,4 +16,6 @@ public interface OrderService { Page findPrevOrderMain(PrevOrderSearch search, Pageable pageable, Long storeId); SliceImpl findOrderHistory(Pageable pageable, Long userId); void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId); + FetchOrderDto fetchOrder(Long userId); + void saveOrder(Long userId); } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java index d1cc9e2..5f969bf 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java @@ -1,9 +1,11 @@ package com.justpickup.orderservice.domain.order.service; +import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.repository.OrderRepository; import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; @@ -103,7 +105,6 @@ public class OrderServiceImpl implements OrderService { @Override @Transactional public void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId) { - orderItemDto.getCount(); //orderItemOption Entity를 생성한다. List orderItemOptions = orderItemDto.getOrderItemOptionDtoList() @@ -119,11 +120,26 @@ public class OrderServiceImpl implements OrderService { //HARD_CODE Long userCouponId=0L; - Optional optionalOrder = orderRepository.findByUserId(userId); + Optional optionalOrder = orderRepository.findByUserIdAndOrderStatus(userId, OrderStatus.PENDING); if(optionalOrder.isPresent()){ - optionalOrder.get().addOrderItem(orderItem); + if(optionalOrder.get().addOrderItem(orderItem) + .getStoreId().equals(storeId)) + throw new RuntimeException("장바구니에 여러 카페의 메뉴를 담을수 없습니다."); }else{ orderRepository.save(Order.of(userId,userCouponId,storeId,orderItemDto.getPrice(),orderItem)); } } + + @Override + public FetchOrderDto fetchOrder(Long userId) { + Order order = orderRepositoryCustom.fetchOrder(userId) + .orElseThrow(RuntimeException::new); + + return new FetchOrderDto(order); + } + + @Override + public void saveOrder(Long userId) { + + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java index b054d95..3ce6811 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java @@ -1,9 +1,11 @@ package com.justpickup.orderservice.domain.order.web; +import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.service.OrderService; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; +import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto; import com.justpickup.orderservice.global.dto.Result; import lombok.AllArgsConstructor; import lombok.Data; @@ -99,7 +101,7 @@ public class OrderCustomerApiController { requestItem.itemId, requestItem.getPrice(), requestItem.getCount(), - requestItem.getItemOptionIds()); + requestItem.getItemOptionIds().stream().map(OrderItemOptionDto::new).collect(Collectors.toList())); orderService.addItemToBasket(orderItemDto,requestItem.getStoreId() ,Long.parseLong(userId)); return ResponseEntity.status(HttpStatus.NO_CONTENT) .body(Result.createSuccessResult(null)); @@ -117,6 +119,58 @@ public class OrderCustomerApiController { } + @GetMapping("/orders") + public ResponseEntity getOrder(@RequestHeader(value = "user-id") String userId){ + FetchOrderDto fetchOrderDto = orderService.fetchOrder(Long.parseLong(userId)); + ResponseOrder responseOrder = new ResponseOrder(fetchOrderDto); + + return ResponseEntity.ok(Result.createSuccessResult(responseOrder)); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ResponseOrder{ + private Long storeId; + private List<_OrderItemDto> _orderItemDtos; + private Long totalPrice; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class _OrderItemDto { + private Long itemId; + private List itemOptionIds; + private Long price; + + public _OrderItemDto(OrderItemDto orderItemDto) { + + this.itemId = orderItemDto.getItemId(); + this.itemOptionIds = orderItemDto.getOrderItemOptionDtoList() + .stream() + .map(OrderItemOptionDto::getId) + .collect(Collectors.toList()); + this.price = orderItemDto.getPrice(); + } + } + + public ResponseOrder(FetchOrderDto fetchOrderDto){ + this.storeId = fetchOrderDto.getStoreId(); + this._orderItemDtos = fetchOrderDto.getOrderItemDtoList().stream() + .map(_OrderItemDto::new) + .collect(Collectors.toList()); + this.totalPrice = fetchOrderDto.getOrderPrice(); + + } + + } + + @PostMapping("/orders") + public ResponseEntity saveOrder(@RequestHeader(value = "user-id") String userId){ + orderService.saveOrder(Long.parseLong(userId)); + + return ResponseEntity.status(HttpStatus.CREATED).body(Result.createSuccessResult(null)); + } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/orderItem/dto/OrderItemDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/orderItem/dto/OrderItemDto.java index ca3969d..3953476 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/orderItem/dto/OrderItemDto.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/orderItem/dto/OrderItemDto.java @@ -42,15 +42,13 @@ public class OrderItemDto { .build(); } - public static OrderItemDto of(Long id, Long itemId, Long price, Long count, List itemOptionIds) { + public static OrderItemDto of(Long id, Long itemId, Long price, Long count, List orderItemOptions) { OrderItemDto orderItemDto = new OrderItemDto(); orderItemDto.id = id; orderItemDto.itemId = itemId; orderItemDto.price = price; orderItemDto.count = count; - orderItemDto.orderItemOptionDtoList = itemOptionIds.stream() - .map(OrderItemOptionDto::new) - .collect(Collectors.toList()); + orderItemDto.orderItemOptionDtoList = orderItemOptions; return orderItemDto; } diff --git a/order-service/src/main/resources/application.yml b/order-service/src/main/resources/application.yml index cf21c99..e85d530 100644 --- a/order-service/src/main/resources/application.yml +++ b/order-service/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 0 + port: 54329 spring: application: From 5d737a1127013b6e760f5afc5dba863c1ce346fc Mon Sep 17 00:00:00 2001 From: hoon7566 Date: Wed, 9 Mar 2022 16:59:09 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat(order-service):=20=EC=A3=BC=EB=AC=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 주문 기능 추가 --- customer-vue/src/api/store.js | 26 +----- customer-vue/src/router/router.js | 2 +- customer-vue/src/views/ItemDetail.vue | 15 ++-- customer-vue/src/views/OrderPage.vue | 8 +- order-service/build.gradle | 3 + order-service/src/docs/asciidoc/api-docs.adoc | 7 +- .../domain/order/dto/OrderDto.java | 7 +- .../domain/order/entity/Order.java | 9 +- .../order/exception/OrderException.java | 11 +++ .../order/service/OrderServiceImpl.java | 77 +++++++++++++++-- .../order/web/OrderCustomerApiController.java | 14 ++-- .../global/config/KafkaConfig.java | 42 ++++++++++ .../src/main/resources/application.yml | 6 +- .../web/OrderCustomerApiControllerTest.java | 83 ++++++++++++++++++- .../domain/item/dto/FetchItemDto.java | 46 ++++++++++ .../storeservice/domain/item/dto/ItemDto.java | 5 -- .../item/repository/ItemRepositoryCustom.java | 4 +- .../domain/item/service/ItemService.java | 4 +- .../domain/item/service/ItemServiceImpl.java | 9 +- .../item/web/ItemCustomerApiController.java | 27 +++--- .../item/web/ItemOwnerApiController.java | 19 +++-- .../domain/store/dto/StoreDto.java | 13 +++ .../item/web/ItemOwnerApiControllerTest.java | 9 +- 23 files changed, 347 insertions(+), 99 deletions(-) create mode 100644 order-service/src/main/java/com/justpickup/orderservice/domain/order/exception/OrderException.java create mode 100644 order-service/src/main/java/com/justpickup/orderservice/global/config/KafkaConfig.java create mode 100644 store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/FetchItemDto.java create mode 100644 store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/StoreDto.java diff --git a/customer-vue/src/api/store.js b/customer-vue/src/api/store.js index 22f0b11..fedeb42 100644 --- a/customer-vue/src/api/store.js +++ b/customer-vue/src/api/store.js @@ -16,33 +16,9 @@ export default { getCategoryList(){ return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category/'); }, - putCategoryList(data){ - return axios({ - method:'put', - url:process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - }, - data: data, - responseType:'json' - }) - }, - getItemById(itemId){ + fetchItem(itemId){ return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+itemId) }, - saveItem(method, itemData){ - return axios({ - method:method, - url: process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/item', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - }, - data: itemData, - responseType:'json' - }) - }, getFavoriteStore(latitude, longitude,){ const options = { params: { diff --git a/customer-vue/src/router/router.js b/customer-vue/src/router/router.js index 2737a03..9a54e2f 100644 --- a/customer-vue/src/router/router.js +++ b/customer-vue/src/router/router.js @@ -60,7 +60,7 @@ const routes = [ component: () => import('../views/LoginPage') }, { - path: "/item/:storeId/:itemId", + path: "/item/:itemId", name: 'itemDetail', component: () => import('../views/ItemDetail') }, diff --git a/customer-vue/src/views/ItemDetail.vue b/customer-vue/src/views/ItemDetail.vue index da391a2..715ee43 100644 --- a/customer-vue/src/views/ItemDetail.vue +++ b/customer-vue/src/views/ItemDetail.vue @@ -40,7 +40,7 @@ append-outer-icon="mdi-plus" prepend-icon="mdi-minus" filled - type="number" + hide-details @click:append-outer="addItemCount(1)" @click:prepend="addItemCount(-1)" /> @@ -91,7 +91,6 @@ export default { name: "ItemDetail", async beforeMount() { console.log(this.$route.params) - this.storeId = this.$route.params.storeId this.itemId = this.$route.params.itemId this.setItem.storeId = this.storeId; await this.getItemData() @@ -102,7 +101,7 @@ export default { }, otherGroup:function(){ return this.parseGroup('OTHER') - } + }, }, data: function() { return { @@ -123,12 +122,14 @@ export default { }, methods: { getItemData: async function (){ - storeApi.getItemById(this.itemId) + storeApi.fetchItem(this.itemId) .then(response=>{ console.log(response) - this.itemData = response.data.data; - this.setItem.itemId = this.itemData.id; - this.setItem.price = this.itemData.price; + this.itemData = response.data.data + this.setItem.itemId = this.itemData.id + this.setItem.price = this.itemData.price + this.storeId = this.itemData.storeId + this.setItem.storeId = this.itemData.storeId }) .catch(error=>{ console.log(error) diff --git a/customer-vue/src/views/OrderPage.vue b/customer-vue/src/views/OrderPage.vue index c5f79a3..df1c272 100644 --- a/customer-vue/src/views/OrderPage.vue +++ b/customer-vue/src/views/OrderPage.vue @@ -19,21 +19,22 @@ {{ orderItem.itemId }} + + 수량 : {{ orderItem.count }} +
{{ orderItem.itemOptionIds.join(', ')}}
- 합계 : {{ orderItem.price }} 원 + 합계 : {{ orderItem.count * orderItem.price }} 원
- - @@ -76,6 +77,7 @@ export default { itemId:Number, itemOptionIds:Array, price:Number, + count:Number, }], totalPrice:Number, diff --git a/order-service/build.gradle b/order-service/build.gradle index f4ad1b7..a692e77 100644 --- a/order-service/build.gradle +++ b/order-service/build.gradle @@ -62,6 +62,9 @@ dependencies { annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError(javax.annotation.Generated) 발생 대응 annotationProcessor "jakarta.annotation:jakarta.annotation-api" + + + } dependencyManagement { diff --git a/order-service/src/docs/asciidoc/api-docs.adoc b/order-service/src/docs/asciidoc/api-docs.adoc index 4f6fe6d..fc03fa9 100644 --- a/order-service/src/docs/asciidoc/api-docs.adoc +++ b/order-service/src/docs/asciidoc/api-docs.adoc @@ -81,4 +81,9 @@ operation::prevOrder-get-BindException[snippets='curl-request,http-request,http- == Just Pick-up === 주문 내역 페이지 -operation::api-customer-order-history[snippets='curl-request,http-request,http-response,request-headers,request-parameters,response-fields'] \ No newline at end of file +operation::api-customer-order-history[snippets='curl-request,http-request,http-response,request-headers,request-parameters,response-fields'] + + + + +operation::add-item-to-basket[snippets='curl-request,http-request,http-response,request-headers,request-body,request-fields'] \ No newline at end of file diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java index 4574286..45545ee 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/OrderDto.java @@ -1,5 +1,7 @@ package com.justpickup.orderservice.domain.order.dto; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.justpickup.orderservice.domain.order.entity.Order; import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; @@ -7,12 +9,14 @@ import com.justpickup.orderservice.domain.orderItem.entity.OrderItem; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; -@Getter @NoArgsConstructor +@Getter @Setter +@NoArgsConstructor public class OrderDto { private Long id; @@ -26,6 +30,7 @@ public class OrderDto { private Long storeId; + @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime orderTime; private Long usedPoint; diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java index 94c114d..aa4d9a6 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/entity/Order.java @@ -75,7 +75,7 @@ public class Order extends BaseEntity { order.addOrderItem(orderItem); order.usedPoint = 0L; - order.orderStatus = OrderStatus.PLACED; + order.orderStatus = OrderStatus.PENDING; order.orderTime = LocalDateTime.now(); return order; } @@ -87,8 +87,13 @@ public class Order extends BaseEntity { public Order addOrderItem(OrderItem orderItem) { this.orderItems.add(orderItem); - this.orderPrice += orderItem.getPrice(); + this.orderPrice += (orderItem.getPrice()*orderItem.getCount()); orderItem.setOrder(this); return this; } + + public Order setOrderStatus(OrderStatus orderStatus){ + this.orderStatus = orderStatus; + return this; + } } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/exception/OrderException.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/exception/OrderException.java new file mode 100644 index 0000000..e03112f --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/exception/OrderException.java @@ -0,0 +1,11 @@ +package com.justpickup.orderservice.domain.order.exception; + +import com.justpickup.orderservice.global.exception.CustomException; +import org.springframework.http.HttpStatus; + +public class OrderException extends CustomException { + + public OrderException(String message) { + super(HttpStatus.CONFLICT, message); + } +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java index 5f969bf..4e847cd 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java @@ -1,11 +1,17 @@ package com.justpickup.orderservice.domain.order.service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.entity.Order; import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.order.exception.OrderException; import com.justpickup.orderservice.domain.order.repository.OrderRepository; import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; @@ -17,15 +23,17 @@ import com.justpickup.orderservice.global.client.store.GetItemResponse; import com.justpickup.orderservice.global.client.store.StoreClient; import com.justpickup.orderservice.global.client.user.GetCustomerResponse; import com.justpickup.orderservice.global.client.user.UserClient; -import lombok.RequiredArgsConstructor; +import lombok.*; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; import org.springframework.data.support.PageableExecutionUtils; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -42,6 +50,7 @@ public class OrderServiceImpl implements OrderService { private final OrderRepositoryCustom orderRepositoryCustom; private final StoreClient storeClient; private final UserClient userClient; + private final KafkaTemplate kafkaTemplate; @Override public List findOrderMain(OrderSearchCondition condition, Long storeId) { @@ -124,22 +133,80 @@ public class OrderServiceImpl implements OrderService { if(optionalOrder.isPresent()){ if(optionalOrder.get().addOrderItem(orderItem) .getStoreId().equals(storeId)) - throw new RuntimeException("장바구니에 여러 카페의 메뉴를 담을수 없습니다."); + throw new OrderException("장바구니에 여러 카페의 메뉴를 담을수 없습니다."); }else{ - orderRepository.save(Order.of(userId,userCouponId,storeId,orderItemDto.getPrice(),orderItem)); + orderRepository.save(Order.of(userId,userCouponId,storeId,0L,orderItem)); } } @Override public FetchOrderDto fetchOrder(Long userId) { Order order = orderRepositoryCustom.fetchOrder(userId) - .orElseThrow(RuntimeException::new); + .orElseThrow(() -> new OrderException("장바구니 정보를 찾을 수 없습니다.")); return new FetchOrderDto(order); } @Override + @Transactional public void saveOrder(Long userId) { - + Order order = orderRepository.findByUserIdAndOrderStatus(userId, OrderStatus.PENDING) + .orElseThrow(() -> new OrderException("장바구니 정보를 찾을 수 없습니다.")) + .setOrderStatus(OrderStatus.PLACED); + try{ + send("orderPlaced",KafkaSendOrderDto.createPrimitiveField(order)); + }catch (Exception ex){ + throw new OrderException(ex.getMessage()); + } } + + + public void send(String topic, KafkaSendOrderDto kafkaSendOrderDto) throws Exception{ + ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); + String jsonInString = mapper.writeValueAsString(kafkaSendOrderDto); + kafkaTemplate.send(topic, jsonInString); + log.info("kafka Producer sent data from the Order microservice: "+ kafkaSendOrderDto); + } + + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + static class KafkaSendOrderDto{ + private Long id; + + private Long userId; + + private String userName; + + private Long userCouponId; + + private Long orderPrice; + + private Long storeId; + +// @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime orderTime; + + private Long usedPoint; + + private OrderStatus orderStatus; + + private List orderItemDtoList; + + // == 생성 메소드 == // + public static KafkaSendOrderDto createPrimitiveField(Order order) { + return KafkaSendOrderDto.builder() + .id(order.getId()) + .userId(order.getUserId()) + .userCouponId(order.getUserCouponId()) + .orderPrice(order.getOrderPrice()) + .orderTime(order.getOrderTime()) + .storeId(order.getStoreId()) + .usedPoint(order.getUsedPoint()) + .orderStatus(order.getOrderStatus()) + .build(); + } + } + } diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java index 3ce6811..9e6695f 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiController.java @@ -98,7 +98,7 @@ public class OrderCustomerApiController { public ResponseEntity addItemToBasket( @RequestBody RequestItem requestItem, @RequestHeader(value = "user-id") String userId){ OrderItemDto orderItemDto = OrderItemDto.of(-1L, - requestItem.itemId, + requestItem.getItemId(), requestItem.getPrice(), requestItem.getCount(), requestItem.getItemOptionIds().stream().map(OrderItemOptionDto::new).collect(Collectors.toList())); @@ -120,17 +120,17 @@ public class OrderCustomerApiController { } @GetMapping("/orders") - public ResponseEntity getOrder(@RequestHeader(value = "user-id") String userId){ + public ResponseEntity fetchOrder(@RequestHeader(value = "user-id") String userId){ FetchOrderDto fetchOrderDto = orderService.fetchOrder(Long.parseLong(userId)); - ResponseOrder responseOrder = new ResponseOrder(fetchOrderDto); + FetchOrderResponse fetchOrderResponse = new FetchOrderResponse(fetchOrderDto); - return ResponseEntity.ok(Result.createSuccessResult(responseOrder)); + return ResponseEntity.ok(Result.createSuccessResult(fetchOrderResponse)); } @Data @NoArgsConstructor @AllArgsConstructor - public static class ResponseOrder{ + public static class FetchOrderResponse { private Long storeId; private List<_OrderItemDto> _orderItemDtos; private Long totalPrice; @@ -142,6 +142,7 @@ public class OrderCustomerApiController { private Long itemId; private List itemOptionIds; private Long price; + private Long count; public _OrderItemDto(OrderItemDto orderItemDto) { @@ -151,10 +152,11 @@ public class OrderCustomerApiController { .map(OrderItemOptionDto::getId) .collect(Collectors.toList()); this.price = orderItemDto.getPrice(); + this.count = orderItemDto.getCount(); } } - public ResponseOrder(FetchOrderDto fetchOrderDto){ + public FetchOrderResponse(FetchOrderDto fetchOrderDto){ this.storeId = fetchOrderDto.getStoreId(); this._orderItemDtos = fetchOrderDto.getOrderItemDtoList().stream() .map(_OrderItemDto::new) diff --git a/order-service/src/main/java/com/justpickup/orderservice/global/config/KafkaConfig.java b/order-service/src/main/java/com/justpickup/orderservice/global/config/KafkaConfig.java new file mode 100644 index 0000000..f090c97 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/global/config/KafkaConfig.java @@ -0,0 +1,42 @@ +package com.justpickup.orderservice.global.config; + +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; + +import java.util.HashMap; +import java.util.Map; + +@EnableKafka +@Configuration +public class KafkaConfig { + + public KafkaConfig(@Value("${kafka.host}") String kafkaServerHost, + @Value("${kafka.port}")String kafkaServerPort) { + this.kafkaServerHost = kafkaServerHost; + this.kafkaServerPort = kafkaServerPort; + } + private final String kafkaServerHost; + private final String kafkaServerPort; + + @Bean + public ProducerFactory producerFactory(){ + Map properties = new HashMap<>(); + properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServerHost+":"+kafkaServerPort); + properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + + return new DefaultKafkaProducerFactory<>(properties); + } + + @Bean + public KafkaTemplate kafkaTemplate(){ + return new KafkaTemplate<>(producerFactory()); + } +} diff --git a/order-service/src/main/resources/application.yml b/order-service/src/main/resources/application.yml index e85d530..3a554d1 100644 --- a/order-service/src/main/resources/application.yml +++ b/order-service/src/main/resources/application.yml @@ -36,4 +36,8 @@ logging: # jpa query, parameter 로그 (p6spy) decorator.datasource.p6spy: - enable-logging: true \ No newline at end of file + enable-logging: true + +kafka: + host: 127.0.0.1 + port: 9092 \ No newline at end of file diff --git a/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java b/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java index 5447e18..eed18ce 100644 --- a/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java +++ b/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java @@ -2,13 +2,16 @@ package com.justpickup.orderservice.domain.order.web; import com.fasterxml.jackson.databind.ObjectMapper; import com.justpickup.orderservice.config.TestConfig; +import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.repository.OrderRepository; import com.justpickup.orderservice.domain.order.service.OrderService; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; +import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -17,20 +20,23 @@ import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; 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.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -117,4 +123,77 @@ class OrderCustomerApiControllerTest { return new SliceImpl<>(contents, pageable, true); } + + @Test + @DisplayName("장바구니 아이템 추가_성공") + void addItemToBasket() throws Exception { + //Given + OrderCustomerApiController.RequestItem requestItem; +// OrderItemDto orderItemDto; +// FetchOrderDto fetchOrderDto; + { + //givenData + requestItem = new OrderCustomerApiController.RequestItem( + 102L, 1L, 3000L, 4L, List.of(1L, 2L, 3L, 4L, 5L) + ); + +// orderItemDto = OrderItemDto.of(-1L, +// requestItem.getItemId(), +// requestItem.getPrice(), +// requestItem.getCount(), +// requestItem.getItemOptionIds().stream().map(OrderItemOptionDto::new).collect(Collectors.toList())); + + //willReturn data + + } + //When + String body = objectMapper.writeValueAsString(requestItem); + + ResultActions actions = mockMvc.perform(post(url + "/item") + .header("user-id", "2") + .content(body) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ); + + //Then + + actions.andExpect(status().isNoContent()) + .andDo(print()) + .andDo(document("add-item-to-basket", + requestHeaders(headerWithName("user-id").description("유저 고유번호")), + requestFields( + fieldWithPath("itemId").description("아이템 고유번호"), + fieldWithPath("storeId").description("매장 고유번호"), + fieldWithPath("price").description("아이템 가격"), + fieldWithPath("count").description("아이템 갯수"), + fieldWithPath("itemOptionIds").description("아이템 옵션들") + ) + )); + } + + @Test + @DisplayName("장바구니 정보 조회_성공") + void fetchOrder() throws Exception{ + //Given + + //When + + //Then + + } + + @Test + @DisplayName("주문 및 mq produce_성공") + void saveOrder() throws Exception{ + //Given + + //When + + //Then + + } + + + } \ No newline at end of file diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/FetchItemDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/FetchItemDto.java new file mode 100644 index 0000000..cf2fc09 --- /dev/null +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/FetchItemDto.java @@ -0,0 +1,46 @@ +package com.justpickup.storeservice.domain.item.dto; + +import com.justpickup.storeservice.domain.category.dto.CategoryDto; +import com.justpickup.storeservice.domain.item.entity.Item; +import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; +import com.justpickup.storeservice.domain.store.dto.StoreDto; +import com.justpickup.storeservice.global.entity.Yn; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FetchItemDto { + + private Long id; + + private String name; + + private Yn salesYn; + + private Long price; + + private CategoryDto categoryDto; + + private List itemOptions; + + private StoreDto storeDto; + + public FetchItemDto(Item item) { + this.id = item.getId(); + this.name = item.getName(); + this.salesYn = item.getSalesYn(); + this.price = item.getPrice(); + this.categoryDto = new CategoryDto(item.getCategory()); + this.itemOptions = item.getItemOptions().stream().map(ItemOptionDto::new).collect(Collectors.toList()); + this.storeDto = new StoreDto(item.getStore().getId(), item.getStore().getName()); + } + +} diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemDto.java index 6b094d2..06bdcba 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemDto.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemDto.java @@ -79,9 +79,4 @@ public class ItemDto { .build(); } - // TODO: 2022/02/03 queryDsl 쿼리 생성 시 구현 필요 -// public static ItemDto createFullItemDto(Item item) { -// return null -// } - } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepositoryCustom.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepositoryCustom.java index de29b2a..bbe3fd8 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepositoryCustom.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepositoryCustom.java @@ -3,9 +3,7 @@ package com.justpickup.storeservice.domain.item.repository; import com.justpickup.storeservice.domain.category.entity.QCategory; import com.justpickup.storeservice.domain.item.entity.Item; import com.justpickup.storeservice.domain.item.entity.QItem; -import com.justpickup.storeservice.domain.itemoption.entity.ItemOption; import com.justpickup.storeservice.domain.itemoption.entity.QItemOption; -import com.justpickup.storeservice.domain.store.entity.QStore; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -22,7 +20,7 @@ public class ItemRepositoryCustom { private final JPAQueryFactory queryFactory; - public Optional findById(Long itemId){ + public Optional fetchItem(Long itemId){ Item item = queryFactory.selectFrom(QItem.item) .join(QItem.item.itemOptions, QItemOption.itemOption).fetchJoin() .join(QItem.item.category,QCategory.category).fetchJoin() diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemService.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemService.java index c1c34c8..a59e454 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemService.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemService.java @@ -1,7 +1,7 @@ package com.justpickup.storeservice.domain.item.service; +import com.justpickup.storeservice.domain.item.dto.FetchItemDto; import com.justpickup.storeservice.domain.item.dto.ItemDto; -import com.justpickup.storeservice.domain.item.web.ItemController; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -12,7 +12,7 @@ public interface ItemService { ItemDto findItemByItemId(Long itemId); - ItemDto findFullItemByItemId(Long itemId); + FetchItemDto fetchItem(Long itemId); Page findItemList(Long storeId,String word, Pageable pageable); diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemServiceImpl.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemServiceImpl.java index f0e71c5..43823b6 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemServiceImpl.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/service/ItemServiceImpl.java @@ -2,13 +2,13 @@ package com.justpickup.storeservice.domain.item.service; import com.justpickup.storeservice.domain.category.entity.Category; import com.justpickup.storeservice.domain.category.repository.CategoryRepository; +import com.justpickup.storeservice.domain.item.dto.FetchItemDto; import com.justpickup.storeservice.domain.item.dto.ItemDto; import com.justpickup.storeservice.domain.item.entity.Item; import com.justpickup.storeservice.domain.item.exception.NotExistItemException; import com.justpickup.storeservice.domain.item.repository.ItemRepository; import com.justpickup.storeservice.domain.item.repository.ItemRepositoryCustom; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; -import com.justpickup.storeservice.domain.itemoption.entity.ItemOption; import com.justpickup.storeservice.domain.itemoption.repository.ItemOptionRepository; import com.justpickup.storeservice.domain.store.entity.Store; import com.justpickup.storeservice.domain.store.repository.StoreRepository; @@ -22,7 +22,6 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @Service @@ -48,11 +47,11 @@ public class ItemServiceImpl implements ItemService { } @Override - public ItemDto findFullItemByItemId(Long itemId) { - Item findItem = itemRepositoryCustom.findById(itemId) + public FetchItemDto fetchItem(Long itemId) { + Item findItem = itemRepositoryCustom.fetchItem(itemId) .orElseThrow(() -> new NotExistItemException("존재하지 않는 아이템 입니다.")); - return ItemDto.createWithCategoryItemDtoAndItemOption(findItem); + return new FetchItemDto(findItem); } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemCustomerApiController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemCustomerApiController.java index 2555d59..a28e6eb 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemCustomerApiController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemCustomerApiController.java @@ -1,5 +1,6 @@ package com.justpickup.storeservice.domain.item.web; +import com.justpickup.storeservice.domain.item.dto.FetchItemDto; import com.justpickup.storeservice.domain.item.dto.ItemDto; import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; @@ -7,17 +8,11 @@ import com.justpickup.storeservice.domain.itemoption.entity.OptionType; import com.justpickup.storeservice.global.dto.Result; import com.justpickup.storeservice.global.entity.Yn; import lombok.*; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @RestController @@ -30,9 +25,9 @@ public class ItemCustomerApiController { @GetMapping("/item/{itemId}") public ResponseEntity getItem(@PathVariable("itemId") Long itemId) { - ItemDto itemByItemId = itemService.findFullItemByItemId(itemId); + FetchItemDto fetchItem = itemService.fetchItem(itemId); - GetItemResponse getItemResponse = new GetItemResponse(itemByItemId); + GetItemResponse getItemResponse = new GetItemResponse(fetchItem); return ResponseEntity.status(HttpStatus.OK) .body(Result.createSuccessResult(getItemResponse)); } @@ -45,16 +40,18 @@ public class ItemCustomerApiController { private Long price; private Long CategoryId; private List itemOptions; + private Long storeId; - public GetItemResponse(ItemDto itemDto) { - this.id = itemDto.getId(); - this.name = itemDto.getName(); - this.salesYn = itemDto.getSalesYn(); - this.price = itemDto.getPrice(); - this.CategoryId = itemDto.getCategoryDto().getId(); - this.itemOptions = itemDto.getItemOptions() + public GetItemResponse(FetchItemDto fetchItemDto) { + this.id = fetchItemDto.getId(); + this.name = fetchItemDto.getName(); + this.salesYn = fetchItemDto.getSalesYn(); + this.price = fetchItemDto.getPrice(); + this.CategoryId = fetchItemDto.getCategoryDto().getId(); + this.itemOptions = fetchItemDto.getItemOptions() .stream().map(ItemOptionResponse::new) .collect(Collectors.toList()); + this.storeId = fetchItemDto.getStoreDto().getStoreId(); } @Data diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiController.java index 8da50a4..918940f 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiController.java @@ -1,5 +1,6 @@ package com.justpickup.storeservice.domain.item.web; +import com.justpickup.storeservice.domain.item.dto.FetchItemDto; import com.justpickup.storeservice.domain.item.dto.ItemDto; import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; @@ -91,9 +92,9 @@ public class ItemOwnerApiController { @GetMapping("/item/{itemId}") public ResponseEntity getItem(@PathVariable("itemId") Long itemId) { - ItemDto itemByItemId = itemService.findFullItemByItemId(itemId); + FetchItemDto fetchItemDto = itemService.fetchItem(itemId); - GetItemResponse getItemResponse = new GetItemResponse(itemByItemId); + GetItemResponse getItemResponse = new GetItemResponse(fetchItemDto); return ResponseEntity.status(HttpStatus.OK) .body(Result.createSuccessResult(getItemResponse)); } @@ -107,13 +108,13 @@ public class ItemOwnerApiController { private Long CategoryId; private List itemOptions; - public GetItemResponse(ItemDto itemDto) { - this.id = itemDto.getId(); - this.name = itemDto.getName(); - this.salesYn = itemDto.getSalesYn(); - this.price = itemDto.getPrice(); - this.CategoryId = itemDto.getCategoryDto().getId(); - this.itemOptions = itemDto.getItemOptions() + public GetItemResponse(FetchItemDto fetchItemDto) { + this.id = fetchItemDto.getId(); + this.name = fetchItemDto.getName(); + this.salesYn = fetchItemDto.getSalesYn(); + this.price = fetchItemDto.getPrice(); + this.CategoryId = fetchItemDto.getCategoryDto().getId(); + this.itemOptions = fetchItemDto.getItemOptions() .stream().map(ItemOptionResponse::new) .collect(Collectors.toList()); } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/StoreDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/StoreDto.java new file mode 100644 index 0000000..fcc49b7 --- /dev/null +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/store/dto/StoreDto.java @@ -0,0 +1,13 @@ +package com.justpickup.storeservice.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StoreDto { + private Long storeId; + private String storeName; +} diff --git a/store-service/src/test/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiControllerTest.java b/store-service/src/test/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiControllerTest.java index b999e7a..0b4a5e7 100644 --- a/store-service/src/test/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiControllerTest.java +++ b/store-service/src/test/java/com/justpickup/storeservice/domain/item/web/ItemOwnerApiControllerTest.java @@ -4,8 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.justpickup.storeservice.config.TestConfig; import com.justpickup.storeservice.domain.category.dto.CategoryDto; import com.justpickup.storeservice.domain.favoritestore.repository.FavoriteStoreRepository; +import com.justpickup.storeservice.domain.item.dto.FetchItemDto; import com.justpickup.storeservice.domain.item.dto.ItemDto; -import com.justpickup.storeservice.domain.item.exception.NotExistItemException; import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.itemoption.entity.OptionType; import com.justpickup.storeservice.domain.store.repository.StoreRepository; @@ -21,15 +21,12 @@ import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; -import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.function.LongSupplier; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -124,7 +121,7 @@ class ItemOwnerApiControllerTest { void getItem() throws Exception { // GIVEN long itemId = 1L; - ItemDto willReturnDto = ItemDto.builder() + FetchItemDto willReturnDto = FetchItemDto.builder() .id(1L) .salesYn(Yn.Y) .price(1500L) @@ -132,7 +129,7 @@ class ItemOwnerApiControllerTest { .itemOptions(new ArrayList<>()) .categoryDto(new CategoryDto()) .build(); - given(itemService.findFullItemByItemId(itemId)) + given(itemService.fetchItem(itemId)) .willReturn(willReturnDto); // WHEN From 58990c759cad249d3debb08e5c3533df9d45d7ef Mon Sep 17 00:00:00 2001 From: hoon7566 Date: Thu, 10 Mar 2022 14:14:28 +0900 Subject: [PATCH 4/4] =?UTF-8?q?test(order-service):=20kafka=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C,?= =?UTF-8?q?=20order=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kafka 전송 테스트 코드 - order 테스트 코드 작성 --- order-service/src/docs/asciidoc/api-docs.adoc | 8 +- .../domain/order/dto/FetchOrderDto.java | 15 +-- .../domain/order/service/OrderSender.java | 69 ++++++++++++ .../order/service/OrderServiceImpl.java | 59 +--------- .../domain/order/service/OrderSenderTest.java | 105 ++++++++++++++++++ .../web/OrderCustomerApiControllerTest.java | 38 ++++++- 6 files changed, 223 insertions(+), 71 deletions(-) create mode 100644 order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderSender.java create mode 100644 order-service/src/test/java/com/justpickup/orderservice/domain/order/service/OrderSenderTest.java diff --git a/order-service/src/docs/asciidoc/api-docs.adoc b/order-service/src/docs/asciidoc/api-docs.adoc index fc03fa9..1814c35 100644 --- a/order-service/src/docs/asciidoc/api-docs.adoc +++ b/order-service/src/docs/asciidoc/api-docs.adoc @@ -83,7 +83,11 @@ operation::prevOrder-get-BindException[snippets='curl-request,http-request,http- === 주문 내역 페이지 operation::api-customer-order-history[snippets='curl-request,http-request,http-response,request-headers,request-parameters,response-fields'] +=== 장바구니 상품 추가 +operation::add-item-to-basket[snippets='curl-request,http-request,http-response,request-headers,request-body,request-fields'] +=== 장바구니 내역 가져오기 +operation::fetch-order[snippets='curl-request,http-request,http-response,request-headers,response-fields'] - -operation::add-item-to-basket[snippets='curl-request,http-request,http-response,request-headers,request-body,request-fields'] \ No newline at end of file +=== 주문하기 +operation::save-order[snippets='curl-request,http-request,http-response,request-headers'] \ No newline at end of file diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java index e002ef8..70f42de 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/dto/FetchOrderDto.java @@ -1,38 +1,27 @@ package com.justpickup.orderservice.domain.order.dto; import com.justpickup.orderservice.domain.order.entity.Order; -import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; -import com.justpickup.orderservice.domain.orderItem.entity.OrderItem; import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @Getter @NoArgsConstructor +@AllArgsConstructor public class FetchOrderDto { private Long id; private Long userId; - private String userName; - - private Long userCouponId; - private Long orderPrice; private Long storeId; - private LocalDateTime orderTime; - - private Long usedPoint; - - private OrderStatus orderStatus; - private List orderItemDtoList; diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderSender.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderSender.java new file mode 100644 index 0000000..cba4a71 --- /dev/null +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderSender.java @@ -0,0 +1,69 @@ +package com.justpickup.orderservice.domain.order.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.justpickup.orderservice.domain.order.entity.Order; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; +import lombok.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +@Slf4j +@RequiredArgsConstructor +public class OrderSender { + + private final KafkaTemplate kafkaTemplate; + + public void orderPlaced( KafkaSendOrderDto kafkaSendOrderDto) throws Exception{ + ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); + String jsonInString = mapper.writeValueAsString(kafkaSendOrderDto); + kafkaTemplate.send("orderPlaced", jsonInString); + log.info("kafka Producer sent data from the Order microservice: "+ kafkaSendOrderDto); + } + + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + static class KafkaSendOrderDto{ + private Long id; + + private Long userId; + + private String userName; + + private Long userCouponId; + + private Long orderPrice; + + private Long storeId; + + private LocalDateTime orderTime; + + private Long usedPoint; + + private OrderStatus orderStatus; + + private List orderItemDtoList; + + // == 생성 메소드 == // + public static KafkaSendOrderDto createPrimitiveField(Order order) { + return KafkaSendOrderDto.builder() + .id(order.getId()) + .userId(order.getUserId()) + .userCouponId(order.getUserCouponId()) + .orderPrice(order.getOrderPrice()) + .orderTime(order.getOrderTime()) + .storeId(order.getStoreId()) + .usedPoint(order.getUsedPoint()) + .orderStatus(order.getOrderStatus()) + .build(); + } + } +} diff --git a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java index 4e847cd..b2e8b22 100644 --- a/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java +++ b/order-service/src/main/java/com/justpickup/orderservice/domain/order/service/OrderServiceImpl.java @@ -1,10 +1,5 @@ package com.justpickup.orderservice.domain.order.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.justpickup.orderservice.domain.order.dto.FetchOrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; @@ -29,11 +24,9 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.SliceImpl; import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -50,7 +43,9 @@ public class OrderServiceImpl implements OrderService { private final OrderRepositoryCustom orderRepositoryCustom; private final StoreClient storeClient; private final UserClient userClient; - private final KafkaTemplate kafkaTemplate; + private final OrderSender orderSender; + + @Override public List findOrderMain(OrderSearchCondition condition, Long storeId) { @@ -154,59 +149,13 @@ public class OrderServiceImpl implements OrderService { .orElseThrow(() -> new OrderException("장바구니 정보를 찾을 수 없습니다.")) .setOrderStatus(OrderStatus.PLACED); try{ - send("orderPlaced",KafkaSendOrderDto.createPrimitiveField(order)); + orderSender.orderPlaced(OrderSender.KafkaSendOrderDto.createPrimitiveField(order)); }catch (Exception ex){ throw new OrderException(ex.getMessage()); } } - public void send(String topic, KafkaSendOrderDto kafkaSendOrderDto) throws Exception{ - ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); - String jsonInString = mapper.writeValueAsString(kafkaSendOrderDto); - kafkaTemplate.send(topic, jsonInString); - log.info("kafka Producer sent data from the Order microservice: "+ kafkaSendOrderDto); - } - @NoArgsConstructor - @Data - @AllArgsConstructor - @Builder - static class KafkaSendOrderDto{ - private Long id; - - private Long userId; - - private String userName; - - private Long userCouponId; - - private Long orderPrice; - - private Long storeId; - -// @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime orderTime; - - private Long usedPoint; - - private OrderStatus orderStatus; - - private List orderItemDtoList; - - // == 생성 메소드 == // - public static KafkaSendOrderDto createPrimitiveField(Order order) { - return KafkaSendOrderDto.builder() - .id(order.getId()) - .userId(order.getUserId()) - .userCouponId(order.getUserCouponId()) - .orderPrice(order.getOrderPrice()) - .orderTime(order.getOrderTime()) - .storeId(order.getStoreId()) - .usedPoint(order.getUsedPoint()) - .orderStatus(order.getOrderStatus()) - .build(); - } - } } diff --git a/order-service/src/test/java/com/justpickup/orderservice/domain/order/service/OrderSenderTest.java b/order-service/src/test/java/com/justpickup/orderservice/domain/order/service/OrderSenderTest.java new file mode 100644 index 0000000..1358d03 --- /dev/null +++ b/order-service/src/test/java/com/justpickup/orderservice/domain/order/service/OrderSenderTest.java @@ -0,0 +1,105 @@ +package com.justpickup.orderservice.domain.order.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.justpickup.orderservice.domain.order.entity.OrderStatus; +import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; +import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.support.SendResult; +import org.springframework.kafka.test.EmbeddedKafkaBroker; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.kafka.test.utils.KafkaTestUtils; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.util.concurrent.ListenableFuture; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@EnableKafka +@DirtiesContext +@EmbeddedKafka(topics = {"orderPlaced"}) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class OrderSenderTest { + + private final String TEST_TOPIC = "orderPlaced"; + + private Consumer consumer; + private KafkaTemplate producer; + + @Autowired + private EmbeddedKafkaBroker embeddedKafkaBroker; + + + @BeforeEach + void setup() { + System.out.println("beforeAll"); + producer = configureProducer(); + consumer = configureConsumer(); + + + } + + private Consumer configureConsumer() { + Map consumerProps = KafkaTestUtils.consumerProps("testGroup", "true", embeddedKafkaBroker); + consumerProps.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + Consumer consumer = new DefaultKafkaConsumerFactory(consumerProps) + .createConsumer(); + consumer.subscribe(Collections.singleton(TEST_TOPIC)); + return consumer; + } + + + private KafkaTemplate configureProducer() { + Map producerProps = new HashMap<>(KafkaTestUtils.producerProps(embeddedKafkaBroker)); + return new KafkaTemplate <>( new DefaultKafkaProducerFactory<>(producerProps)); + } + + + + @Test + void sendOrderPlaced() throws Exception{ + //given + ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); + OrderSender.KafkaSendOrderDto kafkaSendOrderDto = new OrderSender.KafkaSendOrderDto( + 1L,2L,"주문아이디",1L,12000L,2L, LocalDateTime.now(),3000L, OrderStatus.PLACED, + List.of( + OrderItemDto.of(1L,300L,3000L,2L, + List.of(new OrderItemOptionDto(2L) + ,new OrderItemOptionDto(3L)) + ) + ) + ); + String jsonInString = mapper.writeValueAsString(kafkaSendOrderDto); + + //when + ListenableFuture> orderPlaced = producer.send("orderPlaced", jsonInString); + System.out.println(orderPlaced.get().toString()); + //then + + ConsumerRecord singleRecord = KafkaTestUtils.getSingleRecord(consumer, TEST_TOPIC); + assertThat(singleRecord).isNotNull(); + assertThat(singleRecord.value()).isEqualTo(jsonInString); + + } + + +} \ No newline at end of file diff --git a/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java b/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java index eed18ce..d05625a 100644 --- a/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java +++ b/order-service/src/test/java/com/justpickup/orderservice/domain/order/web/OrderCustomerApiControllerTest.java @@ -176,10 +176,39 @@ class OrderCustomerApiControllerTest { @DisplayName("장바구니 정보 조회_성공") void fetchOrder() throws Exception{ //Given + FetchOrderDto fetchOrderDto = + new FetchOrderDto(2L,2L,12000L,2L + ,List.of( + OrderItemDto.of(1L,300L,3000L,2L, + List.of(new OrderItemOptionDto(2L) + ,new OrderItemOptionDto(3L)) + ) + ) + ); + given(orderService.fetchOrder(2L)).willReturn(fetchOrderDto); //When + ResultActions actions = mockMvc.perform(get(url + "/orders") + .header("user-id", "2") + ); + //Then + actions.andExpect(status().isOk()) + .andDo(print()) + .andDo(document("fetch-order", + requestHeaders(headerWithName("user-id").description("유저 고유번호")), + responseFields( + fieldWithPath("code").description("결과 코드 SUCCESS/ERROR"), + fieldWithPath("message").description("메시지"), + fieldWithPath("data.storeId").description("매장 고유번호"), + fieldWithPath("data.totalPrice").description("총 합계"), + fieldWithPath("data._orderItemDtos[*].itemId").description("상품 고유번호"), + fieldWithPath("data._orderItemDtos[*].price").description("상품 가격"), + fieldWithPath("data._orderItemDtos[*].count").description("상품 갯수"), + fieldWithPath("data._orderItemDtos[*].itemOptionIds[*]").description("아이템 옵션들") + ))); + } @@ -189,8 +218,15 @@ class OrderCustomerApiControllerTest { //Given //When - + ResultActions actions = mockMvc.perform(post(url + "/orders") + .header("user-id", "2") + ); //Then + actions.andExpect(status().isCreated()) + .andDo(print()) + .andDo(document("save-order", + requestHeaders(headerWithName("user-id").description("유저 고유번호")) + )); }