From b8a0f64f678c30657f01417b57d5d3b665a1a76b Mon Sep 17 00:00:00 2001 From: BOMIN LYU Date: Tue, 23 Jul 2024 23:10:17 +0900 Subject: [PATCH 01/42] Move from spring-gift-enhancement/step3 --- README.md | 44 ++++- build.gradle | 8 + .../LoginMemberArgumentResolver.java | 61 +++++++ .../gift/Annotation/LoginMemberResolver.java | 11 ++ src/main/java/gift/Config/WebConfig.java | 22 +++ .../gift/Controller/CategoryController.java | 25 +++ .../Controller/GlobalExceptionHandler.java | 45 +++++ .../gift/Controller/MemberController.java | 72 ++++++++ .../gift/Controller/OptionController.java | 83 +++++++++ .../gift/Controller/ProductController.java | 91 ++++++++++ .../gift/Controller/WishlistController.java | 66 +++++++ .../DatabaseInitializer.java | 32 ++++ src/main/java/gift/Entity/Category.java | 41 +++++ src/main/java/gift/Entity/Member.java | 68 ++++++++ src/main/java/gift/Entity/Option.java | 69 ++++++++ src/main/java/gift/Entity/Product.java | 78 +++++++++ src/main/java/gift/Entity/Wishlist.java | 87 ++++++++++ src/main/java/gift/Entity/WishlistId.java | 36 ++++ .../gift/Exception/ForbiddenException.java | 11 ++ .../gift/Exception/UnauthorizedException.java | 11 ++ src/main/java/gift/Mapper/Mapper.java | 88 ++++++++++ src/main/java/gift/Model/CategoryDto.java | 32 ++++ src/main/java/gift/Model/MemberDto.java | 61 +++++++ src/main/java/gift/Model/OptionDto.java | 71 ++++++++ src/main/java/gift/Model/OrderRequestDto.java | 50 ++++++ src/main/java/gift/Model/ProductDto.java | 83 +++++++++ src/main/java/gift/Model/WishlistDto.java | 70 ++++++++ .../Repository/CategoryJpaRepository.java | 8 + .../gift/Repository/MemberJpaRepository.java | 14 ++ .../gift/Repository/OptionJpaRepository.java | 11 ++ .../gift/Repository/ProductJpaRepository.java | 14 ++ .../Repository/WishlistJpaRepository.java | 24 +++ .../java/gift/Service/CategoryService.java | 35 ++++ src/main/java/gift/Service/MemberService.java | 51 ++++++ src/main/java/gift/Service/OptionService.java | 58 +++++++ .../java/gift/Service/ProductService.java | 73 ++++++++ .../java/gift/Service/WishlistService.java | 58 +++++++ src/main/java/gift/Utils/JwtUtil.java | 55 ++++++ src/main/resources/application.properties | 10 ++ src/main/resources/templates/login.html | 30 ++++ src/main/resources/templates/option_form.html | 36 ++++ .../resources/templates/product_form.html | 51 ++++++ src/main/resources/templates/products.html | 143 ++++++++++++++++ src/main/resources/templates/register.html | 29 ++++ .../resources/templates/user_products.html | 100 +++++++++++ src/main/resources/templates/wishlist.html | 81 +++++++++ .../MemberDtoRepositoryTest.java | 98 +++++++++++ .../RepositoryTest/OptionRepositoryTest.java | 115 +++++++++++++ .../ProductDtoRepositoryTest.java | 128 ++++++++++++++ .../WishlistRepositoryTest.java | 162 ++++++++++++++++++ .../gift/ServiceTest/MemberServiceTest.java | 94 ++++++++++ .../gift/ServiceTest/OptionServiceTest.java | 123 +++++++++++++ .../gift/ServiceTest/ProductServiceTest.java | 118 +++++++++++++ .../gift/ServiceTest/WishlistServiceTest.java | 127 ++++++++++++++ 54 files changed, 3261 insertions(+), 1 deletion(-) create mode 100644 src/main/java/gift/Annotation/LoginMemberArgumentResolver.java create mode 100644 src/main/java/gift/Annotation/LoginMemberResolver.java create mode 100644 src/main/java/gift/Config/WebConfig.java create mode 100644 src/main/java/gift/Controller/CategoryController.java create mode 100644 src/main/java/gift/Controller/GlobalExceptionHandler.java create mode 100644 src/main/java/gift/Controller/MemberController.java create mode 100644 src/main/java/gift/Controller/OptionController.java create mode 100644 src/main/java/gift/Controller/ProductController.java create mode 100644 src/main/java/gift/Controller/WishlistController.java create mode 100644 src/main/java/gift/DatabaseInitialize/DatabaseInitializer.java create mode 100644 src/main/java/gift/Entity/Category.java create mode 100644 src/main/java/gift/Entity/Member.java create mode 100644 src/main/java/gift/Entity/Option.java create mode 100644 src/main/java/gift/Entity/Product.java create mode 100644 src/main/java/gift/Entity/Wishlist.java create mode 100644 src/main/java/gift/Entity/WishlistId.java create mode 100644 src/main/java/gift/Exception/ForbiddenException.java create mode 100644 src/main/java/gift/Exception/UnauthorizedException.java create mode 100644 src/main/java/gift/Mapper/Mapper.java create mode 100644 src/main/java/gift/Model/CategoryDto.java create mode 100644 src/main/java/gift/Model/MemberDto.java create mode 100644 src/main/java/gift/Model/OptionDto.java create mode 100644 src/main/java/gift/Model/OrderRequestDto.java create mode 100644 src/main/java/gift/Model/ProductDto.java create mode 100644 src/main/java/gift/Model/WishlistDto.java create mode 100644 src/main/java/gift/Repository/CategoryJpaRepository.java create mode 100644 src/main/java/gift/Repository/MemberJpaRepository.java create mode 100644 src/main/java/gift/Repository/OptionJpaRepository.java create mode 100644 src/main/java/gift/Repository/ProductJpaRepository.java create mode 100644 src/main/java/gift/Repository/WishlistJpaRepository.java create mode 100644 src/main/java/gift/Service/CategoryService.java create mode 100644 src/main/java/gift/Service/MemberService.java create mode 100644 src/main/java/gift/Service/OptionService.java create mode 100644 src/main/java/gift/Service/ProductService.java create mode 100644 src/main/java/gift/Service/WishlistService.java create mode 100644 src/main/java/gift/Utils/JwtUtil.java create mode 100644 src/main/resources/templates/login.html create mode 100644 src/main/resources/templates/option_form.html create mode 100644 src/main/resources/templates/product_form.html create mode 100644 src/main/resources/templates/products.html create mode 100644 src/main/resources/templates/register.html create mode 100644 src/main/resources/templates/user_products.html create mode 100644 src/main/resources/templates/wishlist.html create mode 100644 src/test/java/gift/RepositoryTest/MemberDtoRepositoryTest.java create mode 100644 src/test/java/gift/RepositoryTest/OptionRepositoryTest.java create mode 100644 src/test/java/gift/RepositoryTest/ProductDtoRepositoryTest.java create mode 100644 src/test/java/gift/RepositoryTest/WishlistRepositoryTest.java create mode 100644 src/test/java/gift/ServiceTest/MemberServiceTest.java create mode 100644 src/test/java/gift/ServiceTest/OptionServiceTest.java create mode 100644 src/test/java/gift/ServiceTest/ProductServiceTest.java create mode 100644 src/test/java/gift/ServiceTest/WishlistServiceTest.java diff --git a/README.md b/README.md index 8bbd0354f..7a58279bc 100644 --- a/README.md +++ b/README.md @@ -1 +1,43 @@ -# spring-gift-order \ No newline at end of file +# spring-gift-enhancement +# 1단계 - 상품 카테고리 + +## 요구사항 +### 기능 요구사항 +상품 정보에 카테고리를 추가한다. 상품과 카테고리 모델 간의 관계를 고려하여 설계하고 구현한다. + +- 상품에는 항상 하나의 카테고리가 있어야 한다. +- 상품 카테고리는 수정할 수 있다. +- 관리자 화면에서 상품을 추가할 때 카테고리를 지정할 수 있다. +- 카테고리는 1차 카테고리만 있으며 2차 카테고리는 고려하지 않는다. +- 카테고리의 예시는 아래와 같다. +- 교환권, 상품권, 뷰티, 패션, 식품, 리빙/도서, 레저/스포츠, 아티스트/캐릭터, 유아동/반려, 디지털/가전, 카카오프렌즈, 트렌드 선물, 백화점, ... + +### 프로그래밍 요구사항 +프로그래밍 요구 사항 +구현한 기능에 대해 적절한 테스트 전략을 생각하고 작성한다. +- Repository 계층을 작성했으니 Service 계층 테스트도 작성해본다. + +# 2단계 - 상품 옵션 + +## 요구사항 +### 기능 요구사항 +상품 정보에 옵션을 추가한다. 상품과 옵션 모델 간의 관계를 고려하여 설계하고 구현한다. + +- 상품에는 항상 하나 이상의 옵션이 있어야 한다. +- 옵션 이름은 공백을 포함하여 최대 50자까지 입력할 수 있다. +- 특수 문자 + - 가능: ( ), [ ], +, -, &, /, _ + - 그 외 특수 문자 사용 불가 + - 옵션 수량은 최소 1개 이상 1억 개 미만이다. + - 중복된 옵션은 구매 시 고객에게 불편을 줄 수 있다. 동일한 상품 내의 옵션 이름은 중복될 수 없다. + +# 3단계 - 옵션 수량 차감 + +## 요구사항 +### 기능 요구사항 +상품 옵션의 수량을 지정된 숫자만큼 빼는 기능을 구현한다. +- 별도의 HTTP API를 만들 필요는 없다. +- 서비스 클래스 또는 엔티티 클래스에서 기능을 구현하고 나중에 사용할 수 있도록 한다. + +### 프로그래밍 요구사항 +구현한 기능에 대해 적절한 테스트 전략을 생각하고 작성한다. diff --git a/build.gradle b/build.gradle index df7db9334..abe886a0b 100644 --- a/build.gradle +++ b/build.gradle @@ -21,9 +21,17 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2' runtimeOnly 'com.h2database:h2' + compileOnly 'io.jsonwebtoken:jjwt-api:0.11.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.mockito:mockito-inline:4.9.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + } tasks.named('test') { diff --git a/src/main/java/gift/Annotation/LoginMemberArgumentResolver.java b/src/main/java/gift/Annotation/LoginMemberArgumentResolver.java new file mode 100644 index 000000000..1524028f7 --- /dev/null +++ b/src/main/java/gift/Annotation/LoginMemberArgumentResolver.java @@ -0,0 +1,61 @@ +package gift.Annotation; + +import gift.Model.MemberDto; +import gift.Service.MemberService; +import gift.Utils.JwtUtil; +import io.jsonwebtoken.Claims; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +@Component +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + private final MemberService memberService; + private final JwtUtil jwtUtil; + + @Autowired + public LoginMemberArgumentResolver(MemberService memberService, JwtUtil jwtUtil) { + this.memberService = memberService; + this.jwtUtil = jwtUtil; + } + + @Override + public boolean supportsParameter(MethodParameter methodParameter) { + return methodParameter.getParameterType().equals(MemberDto.class); + } + + @Override + public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { + HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest(); + + // 쿠키에서 JWT 토큰 추출 + String token = null; + if (request.getCookies() != null) { + for (Cookie cookie : request.getCookies()) { + if ("token".equals(cookie.getName())) { + token = cookie.getValue(); + break; + } + } + } + + if (token == null) { + throw new IllegalArgumentException("JWT token not found in cookies"); + } + + Claims claims = jwtUtil.decodeToken(token); //decode + String memberEmail = claims.getSubject(); // subject를 email로 설정했기 때문에 userEmail로 사용 + MemberDto memberDto = memberService.findByEmail(memberEmail); //null이라면 인증된 것이 아닐 것이고 null이 아니라면 인증된 것 + if (memberDto == null) { + throw new IllegalArgumentException("User not found"); + } + return memberDto; + + } +} diff --git a/src/main/java/gift/Annotation/LoginMemberResolver.java b/src/main/java/gift/Annotation/LoginMemberResolver.java new file mode 100644 index 000000000..d8c93ba94 --- /dev/null +++ b/src/main/java/gift/Annotation/LoginMemberResolver.java @@ -0,0 +1,11 @@ +package gift.Annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginMemberResolver { +} diff --git a/src/main/java/gift/Config/WebConfig.java b/src/main/java/gift/Config/WebConfig.java new file mode 100644 index 000000000..12ffb2f78 --- /dev/null +++ b/src/main/java/gift/Config/WebConfig.java @@ -0,0 +1,22 @@ +package gift.Config; + +import gift.Annotation.LoginMemberArgumentResolver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private LoginMemberArgumentResolver loginMemberResolverHandlerMethodArgumentResolver; + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginMemberResolverHandlerMethodArgumentResolver); + } + +} diff --git a/src/main/java/gift/Controller/CategoryController.java b/src/main/java/gift/Controller/CategoryController.java new file mode 100644 index 000000000..cb4994c44 --- /dev/null +++ b/src/main/java/gift/Controller/CategoryController.java @@ -0,0 +1,25 @@ +package gift.Controller; + +import gift.Model.CategoryDto; +import gift.Service.CategoryService; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +import java.util.List; + +@Controller +public class CategoryController { + + private final CategoryService categoryService; + + public CategoryController(CategoryService categoryService) { + this.categoryService = categoryService; + } + + @GetMapping("/api/categories") + public ResponseEntity> getAllCategories() { + List categoryDtoList = categoryService.getAllCategories(); + return ResponseEntity.ok(categoryDtoList); + } +} diff --git a/src/main/java/gift/Controller/GlobalExceptionHandler.java b/src/main/java/gift/Controller/GlobalExceptionHandler.java new file mode 100644 index 000000000..e536ca7b8 --- /dev/null +++ b/src/main/java/gift/Controller/GlobalExceptionHandler.java @@ -0,0 +1,45 @@ +package gift.Controller; + +import gift.Exception.ForbiddenException; +import gift.Exception.UnauthorizedException; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.ui.Model; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(MethodArgumentNotValidException.class) + public String handleMethodArgumentNotValid(MethodArgumentNotValidException ex, Model model, HttpServletRequest request) { + FieldError fieldError = ex.getBindingResult().getFieldError(); + String errorMessage = fieldError.getDefaultMessage(); + + model.addAttribute("error", errorMessage); + model.addAttribute("product", ex.getBindingResult().getTarget()); + + // 에러가 발생한 URL에 따라 다시 해당 페이지로 돌아가기 + String requestUrl = request.getRequestURI(); + if (requestUrl.equals("/api/products/create") || requestUrl.startsWith("/api/products/update")) { + return "product_form"; // product_form 뷰로 포워딩 + } + + return "redirect:/api/products"; + } + + @ExceptionHandler(UnauthorizedException.class) + public ResponseEntity handleUnauthorizedException(UnauthorizedException ex) { + return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(ForbiddenException.class) + public ResponseEntity handleForbiddenException(ForbiddenException ex) { + return new ResponseEntity<>(ex.getMessage(), HttpStatus.FORBIDDEN); + } + +} diff --git a/src/main/java/gift/Controller/MemberController.java b/src/main/java/gift/Controller/MemberController.java new file mode 100644 index 000000000..0dca1cee9 --- /dev/null +++ b/src/main/java/gift/Controller/MemberController.java @@ -0,0 +1,72 @@ +package gift.Controller; + +import gift.Entity.Member; +import gift.Model.MemberDto; +import gift.Service.MemberService; +import gift.Utils.JwtUtil; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import jakarta.servlet.http.HttpServletRequest; + +@Controller +public class MemberController { + + private final MemberService memberService; + private final JwtUtil jwtUtil; + + @Autowired + public MemberController(MemberService memberService, JwtUtil jwtUtil) { + this.memberService = memberService; + this.jwtUtil = jwtUtil; + } + + @GetMapping("/login") + public String login(Model model) { + model.addAttribute("user", new MemberDto()); + return "login"; + } + + @PostMapping(value = "/login") + public String login(@ModelAttribute MemberDto memberDto, Model model, HttpServletResponse response) { + String email = memberDto.getEmail(); + String password = memberDto.getPassword(); + + boolean isAuthenticated = memberService.authenticate(email, password); + if (isAuthenticated) { + boolean isAdmin = memberService.isAdmin(email); + MemberDto authenticatedMember = memberService.findByEmail(email); + String token = jwtUtil.generateToken(authenticatedMember, isAdmin); + // Set token in HttpOnly cookie + Cookie cookie = new Cookie("token", token); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + + if (isAdmin) { + return "redirect:/api/products"; + } + return "redirect:/products"; + } + + model.addAttribute("error", "Authentication failed"); + return "login"; + } + + @RequestMapping(value = "/register", method = {RequestMethod.GET, RequestMethod.POST}) + public String register(@ModelAttribute MemberDto memberDto, Model model, HttpServletRequest request) { + if ("GET".equalsIgnoreCase(request.getMethod())) { + model.addAttribute("user", new MemberDto()); + return "register"; + } else if ("POST".equalsIgnoreCase(request.getMethod())) { + model.addAttribute("user", memberDto); + memberService.register(memberDto); + model.addAttribute("message", "회원가입에 성공했습니다."); + return "login"; + } + return "login"; + } +} diff --git a/src/main/java/gift/Controller/OptionController.java b/src/main/java/gift/Controller/OptionController.java new file mode 100644 index 000000000..6f1f0d438 --- /dev/null +++ b/src/main/java/gift/Controller/OptionController.java @@ -0,0 +1,83 @@ +package gift.Controller; + +import gift.Model.OptionDto; +import gift.Service.OptionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Controller +public class OptionController { + + private final OptionService optionService; + + @Autowired + public OptionController(OptionService optionService) { + this.optionService = optionService; + } + + @GetMapping("/api/products/options/{productId}") + public ResponseEntity> getAllOptionsByProductId(@PathVariable Long productId) { + List options = optionService.getAllOptionsByProductId(productId); + if (options.isEmpty()) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(options); + } + + @GetMapping("/api/products/options/add/{productId}") + public String addOption(Model model, @PathVariable("productId") long productId) { + OptionDto optionDto = new OptionDto(); + optionDto.setProductId(productId); + model.addAttribute("optionDto", optionDto); + return "option_form"; + } + + @PostMapping("/api/products/options/add") + public String addOption(@ModelAttribute OptionDto optionDto, Model model, @RequestParam("productId") long productId) { + model.addAttribute("optionDto", optionDto); + optionDto.setProductId(productId); + optionService.addOption(optionDto); + return "redirect:/api/products"; + } + + @GetMapping("/api/products/options/{productId}/{optionId}/update") + public String updateOption(Model model, @PathVariable long productId, @PathVariable long optionId) { + OptionDto optionDto = optionService.getOptionById(optionId); + model.addAttribute("optionDto", optionDto); + return "option_form"; + } + + @PostMapping("/api/products/options/{productId}/{optionId}/update") + public ResponseEntity updateOption(@PathVariable long productId, @PathVariable long optionId, @ModelAttribute OptionDto optionDto, Model model) { + try { + model.addAttribute("optionDto", optionDto); + optionDto.setProductId(productId); + optionDto.setId(optionId); + optionService.updateOption(optionDto); + HttpHeaders headers = new HttpHeaders(); + headers.add("Location", "/api/products"); + return new ResponseEntity<>("Option updated successfully", headers, HttpStatus.SEE_OTHER); + } catch (Exception e) { + return ResponseEntity.badRequest().body("Error updating option"); + } + } + + @DeleteMapping("/api/products/options/{optionId}/delete") + public ResponseEntity deleteOption(@PathVariable long optionId) { + try { + optionService.deleteOption(optionId); + HttpHeaders headers = new HttpHeaders(); + headers.add("Location", "/api/products"); + return new ResponseEntity<>("Option updated successfully", headers, HttpStatus.SEE_OTHER); + } catch (Exception e) { + return ResponseEntity.badRequest().body("Error deleting option"); + } + } +} diff --git a/src/main/java/gift/Controller/ProductController.java b/src/main/java/gift/Controller/ProductController.java new file mode 100644 index 000000000..f89a6392e --- /dev/null +++ b/src/main/java/gift/Controller/ProductController.java @@ -0,0 +1,91 @@ +package gift.Controller; + +import gift.Model.ProductDto; +import gift.Service.CategoryService; +import gift.Service.ProductService; + +import java.util.Optional; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +@Controller +public class ProductController { + + private final ProductService productService; + private final CategoryService categoryService; + + @Autowired + public ProductController(ProductService productService, CategoryService categoryService) { + this.productService = productService; + this.categoryService = categoryService; + } + + @GetMapping("/api/products") + public String getAllProductsByRoot(Model model, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + Page paging = productService.getAllProductsByPage(pageable); + model.addAttribute("paging", paging); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", paging.getTotalPages()); + return "products"; + } + + @GetMapping("/products") + public String getAllProductsByUser(Model model, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + Page paging = productService.getAllProductsByPage(pageable); + model.addAttribute("paging", paging); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", paging.getTotalPages()); + return "user_products"; + } + + @RequestMapping(value = "/api/products/create", method = {RequestMethod.GET, RequestMethod.POST}) + public String createProduct(@Valid @ModelAttribute ProductDto productDto, HttpServletRequest request, Model model) { + if ("GET".equalsIgnoreCase(request.getMethod())) { + model.addAttribute("product", new ProductDto()); + model.addAttribute("categories", categoryService.getAllCategories()); + return "product_form"; + } else if ("POST".equalsIgnoreCase(request.getMethod())) { + model.addAttribute("product", productDto); + productService.saveProduct(productDto); + return "redirect:/api/products"; + } + return "error"; + } + + @RequestMapping(value = "/api/products/update/{id}", method = {RequestMethod.GET, RequestMethod.POST}) + public String updateProductById(@PathVariable Long id, @Valid @ModelAttribute ProductDto productDtoDetails, HttpServletRequest request, Model model) { + if ("GET".equalsIgnoreCase(request.getMethod())) { + Optional optionalProduct = productService.getProductById(id); + model.addAttribute("product", optionalProduct.get()); + model.addAttribute("categories", categoryService.getAllCategories()); + return "product_form"; + } else if ("POST".equalsIgnoreCase(request.getMethod())) { + productService.updateProduct(productDtoDetails); + return "redirect:/api/products"; + } + return "error"; + } + + @PostMapping("/api/products/delete/{id}") + public String deleteProduct(@PathVariable Long id, Model model) { + Optional optionalProduct = productService.getProductById(id); + model.addAttribute("product", optionalProduct.get()); + productService.deleteProduct(id); + return "redirect:/api/products"; // 제품 목록 페이지로 리디렉션 + } + +} diff --git a/src/main/java/gift/Controller/WishlistController.java b/src/main/java/gift/Controller/WishlistController.java new file mode 100644 index 000000000..bf7e9c741 --- /dev/null +++ b/src/main/java/gift/Controller/WishlistController.java @@ -0,0 +1,66 @@ +package gift.Controller; + +import gift.Annotation.LoginMemberResolver; +import gift.Entity.Wishlist; +import gift.Model.MemberDto; +import gift.Model.ProductDto; +import gift.Model.WishlistDto; +import gift.Service.WishlistService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@Controller +public class WishlistController { + + private final WishlistService wishlistService; + + @Autowired + public WishlistController(WishlistService wishlistService) { + this.wishlistService = wishlistService; + } + + @GetMapping("/wishlist") + public String getWishlist(@LoginMemberResolver MemberDto memberDto, Model model, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size); + Page paging = wishlistService.getWishlistByPage(memberDto, pageable); + model.addAttribute("paging", paging); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", paging.getTotalPages()); + return "wishlist"; + } + + @PostMapping("/wishlist/add") + public String addWishlistItem(@LoginMemberResolver MemberDto memberDto, @RequestBody WishlistDto wishlistDto) { + if (memberDto == null) { + return "redirect:/login"; + } + wishlistDto.setUserId(memberDto.getId()); + wishlistService.addWishlistItem(wishlistDto); + return "redirect:/products"; + } + + @PostMapping("/wishlist/remove") + public String removeWishlistItem(@LoginMemberResolver MemberDto memberDto, @RequestBody WishlistDto wishlistDto) { + if (memberDto == null) { + return "redirect:/login"; + } + + Optional wishlistOptional = wishlistService.getWishlist(memberDto.getId()).stream() + .filter(wishlist -> wishlist.getProductId() == wishlistDto.getProductId()) + .findFirst(); + wishlistDto.setUserId(memberDto.getId()); + + wishlistService.removeWishlistItem(wishlistDto, wishlistOptional.get()); + + return "redirect:/wishlist"; + } +} diff --git a/src/main/java/gift/DatabaseInitialize/DatabaseInitializer.java b/src/main/java/gift/DatabaseInitialize/DatabaseInitializer.java new file mode 100644 index 000000000..08b78e7dc --- /dev/null +++ b/src/main/java/gift/DatabaseInitialize/DatabaseInitializer.java @@ -0,0 +1,32 @@ +package gift.DatabaseInitialize; + +import gift.Entity.Category; +import gift.Repository.CategoryJpaRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +public class DatabaseInitializer implements CommandLineRunner { + + private final CategoryJpaRepository categoryJpaRepository; + + @Autowired + public DatabaseInitializer(CategoryJpaRepository categoryJpaRepository) { + this.categoryJpaRepository = categoryJpaRepository; + } + + @Override + public void run(String... args) throws Exception { + categoryJpaRepository.save(new Category(1, "교환권")); + categoryJpaRepository.save(new Category(2, "상품권")); + categoryJpaRepository.save(new Category(3, "뷰티")); + categoryJpaRepository.save(new Category(4, "패션")); + categoryJpaRepository.save(new Category(5, "식품")); + categoryJpaRepository.save(new Category(6, "리빙/도서")); + categoryJpaRepository.save(new Category(7, "레저/스포츠")); + + } + + +} diff --git a/src/main/java/gift/Entity/Category.java b/src/main/java/gift/Entity/Category.java new file mode 100644 index 000000000..9e3124617 --- /dev/null +++ b/src/main/java/gift/Entity/Category.java @@ -0,0 +1,41 @@ +package gift.Entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Category { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long categoryId; + private String name; + + protected Category() { + + } + + public Category(long categoryId, String name) { + this.categoryId = categoryId; + this.name = name; + } + + + public long getCategoryId() { + return categoryId; + } + + public void setCategoryId(long categoryId) { + this.categoryId = categoryId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/gift/Entity/Member.java b/src/main/java/gift/Entity/Member.java new file mode 100644 index 000000000..431e67381 --- /dev/null +++ b/src/main/java/gift/Entity/Member.java @@ -0,0 +1,68 @@ +package gift.Entity; + +import gift.Model.MemberDto; +import jakarta.persistence.*; + +@Entity +public class Member { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long userId; + private String email; + private String name; + private String password; + private boolean isAdmin; + + protected Member() { + } + + public Member(long userId, String email, String name, String password, boolean isAdmin) { + this.userId = userId; + this.email = email; + this.name = name; + this.password = password; + this.isAdmin = isAdmin; + } + + // Getters and setters + public long getId() { + return userId; + } + + public void setId(Long userId) { + this.userId = userId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isAdmin() { + return isAdmin; + } + + public void setAdmin(boolean admin) { + isAdmin = admin; + } +} \ No newline at end of file diff --git a/src/main/java/gift/Entity/Option.java b/src/main/java/gift/Entity/Option.java new file mode 100644 index 000000000..a78d2fc8b --- /dev/null +++ b/src/main/java/gift/Entity/Option.java @@ -0,0 +1,69 @@ +package gift.Entity; + +import jakarta.persistence.*; + +@Entity +public class Option { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) + @JoinColumn(name = "productId", referencedColumnName = "productId") + private Product product; + private String name; + private int price; + private int quantity; + + protected Option() { + + } + + public Option(long id, Product product, String name, int price, int quantity) { + this.id = id; + this.product = product; + this.name = name; + this.price = price; + this.quantity = quantity; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public Product getProduct() { + return product; + } + + public void setProduct(Product product) { + this.product = product; + } +} diff --git a/src/main/java/gift/Entity/Product.java b/src/main/java/gift/Entity/Product.java new file mode 100644 index 000000000..0ea2014fd --- /dev/null +++ b/src/main/java/gift/Entity/Product.java @@ -0,0 +1,78 @@ +package gift.Entity; + +import jakarta.persistence.*; + +@Entity +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long productId; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) + @JoinColumn(name = "categoryId", referencedColumnName = "categoryId") + private Category category; + private String name; + private int price; + private String imageUrl; + private boolean isDeleted; + + protected Product() { + } + + public Product(long productId, String name, Category category, int price, String imageUrl, boolean isDeleted) { + this.productId = productId; + this.name = name; + this.category = category; + this.price = price; + this.imageUrl = imageUrl; + this.isDeleted = isDeleted; + } + + public long getId() { + return productId; + } + + public void setId(Long productId) { + this.productId = productId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public boolean isDeleted() { + return isDeleted; + } + + public void setDeleted(boolean deleted) { + isDeleted = deleted; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } +} diff --git a/src/main/java/gift/Entity/Wishlist.java b/src/main/java/gift/Entity/Wishlist.java new file mode 100644 index 000000000..0f4bb58fc --- /dev/null +++ b/src/main/java/gift/Entity/Wishlist.java @@ -0,0 +1,87 @@ +package gift.Entity; + +import gift.Model.MemberDto; +import gift.Model.ProductDto; +import gift.Model.WishlistDto; +import jakarta.persistence.*; + +@Entity +public class Wishlist { + + @EmbeddedId + private WishlistId id; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) + @MapsId("userId") + @JoinColumn(name = "userId", referencedColumnName = "userId") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) + @MapsId("productId") + @JoinColumn(name = "productId", referencedColumnName = "productId") + private Product product; + + private String productName; + private int count; + private int price; + + protected Wishlist() { + } + + public Wishlist(WishlistId id, Member member, Product product, String productName, int count, int price) { + this.id = id; + this.member = member; + this.product = product; + this.productName = productName; + this.count = count; + this.price = price; + } + + public WishlistId getId() { + return id; + } + + public void setId(WishlistId id) { + this.id = id; + } + + public long getUserId() { + return id.getUserId(); + } + + public void setUserId(long userId) { + id.setUserId(userId); + } + + public long getProductId() { + return id.getProductId(); + } + + public void setProductId(long productId) { + id.setProductId(productId); + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } +} \ No newline at end of file diff --git a/src/main/java/gift/Entity/WishlistId.java b/src/main/java/gift/Entity/WishlistId.java new file mode 100644 index 000000000..6aa003aa5 --- /dev/null +++ b/src/main/java/gift/Entity/WishlistId.java @@ -0,0 +1,36 @@ +package gift.Entity; + +import jakarta.persistence.Embeddable; + +import java.io.Serializable; + +@Embeddable +public class WishlistId implements Serializable { + + private long userId; + private long productId; + + protected WishlistId() { + } + + public WishlistId(long userId, long productId) { + this.userId = userId; + this.productId = productId; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public long getProductId() { + return productId; + } + + public void setProductId(long productId) { + this.productId = productId; + } +} \ No newline at end of file diff --git a/src/main/java/gift/Exception/ForbiddenException.java b/src/main/java/gift/Exception/ForbiddenException.java new file mode 100644 index 000000000..cc48acc25 --- /dev/null +++ b/src/main/java/gift/Exception/ForbiddenException.java @@ -0,0 +1,11 @@ +package gift.Exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.FORBIDDEN) +public class ForbiddenException extends RuntimeException { + public ForbiddenException(String message) { + super(message); + } +} diff --git a/src/main/java/gift/Exception/UnauthorizedException.java b/src/main/java/gift/Exception/UnauthorizedException.java new file mode 100644 index 000000000..2ff78ad99 --- /dev/null +++ b/src/main/java/gift/Exception/UnauthorizedException.java @@ -0,0 +1,11 @@ +package gift.Exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.UNAUTHORIZED) +public class UnauthorizedException extends RuntimeException { + public UnauthorizedException(String message) { + super(message); + } +} diff --git a/src/main/java/gift/Mapper/Mapper.java b/src/main/java/gift/Mapper/Mapper.java new file mode 100644 index 000000000..c9c05567b --- /dev/null +++ b/src/main/java/gift/Mapper/Mapper.java @@ -0,0 +1,88 @@ +package gift.Mapper; + +import gift.Entity.*; +import gift.Model.*; +import gift.Service.CategoryService; +import gift.Service.ProductService; +import gift.Service.MemberService; +import gift.Service.WishlistService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +public class Mapper { + + private final ProductService productService; + private final MemberService memberService; + private final WishlistService wishlistService; + private final CategoryService categoryService; + + @Autowired + public Mapper(@Lazy ProductService productService, @Lazy MemberService memberService, @Lazy WishlistService wishListService, @Lazy CategoryService categoryService) { + this.productService = productService; + this.memberService = memberService; + this.wishlistService = wishListService; + this.categoryService = categoryService; + } + + + public Wishlist wishlistDtoToEntity(WishlistDto wishlistDto) { + Optional memberDtoOptional = memberService.findByUserId(wishlistDto.getUserId()); + MemberDto memberDto = memberDtoOptional.get(); + + Optional productDtoOptional = productService.getProductById(wishlistDto.getProductId()); + ProductDto productDto = productDtoOptional.get(); + productDto.setCategoryId(productDtoOptional.get().getCategoryId()); + + WishlistId id = new WishlistId(memberDto.getId(), productDto.getId()); + return new Wishlist(id, memberDtoToEntity(memberDto), productDtoToEntity(productDto), wishlistDto.getProductName(), wishlistDto.getCount(), wishlistDto.getPrice()); + + } + + public WishlistDto wishlistToDto(Wishlist wishlist) { + return new WishlistDto(wishlist.getUserId(), wishlist.getProductId(), wishlist.getCount(), 0, wishlist.getProductName(), wishlist.getPrice()); + } + + public Category categoryDtoToEntity(CategoryDto categoryDto) { + return new Category(categoryDto.getId(), categoryDto.getName()); + } + + public CategoryDto categoryToDto(Category category) { + return new CategoryDto(category.getCategoryId(), category.getName()); + } + + //categoryService를 포함하기엔 뭔가 일관성이 깨지는 느낌인데??? + public Product productDtoToEntity(ProductDto productDto) { + Category category = categoryService.getCategoryById(productDto.getCategoryId()).get(); + CategoryDto categoryDto = categoryToDto(category); + return new Product(productDto.getId(), productDto.getName(), categoryDtoToEntity(categoryDto), productDto.getPrice(), productDto.getImageUrl(), productDto.isDeleted()); + } + + public ProductDto productToDto(Product product) { + Category category = categoryService.getCategoryById(product.getCategory().getCategoryId()).get(); + + return new ProductDto(product.getId(), product.getName(), categoryToDto(category).getId(), product.getPrice(), product.getImageUrl(), product.isDeleted()); + } + + public Member memberDtoToEntity(MemberDto memberDto) { + return new Member(memberDto.getId(), memberDto.getEmail(), memberDto.getName(), memberDto.getPassword(), memberDto.isAdmin()); + } + + public MemberDto memberToDto(Member member) { + return new MemberDto(member.getId(), member.getEmail(), member.getName(), member.getPassword(), member.isAdmin()); + } + + public OptionDto optionToDto(Option option) { + return new OptionDto(option.getId(), option.getProduct().getId(), option.getName(), option.getPrice(), option.getQuantity()); + } + + public Option optionDtoToEntity(OptionDto optionDto) { + Optional productDtoOptional = productService.getProductById(optionDto.getProductId()); + ProductDto productDto = productDtoOptional.get(); + return new Option(optionDto.getId(), productDtoToEntity(productDto), optionDto.getName(), optionDto.getPrice(), optionDto.getQuantity()); + } + +} diff --git a/src/main/java/gift/Model/CategoryDto.java b/src/main/java/gift/Model/CategoryDto.java new file mode 100644 index 000000000..e047d81a3 --- /dev/null +++ b/src/main/java/gift/Model/CategoryDto.java @@ -0,0 +1,32 @@ +package gift.Model; + +public class CategoryDto { + + private long id; + private String name; + + public CategoryDto() { + + } + + public CategoryDto(long id, String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/gift/Model/MemberDto.java b/src/main/java/gift/Model/MemberDto.java new file mode 100644 index 000000000..867546fab --- /dev/null +++ b/src/main/java/gift/Model/MemberDto.java @@ -0,0 +1,61 @@ +package gift.Model; + +public class MemberDto { + private long id; + private String email; + private String name; + private String password; + private boolean isAdmin; + + public MemberDto() { + + } + + public MemberDto(long id, String email, String password, String name, boolean isAdmin) { + this.id = id; + this.email = email; + this.password = password; + this.name = name; + this.isAdmin = isAdmin; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public boolean isAdmin() { + return isAdmin; + } + + public void setAdmin(boolean admin) { + this.isAdmin = admin; + } +} diff --git a/src/main/java/gift/Model/OptionDto.java b/src/main/java/gift/Model/OptionDto.java new file mode 100644 index 000000000..941a2c59a --- /dev/null +++ b/src/main/java/gift/Model/OptionDto.java @@ -0,0 +1,71 @@ +package gift.Model; + +import jakarta.validation.constraints.*; + +public class OptionDto { + + private long id; + private long productId; + @Size(min = 1, max = 50, message = "이름의 글자 수는 1자 이상, 50자 이하여야 합니다.") + @Pattern(regexp = "^[\\w\\s()+\\-/&_\\[\\]가-힣]*$", message = "( ), [ ], +, -, &, /, _" + + "외의 다른 특수 문자 사용 불가") + @NotNull(message = "옵션 이름은 필수입니다.") + private String name; + private int price; + + @Min(value = 1, message = "옵션의 수량은 최소 하나 이상입니다.") + @Max(value = 100_000_000, message = "옵션의 수량은 1억 이하입니다.") + private int quantity; + + public OptionDto() { + } + + public OptionDto(long id, long productId, String name, int price, int quantity) { + this.id = id; + this.productId = productId; + this.name = name; + this.price = price; + this.quantity = quantity; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + + public long getProductId() { + return productId; + } + + public void setProductId(long productId) { + this.productId = productId; + } +} diff --git a/src/main/java/gift/Model/OrderRequestDto.java b/src/main/java/gift/Model/OrderRequestDto.java new file mode 100644 index 000000000..3ae6172a9 --- /dev/null +++ b/src/main/java/gift/Model/OrderRequestDto.java @@ -0,0 +1,50 @@ +package gift.Model; + +public class OrderRequestDto { + long productId; + long optionId; + int quantity; + long memberId; + + public OrderRequestDto() { + } + + public OrderRequestDto(long productId, long optionId, int quantity, long memberId) { + this.productId = productId; + this.optionId = optionId; + this.quantity = quantity; + this.memberId = memberId; + } + + public long getProductId() { + return productId; + } + + public void setProductId(long productId) { + this.productId = productId; + } + + public long getOptionId() { + return optionId; + } + + public void setOptionId(long optionId) { + this.optionId = optionId; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public long getMemberId() { + return memberId; + } + + public void setMemberId(long memberId) { + this.memberId = memberId; + } +} diff --git a/src/main/java/gift/Model/ProductDto.java b/src/main/java/gift/Model/ProductDto.java new file mode 100644 index 000000000..0da98ff07 --- /dev/null +++ b/src/main/java/gift/Model/ProductDto.java @@ -0,0 +1,83 @@ +package gift.Model; + +import jakarta.persistence.*; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public class ProductDto { + + private long id; + @Size(min = 1, max = 15, message = "글자 수는 1자 이상, 15자 이하여야 합니다.") + @Pattern(regexp = "^[\\w\\s()+\\-/&_\\[\\]가-힣]*$", message = "( ), [ ], +, -, &, /, _" + + "외의 다른 특수 문자 사용 불가") + @Pattern(regexp = "^(?!.*카카오).*$", message = "\"카카오\"가 포함된 문구는 담당 MD와 협의한 경우에만 사용할 수 있습니다.") + private String name; + private long categoryId; + private int price; + private String imageUrl; + private boolean isDeleted; + + public ProductDto() { + + } + + public ProductDto(long id, String name, long categoryId, int price, String imageUrl, boolean isDeleted) { + this.id = id; + this.name = name; + this.categoryId = categoryId; + this.price = price; + this.imageUrl = imageUrl; + this.isDeleted = isDeleted; + } + + public String getName() { + + return name; + } + + public int getPrice() { + + return price; + } + + public String getImageUrl() { + + return imageUrl; + } + + public boolean isDeleted() { + return isDeleted; + } + + public void setDeleted(boolean deleted) { + isDeleted = deleted; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public void setPrice(int price) { + this.price = price; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getCategoryId() { + return categoryId; + } + + public void setCategoryId(long categoryId) { + this.categoryId = categoryId; + } +} diff --git a/src/main/java/gift/Model/WishlistDto.java b/src/main/java/gift/Model/WishlistDto.java new file mode 100644 index 000000000..1bfd0f486 --- /dev/null +++ b/src/main/java/gift/Model/WishlistDto.java @@ -0,0 +1,70 @@ +package gift.Model; + +public class WishlistDto { + private long userId; + private long productId; + private int count; // 담은 개수 + private int quantity;//뺄 개수 + private String productName; + private int price; + + public WishlistDto() { + } + + public WishlistDto(long userId, long productId, int count, int quantity, String productName, int price) { + this.userId = userId; + this.productId = productId; + this.count = count; + this.quantity = quantity; + this.productName = productName; + this.price = price; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public long getProductId() { + return productId; + } + + public void setProductId(long productId) { + this.productId = productId; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } +} diff --git a/src/main/java/gift/Repository/CategoryJpaRepository.java b/src/main/java/gift/Repository/CategoryJpaRepository.java new file mode 100644 index 000000000..d5f22dbca --- /dev/null +++ b/src/main/java/gift/Repository/CategoryJpaRepository.java @@ -0,0 +1,8 @@ +package gift.Repository; + +import gift.Entity.Category; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryJpaRepository extends JpaRepository { + +} diff --git a/src/main/java/gift/Repository/MemberJpaRepository.java b/src/main/java/gift/Repository/MemberJpaRepository.java new file mode 100644 index 000000000..b333a3d41 --- /dev/null +++ b/src/main/java/gift/Repository/MemberJpaRepository.java @@ -0,0 +1,14 @@ +package gift.Repository; + +import gift.Entity.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface MemberJpaRepository extends JpaRepository { + + Optional findByEmail(String email); + + Optional findByEmailAndPassword(String email, String password); + +} diff --git a/src/main/java/gift/Repository/OptionJpaRepository.java b/src/main/java/gift/Repository/OptionJpaRepository.java new file mode 100644 index 000000000..3653c69c3 --- /dev/null +++ b/src/main/java/gift/Repository/OptionJpaRepository.java @@ -0,0 +1,11 @@ +package gift.Repository; + +import gift.Entity.Option; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface OptionJpaRepository extends JpaRepository{ + List