feat(order-service): order-service feign 통신

- store-service와 feign 통신 코드 작성
This commit is contained in:
hoon7566
2022-03-14 21:16:28 +09:00
parent 31675ef6d2
commit 47491f3245
19 changed files with 298 additions and 111 deletions

View File

@@ -46,7 +46,7 @@ spring:
allow-credentials: true
routes:
- id: order-service
uri: lb://ORDER-SERVCIE
uri: lb://ORDER-SERVICE
predicates:
- Path=/order-service/**
filters:
@@ -54,7 +54,7 @@ spring:
- RewritePath=/order-service/(?<segment>.*),/$\{segment}
- id: store-service
uri: lb://STORE-SERVCIE
uri: lb://STORE-SERVICE
predicates:
- Path=/store-service/**
filters:

View File

@@ -2,12 +2,12 @@
<div>
<v-row>
<v-col>
<div class="text-h4" style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{{ orderData.storeId }}</div>
<div class="text-h4" style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{{ orderData.storeName }}</div>
</v-col>
</v-row>
<v-row>
<v-col
v-for=" orderItem in orderData._orderItemDtos"
v-for=" orderItem in orderData.orderItemDtoList"
:key = "orderItem.itemId"
>
<v-card
@@ -17,13 +17,15 @@
<v-list-item three-line>
<v-list-item-content>
<v-list-item-title class="text-h5 mb-3">
{{ orderItem.itemId }}
{{ orderItem.itemName }}
</v-list-item-title>
<v-list-item-subtitle class="mb-5">
수량 : {{ orderItem.count }}
</v-list-item-subtitle>
<div class="text-body-1 mb-5">
{{ orderItem.itemOptionIds.join(', ')}}
<div class="text-body-1 mb-5" style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">
{{ orderItem.orderItemOptionDtoList ?
orderItem.orderItemOptionDtoList.map(x=>x.name).join(', ')
: null}}
</div>
<div class="text--primary">
합계 : <b> {{ orderItem.count * orderItem.price }} </b>
@@ -46,7 +48,7 @@
</v-row>
<v-row>
<v-col>
<div> 합계 : {{orderData.totalPrice}} </div>
<div> 합계 : {{orderData.orderPrice}} </div>
</v-col>
</v-row>
<v-btn
@@ -72,24 +74,17 @@ export default {
data: function(){
return {
orderData:{
storeId:Number,
_orderItemDtos:[{
itemId:Number,
itemOptionIds:Array,
price:Number,
count:Number,
}],
totalPrice:Number,
// storeName:Number,
// orderItemDtoList:[{
// name:Number,
// itemOptionIds:Array,
// price:Number,
// count:Number,
// }],
// orderPrice:Number,
},
}
},
computed:{
test:function (a){
return a;
}
},
methods:{
saveOrder: function(){
@@ -106,11 +101,13 @@ export default {
getOrder: function(){
orderApi.getOrder()
.then(response=>{
console.log(response)
this.orderData=response.data.data
})
.catch(error=>{
console.log(error)
this.$router.replace("/")
console.log(error.response)
// this.$router.replace("/")
})
},
}

View File

@@ -40,7 +40,3 @@ logging:
# jpa query, parameter 로그 (p6spy)
decorator.datasource.p6spy:
enable-logging: true
#feign key
token:
feign: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJmZWlnbiIsImV4cCI6MTE2NDY5NzY4NzAsImlhdCI6MTY0Njk3Njg3MH0.5x4Nx7oMnpF0_kZpbZsiB1u9eEbQ4IKIhJlEsa3D22cjZjvTHKz57GCz0sgXb_olhSNIVv9xF41A29-XYiFeBQ

View File

@@ -1,18 +1,15 @@
package com.justpickup.orderservice.domain.order.dto;
import com.justpickup.orderservice.domain.order.entity.Order;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto;
import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import com.justpickup.orderservice.domain.orderItem.entity.OrderItem;
import com.justpickup.orderservice.global.client.store.GetItemResponse;
import lombok.*;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FetchOrderDto {
private Long id;
@@ -20,19 +17,36 @@ public class FetchOrderDto {
private Long orderPrice;
private Long storeId;
private String storeName;
private List<OrderItemDto> orderItemDtoList;
@Getter
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class OrderItemDto{
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());
private Long id;
private Long itemId;
private String itemName;
private List<GetItemResponse.ItemOptionDto> orderItemOptionDtoList;
private Long price;
private Long count;
public OrderItemDto(GetItemResponse getItemResponse, OrderItem orderItem) {
this.id = orderItem.getId();
this.itemId = getItemResponse.getId();
this.itemName = getItemResponse.getName();
this.orderItemOptionDtoList = getItemResponse.getItemOptions();
this.price = orderItem.getPrice();
this.count = orderItem.getCount();
}
}
}

View File

@@ -16,6 +16,7 @@ import java.util.List;
@Entity
@Table(name = "orders")
@Getter
@EntityListeners(value = {OrderListener.class})
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order extends BaseEntity {
@@ -108,4 +109,8 @@ public class Order extends BaseEntity {
public void reject() {
this.orderStatus = OrderStatus.REJECT;
}
public void fail() {
this.orderStatus = OrderStatus.FAIL;
}
}

View File

@@ -1,18 +1,45 @@
package com.justpickup.orderservice.domain.order.entity;
import com.justpickup.orderservice.domain.order.exception.OrderException;
import com.justpickup.orderservice.domain.order.service.OrderSender;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PostUpdate;
@Slf4j
@NoArgsConstructor
public class OrderListener {
@Autowired
@Lazy
private OrderSender orderSender;
@PostUpdate
private void postUpdate(Order order) {
@Transactional(propagation = Propagation.REQUIRES_NEW)
void postUpdate(Order order) {
OrderStatus orderStatus = order.getOrderStatus();
if (orderStatus == OrderStatus.ORDER) {
// TODO: 2022/03/10 Kafka 알림 전송
log.info("[OrderListener] {}", OrderStatus.ORDER.name());
try{
orderSender.orderPlaced(OrderSender.KafkaSendOrderDto.createPrimitiveField(order));
}catch (Exception ex){
order.fail();
throw new OrderException(ex.getMessage());
}
} else if (orderStatus == OrderStatus.PLACED) {
log.info("[OrderListener] {}", OrderStatus.PLACED.name());
}

View File

@@ -116,55 +116,12 @@ public class OrderCustomerApiController {
private Long price;
private Long count;
private List<Long> itemOptionIds ;
}
@GetMapping("/orders")
public ResponseEntity fetchOrder(@RequestHeader(value = "user-id") String userId){
FetchOrderDto fetchOrderDto = orderService.fetchOrder(Long.parseLong(userId));
FetchOrderResponse fetchOrderResponse = new FetchOrderResponse(fetchOrderDto);
return ResponseEntity.ok(Result.createSuccessResult(fetchOrderResponse));
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class FetchOrderResponse {
private Long storeId;
private List<_OrderItemDto> _orderItemDtos;
private Long totalPrice;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class _OrderItemDto {
private Long itemId;
private List<Long> itemOptionIds;
private Long price;
private Long count;
public _OrderItemDto(OrderItemDto orderItemDto) {
this.itemId = orderItemDto.getItemId();
this.itemOptionIds = orderItemDto.getOrderItemOptionDtoList()
.stream()
.map(OrderItemOptionDto::getId)
.collect(Collectors.toList());
this.price = orderItemDto.getPrice();
this.count = orderItemDto.getCount();
}
}
public FetchOrderResponse(FetchOrderDto fetchOrderDto){
this.storeId = fetchOrderDto.getStoreId();
this._orderItemDtos = fetchOrderDto.getOrderItemDtoList().stream()
.map(_OrderItemDto::new)
.collect(Collectors.toList());
this.totalPrice = fetchOrderDto.getOrderPrice();
}
return ResponseEntity.ok(Result.createSuccessResult(fetchOrderDto));
}
@PostMapping("/orders")

View File

@@ -1,12 +1,34 @@
package com.justpickup.orderservice.global.client.store;
import com.justpickup.orderservice.global.entity.Yn;
import lombok.Data;
import lombok.*;
@Data
import java.util.List;
import java.util.stream.Collectors;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class GetItemResponse {
private Long id;
private String name;
private Yn salesYn;
private Long price;
private List<ItemOptionDto> itemOptions;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class ItemOptionDto{
private Long id;
private OptionType optionType;
private String name;
}
}

View File

@@ -31,6 +31,7 @@ public class KafkaConfig {
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);
// properties.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 5000);
return new DefaultKafkaProducerFactory<>(properties);
}

View File

@@ -43,7 +43,7 @@ spring:
allow-credentials: true
routes:
- id: order-service
uri: lb://ORDER-SERVCIE
uri: lb://ORDER-SERVICE
predicates:
- Path=/order-service/**
filters:
@@ -51,7 +51,7 @@ spring:
- RewritePath=/order-service/(?<segment>.*),/$\{segment}
- id: store-service
uri: lb://STORE-SERVCIE
uri: lb://STORE-SERVICE
predicates:
- Path=/store-service/**
filters:

View File

@@ -0,0 +1,57 @@
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.itemoption.entity.ItemOption;
import com.justpickup.storeservice.domain.itemoption.entity.OptionType;
import com.justpickup.storeservice.global.entity.Yn;
import lombok.*;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GetItemDto {
private Long id;
private String name;
private Yn salesYn;
private Long price;
private List<ItemOptionDto> itemOptions;
public GetItemDto(Item item) {
this.id = item.getId();
this.name = item.getName();
this.salesYn = item.getSalesYn();
this.price = item.getPrice();
this.itemOptions = item.getItemOptions().stream().
map(ItemOptionDto::new)
.collect(Collectors.toList());
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
static class ItemOptionDto{
private Long id;
private OptionType optionType;
private String name;
public ItemOptionDto (ItemOption itemOption){
this.id = itemOption.getId();
this.optionType = itemOption.getOptionType();
this.name = itemOption.getName();
}
}
}

View File

@@ -1,9 +1,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.QItemOption;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
@@ -14,6 +12,10 @@ import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import static com.justpickup.storeservice.domain.category.entity.QCategory.category;
import static com.justpickup.storeservice.domain.item.entity.QItem.item;
import static com.justpickup.storeservice.domain.itemoption.entity.QItemOption.itemOption;
@Repository
@RequiredArgsConstructor
public class ItemRepositoryCustom {
@@ -21,15 +23,25 @@ public class ItemRepositoryCustom {
private final JPAQueryFactory queryFactory;
public Optional<Item> fetchItem(Long itemId){
Item item = queryFactory.selectFrom(QItem.item)
.join(QItem.item.itemOptions, QItemOption.itemOption).fetchJoin()
.join(QItem.item.category,QCategory.category).fetchJoin()
.where(QItem.item.id.eq(itemId))
Item fetchItem = queryFactory.selectFrom(item)
.join(item.itemOptions, itemOption).fetchJoin()
.join(item.category,category).fetchJoin()
.where(item.id.eq(itemId))
.fetchOne();
return Optional.ofNullable(item);
return Optional.ofNullable(fetchItem);
}
public List<Item> getItemAndItemOptions(List<Long> itemIds){
return queryFactory.selectFrom(item)
.join(item.itemOptions,itemOption).fetchJoin()
.where(item.id.in(itemIds))
.fetch();
}
public Page<Item> findItem(Long userId,String word, Pageable pageable){
//count 가져오기

View File

@@ -1,6 +1,7 @@
package com.justpickup.storeservice.domain.item.service;
import com.justpickup.storeservice.domain.item.dto.FetchItemDto;
import com.justpickup.storeservice.domain.item.dto.GetItemDto;
import com.justpickup.storeservice.domain.item.dto.ItemDto;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto;
import org.springframework.data.domain.Page;
@@ -12,6 +13,7 @@ public interface ItemService {
ItemDto findItemByItemId(Long itemId);
List<GetItemDto> getItemAndItemOptions(List<Long> itemIds);
FetchItemDto fetchItem(Long itemId);
Page<ItemDto> findItemList(Long userId,String word, Pageable pageable);

View File

@@ -3,6 +3,7 @@ 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.GetItemDto;
import com.justpickup.storeservice.domain.item.dto.ItemDto;
import com.justpickup.storeservice.domain.item.entity.Item;
import com.justpickup.storeservice.domain.item.exception.NotExistItemException;
@@ -46,6 +47,15 @@ public class ItemServiceImpl implements ItemService {
return ItemDto.createWithCategoryItemDtoAndItemOption(findItem);
}
@Override
public List<GetItemDto> getItemAndItemOptions(List<Long> itemIds) {
List<Item> items = itemRepositoryCustom.getItemAndItemOptions(itemIds);
return items.stream()
.map(GetItemDto::new)
.collect(Collectors.toList());
}
@Override
public FetchItemDto fetchItem(Long itemId) {
Item findItem = itemRepositoryCustom.fetchItem(itemId)

View File

@@ -1,6 +1,7 @@
package com.justpickup.storeservice.domain.item.web;
import com.justpickup.storeservice.domain.item.dto.FetchItemDto;
import com.justpickup.storeservice.domain.item.dto.GetItemDto;
import com.justpickup.storeservice.domain.item.dto.ItemDto;
import com.justpickup.storeservice.domain.item.service.ItemService;
import com.justpickup.storeservice.domain.itemoption.dto.ItemOptionDto;
@@ -22,9 +23,16 @@ public class ItemCustomerApiController {
private final ItemService itemService;
@GetMapping("/items/{itemId}")
public ResponseEntity getItemAndItemOptions(@PathVariable("itemId") List<Long> itemId) {
List<GetItemDto> itemList = itemService.getItemAndItemOptions(itemId);
return ResponseEntity.status(HttpStatus.OK)
.body(Result.createSuccessResult(itemList));
}
@GetMapping("/item/{itemId}")
public ResponseEntity getItem(@PathVariable("itemId") Long itemId) {
public ResponseEntity fetchItem(@PathVariable("itemId") Long itemId) {
FetchItemDto fetchItem = itemService.fetchItem(itemId);
GetItemResponse getItemResponse = new GetItemResponse(fetchItem);

View File

@@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
//@Component
@RequiredArgsConstructor
public class SqlCommandLineRunner implements CommandLineRunner {

View File

@@ -3,7 +3,7 @@ server:
spring:
application:
name: store-servcie
name: store-service
config:
import: optional:configserver:http://127.0.0.1:8888
cloud:
@@ -18,6 +18,8 @@ spring:
properties:
hibernate:
default_batch_fetch_size: 1000
defer-datasource-initialization: true
datasource:
driver-class-name: org.postgresql.Driver
@@ -25,6 +27,11 @@ spring:
username: postgres
password: admin
sql:
init:
data-locations: classpath:data/data.sql
mode: always
eureka:
client:
@@ -42,7 +49,3 @@ logging:
# jpa query, parameter 로그 (p6spy)
decorator.datasource.p6spy:
enable-logging: true
#feign key
token:
feign: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJmZWlnbiIsImV4cCI6MTE2NDY5NzY4NzAsImlhdCI6MTY0Njk3Njg3MH0.5x4Nx7oMnpF0_kZpbZsiB1u9eEbQ4IKIhJlEsa3D22cjZjvTHKz57GCz0sgXb_olhSNIVv9xF41A29-XYiFeBQ

View File

@@ -0,0 +1,77 @@
-- store
INSERT INTO public.store(
store_id, created_at, created_by, last_modified_at, last_modified_by, city, street, zipcode, business_end_time, business_start_time, phone_number, photo_name, photo_path, user_id, map_id)
VALUES (1, now(), 1, now(), 1, '서울시', '광화문로', '123-456', to_timestamp('20:00:00', 'HH24:MI:SS'), to_timestamp('09:00:00', 'HH24:MI:SS'), '010-9418-1307', '사진명1', '/Users/sangbum/Desktop', 1, null);
-- category
INSERT INTO public.category(
category_id, created_at, created_by, last_modified_at, last_modified_by, name, orders, store_id)
VALUES (10, now(), 1, now(), 1, '카테고리1', 0, 1);
INSERT INTO public.category(
category_id, created_at, created_by, last_modified_at, last_modified_by, name, orders, store_id)
VALUES (11, now(), 1, now(), 1, '카테고리2', 1, 1);
-- item
INSERT INTO public.item(
item_id, created_at, created_by, last_modified_at, last_modified_by, name, photo_name, photo_path, price, sales_yn, category_id, store_id)
VALUES (100, now(), 1, now(), 1, '아이템1', '아이템_사진명', '/Users/sangbum/Desktop', 1000, 'Y', 10, 1);
INSERT INTO public.item(
item_id, created_at, created_by, last_modified_at, last_modified_by, name, photo_name, photo_path, price, sales_yn, category_id, store_id)
VALUES (101, now(), 1, now(), 1, '아이템2', '아이템_사진명2', '/Users/sangbum/Desktop', 2000, 'Y', 10, 1);
INSERT INTO public.item(
item_id, created_at, created_by, last_modified_at, last_modified_by, name, photo_name, photo_path, price, sales_yn, category_id, store_id)
VALUES (102, now(), 1, now(), 1, '아이템3', '아이템_사진명3', '/Users/sangbum/Desktop', 3000, 'Y', 11, 1);
-- item option
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1000, now(), 1, now(), 1, 'ICE', 'REQUIRED', 100);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1001, now(), 1, now(), 1, 'HOT', 'REQUIRED', 100);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1002, now(), 1, now(), 1, '샷 추가', 'OTHER', 100);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1003, now(), 1, now(), 1, '투샷 추카', 'OTHER', 100);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1004, now(), 1, now(), 1, 'ICE', 'REQUIRED', 101);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1005, now(), 1, now(), 1, 'HOT', 'REQUIRED', 101);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1006, now(), 1, now(), 1, '샷 추가', 'OTHER', 101);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1007, now(), 1, now(), 1, '투샷 추카', 'OTHER', 101);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1008, now(), 1, now(), 1, 'ICE', 'REQUIRED', 102);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1009, now(), 1, now(), 1, 'HOT', 'REQUIRED', 102);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1010, now(), 1, now(), 1, '샷 추가', 'OTHER', 102);
INSERT INTO public.item_option(
item_option_id, created_at, created_by, last_modified_at, last_modified_by, name, option_type, item_id)
VALUES (1011, now(), 1, now(), 1, '투샷 추카', 'OTHER', 102);

View File

@@ -50,7 +50,6 @@ decorator.datasource.p6spy:
token:
access-expired-time: 3600000
refresh-expired-time: 604800000
secret: my-secret
secret: $2a$10$q42lY7Y18xqrFt1qbODZIO4OMTeOxnrCe7tF3n9bazJinVE7VH5Pi
refresh-token-name: refresh-token
access-token-name: access-token
fegin: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJmZWlnbiIsImV4cCI6MTE2NDY5NzY4NzAsImlhdCI6MTY0Njk3Njg3MH0.5x4Nx7oMnpF0_kZpbZsiB1u9eEbQ4IKIhJlEsa3D22cjZjvTHKz57GCz0sgXb_olhSNIVv9xF41A29-XYiFeBQ
access-token-name: access-token