Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ repositories {
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation group: 'com.auth0', name: 'java-jwt', version: '4.3.0'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/shop/mtcoding/metamall/MetamallApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import shop.mtcoding.metamall.model.orderproduct.OrderProduct;
import shop.mtcoding.metamall.model.orderproduct.OrderProductRepository;
import shop.mtcoding.metamall.model.ordersheet.OrderSheet;
import shop.mtcoding.metamall.model.ordersheet.OrderSheetRepository;
import shop.mtcoding.metamall.model.order.product.OrderProductRepository;
import shop.mtcoding.metamall.model.order.sheet.OrderSheetRepository;
import shop.mtcoding.metamall.model.product.ProductRepository;
import shop.mtcoding.metamall.model.user.User;
import shop.mtcoding.metamall.model.user.UserRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ public class FilterRegisterConfig {
public FilterRegistrationBean<?> jwtVerifyFilterAdd() {
FilterRegistrationBean<JwtVerifyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new JwtVerifyFilter());
registration.addUrlPatterns("/user/*");
registration.addUrlPatterns("/user/*"); //토큰
registration.addUrlPatterns("/products/*"); //토큰
registration.addUrlPatterns("/orders/*"); //토큰
registration.addUrlPatterns("/admin/*");
registration.addUrlPatterns("/seller/*");
registration.setOrder(1);
return registration;
}
}
}
7 changes: 7 additions & 0 deletions src/main/java/shop/mtcoding/metamall/config/FinalObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package shop.mtcoding.metamall.config;

public class FinalObject {
public final static String ROLE_USER = "USER";
public final static String ROLE_SELLER = "SELLER";
public final static String ROLE_ADMIN = "ADMIN";
}
49 changes: 49 additions & 0 deletions src/main/java/shop/mtcoding/metamall/config/MyWebMvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package shop.mtcoding.metamall.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import shop.mtcoding.metamall.core.intercepter.MyAdminInterceptor;
import shop.mtcoding.metamall.core.intercepter.MySellerInterceptor;
import shop.mtcoding.metamall.core.resolver.MySessionArgumentResolver;

import java.util.List;

@RequiredArgsConstructor
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

private final MyAdminInterceptor adminInterceptor;
private final MySellerInterceptor sellerInterceptor;
private final MySessionArgumentResolver mySessionArgumentResolver;

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*") // GET, POST, PUT, DELETE (Javascript 요청 허용)
.allowedOriginPatterns("*") // 모든 IP 주소 허용 (프론트 앤드 IP만 허용하게 변경해야함. * 안됨)
.allowCredentials(true)
.exposedHeaders("Authorization"); // 옛날에는 디폴트로 브라우저에 노출되어 있었는데 지금은 아님
}


// AOP는 매개변수 값 확인해서 권한 비교해야할 때 사용
// Interceptor는 세션 권한으로 체크할 때 사용
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminInterceptor)
.addPathPatterns("/admin/**");

registry.addInterceptor(sellerInterceptor)
.addPathPatterns("/seller/**");
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(mySessionArgumentResolver);
}
}
18 changes: 0 additions & 18 deletions src/main/java/shop/mtcoding/metamall/config/WebMvcConfig.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package shop.mtcoding.metamall.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import shop.mtcoding.metamall.core.exception.Exception400;
import shop.mtcoding.metamall.dto.ResponseDTO;
import shop.mtcoding.metamall.dto.user.UserRequest;
import shop.mtcoding.metamall.model.user.User;
import shop.mtcoding.metamall.model.user.UserRepository;

import javax.validation.Valid;

/**
* 권한 변경
*/
@RequiredArgsConstructor
@RestController
public class AdminController {
private final UserRepository userRepository;

@Transactional // 트랜잭션이 시작되지 않으면 강제로 em.flush() 를 할 수 없고, 더티체킹도 할 수 없다. (원래는 서비스에서)
@PutMapping("/admin/user/{id}/role")
public ResponseEntity<?> updateRole(@PathVariable Long id, @RequestBody @Valid UserRequest.RoleUpdateDTO roleUpdateDTO, Errors errors) {
User userPS = userRepository.findById(id)
.orElseThrow(()-> new Exception400("id", "해당 유저를 찾을 수 없습니다"));
userPS.updateRole(roleUpdateDTO.getRole());

ResponseDTO<?> responseDto = new ResponseDTO<>();
return ResponseEntity.ok().body(responseDto);
}
}
152 changes: 152 additions & 0 deletions src/main/java/shop/mtcoding/metamall/controller/OrderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package shop.mtcoding.metamall.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;
import shop.mtcoding.metamall.model.order.product.OrderProductRepository;
import shop.mtcoding.metamall.model.order.sheet.OrderSheetRepository;
import shop.mtcoding.metamall.model.product.ProductRepository;
import shop.mtcoding.metamall.model.user.UserRepository;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import shop.mtcoding.metamall.core.annotation.MySessionStore;
import shop.mtcoding.metamall.core.exception.Exception400;
import shop.mtcoding.metamall.core.exception.Exception403;
import shop.mtcoding.metamall.core.session.SessionUser;
import shop.mtcoding.metamall.dto.ResponseDTO;
import shop.mtcoding.metamall.dto.order.OrderRequest;
import shop.mtcoding.metamall.model.order.product.OrderProduct;
import shop.mtcoding.metamall.model.order.product.OrderProductRepository;
import shop.mtcoding.metamall.model.order.sheet.OrderSheet;
import shop.mtcoding.metamall.model.order.sheet.OrderSheetRepository;
import shop.mtcoding.metamall.model.product.Product;
import shop.mtcoding.metamall.model.product.ProductRepository;
import shop.mtcoding.metamall.model.user.User;
import shop.mtcoding.metamall.model.user.UserRepository;

import javax.validation.Valid;
import java.util.List;

/**
* 주문하기(고객), 주문목록보기(고객), 주문목록보기(판매자), 주문취소하기(고객), 주문취소하기(판매자)
*/
@RequiredArgsConstructor
@RestController
public class OrderController {
private final OrderProductRepository orderProductRepository;
private final OrderSheetRepository orderSheetRepository;
private final ProductRepository productRepository;
private final UserRepository userRepository;

@Transactional
@PostMapping("/orders")
public ResponseEntity<?> save(@RequestBody @Valid OrderRequest.SaveDTO saveDTO, Errors errors, @MySessionStore SessionUser sessionUser) {
// 1. 세션값으로 유저 찾기
User userPS = userRepository.findById(sessionUser.getId())
.orElseThrow(
() -> new Exception400("id", "해당 유저를 찾을 수 없습니다")
);

// 2. 상품 찾기 (여러개의 상품)
List<Product> productListPS =
productRepository.findAllById(saveDTO.getIds());

// 3. 주문 상품
List<OrderProduct> orderProductListPS = saveDTO.toEntity(productListPS);

// 4. 주문서 만들기
Integer totalPrice = orderProductListPS.stream().mapToInt((orderProduct)-> orderProduct.getOrderPrice()).sum();
OrderSheet orderSheet = OrderSheet.builder()
.user(userPS)
.totalPrice(totalPrice)
.build();
OrderSheet orderSheetPS = orderSheetRepository.save(orderSheet);

// 5. 주문서에 상품추가하고 재고감소하기
orderProductListPS.stream().forEach(
(orderProductPS -> {
orderSheetPS.addOrderProduct(orderProductPS);
orderProductPS.getProduct().updateQty(orderProductPS.getCount());
})
);

// 6. 응답하기
ResponseDTO<?> responseDto = new ResponseDTO<>().data(orderSheetPS);
return ResponseEntity.ok().body(responseDto);
}

// 유저 주문서 조회
@GetMapping("/orders")
public ResponseEntity<?> findByUserId(@MySessionStore SessionUser sessionUser){
List<OrderSheet> orderSheetListPS = orderSheetRepository.findByUserId(sessionUser.getId());
ResponseDTO<?> responseDto = new ResponseDTO<>().data(orderSheetListPS);
return ResponseEntity.ok().body(responseDto);
}

// 그림 설명 필요!!
// 배달의 민족은 하나의 판매자에게서만 주문을 할 수 있다. (다른 판매자의 상품이 담기면, 하나만 담을 수 있게 로직이 변한다)
// 쇼핑몰은 여러 판매자에게서 주문을 할 수 있다.

// 판매자 주문서 조회
@GetMapping("/seller/orders")
public ResponseEntity<?> findBySellerId(){
// 판매자는 한명이기 때문에 orderProductRepository.findAll() 해도 된다.
List<OrderSheet> orderSheetListPS = orderSheetRepository.findAll();
ResponseDTO<?> responseDto = new ResponseDTO<>().data(orderSheetListPS);
return ResponseEntity.ok().body(responseDto);
}

// 유저 주문 취소
@DeleteMapping("/orders/{id}")
public ResponseEntity<?> delete(@PathVariable Long id, @MySessionStore SessionUser sessionUser){
// 1. 주문서 찾기
OrderSheet orderSheetPS = orderSheetRepository.findById(id).orElseThrow(
()-> new Exception400("id", "해당 주문을 찾을 수 없습니다")
);

// 2. 해당 주문서의 주인 여부 확인
if(!orderSheetPS.getUser().getId().equals(sessionUser.getId())){
throw new Exception403("권한이 없습니다");
}

// 3. 재고 변경하기
orderSheetPS.getOrderProductList().stream().forEach(orderProduct -> {
orderProduct.getProduct().rollbackQty(orderProduct.getCount());
});

// 4. 주문서 삭제하기 (casecade 옵션)
orderSheetRepository.delete(orderSheetPS);

// 5. 응답하기
ResponseDTO<?> responseDto = new ResponseDTO<>();
return ResponseEntity.ok().body(responseDto);
}

// 판매자 주문 취소
@DeleteMapping("/seller/orders/{id}")
public ResponseEntity<?> deleteSeller(@PathVariable Long id){
// 1. 주문서 찾기
OrderSheet orderSheetPS = orderSheetRepository.findById(id).orElseThrow(
()-> new Exception400("id", "해당 주문을 찾을 수 없습니다")
);

// 2. 재고 변경하기
orderSheetPS.getOrderProductList().stream().forEach(orderProduct -> {
orderProduct.getProduct().rollbackQty(orderProduct.getCount());
});

// 3. 주문서 삭제하기 (casecade 옵션)
orderSheetRepository.delete(orderSheetPS);

// 4. 응답하기
ResponseDTO<?> responseDto = new ResponseDTO<>();
return ResponseEntity.ok().body(responseDto);
}

// 성공 200 통일
// 실패 400, 401, 403, 404, 500
// GET, POST 밖에 못쓸때는 @PostMapping("/seller/orders/{id}/delete") 이런식으로
}
Loading