Merge branch 'master' into common/p6spy-query-format

This commit is contained in:
Sangbum Park
2022-02-10 17:42:05 +09:00
committed by GitHub
31 changed files with 1447 additions and 9 deletions

View File

@@ -0,0 +1,14 @@
package com.justpickup.ownerfrontendservice.domain.category.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class CategoryController {
@GetMapping("/category")
public String category(){
return "/domain/category/category";
}
}

View File

@@ -0,0 +1,202 @@
<!DOCTYPE html>
<html lang="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/layout}"
>
<head></head>
<!-- Begin Page Content -->
<div layout:fragment="content" class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-2 text-gray-800">category </h1>
<p class="mb-4"> 버튼을 눌러 카테고리 등록</p>
<div class="row">
<div class="col-xl-12">
<a href="#" class="btn btn-info btn-icon-split" data-toggle="modal" data-target="#myModal" >
<span class="icon text-white-50">
<i class="fas fa-info-circle"></i>
</span>
<span class="text">카테고리 생성</span>
</a>
</div>
</div>
<!-- 카테고리 Modal -->
<div class="modal fade " id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">category 등록</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-8">
<h2>Category List </h2>
<ul id="categoryList" class="list-group border border-info">
<li class="list-group-item d-flex justify-content-between align-items-center" role="button">
<span class="list-element" contenteditable="true" data-value="1"> A list item</span>
<span class="badge badge-danger badge-pill remove-element" role="button" >삭제</span>
</li>
</ul>
</div>
</div>
<div class="row m-2 text-right">
<div class="col-8">
<a id="btn_addCategory" href="#" class="btn btn-primary btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-plus"></i>
</span>
</a>
<a id="btn_save" href="#" class="btn btn-success btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-save"></i>
</span>
</a>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">닫기</button>
</div>
</div>
</div>
</div>
<script>
let deletedList =[];
function init(){
dragInit();
$(document).on("click","#btn_addCategory",function (){clickAddCategory();})
$(document).on("click","#btn_save",function (){clickSave();})
$(document).on("dblclick",".list-element",function(){ dblclickCategoryList(this);})
$(document).on("keydown",".list-element",function (event){
if (event.keyCode == 13) $("#btn_addCategory").focus()
})
$(document).on("click",".remove-element",function(){ clickRemoveElement(this);})
$('#myModal').on('shown.bs.modal', function () { initCategoryList(); })
}
function initCategoryList(){
$("#categoryList").empty();
deletedList = [];
$.ajax({
type: 'get'
, url: '/store-service/category'
, success: function (ajaxData, status, request) {
console.log(ajaxData)
$(ajaxData.data).each(function (index,element) {
$("#categoryList").append("<li class=\"list-group-item d-flex justify-content-between align-items-center\" role=\"button\">\n" +
" <span class=\"list-element\" contenteditable=\"true\" data-id=\""+element.categoryId+"\" >"+element.name+"</span>\n" +
" <span class=\"badge badge-danger badge-pill remove-element \" role=\"button\" >삭제</span>\n" +
" </li>");
});
}
});
}
function dragInit(){
$( "#categoryList" ).sortable({
revert: true,
revertDuration: 150
});
}
function clickAddCategory(){
$("#categoryList").append("<li class=\"list-group-item d-flex justify-content-between align-items-center\" role=\"button\">\n" +
" <span class=\"list-element\" contenteditable=\"true\" > A list item</span>\n" +
" <span class=\"badge badge-danger badge-pill remove-element \" role=\"button\" >삭제</span>\n" +
" </li>");
}
function clickSave(){
let categoryArr =[];
let order = 1;
$("#categoryList li .list-element").each(function (index,element) {
let category = {
categoryId : $(element).attr('data-id'),
name : $(element).text(),
order : order++
}
categoryArr.push(category)
});
let data = {
storeId : "1",
categoryList: categoryArr,
deletedList: deletedList
}
console.log(data)
$.ajax({
type: 'put'
, async: true
, url: '/store-service/category'
, data: JSON.stringify(data)
,dataType : "text"
, beforeSend: function(xhr) {
xhr.setRequestHeader("Content-type","application/json; charset=utf-8");
}
, success: function (ajaxData, status, request) {
alert("저장 성공");
}
, error: function(request, status, err) {
alert("저장 실패");
}
, complete: function(request, status) { }
});
$("#myModal").modal('toggle');
}
function dblclickCategoryList(ele) {
$(ele).focus();
const newRange = document.createRange();
newRange.setStart(ele, 1);
newRange.setEnd(ele, 1);
const selection = document.getSelection();
selection.removeAllRanges();
selection.addRange(newRange);
}
function clickRemoveElement(item){
let category = {
categoryId : $(item).parent().children(".list-element").attr('data-id'),
name : $(item).parent().children(".list-element").text(),
order:""
}
deletedList.push(category)
$(item).parent().remove();
}
</script>
</div>
</html>

View File

@@ -44,6 +44,7 @@
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->

View File

@@ -4,6 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
**/src/main/generated/
### STS ###
.apt_generated
@@ -26,6 +27,7 @@ out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/

View File

@@ -64,8 +64,17 @@
== snippets 작성 컨벤션
domain-httpRequestCode-etc
== 상품
=== 상품 조회
operation::item-get[snippets='curl-request,http-request,http-response,path-parameters,response-fields']
=== 상품 조회 (존재하지 않는 상품)
operation::item-get-notExistItemException[snippets='curl-request,http-request,http-response,path-parameters,response-fields']
== 주문
=== 점주 서비스 - 카테고리 페이지
- 페이지 offset : 6
== 카테고리 조회
operation::get-categoryList[snippets='curl-request,http-request,http-response,request-parameters,response-fields']
---
== 카테고리 수정
operation::put-categoryList[snippets='curl-request,http-request,http-response,request-parameters,response-fields']

View File

@@ -0,0 +1,71 @@
package com.justpickup.storeservice.domain.category.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QCategory is a Querydsl query type for Category
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QCategory extends EntityPathBase<Category> {
private static final long serialVersionUID = -1430562590L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QCategory category = new QCategory("category");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
public final ListPath<com.justpickup.storeservice.domain.item.entity.Item, com.justpickup.storeservice.domain.item.entity.QItem> items = this.<com.justpickup.storeservice.domain.item.entity.Item, com.justpickup.storeservice.domain.item.entity.QItem>createList("items", com.justpickup.storeservice.domain.item.entity.Item.class, com.justpickup.storeservice.domain.item.entity.QItem.class, PathInits.DIRECT2);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final StringPath name = createString("name");
public final NumberPath<Integer> order = createNumber("order", Integer.class);
public final com.justpickup.storeservice.domain.store.entity.QStore store;
public QCategory(String variable) {
this(Category.class, forVariable(variable), INITS);
}
public QCategory(Path<? extends Category> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QCategory(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QCategory(PathMetadata metadata, PathInits inits) {
this(Category.class, metadata, inits);
}
public QCategory(Class<? extends Category> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.store = inits.isInitialized("store") ? new com.justpickup.storeservice.domain.store.entity.QStore(forProperty("store"), inits.get("store")) : null;
}
}

View File

@@ -0,0 +1,67 @@
package com.justpickup.storeservice.domain.favoritestore.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QFavoriteStore is a Querydsl query type for FavoriteStore
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QFavoriteStore extends EntityPathBase<FavoriteStore> {
private static final long serialVersionUID = -356764916L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QFavoriteStore favoriteStore = new QFavoriteStore("favoriteStore");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final com.justpickup.storeservice.domain.store.entity.QStore store;
public final NumberPath<Long> userId = createNumber("userId", Long.class);
public QFavoriteStore(String variable) {
this(FavoriteStore.class, forVariable(variable), INITS);
}
public QFavoriteStore(Path<? extends FavoriteStore> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QFavoriteStore(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QFavoriteStore(PathMetadata metadata, PathInits inits) {
this(FavoriteStore.class, metadata, inits);
}
public QFavoriteStore(Class<? extends FavoriteStore> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.store = inits.isInitialized("store") ? new com.justpickup.storeservice.domain.store.entity.QStore(forProperty("store"), inits.get("store")) : null;
}
}

View File

@@ -0,0 +1,79 @@
package com.justpickup.storeservice.domain.item.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QItem is a Querydsl query type for Item
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QItem extends EntityPathBase<Item> {
private static final long serialVersionUID = -2047337460L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QItem item = new QItem("item");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
public final com.justpickup.storeservice.domain.category.entity.QCategory category;
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
public final ListPath<com.justpickup.storeservice.domain.itemoption.entity.ItemOption, com.justpickup.storeservice.domain.itemoption.entity.QItemOption> itemOptions = this.<com.justpickup.storeservice.domain.itemoption.entity.ItemOption, com.justpickup.storeservice.domain.itemoption.entity.QItemOption>createList("itemOptions", com.justpickup.storeservice.domain.itemoption.entity.ItemOption.class, com.justpickup.storeservice.domain.itemoption.entity.QItemOption.class, PathInits.DIRECT2);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final StringPath name = createString("name");
public final com.justpickup.storeservice.global.entity.QPhoto photo;
public final NumberPath<Long> price = createNumber("price", Long.class);
public final EnumPath<com.justpickup.storeservice.global.entity.Yn> salesYn = createEnum("salesYn", com.justpickup.storeservice.global.entity.Yn.class);
public final com.justpickup.storeservice.domain.store.entity.QStore store;
public QItem(String variable) {
this(Item.class, forVariable(variable), INITS);
}
public QItem(Path<? extends Item> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QItem(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QItem(PathMetadata metadata, PathInits inits) {
this(Item.class, metadata, inits);
}
public QItem(Class<? extends Item> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.category = inits.isInitialized("category") ? new com.justpickup.storeservice.domain.category.entity.QCategory(forProperty("category"), inits.get("category")) : null;
this.photo = inits.isInitialized("photo") ? new com.justpickup.storeservice.global.entity.QPhoto(forProperty("photo")) : null;
this.store = inits.isInitialized("store") ? new com.justpickup.storeservice.domain.store.entity.QStore(forProperty("store"), inits.get("store")) : null;
}
}

View File

@@ -0,0 +1,71 @@
package com.justpickup.storeservice.domain.itemoption.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QItemOption is a Querydsl query type for ItemOption
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QItemOption extends EntityPathBase<ItemOption> {
private static final long serialVersionUID = -374806570L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QItemOption itemOption = new QItemOption("itemOption");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
public final com.justpickup.storeservice.domain.item.entity.QItem item;
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final StringPath name = createString("name");
public final EnumPath<OptionType> optionType = createEnum("optionType", OptionType.class);
public final NumberPath<Long> price = createNumber("price", Long.class);
public QItemOption(String variable) {
this(ItemOption.class, forVariable(variable), INITS);
}
public QItemOption(Path<? extends ItemOption> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QItemOption(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QItemOption(PathMetadata metadata, PathInits inits) {
this(ItemOption.class, metadata, inits);
}
public QItemOption(Class<? extends ItemOption> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.item = inits.isInitialized("item") ? new com.justpickup.storeservice.domain.item.entity.QItem(forProperty("item"), inits.get("item")) : null;
}
}

View File

@@ -0,0 +1,51 @@
package com.justpickup.storeservice.domain.map.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
/**
* QMap is a Querydsl query type for Map
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QMap extends EntityPathBase<Map> {
private static final long serialVersionUID = -1253033268L;
public static final QMap map = new QMap("map");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public QMap(String variable) {
super(Map.class, forVariable(variable));
}
public QMap(Path<? extends Map> path) {
super(path.getType(), path.getMetadata());
}
public QMap(PathMetadata metadata) {
super(Map.class, metadata);
}
}

View File

@@ -0,0 +1,79 @@
package com.justpickup.storeservice.domain.review.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QReview is a Querydsl query type for Review
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QReview extends EntityPathBase<Review> {
private static final long serialVersionUID = -573894826L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QReview review = new QReview("review");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
public final StringPath content = createString("content");
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final NumberPath<Long> orderId = createNumber("orderId", Long.class);
public final com.justpickup.storeservice.global.entity.QPhoto photo;
public final com.justpickup.storeservice.domain.reviewreply.entity.QReviewReply reviewReply;
public final NumberPath<Integer> starRating = createNumber("starRating", Integer.class);
public final com.justpickup.storeservice.domain.store.entity.QStore store;
public final NumberPath<Long> userId = createNumber("userId", Long.class);
public QReview(String variable) {
this(Review.class, forVariable(variable), INITS);
}
public QReview(Path<? extends Review> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QReview(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QReview(PathMetadata metadata, PathInits inits) {
this(Review.class, metadata, inits);
}
public QReview(Class<? extends Review> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.photo = inits.isInitialized("photo") ? new com.justpickup.storeservice.global.entity.QPhoto(forProperty("photo")) : null;
this.reviewReply = inits.isInitialized("reviewReply") ? new com.justpickup.storeservice.domain.reviewreply.entity.QReviewReply(forProperty("reviewReply")) : null;
this.store = inits.isInitialized("store") ? new com.justpickup.storeservice.domain.store.entity.QStore(forProperty("store"), inits.get("store")) : null;
}
}

View File

@@ -0,0 +1,53 @@
package com.justpickup.storeservice.domain.reviewreply.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
/**
* QReviewReply is a Querydsl query type for ReviewReply
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QReviewReply extends EntityPathBase<ReviewReply> {
private static final long serialVersionUID = -1004430868L;
public static final QReviewReply reviewReply = new QReviewReply("reviewReply");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
public final StringPath content = createString("content");
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public QReviewReply(String variable) {
super(ReviewReply.class, forVariable(variable));
}
public QReviewReply(Path<? extends ReviewReply> path) {
super(path.getType(), path.getMetadata());
}
public QReviewReply(PathMetadata metadata) {
super(ReviewReply.class, metadata);
}
}

View File

@@ -0,0 +1,83 @@
package com.justpickup.storeservice.domain.store.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.PathInits;
/**
* QStore is a Querydsl query type for Store
*/
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QStore extends EntityPathBase<Store> {
private static final long serialVersionUID = 358375596L;
private static final PathInits INITS = PathInits.DIRECT2;
public static final QStore store = new QStore("store");
public final com.justpickup.storeservice.global.entity.QBaseEntity _super = new com.justpickup.storeservice.global.entity.QBaseEntity(this);
public final com.justpickup.storeservice.global.entity.QAddress address;
public final DateTimePath<java.time.LocalDateTime> businessEndTime = createDateTime("businessEndTime", java.time.LocalDateTime.class);
public final DateTimePath<java.time.LocalDateTime> businessStartTime = createDateTime("businessStartTime", java.time.LocalDateTime.class);
public final ListPath<com.justpickup.storeservice.domain.category.entity.Category, com.justpickup.storeservice.domain.category.entity.QCategory> categories = this.<com.justpickup.storeservice.domain.category.entity.Category, com.justpickup.storeservice.domain.category.entity.QCategory>createList("categories", com.justpickup.storeservice.domain.category.entity.Category.class, com.justpickup.storeservice.domain.category.entity.QCategory.class, PathInits.DIRECT2);
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;
//inherited
public final NumberPath<Long> createdBy = _super.createdBy;
public final NumberPath<Long> id = createNumber("id", Long.class);
public final ListPath<com.justpickup.storeservice.domain.item.entity.Item, com.justpickup.storeservice.domain.item.entity.QItem> items = this.<com.justpickup.storeservice.domain.item.entity.Item, com.justpickup.storeservice.domain.item.entity.QItem>createList("items", com.justpickup.storeservice.domain.item.entity.Item.class, com.justpickup.storeservice.domain.item.entity.QItem.class, PathInits.DIRECT2);
//inherited
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = _super.lastModifiedAt;
//inherited
public final NumberPath<Long> lastModifiedBy = _super.lastModifiedBy;
public final com.justpickup.storeservice.domain.map.entity.QMap map;
public final StringPath phoneNumber = createString("phoneNumber");
public final com.justpickup.storeservice.global.entity.QPhoto photo;
public final NumberPath<Long> userId = createNumber("userId", Long.class);
public QStore(String variable) {
this(Store.class, forVariable(variable), INITS);
}
public QStore(Path<? extends Store> path) {
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}
public QStore(PathMetadata metadata) {
this(metadata, PathInits.getFor(metadata, INITS));
}
public QStore(PathMetadata metadata, PathInits inits) {
this(Store.class, metadata, inits);
}
public QStore(Class<? extends Store> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.address = inits.isInitialized("address") ? new com.justpickup.storeservice.global.entity.QAddress(forProperty("address")) : null;
this.map = inits.isInitialized("map") ? new com.justpickup.storeservice.domain.map.entity.QMap(forProperty("map")) : null;
this.photo = inits.isInitialized("photo") ? new com.justpickup.storeservice.global.entity.QPhoto(forProperty("photo")) : null;
}
}

View File

@@ -0,0 +1,41 @@
package com.justpickup.storeservice.global.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
/**
* QAddress is a Querydsl query type for Address
*/
@Generated("com.querydsl.codegen.DefaultEmbeddableSerializer")
public class QAddress extends BeanPath<Address> {
private static final long serialVersionUID = -1606742445L;
public static final QAddress address = new QAddress("address");
public final StringPath city = createString("city");
public final StringPath street = createString("street");
public final StringPath zipcode = createString("zipcode");
public QAddress(String variable) {
super(Address.class, forVariable(variable));
}
public QAddress(Path<? extends Address> path) {
super(path.getType(), path.getMetadata());
}
public QAddress(PathMetadata metadata) {
super(Address.class, metadata);
}
}

View File

@@ -0,0 +1,43 @@
package com.justpickup.storeservice.global.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
/**
* QBaseEntity is a Querydsl query type for BaseEntity
*/
@Generated("com.querydsl.codegen.DefaultSupertypeSerializer")
public class QBaseEntity extends EntityPathBase<BaseEntity> {
private static final long serialVersionUID = -1618660523L;
public static final QBaseEntity baseEntity = new QBaseEntity("baseEntity");
public final DateTimePath<java.time.LocalDateTime> createdAt = createDateTime("createdAt", java.time.LocalDateTime.class);
public final NumberPath<Long> createdBy = createNumber("createdBy", Long.class);
public final DateTimePath<java.time.LocalDateTime> lastModifiedAt = createDateTime("lastModifiedAt", java.time.LocalDateTime.class);
public final NumberPath<Long> lastModifiedBy = createNumber("lastModifiedBy", Long.class);
public QBaseEntity(String variable) {
super(BaseEntity.class, forVariable(variable));
}
public QBaseEntity(Path<? extends BaseEntity> path) {
super(path.getType(), path.getMetadata());
}
public QBaseEntity(PathMetadata metadata) {
super(BaseEntity.class, metadata);
}
}

View File

@@ -0,0 +1,39 @@
package com.justpickup.storeservice.global.entity;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;
/**
* QPhoto is a Querydsl query type for Photo
*/
@Generated("com.querydsl.codegen.DefaultEmbeddableSerializer")
public class QPhoto extends BeanPath<Photo> {
private static final long serialVersionUID = 329628753L;
public static final QPhoto photo = new QPhoto("photo");
public final StringPath name = createString("name");
public final StringPath path = createString("path");
public QPhoto(String variable) {
super(Photo.class, forVariable(variable));
}
public QPhoto(Path<? extends Photo> path) {
super(path.getType(), path.getMetadata());
}
public QPhoto(PathMetadata metadata) {
super(Photo.class, metadata);
}
}

View File

@@ -0,0 +1,49 @@
package com.justpickup.storeservice.domain.category.dto;
import com.justpickup.storeservice.domain.category.entity.Category;
import com.justpickup.storeservice.domain.category.web.CategoryController;
import com.justpickup.storeservice.domain.item.entity.Item;
import com.justpickup.storeservice.domain.store.entity.Store;
import lombok.*;
import java.util.List;
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CategoryDto {
private Long id;
private String name;
private Integer order;
private Store store;
private List<Item> items;
public CategoryDto(Category category) {
this.id = category.getId();
this.name = category.getName();
this.order = category.getOrder();
this.store = category.getStore();
this.items = category.getItems();
}
public CategoryDto(CategoryController.PutCategoryRequest.Category category) {
this.id = category.getCategoryId();
this.name = category.getName();
this.order = category.getOrder();
}
public static Category createCategory(CategoryDto categoryDto){
Category category = Category.createCategory(
categoryDto.getId()
,categoryDto.getName()
, categoryDto.getOrder()
, categoryDto.getStore());
return category;
}
public void setStore(Store store){
this.store=store;
}
}

View File

@@ -8,7 +8,6 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
import static javax.persistence.FetchType.LAZY;
@@ -24,7 +23,8 @@ public class Category extends BaseEntity {
private String name;
private Integer orders;
@Column(name = "orders")
private Integer order;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "store_id")
@@ -43,4 +43,21 @@ public class Category extends BaseEntity {
items.add(item);
item.setCategory(this);
}
public void changeNameAndOrder(String name , Integer order){
this.name = name;
this.order = order;
}
private Category (Long id , String name, Integer order, Store store){
this.id = id;
this.name = name;
this.order = order;
this.store = store;
}
public static Category createCategory(Long id ,String name, Integer order, Store store){
return new Category(id,name,order,store);
}
}

View File

@@ -0,0 +1,11 @@
package com.justpickup.storeservice.domain.category.exception;
import com.justpickup.storeservice.global.exception.CustomException;
import org.springframework.http.HttpStatus;
public class NotFoundStoreException extends CustomException {
public NotFoundStoreException(HttpStatus status, String message){
super(status,message);
}
}

View File

@@ -0,0 +1,13 @@
package com.justpickup.storeservice.domain.category.repository;
import com.justpickup.storeservice.domain.category.entity.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {
List<Category> findAllByStoreIdOrderByOrder(Long storeId);
}

View File

@@ -0,0 +1,77 @@
package com.justpickup.storeservice.domain.category.service;
import com.justpickup.storeservice.domain.category.dto.CategoryDto;
import com.justpickup.storeservice.domain.category.entity.Category;
import com.justpickup.storeservice.domain.category.exception.NotFoundStoreException;
import com.justpickup.storeservice.domain.category.repository.CategoryRepository;
import com.justpickup.storeservice.domain.store.entity.Store;
import com.justpickup.storeservice.domain.store.repository.StoreRepository;
import com.justpickup.storeservice.global.exception.CustomException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CategoryService {
private final CategoryRepository categoryRepository;
private final StoreRepository storeRepository;
public List<CategoryDto> getCategoryList(Long storeId){
return categoryRepository.findAllByStoreIdOrderByOrder(storeId)
.stream()
.map(CategoryDto::new)
.collect(Collectors.toList());
}
@Transactional(readOnly = false)
public void putCategoryList(Long storeId , List<CategoryDto> categoryDtoList , List<CategoryDto> deletedCategoryDtoList ){
Store store = storeRepository.findById(storeId)
.orElseThrow(() -> new NotFoundStoreException(HttpStatus.BAD_REQUEST,"존재하지않는 Store"));
List<Category> categoryList =categoryDtoList.stream()
.map(categoryDto -> {
categoryDto.setStore(store);
return CategoryDto.createCategory(categoryDto);
})
.collect(Collectors.toList());
List<Category> deletedCategoryList =deletedCategoryDtoList.stream()
.map(categoryDto -> {
categoryDto.setStore(store);
return CategoryDto.createCategory(categoryDto);
})
.collect(Collectors.toList());
categoryList.forEach(
category -> {
if (category.getId() ==null)
categoryRepository.save(category);
else {
categoryRepository.findById(category.getId())
.orElseThrow(() -> new NotFoundStoreException(HttpStatus.BAD_REQUEST,"존재하지않는 Category"))
.changeNameAndOrder(category.getName(),category.getOrder());
}
}
);
deletedCategoryList.forEach(
category -> {
if (category.getId() !=null)
categoryRepository.delete(categoryRepository.findById(category.getId())
.orElseThrow(() -> new NotFoundStoreException(HttpStatus.BAD_REQUEST,"존재하지않는 Category")));
}
);
}
}

View File

@@ -0,0 +1,86 @@
package com.justpickup.storeservice.domain.category.web;
import com.justpickup.storeservice.domain.category.dto.CategoryDto;
import com.justpickup.storeservice.domain.category.service.CategoryService;
import com.justpickup.storeservice.global.dto.Result;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequiredArgsConstructor
@Slf4j
public class CategoryController {
private final CategoryService categoryService;
@GetMapping("/category")
public ResponseEntity getCategoryList( ){
// TODO: 2022-02-09 storeId hard coding 변경해야함
Long storeId = 1L;
List<CategoryDto> categoryList = categoryService.getCategoryList(storeId);
List<CategoryResponse> categoryResponseList = categoryList.stream()
.map(CategoryResponse::new)
.collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.OK)
.body(Result.createSuccessResult(categoryResponseList));
}
@Data
static class CategoryResponse{
private Long categoryId;
private String name;
private Integer order;
public CategoryResponse (CategoryDto categoryDto){
this.categoryId = categoryDto.getId();
this.name= categoryDto.getName();
this.order= categoryDto.getOrder();
}
}
@PutMapping("/category")
public ResponseEntity putCategoryList( @RequestBody PutCategoryRequest categoryRequest){
List<CategoryDto> categoryList = categoryRequest.getCategoryList().stream()
.map(CategoryDto::new)
.collect(Collectors.toList());
List<CategoryDto> deletedList = categoryRequest.getDeletedList().stream()
.map(CategoryDto::new)
.collect(Collectors.toList());
categoryService.putCategoryList(categoryRequest.getStoreId(),categoryList,deletedList);
return ResponseEntity.status(HttpStatus.NO_CONTENT)
.body(Result.createSuccessResult(null));
}
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public static class PutCategoryRequest{
private Long storeId;
private List<Category> categoryList;
private List<Category> deletedList;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Category{
private Long categoryId;
private String name;
private Integer order;
}
}
}

View File

@@ -0,0 +1,9 @@
package com.justpickup.storeservice.domain.store.repository;
import com.justpickup.storeservice.domain.store.entity.Store;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StoreRepository extends JpaRepository<Store,Long> {
}

View File

@@ -0,0 +1,12 @@
package com.justpickup.storeservice.global.client.exception;
import com.justpickup.storeservice.global.exception.CustomException;
import org.springframework.http.HttpStatus;
public class FeignClientException extends CustomException {
public FeignClientException(HttpStatus status, String message) {
super(status, message);
}
}

View File

@@ -0,0 +1,38 @@
package com.justpickup.storeservice.global.client.exception;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.justpickup.storeservice.global.dto.Result;
import feign.Response;
import feign.codec.ErrorDecoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@RequiredArgsConstructor
@Slf4j
public class FeignClientExceptionErrorDecoder implements ErrorDecoder {
private final ObjectMapper objectMapper;
@Override
public Exception decode(String methodKey, Response response) {
String message = null;
if (response.body() != null) {
try {
Result result = objectMapper.readValue(response.body().asInputStream(), Result.class);
message = result.getMessage();
} catch (IOException e) {
String catchErrorMessage = "Error Deserializing response body from failed feign request response.";
log.warn(methodKey + catchErrorMessage, e);
return new FeignClientException(HttpStatus.INTERNAL_SERVER_ERROR, "고객센터로 문의해주세요.");
}
}
return new FeignClientException(HttpStatus.INTERNAL_SERVER_ERROR, message);
}
}

View File

@@ -0,0 +1,10 @@
package com.justpickup.storeservice.global.client.user;
import lombok.Data;
@Data
public class GetCustomerResponse {
private Long userId;
private String userName;
private String phoneNumber;
}

View File

@@ -0,0 +1,13 @@
package com.justpickup.storeservice.global.client.user;
import com.justpickup.storeservice.global.dto.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "USER-SERVICE", url = "127.0.0.1:8001/user-service")
public interface UserClient {
@GetMapping("/customer/{userId}")
Result<GetCustomerResponse> getUser(@PathVariable("userId") Long userId);
}

View File

@@ -0,0 +1,14 @@
package com.justpickup.storeservice.global.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignClientConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

View File

@@ -0,0 +1,22 @@
package com.justpickup.storeservice.global.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Configuration
@EnableJpaAuditing
public class QueryDslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(this.entityManager);
}
}

View File

@@ -8,11 +8,10 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.pr
@TestConfiguration
public class TestConfig {
@Bean
public RestDocsMockMvcConfigurationCustomizer restDocsMockMvcConfigurationCustomizer() {
return configurer -> configurer.operationPreprocessors()
.withRequestDefaults(prettyPrint())
.withResponseDefaults(prettyPrint());
}
}
}

View File

@@ -0,0 +1,163 @@
package com.justpickup.storeservice.domain.category.web;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.justpickup.storeservice.config.TestConfig;
import com.justpickup.storeservice.domain.category.dto.CategoryDto;
import com.justpickup.storeservice.domain.category.service.CategoryService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.request.RequestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
@WebMvcTest(CategoryController.class)
@Import(TestConfig.class)
@AutoConfigureRestDocs(uriHost = "127.0.0.1",uriPort = 8001)
class CategoryControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private CategoryService categoryService;
@Test
@DisplayName("카테고리리스트_가져오기_성공")
void getCategoryList_success() throws Exception {
//given
Long storeId = 1L;
List<CategoryDto> categoryDtoList = new ArrayList<>();
categoryDtoList.add(CategoryDto.builder()
.id(10L)
.name("카테고리1")
.order(1)
.build());
categoryDtoList.add(CategoryDto.builder()
.id(11L)
.name("카테고리2")
.order(2)
.build());
BDDMockito.given(categoryService.getCategoryList(1L)).willReturn(categoryDtoList);
//when
ResultActions actions = mockMvc.perform(MockMvcRequestBuilders
.get("/category")
.param("storeId",String.valueOf(storeId))
);
//then
actions.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("data[0].categoryId").value("10"))
.andExpect(MockMvcResultMatchers.jsonPath("data[0].name").value("카테고리1"))
.andExpect(MockMvcResultMatchers.jsonPath("data[1].categoryId").value("11"))
.andExpect(MockMvcResultMatchers.jsonPath("data[1].name").value("카테고리2"))
.andDo(MockMvcResultHandlers.print())
.andDo(MockMvcRestDocumentation.document("get-categoryList",
requestParameters(
parameterWithName("storeId").description("매장 고유 번호")
),
responseFields(
fieldWithPath("code").description("결과 코드 SUCCESS/ERROR"),
fieldWithPath("message").description("메시지"),
fieldWithPath("data[*].categoryId").description("카테고리 고유 번호"),
fieldWithPath("data[*].name").description("카테고리 명"),
fieldWithPath("data[*].order").description("순서")
)
));
}
@Test
@DisplayName("카테고리리스트_수정_성공")
void putCategoryList_success() throws Exception {
//given
Long storeId = 1L;
List<CategoryController.PutCategoryRequest.Category> categoryList = new ArrayList<>();
categoryList.add(CategoryController.PutCategoryRequest.Category.builder()
.categoryId(10L)
.name("카테고리1")
.order(2)
.build());
categoryList.add(CategoryController.PutCategoryRequest.Category.builder()
.categoryId(11L)
.name("카테고리2")
.order(1)
.build());
List<CategoryController.PutCategoryRequest.Category> deletedList = new ArrayList<>();
deletedList.add(CategoryController.PutCategoryRequest.Category.builder()
.categoryId(11L)
.name("Non Coffee")
.order(3)
.build());
CategoryController.PutCategoryRequest putCategoryRequest =
CategoryController.PutCategoryRequest.builder()
.storeId(storeId)
.categoryList(categoryList)
.deletedList(deletedList)
.build();
//when
ResultActions actions = mockMvc.perform(
MockMvcRequestBuilders
.put("/category")
.content(objectMapper.writeValueAsString(putCategoryRequest) )
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
);
//then
actions.andExpect(MockMvcResultMatchers.status().isNoContent())
.andDo(MockMvcResultHandlers.print())
.andDo(MockMvcRestDocumentation.document("put-categoryList",
requestFields(
fieldWithPath("storeId").description("매장 고유 번호"),
fieldWithPath("categoryList").description("수정된 카테고리 리스트"),
fieldWithPath("categoryList[*].categoryId").description("카테고리 고유 번호"),
fieldWithPath("categoryList[*].name").description("카테고리명"),
fieldWithPath("categoryList[*].order").description("순서"),
fieldWithPath("deletedList").description("삭제된 카테고리 리스트"),
fieldWithPath("deletedList[*].categoryId").description("카테고리 고유 번호"),
fieldWithPath("deletedList[*].name").description("카테고리명"),
fieldWithPath("deletedList[*].order").description("순서")
)
));
}
}