feat(customer-vue, order-service): 상품 상세페이지, 장바구니 기능 추가

- 상품 상세페이지
- 장바구니 기능 추가
This commit is contained in:
hoon7566
2022-03-08 17:14:25 +09:00
parent 053f33654a
commit b6583eaec2
19 changed files with 429 additions and 12 deletions

View File

@@ -8,5 +8,13 @@ export default {
}
}
return axios.get(process.env.VUE_APP_ORDER_API_URL + "/order/history", options);
},
addItemToBasket(item) {
item.itemOptionIds =[];
for (const itemId of item.otherOptions) {
item.itemOptionIds.push(itemId)
}
item.itemOptionIds.push(item.requireOption)
return axios.post(process.env.VUE_APP_ORDER_API_URL+'/order/item', item);
}
}

View File

@@ -29,7 +29,7 @@ export default {
})
},
getItemById(itemId){
return axios.get(process.env.VUE_APP_CUSTOMER_SERVICE_BASEURL+'/store-service/item/'+itemId)
return axios.get(process.env.VUE_APP_STORE_API_URL+'/item/'+itemId)
},
saveItem(method, itemData){
return axios({

View File

@@ -61,6 +61,11 @@ const routes = [
},
]
},
{
path: "/item/:storeId/:itemId",
name: 'itemDetail',
component: () => import('../views/ItemDetail')
},
{
path: '/auth',

View File

@@ -1,5 +1,5 @@
<template>
<v-container>
<v-container >
<v-row justify="center">
<v-col>
<div class="text-h5">

View File

@@ -0,0 +1,183 @@
<template>
<v-main>
<v-container >
<v-row>
<v-col>
<v-img :src="require('@/assets/store.jpeg')"
:aspect-ratio="16/9"
/>
</v-col>
</v-row>
<v-row >
<v-col >
<v-subheader >
{{itemData.name}}
</v-subheader>
</v-col>
</v-row>
<v-row >
<v-col class="text-h3">
<v-container>
<span class="text-h3">가격</span>
</v-container>
</v-col>
<v-spacer></v-spacer>
<v-spacer></v-spacer>
<v-col >
<v-container>
<div class="text-h3">{{ itemData.price }}</div>
</v-container>
</v-col>
</v-row>
<v-divider/>
<v-row >
<v-col >
<v-container>
<div class="text-h3">수량</div>
</v-container>
</v-col>
<v-spacer></v-spacer>
<v-spacer></v-spacer>
<v-col >
<v-container>
<v-text-field
v-model="setItem.count"
append-outer-icon="mdi-plus"
prepend-icon="mdi-minus"
filled
label="수량"
type="number"
@click:append-outer="addItemCount(1)"
@click:prepend="addItemCount(-1)"
/>
</v-container>
</v-col>
</v-row>
<v-divider/>
<v-row>
<v-col>
<v-container>
<div class="text-h3"> 필수 옵션</div>
<v-radio-group v-model="setItem.requireOption">
<v-radio
v-for="itemOption in requireGroup"
:key="itemOption.id"
:label="itemOption.name"
:value="itemOption.id"
/>
</v-radio-group>
</v-container>
</v-col>
</v-row>
<v-divider/>
<v-row>
<v-col>
<v-container>
<div class="text-h3"> 추가 옵션</div>
<v-checkbox
class="shrink mr-2 mt-0"
v-model="setItem.otherOptions"
v-for="itemOption in otherGroup"
:key="itemOption.id"
:label="itemOption.name"
:value="itemOption.id"
/>
</v-container>
</v-col>
</v-row>
<v-btn
block
@click="addItem"
>담기</v-btn>
</v-container>
</v-main>
</template>
<script>
import storeApi from "@/api/store";
import orderApi from "@/api/order";
export default {
name: "ItemDetail",
mounted() {
console.log(this.$route.params)
this.storeId = this.$route.params.storeId
this.itemId = this.$route.params.itemId
this.setItem.storeId = this.storeId;
this.getItemData()
},
computed: {
requireGroup:function(){
return this.parseGroup('REQUIRED')
},
otherGroup:function(){
return this.parseGroup('OTHER')
}
},
data: function() {
return {
storeId: -1,
itemId: -1,
itemData: {
itemOptions:[],
},
setItem:{
count:0,
storeId:-1,
itemId:-1,
price:0,
requireOption:{},
otherOptions:[],
},
}
},
methods: {
getItemData: function (){
storeApi.getItemById(this.itemId)
.then(response=>{
console.log(response)
this.itemData = response.data.data;
this.setItem.itemId = this.itemData.id;
this.setItem.price = this.itemData.price;
})
.catch(error=>{
console.log(error)
})
},
parseGroup: function (type){
let group= [];
for (const groupElement of this.itemData.itemOptions) {
if(groupElement.optionType===type) group.push(groupElement)
}
return group;
},
addItemCount: function (v){
this.setItem.count =
this.setItem.count+v >=0? this.setItem.count+v: 0;
},
addItem: function(){
console.log(this.setItem)
orderApi.addItemToBasket(this.setItem)
.then(response=>{
console.log(response)
})
.catch(error=>{
console.log(error)
})
}
},
}
</script>
<style scoped>
.container {
max-width: 768px;
background-color: white;
height: 100%;
}
main {
background-color: #f2f2f2!important;
}
</style>

View File

@@ -64,6 +64,22 @@ public class Order extends BaseEntity {
return order;
}
public static Order of(Long userId, Long userCouponId, Long storeId, Long orderPrice,
OrderItem orderItem) {
Order order = new Order();
order.userId = userId;
order.userCouponId = userCouponId;
order.storeId = storeId;
order.orderPrice = orderPrice;
order.addOrderItem(orderItem);
order.usedPoint = 0L;
order.orderStatus = OrderStatus.PLACED;
order.orderTime = LocalDateTime.now();
return order;
}
public void setTransaction(Transaction transaction) {
this.transaction = transaction;
transaction.setOrder(this);

View File

@@ -3,6 +3,8 @@ package com.justpickup.orderservice.domain.order.repository;
import com.justpickup.orderservice.domain.order.entity.Order;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderRepository extends JpaRepository<Order, Long> {
import java.util.Optional;
public interface OrderRepository extends JpaRepository<Order, Long> {
Optional<Order> findByUserId(Long userId);
}

View File

@@ -3,6 +3,7 @@ package com.justpickup.orderservice.domain.order.service;
import com.justpickup.orderservice.domain.order.dto.OrderDto;
import com.justpickup.orderservice.domain.order.dto.OrderSearchCondition;
import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
@@ -13,4 +14,5 @@ public interface OrderService {
List<OrderDto> findOrderMain(OrderSearchCondition condition, Long storeId);
Page<OrderDto> findPrevOrderMain(PrevOrderSearch search, Pageable pageable, Long storeId);
SliceImpl<OrderDto> findOrderHistory(Pageable pageable, Long userId);
void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId);
}

View File

@@ -6,6 +6,11 @@ import com.justpickup.orderservice.domain.order.dto.PrevOrderSearch;
import com.justpickup.orderservice.domain.order.entity.Order;
import com.justpickup.orderservice.domain.order.repository.OrderRepository;
import com.justpickup.orderservice.domain.order.repository.OrderRepositoryCustom;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto;
import com.justpickup.orderservice.domain.orderItem.entity.OrderItem;
import com.justpickup.orderservice.domain.orderItem.repository.OrderItemRepository;
import com.justpickup.orderservice.domain.orderItemOption.entity.OrderItemOption;
import com.justpickup.orderservice.domain.orderItemOption.repository.OrderItemOptionRepository;
import com.justpickup.orderservice.global.client.store.GetItemResponse;
import com.justpickup.orderservice.global.client.store.StoreClient;
import com.justpickup.orderservice.global.client.user.GetCustomerResponse;
@@ -20,6 +25,7 @@ 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
@@ -29,6 +35,8 @@ import java.util.stream.Collectors;
public class OrderServiceImpl implements OrderService {
private final OrderRepository orderRepository;
private final OrderItemRepository orderItemRepository;
private final OrderItemOptionRepository orderItemOptionRepository;
private final OrderRepositoryCustom orderRepositoryCustom;
private final StoreClient storeClient;
private final UserClient userClient;
@@ -91,4 +99,31 @@ public class OrderServiceImpl implements OrderService {
});
});
}
@Override
@Transactional
public void addItemToBasket(OrderItemDto orderItemDto,Long storeId, Long userId) {
orderItemDto.getCount();
//orderItemOption Entity를 생성한다.
List<OrderItemOption> orderItemOptions = orderItemDto.getOrderItemOptionDtoList()
.stream().map(orderItemOptionDto -> OrderItemOption.of(orderItemDto.getId()))
.collect(Collectors.toList());
//orderItem을 Entity를 생성한다.
OrderItem orderItem = OrderItem.of(orderItemDto.getItemId()
, orderItemDto.getPrice()
, orderItemDto.getCount()
,orderItemOptions);
//HARD_CODE
Long userCouponId=0L;
Optional<Order> optionalOrder = orderRepository.findByUserId(userId);
if(optionalOrder.isPresent()){
optionalOrder.get().addOrderItem(orderItem);
}else{
orderRepository.save(Order.of(userId,userCouponId,storeId,orderItemDto.getPrice(),orderItem));
}
}
}

View File

@@ -5,6 +5,7 @@ import com.justpickup.orderservice.domain.order.entity.OrderStatus;
import com.justpickup.orderservice.domain.order.service.OrderService;
import com.justpickup.orderservice.domain.orderItem.dto.OrderItemDto;
import com.justpickup.orderservice.global.dto.Result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
@@ -14,10 +15,7 @@ import org.springframework.data.domain.SliceImpl;
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.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.time.format.DateTimeFormatter;
import java.util.List;
@@ -89,4 +87,37 @@ public class OrderCustomerApiController {
}
}
}
/**
* order
*/
@PostMapping("item")
public ResponseEntity addItemToBasket( @RequestBody RequestItem requestItem,
@RequestHeader(value = "user-id") String userId){
OrderItemDto orderItemDto = OrderItemDto.of(-1L,
requestItem.itemId,
requestItem.getPrice(),
requestItem.getCount(),
requestItem.getItemOptionIds());
orderService.addItemToBasket(orderItemDto,requestItem.getStoreId() ,Long.parseLong(userId));
return ResponseEntity.status(HttpStatus.NO_CONTENT)
.body(Result.createSuccessResult(null));
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class RequestItem{
private Long itemId;
private Long storeId;
private Long price;
private Long count;
private List<Long> itemOptionIds ;
}
}

View File

@@ -1,10 +1,14 @@
package com.justpickup.orderservice.domain.orderItem.dto;
import com.justpickup.orderservice.domain.orderItem.entity.OrderItem;
import com.justpickup.orderservice.domain.orderItemOption.dto.OrderItemOptionDto;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.stream.Collectors;
@Getter @NoArgsConstructor
public class OrderItemDto {
@@ -14,7 +18,7 @@ public class OrderItemDto {
private String itemName;
// private List<OrderItemOptionDto> orderItemOptionDtoList;
private List<OrderItemOptionDto> orderItemOptionDtoList;
private Long price;
@@ -38,6 +42,18 @@ public class OrderItemDto {
.build();
}
public static OrderItemDto of(Long id, Long itemId, Long price, Long count, List<Long> itemOptionIds) {
OrderItemDto orderItemDto = new OrderItemDto();
orderItemDto.id = id;
orderItemDto.itemId = itemId;
orderItemDto.price = price;
orderItemDto.count = count;
orderItemDto.orderItemOptionDtoList = itemOptionIds.stream()
.map(OrderItemOptionDto::new)
.collect(Collectors.toList());
return orderItemDto;
}
// == 변수 변경 메소드 == //
public void setItemName(String itemName) {
this.itemName = itemName;

View File

@@ -54,4 +54,15 @@ public class OrderItem extends BaseEntity {
}
return orderItem;
}
public static OrderItem of(Long itemId, Long price, Long count, List<OrderItemOption> orderItemOptions) {
OrderItem orderItem = new OrderItem();
orderItem.itemId = itemId;
orderItem.price = price;
orderItem.count = count;
for (OrderItemOption orderItemOption : orderItemOptions) {
orderItem.addOrderItemOption(orderItemOption);
}
return orderItem;
}
}

View File

@@ -0,0 +1,14 @@
package com.justpickup.orderservice.domain.orderItemOption.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class OrderItemOptionDto {
private Long id;
public OrderItemOptionDto(Long id) {
this.id = id;
}
}

View File

@@ -32,4 +32,11 @@ public class OrderItemOption extends BaseEntity {
OrderItemOption orderItemOption = new OrderItemOption();
return orderItemOption;
}
public static OrderItemOption of(Long itemOptionId) {
OrderItemOption orderItemOption = new OrderItemOption();
orderItemOption.itemOptionId = itemOptionId;
return orderItemOption;
}
}

View File

@@ -0,0 +1,8 @@
package com.justpickup.orderservice.domain.orderItemOption.repository;
import com.justpickup.orderservice.domain.orderItemOption.entity.OrderItemOption;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderItemOptionRepository extends JpaRepository<OrderItemOption , Long> {
}

View File

@@ -7,7 +7,7 @@ spring:
jpa:
hibernate:
ddl-auto: validate
ddl-auto: create-drop
generate-ddl: true
open-in-view: false
properties:

View File

@@ -0,0 +1,81 @@
package com.justpickup.storeservice.domain.item.web;
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.OptionType;
import com.justpickup.storeservice.global.dto.Result;
import com.justpickup.storeservice.global.entity.Yn;
import lombok.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/customer")
public class ItemCustomerApiController {
private final ItemService itemService;
@GetMapping("/item/{itemId}")
public ResponseEntity getItem(@PathVariable("itemId") Long itemId) {
ItemDto itemByItemId = itemService.findFullItemByItemId(itemId);
GetItemResponse getItemResponse = new GetItemResponse(itemByItemId);
return ResponseEntity.status(HttpStatus.OK)
.body(Result.createSuccessResult(getItemResponse));
}
@Data @NoArgsConstructor @AllArgsConstructor
static class GetItemResponse {
private Long id;
private String name;
private Yn salesYn;
private Long price;
private Long CategoryId;
private List<ItemOptionResponse> itemOptions;
public GetItemResponse(ItemDto itemDto) {
this.id = itemDto.getId();
this.name = itemDto.getName();
this.salesYn = itemDto.getSalesYn();
this.price = itemDto.getPrice();
this.CategoryId = itemDto.getCategoryDto().getId();
this.itemOptions = itemDto.getItemOptions()
.stream().map(ItemOptionResponse::new)
.collect(Collectors.toList());
}
@Data
static class ItemOptionResponse{
private Long id;
private OptionType optionType;
private Long price;
private String name;
public ItemOptionResponse(ItemOptionDto itemOptionDto) {
this.id = itemOptionDto.getId();
this.optionType = itemOptionDto.getOptionType();
this.price = itemOptionDto.getPrice();
this.name = itemOptionDto.getName();
}
}
}
}

View File

@@ -7,7 +7,7 @@ spring:
jpa:
hibernate:
ddl-auto: validate
ddl-auto: create-drop
generate-ddl: true
open-in-view: false
properties:

View File

@@ -8,8 +8,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import java.util.List;
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {