From 54f19fcad2ec2676cf489fdccb31fc81fb9c8145 Mon Sep 17 00:00:00 2001 From: hoon7566 Date: Fri, 25 Feb 2022 16:38:24 +0900 Subject: [PATCH] =?UTF-8?q?feat(store-service,=20owner-vue):=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EC=88=98=EC=A0=95=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 아이템 수정 아이템 옵션 추가 기능 개발 --- .../filter/GlobalFilter.java | 54 ++++++ .../src/main/resources/application.yml | 10 +- owner-vue/.env | 1 + owner-vue/src/main.js | 4 + owner-vue/src/util/customUtil.js | 9 + owner-vue/src/views/Category.vue | 8 +- owner-vue/src/views/ItemOption.vue | 77 ++++++++ owner-vue/src/views/Menu.vue | 64 +++++-- owner-vue/src/views/MenuItem.vue | 177 ++++++++++++++++++ owner-vue/vue.config.js | 12 -- .../storeservice/domain/item/entity/Item.java | 5 + .../domain/item/service/ItemService.java | 4 + .../domain/item/service/ItemServiceImpl.java | 23 +++ .../domain/item/web/ItemController.java | 64 +++++-- .../domain/itemoption/dto/ItemOptionDto.java | 7 + .../domain/itemoption/entity/ItemOption.java | 7 + 16 files changed, 485 insertions(+), 41 deletions(-) create mode 100644 owner-apigateway-service/src/main/java/com/justpickup/ownerapigatewayservice/filter/GlobalFilter.java create mode 100644 owner-vue/.env create mode 100644 owner-vue/src/util/customUtil.js create mode 100644 owner-vue/src/views/ItemOption.vue create mode 100644 owner-vue/src/views/MenuItem.vue diff --git a/owner-apigateway-service/src/main/java/com/justpickup/ownerapigatewayservice/filter/GlobalFilter.java b/owner-apigateway-service/src/main/java/com/justpickup/ownerapigatewayservice/filter/GlobalFilter.java new file mode 100644 index 0000000..a34d533 --- /dev/null +++ b/owner-apigateway-service/src/main/java/com/justpickup/ownerapigatewayservice/filter/GlobalFilter.java @@ -0,0 +1,54 @@ +package com.justpickup.ownerapigatewayservice.filter; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +@Slf4j + +public class GlobalFilter extends AbstractGatewayFilterFactory { + private static final String TEST_CIRCUIT_BREAKER = "testCircuitBreaker"; + + public GlobalFilter(){ + super(Config.class); + } + + @Override + public GatewayFilter apply(Config config) { + return (exchange, chain) -> { + ServerHttpRequest request = exchange.getRequest(); // reactive포함된거로 import + ServerHttpResponse response = exchange.getResponse(); + + log.info("Global com.example.scg.filter baseMessgae: {}", config.getBaseMessage()); + + // Global pre Filter + if (config.isPreLogger()){ + log.info("Global Filter Start: request id -> {}" , request.getId()); + log.info("Global Filter Start: request path -> {}" , request.getPath()); + } + + // Global Post Filter + //Mono는 webflux에서 단일값 전송할때 Mono값으로 전송 + return chain.filter(exchange).then(Mono.fromRunnable(()->{ + + if (config.isPostLogger()){ + log.info("Global Filter End: response statuscode -> {}" , response.getStatusCode()); + } + })); + + }; + } + + @Data + public static class Config { + private String baseMessage; + private boolean preLogger; + private boolean postLogger; + } +} diff --git a/owner-apigateway-service/src/main/resources/application.yml b/owner-apigateway-service/src/main/resources/application.yml index 59e992e..98f3cdf 100644 --- a/owner-apigateway-service/src/main/resources/application.yml +++ b/owner-apigateway-service/src/main/resources/application.yml @@ -14,16 +14,24 @@ spring: cloud: gateway: + default-filters: + - name: GlobalFilter + args: + baseMessage: Spring Cloud Gateway Global Filter + preLogger: true + postLogger: true globalcors: cors-configurations: '[/**]': - allowedOrigins: "http://localhost:8080" + allowedOrigins: "*" + allowedHeaders: "*" allowedMethods: - POST - GET - PUT - OPTIONS - DELETE +# add-to-simple-url-handler-mapping: true routes: - id: owner-frontend-service uri: lb://OWNER-FRONTEND-SERVICE diff --git a/owner-vue/.env b/owner-vue/.env new file mode 100644 index 0000000..c7f7a1a --- /dev/null +++ b/owner-vue/.env @@ -0,0 +1 @@ +VUE_APP_OWNER_SERVICE_BASEURL=http://localhost:8001 \ No newline at end of file diff --git a/owner-vue/src/main.js b/owner-vue/src/main.js index 76b1f26..effb410 100644 --- a/owner-vue/src/main.js +++ b/owner-vue/src/main.js @@ -3,9 +3,13 @@ import App from './App.vue' import vuetify from './plugins/vuetify' import router from './router' import axios from "axios"; +import customUtil from './util/customUtil' Vue.config.productionTip = false Vue.prototype.$axios = axios; +Vue.prototype.$customUtil = customUtil; + +console.log(process.env) new Vue({ vuetify, diff --git a/owner-vue/src/util/customUtil.js b/owner-vue/src/util/customUtil.js new file mode 100644 index 0000000..4c3ddde --- /dev/null +++ b/owner-vue/src/util/customUtil.js @@ -0,0 +1,9 @@ +export default { + deepCopy : function (o) { + let result = {}; + if (typeof o === "object" && o !== null) + for (let i in o) result[i] = this.deepCopy(o[i]); + else result = o; + return result; + } +} \ No newline at end of file diff --git a/owner-vue/src/views/Category.vue b/owner-vue/src/views/Category.vue index 7f6900d..95c0f43 100644 --- a/owner-vue/src/views/Category.vue +++ b/owner-vue/src/views/Category.vue @@ -114,9 +114,11 @@ export default { } data.categoryList.push(category) }) + console.log(data) + this.$axios({ method:'put', - url:'/store-service/category', + url:process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/category', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8' @@ -133,9 +135,10 @@ export default { }, getCategoryList:function(){ var vm =this; + console.log(process.env.OWNER_SERVICE_BASEURL) this.$axios({ method:'get', - url:'/store-service/category', + url: process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/category', responseType:'json' }) .then(function (response) { @@ -145,6 +148,7 @@ export default { } }, mounted() { + alert() this.getCategoryList(); } } diff --git a/owner-vue/src/views/ItemOption.vue b/owner-vue/src/views/ItemOption.vue new file mode 100644 index 0000000..9bf5f35 --- /dev/null +++ b/owner-vue/src/views/ItemOption.vue @@ -0,0 +1,77 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/views/Menu.vue b/owner-vue/src/views/Menu.vue index 16ca0f1..44398f6 100644 --- a/owner-vue/src/views/Menu.vue +++ b/owner-vue/src/views/Menu.vue @@ -8,6 +8,7 @@ :color="modalSet.color.red" :name="modalSet.words.register" @save="itemSave" + @addItemOption="addItemOption" /> @@ -43,8 +44,9 @@ :icon="modalSet.icon.modify" :color="modalSet.color.primary" :name="modalSet.words.modify" - @init="editItem(item)" + @init="editModalOpen(item)" @save="itemSave" + @addItemOption="addItemOption" /> @@ -111,10 +113,10 @@ export default { itemId : Number, itemName : String, itemPrice : Number, - category: String, + categoryId: Number, categoryList : ['카테고리1','카테고리2'], - requiredOption : ['Ice' , 'Hot'], - otherOption : ['얼음많이','샷추가','생크림많이','덜 뜨겁게'] + requiredOption : [], + otherOption : [] }, page: 1, pageCount: 1, @@ -145,7 +147,7 @@ export default { } this.$axios({ method:'get', - url:'/store-service/item', + url:process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/item', params : searchParam, responseType:'json' }) @@ -161,7 +163,7 @@ export default { this.modalData = { itemName : '', itemPrice : 0, - category: '', + categoryId: 0, categoryList : [], requiredOption : [], otherOption : [] @@ -169,41 +171,73 @@ export default { this.$axios({ method:'get', - url:'/store-service/category', + url: process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/category', responseType:'json' }) .then(function (response) { response.data.data.forEach(function (ele){ - vm.modalData.categoryList.push(ele.name) + vm.modalData.categoryList.push(ele) }) }); }, - editItem:function(item){ + editModalOpen:function(item){ var vm = this this.getModalData(); // var vm =this; this.$axios({ method:'get', - url:'/store-service/item/'+item.id, + url: process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/item/'+item.id, responseType:'json' }) .then(function (response) { + console.log(response) var item = response.data.data; + console.log(item) vm.modalData.itemId = item.id; vm.modalData.itemName = item.name; vm.modalData.itemPrice = item.price; - vm.modalData.category = item.categoryName; + vm.modalData.categoryId = item.categoryId; item.itemOptions.forEach(function(ele){ + + console.log(ele) if(ele.optionType === "REQUIRED") - vm.modalData.requiredOption.push(ele.name) + vm.modalData.requiredOption.push(ele) else - vm.modalData.otherOption.push(ele.name) + vm.modalData.otherOption.push(ele) }) }); - console.log(this.modalData) }, itemSave:function(){ - console.log(this.modalData) + var method ='' + var itemData = this.modalData; + if (this.modalData.itemId!=null) + method='put' + else + method='post' + + this.$axios({ + method:method, + url: process.env.VUE_APP_OWNER_SERVICE_BASEURL+'/store-service/item', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json;charset=UTF-8' + }, + data: itemData, + responseType:'json' + }) + .then(response => console.log(response)) + .catch(reason => console.log(reason)) + + }, + addItemOption:function (itemOptionValue,type){ + var item = { + name:itemOptionValue, + optionType:type + } + if(type ==='REQUIRED') + this.modalData.requiredOption.push(item) + else + this.modalData.otherOption.push(item) } }, diff --git a/owner-vue/src/views/MenuItem.vue b/owner-vue/src/views/MenuItem.vue new file mode 100644 index 0000000..df6775e --- /dev/null +++ b/owner-vue/src/views/MenuItem.vue @@ -0,0 +1,177 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/vue.config.js b/owner-vue/vue.config.js index bc0acb2..167eb2e 100644 --- a/owner-vue/vue.config.js +++ b/owner-vue/vue.config.js @@ -2,16 +2,4 @@ module.exports = { transpileDependencies: [ 'vuetify' ], - devServer:{ - proxy:{ - 'store-service/' :{ - target: 'http://localhost:8001', - ws:true, - }, - 'order-service/' :{ - target: 'http://localhost:8001', - ws:true, - } - } - } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/entity/Item.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/entity/Item.java index 356b527..7315f9d 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/entity/Item.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/entity/Item.java @@ -62,6 +62,11 @@ public class Item extends BaseEntity { category.getItems().add(this); } + public void setItemNameAndPrice(String name , Long price){ + this.name = name; + this.price = price; + } + // == 생성 메소드 == // public static Item createdItem(Category category, Store store, List itemOptions) { Item item = new Item(); 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 ad7df81..475c012 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,6 +1,8 @@ package com.justpickup.storeservice.domain.item.service; 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; @@ -11,4 +13,6 @@ public interface ItemService { ItemDto findItemByItemId(Long itemId); Page findItemList(Long storeId,String word, Pageable pageable); + + void putItem(Long itemId, String itemName, Long itemPrice, List itemOption); } 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 78d2ebd..7433e29 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 @@ -5,6 +5,9 @@ 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.repository.StoreRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,6 +17,8 @@ import org.springframework.data.support.PageableExecutionUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Service @@ -23,6 +28,7 @@ import java.util.stream.Collectors; public class ItemServiceImpl implements ItemService { private final ItemRepository itemRepository; + private final ItemOptionRepository itemOptionRepository; private final ItemRepositoryCustom itemRepositoryCustom; private final StoreRepository storeRepository; @@ -44,5 +50,22 @@ public class ItemServiceImpl implements ItemService { .collect(Collectors.toList()),pageable,itemList::getTotalElements); } + @Override + @Transactional + public void putItem(Long itemId, String itemName, Long itemPrice, List itemOptionDtos) { + Item item = itemRepository.findById(itemId) + .orElseThrow(() -> new NotExistItemException("존재하지 않는 아이템 입니다.")); + + item.setItemNameAndPrice(itemName,itemPrice); + itemOptionDtos.stream() + .map(itemOptionDto -> { + if(itemOptionDto.getId()==null) + return ItemOptionDto.createItemOption(itemOptionDto,item); + else + return itemOptionRepository.findById(itemOptionDto.getId()) + .orElseThrow(() -> new NotExistItemException("존재하지 않는 아이템 옵션 입니다.")); + }) + .forEach(itemOptionRepository::save); + } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemController.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemController.java index 568af7d..f674b76 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemController.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/web/ItemController.java @@ -1,19 +1,12 @@ package com.justpickup.storeservice.domain.item.web; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.justpickup.storeservice.domain.item.dto.ItemDto; import com.justpickup.storeservice.domain.item.service.ItemService; 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.dto.Result; import com.justpickup.storeservice.global.entity.Yn; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; -import org.hibernate.annotations.Parameter; +import lombok.*; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -21,7 +14,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.io.Serializable; import java.util.List; import java.util.stream.Collectors; @@ -104,7 +96,7 @@ public class ItemController { private String name; private Yn salesYn; private Long price; - private String CategoryName; + private Long CategoryId; private List itemOptions; public GetItemResponse(ItemDto itemDto) { @@ -112,7 +104,7 @@ public class ItemController { this.name = itemDto.getName(); this.salesYn = itemDto.getSalesYn(); this.price = itemDto.getPrice(); - this.CategoryName = itemDto.getCategoryDto().getName(); + this.CategoryId = itemDto.getCategoryDto().getId(); this.itemOptions = itemDto.getItemOptions() .stream().map(ItemOptionResponse::new) .collect(Collectors.toList()); @@ -137,4 +129,54 @@ public class ItemController { } } } + + @PutMapping("/item") + public ResponseEntity putItem(@RequestBody ItemRequest putItemRequest){ + + List itemOption = putItemRequest.getRequiredOption().stream().map(ItemRequest.ItemOptionRequest::createItemDto).collect(Collectors.toList()); + itemOption.addAll(putItemRequest.getOtherOption().stream().map(ItemRequest.ItemOptionRequest::createItemDto).collect(Collectors.toList())); + + itemService.putItem(putItemRequest.getItemId() + , putItemRequest.getItemName() + , putItemRequest.getItemPrice() + , itemOption); + + + return ResponseEntity.status(HttpStatus.NO_CONTENT) + .body(Result.createSuccessResult(null)); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class ItemRequest { + private Long itemId; + private String itemName; + private Long itemPrice; + private List requiredOption; + private List otherOption; + + @Data + @AllArgsConstructor + @NoArgsConstructor + @Builder + public static class ItemOptionRequest { + private Long id; + private String name; + private OptionType optionType; + private Long price; + + public static ItemOptionDto createItemDto(ItemOptionRequest itemOptionRequest){ + return ItemOptionDto.builder() + .id(itemOptionRequest.getId()) + .name(itemOptionRequest.getName()) + .price(itemOptionRequest.getPrice()) + .optionType(itemOptionRequest.getOptionType()) + .build(); + + } + } + } + } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/dto/ItemOptionDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/dto/ItemOptionDto.java index e7ee14a..0ec7b5b 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/dto/ItemOptionDto.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/dto/ItemOptionDto.java @@ -1,5 +1,6 @@ package com.justpickup.storeservice.domain.itemoption.dto; +import com.justpickup.storeservice.domain.item.entity.Item; import com.justpickup.storeservice.domain.itemoption.entity.ItemOption; import com.justpickup.storeservice.domain.itemoption.entity.OptionType; import lombok.AllArgsConstructor; @@ -29,4 +30,10 @@ public class ItemOptionDto { this.price = itemOption.getPrice(); this.name = itemOption.getName(); } + + public static ItemOption createItemOption (ItemOptionDto itemOptionDto, Item item){ + + return new ItemOption(itemOptionDto.getOptionType(),itemOptionDto.getPrice(),itemOptionDto.getName(),item); + + } } diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/entity/ItemOption.java b/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/entity/ItemOption.java index e6417dc..f1a24aa 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/entity/ItemOption.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/itemoption/entity/ItemOption.java @@ -35,4 +35,11 @@ public class ItemOption extends BaseEntity { this.item = item; item.getItemOptions().add(this); } + + public ItemOption(OptionType optionType, Long price, String name, Item item) { + this.optionType = optionType; + this.price = price; + this.name = name; + this.item = item; + } }