feat(order-service): 주문

- 주문 기능 추가
This commit is contained in:
hoon7566
2022-03-09 16:59:09 +09:00
parent 7cfc4bc47f
commit 5d737a1127
23 changed files with 347 additions and 99 deletions

View File

@@ -16,33 +16,9 @@ export default {
getCategoryList(){ getCategoryList(){
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category/'); return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/category/');
}, },
putCategoryList(data){ fetchItem(itemId){
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){
return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+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,){ getFavoriteStore(latitude, longitude,){
const options = { const options = {
params: { params: {

View File

@@ -60,7 +60,7 @@ const routes = [
component: () => import('../views/LoginPage') component: () => import('../views/LoginPage')
}, },
{ {
path: "/item/:storeId/:itemId", path: "/item/:itemId",
name: 'itemDetail', name: 'itemDetail',
component: () => import('../views/ItemDetail') component: () => import('../views/ItemDetail')
}, },

View File

@@ -40,7 +40,7 @@
append-outer-icon="mdi-plus" append-outer-icon="mdi-plus"
prepend-icon="mdi-minus" prepend-icon="mdi-minus"
filled filled
type="number" hide-details
@click:append-outer="addItemCount(1)" @click:append-outer="addItemCount(1)"
@click:prepend="addItemCount(-1)" @click:prepend="addItemCount(-1)"
/> />
@@ -91,7 +91,6 @@ export default {
name: "ItemDetail", name: "ItemDetail",
async beforeMount() { async beforeMount() {
console.log(this.$route.params) console.log(this.$route.params)
this.storeId = this.$route.params.storeId
this.itemId = this.$route.params.itemId this.itemId = this.$route.params.itemId
this.setItem.storeId = this.storeId; this.setItem.storeId = this.storeId;
await this.getItemData() await this.getItemData()
@@ -102,7 +101,7 @@ export default {
}, },
otherGroup:function(){ otherGroup:function(){
return this.parseGroup('OTHER') return this.parseGroup('OTHER')
} },
}, },
data: function() { data: function() {
return { return {
@@ -123,12 +122,14 @@ export default {
}, },
methods: { methods: {
getItemData: async function (){ getItemData: async function (){
storeApi.getItemById(this.itemId) storeApi.fetchItem(this.itemId)
.then(response=>{ .then(response=>{
console.log(response) console.log(response)
this.itemData = response.data.data; this.itemData = response.data.data
this.setItem.itemId = this.itemData.id; this.setItem.itemId = this.itemData.id
this.setItem.price = this.itemData.price; this.setItem.price = this.itemData.price
this.storeId = this.itemData.storeId
this.setItem.storeId = this.itemData.storeId
}) })
.catch(error=>{ .catch(error=>{
console.log(error) console.log(error)

View File

@@ -19,21 +19,22 @@
<v-list-item-title class="text-h5 mb-3"> <v-list-item-title class="text-h5 mb-3">
{{ orderItem.itemId }} {{ orderItem.itemId }}
</v-list-item-title> </v-list-item-title>
<v-list-item-subtitle class="mb-5">
수량 : {{ orderItem.count }}
</v-list-item-subtitle>
<div class="text-body-1 mb-5"> <div class="text-body-1 mb-5">
{{ orderItem.itemOptionIds.join(', ')}} {{ orderItem.itemOptionIds.join(', ')}}
</div> </div>
<div class="text--primary"> <div class="text--primary">
합계 : <b> {{ orderItem.price }} </b> 합계 : <b> {{ orderItem.count * orderItem.price }} </b>
</div> </div>
</v-list-item-content> </v-list-item-content>
<v-list-item-avatar <v-list-item-avatar
tile tile
size="100" size="100"
> >
<v-img :src="require('@/assets/store.jpeg')"></v-img> <v-img :src="require('@/assets/store.jpeg')"></v-img>
</v-list-item-avatar> </v-list-item-avatar>
</v-list-item> </v-list-item>
<v-card-actions class="pb-2"> <v-card-actions class="pb-2">
@@ -76,6 +77,7 @@ export default {
itemId:Number, itemId:Number,
itemOptionIds:Array, itemOptionIds:Array,
price:Number, price:Number,
count:Number,
}], }],
totalPrice:Number, totalPrice:Number,

View File

@@ -62,6 +62,9 @@ dependencies {
annotationProcessor "jakarta.persistence:jakarta.persistence-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// java.lang.NoClassDefFoundError(javax.annotation.Generated) 발생 대응 // java.lang.NoClassDefFoundError(javax.annotation.Generated) 발생 대응
annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.annotation:jakarta.annotation-api"
} }
dependencyManagement { dependencyManagement {

View File

@@ -81,4 +81,9 @@ operation::prevOrder-get-BindException[snippets='curl-request,http-request,http-
== Just Pick-up == Just Pick-up
=== 주문 내역 페이지 === 주문 내역 페이지
operation::api-customer-order-history[snippets='curl-request,http-request,http-response,request-headers,request-parameters,response-fields'] 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']

View File

@@ -1,5 +1,7 @@
package com.justpickup.orderservice.domain.order.dto; 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.Order;
import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.entity.OrderStatus;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; 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.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter @NoArgsConstructor @Getter @Setter
@NoArgsConstructor
public class OrderDto { public class OrderDto {
private Long id; private Long id;
@@ -26,6 +30,7 @@ public class OrderDto {
private Long storeId; private Long storeId;
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime orderTime; private LocalDateTime orderTime;
private Long usedPoint; private Long usedPoint;

View File

@@ -75,7 +75,7 @@ public class Order extends BaseEntity {
order.addOrderItem(orderItem); order.addOrderItem(orderItem);
order.usedPoint = 0L; order.usedPoint = 0L;
order.orderStatus = OrderStatus.PLACED; order.orderStatus = OrderStatus.PENDING;
order.orderTime = LocalDateTime.now(); order.orderTime = LocalDateTime.now();
return order; return order;
} }
@@ -87,8 +87,13 @@ public class Order extends BaseEntity {
public Order addOrderItem(OrderItem orderItem) { public Order addOrderItem(OrderItem orderItem) {
this.orderItems.add(orderItem); this.orderItems.add(orderItem);
this.orderPrice += orderItem.getPrice(); this.orderPrice += (orderItem.getPrice()*orderItem.getCount());
orderItem.setOrder(this); orderItem.setOrder(this);
return this; return this;
} }
public Order setOrderStatus(OrderStatus orderStatus){
this.orderStatus = orderStatus;
return this;
}
} }

View File

@@ -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);
}
}

View File

@@ -1,11 +1,17 @@
package com.justpickup.orderservice.domain.order.service; 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.FetchOrderDto;
import com.justpickup.orderservice.domain.order.dto.OrderDto; import com.justpickup.orderservice.domain.order.dto.OrderDto;
import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition; import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition;
import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch; import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch;
import com.justpickup.orderservice.domain.order.entity.Order; import com.justpickup.orderservice.domain.order.entity.Order;
import com.justpickup.orderservice.domain.order.entity.OrderStatus; 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.OrderRepository;
import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom; import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; 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.store.StoreClient;
import com.justpickup.orderservice.global.client.user.GetCustomerResponse; import com.justpickup.orderservice.global.client.user.GetCustomerResponse;
import com.justpickup.orderservice.global.client.user.UserClient; import com.justpickup.orderservice.global.client.user.UserClient;
import lombok.RequiredArgsConstructor; import lombok.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl; import org.springframework.data.domain.SliceImpl;
import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -42,6 +50,7 @@ public class OrderServiceImpl implements OrderService {
private final OrderRepositoryCustom orderRepositoryCustom; private final OrderRepositoryCustom orderRepositoryCustom;
private final StoreClient storeClient; private final StoreClient storeClient;
private final UserClient userClient; private final UserClient userClient;
private final KafkaTemplate<String, String> kafkaTemplate;
@Override @Override
public List<OrderDto> findOrderMain(OrderSearchCondition condition, Long storeId) { public List<OrderDto> findOrderMain(OrderSearchCondition condition, Long storeId) {
@@ -124,22 +133,80 @@ public class OrderServiceImpl implements OrderService {
if(optionalOrder.isPresent()){ if(optionalOrder.isPresent()){
if(optionalOrder.get().addOrderItem(orderItem) if(optionalOrder.get().addOrderItem(orderItem)
.getStoreId().equals(storeId)) .getStoreId().equals(storeId))
throw new RuntimeException("장바구니에 여러 카페의 메뉴를 담을수 없습니다."); throw new OrderException("장바구니에 여러 카페의 메뉴를 담을수 없습니다.");
}else{ }else{
orderRepository.save(Order.of(userId,userCouponId,storeId,orderItemDto.getPrice(),orderItem)); orderRepository.save(Order.of(userId,userCouponId,storeId,0L,orderItem));
} }
} }
@Override @Override
public FetchOrderDto fetchOrder(Long userId) { public FetchOrderDto fetchOrder(Long userId) {
Order order = orderRepositoryCustom.fetchOrder(userId) Order order = orderRepositoryCustom.fetchOrder(userId)
.orElseThrow(RuntimeException::new); .orElseThrow(() -> new OrderException("장바구니 정보를 찾을 수 없습니다."));
return new FetchOrderDto(order); return new FetchOrderDto(order);
} }
@Override @Override
@Transactional
public void saveOrder(Long userId) { 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<OrderItemDto> 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();
}
}
} }

View File

@@ -98,7 +98,7 @@ public class OrderCustomerApiController {
public ResponseEntity addItemToBasket( @RequestBody RequestItem requestItem, public ResponseEntity addItemToBasket( @RequestBody RequestItem requestItem,
@RequestHeader(value = "user-id") String userId){ @RequestHeader(value = "user-id") String userId){
OrderItemDto orderItemDto = OrderItemDto.of(-1L, OrderItemDto orderItemDto = OrderItemDto.of(-1L,
requestItem.itemId, requestItem.getItemId(),
requestItem.getPrice(), requestItem.getPrice(),
requestItem.getCount(), requestItem.getCount(),
requestItem.getItemOptionIds().stream().map(OrderItemOptionDto::new).collect(Collectors.toList())); requestItem.getItemOptionIds().stream().map(OrderItemOptionDto::new).collect(Collectors.toList()));
@@ -120,17 +120,17 @@ public class OrderCustomerApiController {
} }
@GetMapping("/orders") @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)); 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 @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public static class ResponseOrder{ public static class FetchOrderResponse {
private Long storeId; private Long storeId;
private List<_OrderItemDto> _orderItemDtos; private List<_OrderItemDto> _orderItemDtos;
private Long totalPrice; private Long totalPrice;
@@ -142,6 +142,7 @@ public class OrderCustomerApiController {
private Long itemId; private Long itemId;
private List<Long> itemOptionIds; private List<Long> itemOptionIds;
private Long price; private Long price;
private Long count;
public _OrderItemDto(OrderItemDto orderItemDto) { public _OrderItemDto(OrderItemDto orderItemDto) {
@@ -151,10 +152,11 @@ public class OrderCustomerApiController {
.map(OrderItemOptionDto::getId) .map(OrderItemOptionDto::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
this.price = orderItemDto.getPrice(); this.price = orderItemDto.getPrice();
this.count = orderItemDto.getCount();
} }
} }
public ResponseOrder(FetchOrderDto fetchOrderDto){ public FetchOrderResponse(FetchOrderDto fetchOrderDto){
this.storeId = fetchOrderDto.getStoreId(); this.storeId = fetchOrderDto.getStoreId();
this._orderItemDtos = fetchOrderDto.getOrderItemDtoList().stream() this._orderItemDtos = fetchOrderDto.getOrderItemDtoList().stream()
.map(_OrderItemDto::new) .map(_OrderItemDto::new)

View File

@@ -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<String, String> producerFactory(){
Map<String, Object> 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<String, String> kafkaTemplate(){
return new KafkaTemplate<>(producerFactory());
}
}

View File

@@ -36,4 +36,8 @@ logging:
# jpa query, parameter 로그 (p6spy) # jpa query, parameter 로그 (p6spy)
decorator.datasource.p6spy: decorator.datasource.p6spy:
enable-logging: true enable-logging: true
kafka:
host: 127.0.0.1
port: 9092

View File

@@ -2,13 +2,16 @@ package com.justpickup.orderservice.domain.order.web;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.justpickup.orderservice.config.TestConfig; 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.dto.OrderDto;
import com.justpickup.orderservice.domain.order.entity.OrderStatus; import com.justpickup.orderservice.domain.order.entity.OrderStatus;
import com.justpickup.orderservice.domain.order.repository.OrderRepository; import com.justpickup.orderservice.domain.order.repository.OrderRepository;
import com.justpickup.orderservice.domain.order.service.OrderService; import com.justpickup.orderservice.domain.order.service.OrderService;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto; 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.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 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.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl; import org.springframework.data.domain.SliceImpl;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@@ -117,4 +123,77 @@ class OrderCustomerApiControllerTest {
return new SliceImpl<>(contents, pageable, true); 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
}
} }

View File

@@ -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<ItemOptionDto> 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());
}
}

View File

@@ -79,9 +79,4 @@ public class ItemDto {
.build(); .build();
} }
// TODO: 2022/02/03 queryDsl 쿼리 생성 시 구현 필요
// public static ItemDto createFullItemDto(Item item) {
// return null
// }
} }

View File

@@ -3,9 +3,7 @@ package com.justpickup.storeservice.domain.item.repository;
import com.justpickup.storeservice.domain.category.entity.QCategory; import com.justpickup.storeservice.domain.category.entity.QCategory;
import com.justpickup.storeservice.domain.item.entity.Item; import com.justpickup.storeservice.domain.item.entity.Item;
import com.justpickup.storeservice.domain.item.entity.QItem; 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.itemoption.entity.QItemOption;
import com.justpickup.storeservice.domain.store.entity.QStore;
import com.querydsl.jpa.impl.JPAQueryFactory; import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -22,7 +20,7 @@ public class ItemRepositoryCustom {
private final JPAQueryFactory queryFactory; private final JPAQueryFactory queryFactory;
public Optional<Item> findById(Long itemId){ public Optional<Item> fetchItem(Long itemId){
Item item = queryFactory.selectFrom(QItem.item) Item item = queryFactory.selectFrom(QItem.item)
.join(QItem.item.itemOptions, QItemOption.itemOption).fetchJoin() .join(QItem.item.itemOptions, QItemOption.itemOption).fetchJoin()
.join(QItem.item.category,QCategory.category).fetchJoin() .join(QItem.item.category,QCategory.category).fetchJoin()

View File

@@ -1,7 +1,7 @@
package com.justpickup.storeservice.domain.item.service; 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.dto.ItemDto;
import com.justpickup.storeservice.domain.item.web.ItemController;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -12,7 +12,7 @@ public interface ItemService {
ItemDto findItemByItemId(Long itemId); ItemDto findItemByItemId(Long itemId);
ItemDto findFullItemByItemId(Long itemId); FetchItemDto fetchItem(Long itemId);
Page<ItemDto> findItemList(Long storeId,String word, Pageable pageable); Page<ItemDto> findItemList(Long storeId,String word, Pageable pageable);

View File

@@ -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.entity.Category;
import com.justpickup.storeservice.domain.category.repository.CategoryRepository; 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.dto.ItemDto;
import com.justpickup.storeservice.domain.item.entity.Item; import com.justpickup.storeservice.domain.item.entity.Item;
import com.justpickup.storeservice.domain.item.exception.NotExistItemException; import com.justpickup.storeservice.domain.item.exception.NotExistItemException;
import com.justpickup.storeservice.domain.item.repository.ItemRepository; import com.justpickup.storeservice.domain.item.repository.ItemRepository;
import com.justpickup.storeservice.domain.item.repository.ItemRepositoryCustom; import com.justpickup.storeservice.domain.item.repository.ItemRepositoryCustom;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; 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.itemoption.repository.ItemOptionRepository;
import com.justpickup.storeservice.domain.store.entity.Store; import com.justpickup.storeservice.domain.store.entity.Store;
import com.justpickup.storeservice.domain.store.repository.StoreRepository; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@@ -48,11 +47,11 @@ public class ItemServiceImpl implements ItemService {
} }
@Override @Override
public ItemDto findFullItemByItemId(Long itemId) { public FetchItemDto fetchItem(Long itemId) {
Item findItem = itemRepositoryCustom.findById(itemId) Item findItem = itemRepositoryCustom.fetchItem(itemId)
.orElseThrow(() -> new NotExistItemException("존재하지 않는 아이템 입니다.")); .orElseThrow(() -> new NotExistItemException("존재하지 않는 아이템 입니다."));
return ItemDto.createWithCategoryItemDtoAndItemOption(findItem); return new FetchItemDto(findItem);
} }

View File

@@ -1,5 +1,6 @@
package com.justpickup.storeservice.domain.item.web; 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.dto.ItemDto;
import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.item.service.ItemService;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; 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.dto.Result;
import com.justpickup.storeservice.global.entity.Yn; import com.justpickup.storeservice.global.entity.Yn;
import lombok.*; 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.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@RestController @RestController
@@ -30,9 +25,9 @@ public class ItemCustomerApiController {
@GetMapping("/item/{itemId}") @GetMapping("/item/{itemId}")
public ResponseEntity getItem(@PathVariable("itemId") Long 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) return ResponseEntity.status(HttpStatus.OK)
.body(Result.createSuccessResult(getItemResponse)); .body(Result.createSuccessResult(getItemResponse));
} }
@@ -45,16 +40,18 @@ public class ItemCustomerApiController {
private Long price; private Long price;
private Long CategoryId; private Long CategoryId;
private List<ItemOptionResponse> itemOptions; private List<ItemOptionResponse> itemOptions;
private Long storeId;
public GetItemResponse(ItemDto itemDto) { public GetItemResponse(FetchItemDto fetchItemDto) {
this.id = itemDto.getId(); this.id = fetchItemDto.getId();
this.name = itemDto.getName(); this.name = fetchItemDto.getName();
this.salesYn = itemDto.getSalesYn(); this.salesYn = fetchItemDto.getSalesYn();
this.price = itemDto.getPrice(); this.price = fetchItemDto.getPrice();
this.CategoryId = itemDto.getCategoryDto().getId(); this.CategoryId = fetchItemDto.getCategoryDto().getId();
this.itemOptions = itemDto.getItemOptions() this.itemOptions = fetchItemDto.getItemOptions()
.stream().map(ItemOptionResponse::new) .stream().map(ItemOptionResponse::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
this.storeId = fetchItemDto.getStoreDto().getStoreId();
} }
@Data @Data

View File

@@ -1,5 +1,6 @@
package com.justpickup.storeservice.domain.item.web; 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.dto.ItemDto;
import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.item.service.ItemService;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto; import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto;
@@ -91,9 +92,9 @@ public class ItemOwnerApiController {
@GetMapping("/item/{itemId}") @GetMapping("/item/{itemId}")
public ResponseEntity getItem(@PathVariable("itemId") Long 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) return ResponseEntity.status(HttpStatus.OK)
.body(Result.createSuccessResult(getItemResponse)); .body(Result.createSuccessResult(getItemResponse));
} }
@@ -107,13 +108,13 @@ public class ItemOwnerApiController {
private Long CategoryId; private Long CategoryId;
private List<ItemOptionResponse> itemOptions; private List<ItemOptionResponse> itemOptions;
public GetItemResponse(ItemDto itemDto) { public GetItemResponse(FetchItemDto fetchItemDto) {
this.id = itemDto.getId(); this.id = fetchItemDto.getId();
this.name = itemDto.getName(); this.name = fetchItemDto.getName();
this.salesYn = itemDto.getSalesYn(); this.salesYn = fetchItemDto.getSalesYn();
this.price = itemDto.getPrice(); this.price = fetchItemDto.getPrice();
this.CategoryId = itemDto.getCategoryDto().getId(); this.CategoryId = fetchItemDto.getCategoryDto().getId();
this.itemOptions = itemDto.getItemOptions() this.itemOptions = fetchItemDto.getItemOptions()
.stream().map(ItemOptionResponse::new) .stream().map(ItemOptionResponse::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }

View File

@@ -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;
}

View File

@@ -4,8 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.justpickup.storeservice.config.TestConfig; import com.justpickup.storeservice.config.TestConfig;
import com.justpickup.storeservice.domain.category.dto.CategoryDto; import com.justpickup.storeservice.domain.category.dto.CategoryDto;
import com.justpickup.storeservice.domain.favoritestore.repository.FavoriteStoreRepository; 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.dto.ItemDto;
import com.justpickup.storeservice.domain.item.exception.NotExistItemException;
import com.justpickup.storeservice.domain.item.service.ItemService; import com.justpickup.storeservice.domain.item.service.ItemService;
import com.justpickup.storeservice.domain.itemoption.entity.OptionType; import com.justpickup.storeservice.domain.itemoption.entity.OptionType;
import com.justpickup.storeservice.domain.store.repository.StoreRepository; 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.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils; import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import javax.validation.constraints.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.LongSupplier;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@@ -124,7 +121,7 @@ class ItemOwnerApiControllerTest {
void getItem() throws Exception { void getItem() throws Exception {
// GIVEN // GIVEN
long itemId = 1L; long itemId = 1L;
ItemDto willReturnDto = ItemDto.builder() FetchItemDto willReturnDto = FetchItemDto.builder()
.id(1L) .id(1L)
.salesYn(Yn.Y) .salesYn(Yn.Y)
.price(1500L) .price(1500L)
@@ -132,7 +129,7 @@ class ItemOwnerApiControllerTest {
.itemOptions(new ArrayList<>()) .itemOptions(new ArrayList<>())
.categoryDto(new CategoryDto()) .categoryDto(new CategoryDto())
.build(); .build();
given(itemService.findFullItemByItemId(itemId)) given(itemService.fetchItem(itemId))
.willReturn(willReturnDto); .willReturn(willReturnDto);
// WHEN // WHEN