diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc93eb4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/owner-vue/node_modules/ diff --git a/config-service/.idea/.gitignore b/config-service/.idea/.gitignore new file mode 100644 index 0000000..c3f502a --- /dev/null +++ b/config-service/.idea/.gitignore @@ -0,0 +1,8 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml +# 에디터 기반 HTTP 클라이언트 요청 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/owner-apigateway-service/src/main/resources/application.yml b/owner-apigateway-service/src/main/resources/application.yml index 2d45e84..59e992e 100644 --- a/owner-apigateway-service/src/main/resources/application.yml +++ b/owner-apigateway-service/src/main/resources/application.yml @@ -14,6 +14,16 @@ spring: cloud: gateway: + globalcors: + cors-configurations: + '[/**]': + allowedOrigins: "http://localhost:8080" + allowedMethods: + - POST + - GET + - PUT + - OPTIONS + - DELETE routes: - id: owner-frontend-service uri: lb://OWNER-FRONTEND-SERVICE @@ -67,4 +77,4 @@ token: refresh-expired-time: 604800000 secret: my-secret refresh-token-name: refresh-token - access-token-name: access-token \ No newline at end of file + access-token-name: access-token diff --git a/owner-vue/.idea/.gitignore b/owner-vue/.idea/.gitignore new file mode 100644 index 0000000..c3f502a --- /dev/null +++ b/owner-vue/.idea/.gitignore @@ -0,0 +1,8 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml +# 에디터 기반 HTTP 클라이언트 요청 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/owner-vue/babel.config.js b/owner-vue/babel.config.js new file mode 100644 index 0000000..e955840 --- /dev/null +++ b/owner-vue/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/cli-plugin-babel/preset' + ] +} diff --git a/owner-vue/package.json b/owner-vue/package.json new file mode 100644 index 0000000..2b4a234 --- /dev/null +++ b/owner-vue/package.json @@ -0,0 +1,54 @@ +{ + "name": "owner-admin", + "version": "0.1.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint" + }, + "dependencies": { + "@mdi/js": "^6.5.95", + "axios": "^0.26.0", + "core-js": "^3.6.5", + "moment": "^2.29.1", + "vue": "^2.6.11", + "vue-router": "^3.2.0", + "vuedraggable": "^2.24.3", + "vuetify": "^2.4.0" + }, + "devDependencies": { + "@mdi/font": "^6.1.95", + "@vue/cli-plugin-babel": "~4.5.0", + "@vue/cli-plugin-eslint": "~4.5.0", + "@vue/cli-plugin-router": "~4.5.0", + "@vue/cli-service": "~4.5.0", + "babel-eslint": "^10.1.0", + "eslint": "^6.7.2", + "eslint-plugin-vue": "^6.2.2", + "sass": "~1.32.0", + "sass-loader": "^10.0.0", + "vue-cli-plugin-vuetify": "~2.4.2", + "vue-template-compiler": "^2.6.11", + "vuetify-loader": "^1.7.0" + }, + "eslintConfig": { + "root": true, + "env": { + "node": true + }, + "extends": [ + "plugin:vue/essential", + "eslint:recommended" + ], + "parserOptions": { + "parser": "babel-eslint" + }, + "rules": {} + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead" + ] +} diff --git a/owner-vue/public/favicon.ico b/owner-vue/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/owner-vue/public/favicon.ico differ diff --git a/owner-vue/public/index.html b/owner-vue/public/index.html new file mode 100644 index 0000000..c02bc19 --- /dev/null +++ b/owner-vue/public/index.html @@ -0,0 +1,18 @@ + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + +
+ + + diff --git a/owner-vue/src/App.vue b/owner-vue/src/App.vue new file mode 100644 index 0000000..1121e76 --- /dev/null +++ b/owner-vue/src/App.vue @@ -0,0 +1,28 @@ + + + diff --git a/owner-vue/src/api/order.js b/owner-vue/src/api/order.js new file mode 100644 index 0000000..fb44238 --- /dev/null +++ b/owner-vue/src/api/order.js @@ -0,0 +1,23 @@ +import axios from "axios"; + +export default { + requestPrevOrder(startDate, endDate, page) { + const options = { + params: { + startDate: startDate, + endDate: endDate, + page: page + } + } + return axios.get("http://localhost:8001/order-service/prevOrder", options); + }, + requestOrder(orderDate, lastOrderId) { + const options = { + params: { + orderDate: orderDate, + lastOrderId: lastOrderId + } + } + return axios.get("http://localhost:8001/order-service/orderMain", options); + } +} \ No newline at end of file diff --git a/owner-vue/src/assets/logo.png b/owner-vue/src/assets/logo.png new file mode 100644 index 0000000..f3d2503 Binary files /dev/null and b/owner-vue/src/assets/logo.png differ diff --git a/owner-vue/src/assets/logo.svg b/owner-vue/src/assets/logo.svg new file mode 100644 index 0000000..145b6d1 --- /dev/null +++ b/owner-vue/src/assets/logo.svg @@ -0,0 +1 @@ +Artboard 46 diff --git a/owner-vue/src/components/DatePicker.vue b/owner-vue/src/components/DatePicker.vue new file mode 100644 index 0000000..669644e --- /dev/null +++ b/owner-vue/src/components/DatePicker.vue @@ -0,0 +1,55 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/components/OrderCard.vue b/owner-vue/src/components/OrderCard.vue new file mode 100644 index 0000000..5b63bc4 --- /dev/null +++ b/owner-vue/src/components/OrderCard.vue @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/components/Sidebar.vue b/owner-vue/src/components/Sidebar.vue new file mode 100644 index 0000000..c5ac391 --- /dev/null +++ b/owner-vue/src/components/Sidebar.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/owner-vue/src/components/Topbar.vue b/owner-vue/src/components/Topbar.vue new file mode 100644 index 0000000..54684c7 --- /dev/null +++ b/owner-vue/src/components/Topbar.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/owner-vue/src/main.js b/owner-vue/src/main.js new file mode 100644 index 0000000..79288dd --- /dev/null +++ b/owner-vue/src/main.js @@ -0,0 +1,16 @@ +import 'font-awesome/css/font-awesome.min.css' // Ensure you are using css-loader +import Vue from 'vue' +import App from './App.vue' +import vuetify from './plugins/vuetify' +import router from './router' +import axios from "axios"; + +Vue.config.productionTip = false + +new Vue({ + vuetify, + router, + render: h => h(App) +}).$mount('#app') +Vue.component('axios',axios) + diff --git a/owner-vue/src/plugins/vuetify.js b/owner-vue/src/plugins/vuetify.js new file mode 100644 index 0000000..d516d08 --- /dev/null +++ b/owner-vue/src/plugins/vuetify.js @@ -0,0 +1,11 @@ +import '@mdi/font/css/materialdesignicons.css' +import Vue from 'vue'; +import Vuetify from 'vuetify/lib/framework'; + +Vue.use(Vuetify); + +export default new Vuetify({ + icons: { + iconfont: 'mdi', // default - only for display purposes + }, +}); diff --git a/owner-vue/src/router/index.js b/owner-vue/src/router/index.js new file mode 100644 index 0000000..12f7d17 --- /dev/null +++ b/owner-vue/src/router/index.js @@ -0,0 +1,40 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +Vue.use(VueRouter) + +const routes = [ + { + path: '/', + name: 'dashboard', + component: () => import('./../views/Dashboard') + }, + { + path: '/category', + name: 'category', + component: () => import('./../views/Category') + }, + { + path: '/menu', + name: 'menu', + component: () => import('./../views/Menu') + }, + { + path: '/prev-order', + name: 'prev-order', + component: () => import('./../views/PrevOrder') + }, + { + path: '/order', + name: 'order', + component: () => import('./../views/Order.vue') + } +] + +const router = new VueRouter({ + mode: 'history', + base: process.env.BASE_URL, + routes +}) + +export default router diff --git a/owner-vue/src/views/About.vue b/owner-vue/src/views/About.vue new file mode 100644 index 0000000..3fa2807 --- /dev/null +++ b/owner-vue/src/views/About.vue @@ -0,0 +1,5 @@ + diff --git a/owner-vue/src/views/Category.vue b/owner-vue/src/views/Category.vue new file mode 100644 index 0000000..a9679ee --- /dev/null +++ b/owner-vue/src/views/Category.vue @@ -0,0 +1,150 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/views/Dashboard.vue b/owner-vue/src/views/Dashboard.vue new file mode 100644 index 0000000..7eb71a8 --- /dev/null +++ b/owner-vue/src/views/Dashboard.vue @@ -0,0 +1,212 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/views/Home.vue b/owner-vue/src/views/Home.vue new file mode 100644 index 0000000..44553c4 --- /dev/null +++ b/owner-vue/src/views/Home.vue @@ -0,0 +1,15 @@ + + + diff --git a/owner-vue/src/views/Menu.vue b/owner-vue/src/views/Menu.vue new file mode 100644 index 0000000..52db3d3 --- /dev/null +++ b/owner-vue/src/views/Menu.vue @@ -0,0 +1,122 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/views/Order.vue b/owner-vue/src/views/Order.vue new file mode 100644 index 0000000..303a431 --- /dev/null +++ b/owner-vue/src/views/Order.vue @@ -0,0 +1,119 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/src/views/PrevOrder.vue b/owner-vue/src/views/PrevOrder.vue new file mode 100644 index 0000000..be67d30 --- /dev/null +++ b/owner-vue/src/views/PrevOrder.vue @@ -0,0 +1,163 @@ + + + + + \ No newline at end of file diff --git a/owner-vue/vue.config.js b/owner-vue/vue.config.js new file mode 100644 index 0000000..bc0acb2 --- /dev/null +++ b/owner-vue/vue.config.js @@ -0,0 +1,17 @@ +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/dto/ItemDto.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemDto.java index f620c9c..2dc323e 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 @@ -1,11 +1,17 @@ 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.global.entity.Yn; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder public class ItemDto { private Long id; @@ -16,15 +22,15 @@ public class ItemDto { private Long price; + private CategoryDto categoryDto; + /* private PhotoDto photoDto; - private CategoryDto categoryDto; private StoreDto storeDto; private List itemOptionDtoList; */ // == 생성 메소드 == // - @Builder public ItemDto(Long id, String name, Yn salesYn, Long price) { this.id = id; this.name = name; @@ -41,6 +47,16 @@ public class ItemDto { .build(); } + public static ItemDto createWithCategoryItemDto(Item item) { + return ItemDto.builder() + .id(item.getId()) + .name(item.getName()) + .categoryDto(new CategoryDto(item.getCategory())) + .price(item.getPrice()) + .salesYn(item.getSalesYn()) + .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/dto/ItemSearch.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemSearch.java new file mode 100644 index 0000000..de0d9c2 --- /dev/null +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/dto/ItemSearch.java @@ -0,0 +1,20 @@ +package com.justpickup.storeservice.domain.item.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ItemSearch { + + @NotNull + private String type; + + private String word; + + +} diff --git a/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepository.java b/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepository.java index de7b237..3e6b1d9 100644 --- a/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepository.java +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepository.java @@ -1,7 +1,12 @@ package com.justpickup.storeservice.domain.item.repository; import com.justpickup.storeservice.domain.item.entity.Item; +import com.justpickup.storeservice.domain.store.entity.Store; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface ItemRepository extends JpaRepository { + + List findByStore(Store store); } 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 new file mode 100644 index 0000000..bcf1f2b --- /dev/null +++ b/store-service/src/main/java/com/justpickup/storeservice/domain/item/repository/ItemRepositoryCustom.java @@ -0,0 +1,53 @@ +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.store.entity.QStore; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.support.PageableExecutionUtils; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class ItemRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + public Page findItem(Long storeId,String word, Pageable pageable){ + + //count 가져오기 + Long count = queryFactory.select(QItem.item.count()) + .from(QItem.item) + .join(QItem.item.category) + .leftJoin(QItem.item.store) + .on(QItem.item.store.id.eq(storeId)) + .where( + QItem.item.name.contains(word) + .or(QItem.item.category.name.contains(word)) + ) + .limit(pageable.getPageSize()) + .offset(pageable.getOffset()) + .fetchOne(); + + //List 가져오기 + List itemList = queryFactory.selectFrom(QItem.item) + .join(QItem.item.category).fetchJoin() + .leftJoin(QItem.item.store) + .on(QItem.item.store.id.eq(storeId)) + .where( + QItem.item.name.contains(word) + .or(QItem.item.category.name.contains(word)) + ) + .limit(pageable.getPageSize()) + .offset(pageable.getOffset()) + .fetch(); + + return PageableExecutionUtils.getPage(itemList,pageable,() -> count); + } +} 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 518088d..ad7df81 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,8 +1,14 @@ package com.justpickup.storeservice.domain.item.service; import com.justpickup.storeservice.domain.item.dto.ItemDto; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; public interface ItemService { ItemDto findItemByItemId(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 9722720..fe9a422 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 @@ -1,14 +1,26 @@ package com.justpickup.storeservice.domain.item.service; +import com.justpickup.storeservice.domain.category.exception.NotFoundStoreException; import com.justpickup.storeservice.domain.item.dto.ItemDto; +import com.justpickup.storeservice.domain.item.dto.ItemSearch; 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.store.entity.Store; +import com.justpickup.storeservice.domain.store.repository.StoreRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +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.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.stream.Collectors; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -16,6 +28,8 @@ import org.springframework.transaction.annotation.Transactional; public class ItemServiceImpl implements ItemService { private final ItemRepository itemRepository; + private final ItemRepositoryCustom itemRepositoryCustom; + private final StoreRepository storeRepository; @Override @@ -25,4 +39,15 @@ public class ItemServiceImpl implements ItemService { return ItemDto.createItemDto(findItem); } + + @Override + public Page findItemList( Long storeId,String word, Pageable pageable) { + + Page itemList = itemRepositoryCustom.findItem(storeId,word,pageable); + return PageableExecutionUtils.getPage(itemList.stream() + .map(ItemDto::createWithCategoryItemDto) + .collect(Collectors.toList()),pageable,itemList::getTotalElements); + } + + } 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 21f106d..e11698a 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,5 +1,7 @@ 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.global.dto.Result; @@ -8,21 +10,85 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; +import org.hibernate.annotations.Parameter; +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.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequiredArgsConstructor -@RequestMapping("/item") public class ItemController { private final ItemService itemService; - @GetMapping("/{itemId}") + @GetMapping("/item") + public ResponseEntity> getItemList( @RequestParam String word, + @PageableDefault(page = 0, size = 10) Pageable pageable){ + + Long storeId = 1L; + + Page itemDtoList = itemService.findItemList(storeId,word,pageable); + List itemList = itemDtoList.stream() + .map(GetItemListResponse.Item::new) + .collect(Collectors.toList()); + + GetItemListResponse getItemResponse = new GetItemListResponse( + itemList, + itemDtoList.getNumber(), + itemDtoList.getTotalPages() + ); + + + return ResponseEntity.status(HttpStatus.OK) + .body((Result)Result.createSuccessResult(getItemResponse)); + } + + + @Data @NoArgsConstructor @AllArgsConstructor + static class GetItemListResponse { + private List itemList; + private Page page; + + public GetItemListResponse(List itemList, int startPage,int totalPage) { + this.itemList = itemList; + this.page = new Page(startPage,totalPage); + } + + @Data + static class Item{ + private Long id; + private String name; + private Yn salesYn; + private Long price; + private String categoryName; + + public Item(ItemDto itemDto) { + this.id = itemDto.getId(); + this.name = itemDto.getName(); + this.salesYn = itemDto.getSalesYn(); + this.price = itemDto.getPrice(); + this.categoryName = itemDto.getCategoryDto().getName(); + } + } + + @Data @AllArgsConstructor + static class Page { + int startPage; + int totalPage; + } + + + } + + + @GetMapping("/item/{itemId}") public ResponseEntity getItem(@PathVariable("itemId") Long itemId) { ItemDto itemByItemId = itemService.findItemByItemId(itemId); diff --git a/store-service/src/main/resources/application.yml b/store-service/src/main/resources/application.yml index 96eeaf2..edc6376 100644 --- a/store-service/src/main/resources/application.yml +++ b/store-service/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 0 + port: 12343 spring: application: